From 9cc86e2a0dbea11233720af1b6c6657aa8aed15a Mon Sep 17 00:00:00 2001 From: JamesParrott <80779630+JamesParrott@users.noreply.github.com> Date: Tue, 17 Sep 2024 19:21:03 +0100 Subject: [PATCH 1/2] Test Python 14 alpha on Ubuntu 22.04 --- .github/workflows/run_tests_and_hooks.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/run_tests_and_hooks.yml b/.github/workflows/run_tests_and_hooks.yml index d64480a..0a24eba 100644 --- a/.github/workflows/run_tests_and_hooks.yml +++ b/.github/workflows/run_tests_and_hooks.yml @@ -60,6 +60,8 @@ jobs: include: - os: ubuntu-24.04 python-version: "3.14.0-alpha.0" + - os: ubuntu-22.04 + python-version: "3.14.0-alpha.0" runs-on: ${{ matrix.os }} steps: From 31798dab61483ed4b06fe129eb070d171bcc3a83 Mon Sep 17 00:00:00 2001 From: JamesParrott <80779630+JamesParrott@users.noreply.github.com> Date: Thu, 19 Sep 2024 14:09:53 +0100 Subject: [PATCH 2/2] Fix some Pylint warnings. Silence W0212 in config using pylint_per_file_ignore. Give credit. Requiring pytest >= 3.7 means pathib2 will always be available. Pylint needs the deps installed, of the files it checks Dedupe pip install Setup pylint in CI --- ...ooks.yml => run_tests_hooks_and_tools.yml} | 13 ++++++ README.md | 7 ++- pyproject.toml | 20 +++++++++ requirements.test.txt | 2 +- test_shapefile.py | 44 +++++++++---------- 5 files changed, 60 insertions(+), 26 deletions(-) rename .github/workflows/{run_tests_and_hooks.yml => run_tests_hooks_and_tools.yml} (79%) diff --git a/.github/workflows/run_tests_and_hooks.yml b/.github/workflows/run_tests_hooks_and_tools.yml similarity index 79% rename from .github/workflows/run_tests_and_hooks.yml rename to .github/workflows/run_tests_hooks_and_tools.yml index 0a24eba..4c393a3 100644 --- a/.github/workflows/run_tests_and_hooks.yml +++ b/.github/workflows/run_tests_hooks_and_tools.yml @@ -17,6 +17,19 @@ jobs: - uses: actions/setup-python@v5 - uses: pre-commit/action@v3.0.1 + pylint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + - name: install Pylint and plugin + run: | + python -m pip install --upgrade pip + pip install pytest pylint pylint-per-file-ignores + - name: run Pylint for errors and warnings only, on test_shapefile.py + run: | + pylint --disable=R,C test_shapefile.py + test_on_old_Pythons: strategy: fail-fast: false diff --git a/README.md b/README.md index 8bfc869..15f9f9b 100644 --- a/README.md +++ b/README.md @@ -1440,8 +1440,9 @@ In the same folder as README.md and shapefile.py, from the command line run $ python shapefile.py ``` -Linux/Mac and similar platforms will need to run `$ dos2unix README.md` in order -to correct line endings in README.md. +Linux/Mac and similar platforms may need to run `$ dos2unix README.md` in order +to correct line endings in README.md, if Git has not automatically changed them. + # Contributors @@ -1459,10 +1460,12 @@ fiveham geospatialpython Hannes Ignacio Martinez Vazquez +James Parrott Jason Moujaes Jonty Wareing Karim Bahgat karanrn +Kurt Schwehr Kyle Kelley Louis Tiao Marcin Cuprjak diff --git a/pyproject.toml b/pyproject.toml index fed528d..e4a82a1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,23 @@ [build-system] requires = ["setuptools"] build-backend = "setuptools.build_meta" + +[tool.pylint.MASTER] +load-plugins=[ + "pylint_per_file_ignores", +] + +[tool.pylint.'MESSAGES CONTROL'] +# Silence warning: shapefile.py:2076:20: W0212: Access to a protected +# member _from_geojson of a client class (protected-access) +# +# Silence warnings: test_shapefile.py:{783,786,799,803,06,1195}:19: +# W0212: Access to a protected member _offsets of a +# client class (protected-access) +# +# Toml multi-line string used instead of array due to: +# https://github.com/christopherpickering/pylint-per-file-ignores/issues/160 +per-file-ignores = """ + shapefile.py:W0212 + test_shapefile.py:W0212 +""" \ No newline at end of file diff --git a/requirements.test.txt b/requirements.test.txt index 27472ef..1114173 100644 --- a/requirements.test.txt +++ b/requirements.test.txt @@ -1,2 +1,2 @@ -pytest +pytest >= 3.7 setuptools diff --git a/test_shapefile.py b/test_shapefile.py index c9cd972..f5dd718 100644 --- a/test_shapefile.py +++ b/test_shapefile.py @@ -5,18 +5,16 @@ import datetime import json import os.path -import sys -if sys.version_info.major == 3: +try: from pathlib import Path +except ImportError: + # pathlib2 is a dependency of pytest >= 3.7 + from pathlib2 import Path # third party imports import pytest -if sys.version_info.major == 2: - # required by pytest for python <36 - from pathlib2 import Path - # our imports import shapefile @@ -208,7 +206,7 @@ def test_empty_shape_geo_interface(): """ shape = shapefile.Shape() with pytest.raises(Exception): - shape.__geo_interface__ + getattr(shape, '__geo_interface__') @pytest.mark.parametrize("typ,points,parts,expected", geo_interface_tests) def test_expected_shape_geo_interface(typ, points, parts, expected): @@ -257,17 +255,17 @@ def test_reader_url(): # test with extension url = "https://github.com/nvkelso/natural-earth-vector/blob/master/110m_cultural/ne_110m_admin_0_tiny_countries.shp?raw=true" with shapefile.Reader(url) as sf: - for recShape in sf.iterShapeRecords(): + for __recShape in sf.iterShapeRecords(): pass - assert sf.shp.closed == sf.shx.closed == sf.dbf.closed is True + assert sf.shp.closed is sf.shx.closed is sf.dbf.closed is True # test without extension url = "https://github.com/nvkelso/natural-earth-vector/blob/master/110m_cultural/ne_110m_admin_0_tiny_countries?raw=true" with shapefile.Reader(url) as sf: - for recShape in sf.iterShapeRecords(): + for __recShape in sf.iterShapeRecords(): pass assert len(sf) > 0 - assert sf.shp.closed == sf.shx.closed == sf.dbf.closed is True + assert sf.shp.closed is sf.shx.closed is sf.dbf.closed is True # test no files found url = "https://raw.githubusercontent.com/nvkelso/natural-earth-vector/master/README.md" @@ -278,10 +276,10 @@ def test_reader_url(): # test reading zipfile from url url = "https://github.com/JamesParrott/PyShp_test_shapefile/raw/main/gis_osm_natural_a_free_1.zip" with shapefile.Reader(url) as sf: - for recShape in sf.iterShapeRecords(): + for __recShape in sf.iterShapeRecords(): pass assert len(sf) > 0 - assert sf.shp.closed == sf.shx.closed == sf.dbf.closed is True + assert sf.shp.closed is sf.shx.closed is sf.dbf.closed is True def test_reader_zip(): @@ -290,10 +288,10 @@ def test_reader_zip(): """ # test reading zipfile only with shapefile.Reader("shapefiles/blockgroups.zip") as sf: - for recShape in sf.iterShapeRecords(): + for __recShape in sf.iterShapeRecords(): pass assert len(sf) > 0 - assert sf.shp.closed == sf.shx.closed == sf.dbf.closed is True + assert sf.shp.closed is sf.shx.closed is sf.dbf.closed is True # test require specific path when reading multi-shapefile zipfile with pytest.raises(shapefile.ShapefileException): @@ -302,17 +300,17 @@ def test_reader_zip(): # test specifying the path when reading multi-shapefile zipfile (with extension) with shapefile.Reader("shapefiles/blockgroups_multishapefile.zip/blockgroups2.shp") as sf: - for recShape in sf.iterShapeRecords(): + for __recShape in sf.iterShapeRecords(): pass assert len(sf) > 0 - assert sf.shp.closed == sf.shx.closed == sf.dbf.closed is True + assert sf.shp.closed is sf.shx.closed is sf.dbf.closed is True # test specifying the path when reading multi-shapefile zipfile (without extension) with shapefile.Reader("shapefiles/blockgroups_multishapefile.zip/blockgroups2") as sf: - for recShape in sf.iterShapeRecords(): + for __recShape in sf.iterShapeRecords(): pass assert len(sf) > 0 - assert sf.shp.closed == sf.shx.closed == sf.dbf.closed is True + assert sf.shp.closed is sf.shx.closed is sf.dbf.closed is True # test raising error when can't find shapefile inside zipfile with pytest.raises(shapefile.ShapefileException): @@ -783,7 +781,7 @@ def test_reader_offsets(): # shx offsets should not be read during loading assert not sf._offsets # reading a shape index should trigger reading offsets from shx file - shape = sf.shape(3) + sf.shape(3) assert len(sf._offsets) == len(sf.shapes()) @@ -800,7 +798,7 @@ def test_reader_offsets_no_shx(): assert not sf._offsets # reading a shape index should iterate to the shape # but the list of offsets should remain empty - shape = sf.shape(3) + sf.shape(3) assert not sf._offsets # reading all the shapes should build the list of offsets shapes = sf.shapes() @@ -1180,7 +1178,7 @@ def test_write_shp_shx_only(tmpdir): assert writer.shp and writer.shx and not writer.dbf assert writer.shpNum == 1 assert len(writer) == 1 - assert writer.shp.closed == writer.shx.closed is True + assert writer.shp.closed is writer.shx.closed is True # assert test.shp exists assert os.path.exists(filename+'.shp') @@ -1214,7 +1212,7 @@ def test_write_shp_dbf_only(tmpdir): assert writer.shp and not writer.shx and writer.dbf assert writer.shpNum == writer.recNum == 1 assert len(writer) == 1 - assert writer.shp.closed == writer.dbf.closed is True + assert writer.shp.closed is writer.dbf.closed is True # assert test.shp exists assert os.path.exists(filename+'.shp')