Skip to content

Commit 0647419

Browse files
authored
Merge pull request #287 from JamesParrott/pr/275
Pr/275
2 parents 38dc16f + c12ce65 commit 0647419

File tree

4 files changed

+61
-123
lines changed

4 files changed

+61
-123
lines changed

.github/workflows/build.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
2-
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
2+
# For more information see:
3+
# https://docs.github.com/en/actions/use-cases-and-examples/building-and-testing/building-and-testing-python
34

45
name: build
56

setup.cfg

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,14 @@ keywords = gis, geospatial, geographic, shapefile, shapefiles
1616
classifiers =
1717
Development Status :: 5 - Production/Stable
1818
Programming Language :: Python
19-
Programming Language :: Python :: 2.7
2019
Programming Language :: Python :: 3
2120
Topic :: Scientific/Engineering :: GIS
2221
Topic :: Software Development :: Libraries
2322
Topic :: Software Development :: Libraries :: Python Modules
2423

2524
[options]
2625
py_modules = shapefile
27-
python_requires = >=2.7
26+
python_requires = >=3.8
2827

2928
[bdist_wheel]
3029
universal=1

shapefile.py

Lines changed: 55 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,26 @@
33
Provides read and write support for ESRI Shapefiles.
44
authors: jlawhead<at>geospatialpython.com
55
maintainer: karim.bahgat.norway<at>gmail.com
6-
Compatible with Python versions 2.7-3.x
6+
Compatible with Python versions >= 3.8
77
"""
88

99
__version__ = "2.3.1"
1010

11-
from struct import pack, unpack, calcsize, error, Struct
11+
import array
12+
from datetime import date
13+
import io
14+
import logging
1215
import os
16+
from struct import pack, unpack, calcsize, error, Struct
1317
import sys
14-
import time
15-
import array
1618
import tempfile
17-
import logging
18-
import io
19-
from datetime import date
19+
import time
2020
import zipfile
2121

22+
from urllib.error import HTTPError
23+
from urllib.parse import urlparse, urlunparse
24+
from urllib.request import urlopen, Request
25+
2226
# Create named logger
2327
logger = logging.getLogger(__name__)
2428

@@ -74,112 +78,51 @@
7478
5: 'RING'}
7579

7680

77-
# Python 2-3 handling
78-
79-
PYTHON3 = sys.version_info[0] == 3
80-
81-
if PYTHON3:
82-
xrange = range
83-
izip = zip
84-
85-
from urllib.parse import urlparse, urlunparse
86-
from urllib.error import HTTPError
87-
from urllib.request import urlopen, Request
88-
89-
else:
90-
from itertools import izip
91-
92-
from urlparse import urlparse, urlunparse
93-
from urllib2 import HTTPError
94-
from urllib2 import urlopen, Request
95-
96-
81+
xrange = range
82+
izip = zip
83+
9784
# Helpers
9885

9986
MISSING = [None,'']
10087
NODATA = -10e38 # as per the ESRI shapefile spec, only used for m-values.
10188

102-
if PYTHON3:
103-
def b(v, encoding='utf-8', encodingErrors='strict'):
104-
if isinstance(v, str):
105-
# For python 3 encode str to bytes.
106-
return v.encode(encoding, encodingErrors)
107-
elif isinstance(v, bytes):
108-
# Already bytes.
109-
return v
110-
elif v is None:
111-
# Since we're dealing with text, interpret None as ""
112-
return b""
113-
else:
114-
# Force string representation.
115-
return str(v).encode(encoding, encodingErrors)
116-
117-
def u(v, encoding='utf-8', encodingErrors='strict'):
118-
if isinstance(v, bytes):
119-
# For python 3 decode bytes to str.
120-
return v.decode(encoding, encodingErrors)
121-
elif isinstance(v, str):
122-
# Already str.
123-
return v
124-
elif v is None:
125-
# Since we're dealing with text, interpret None as ""
126-
return ""
127-
else:
128-
# Force string representation.
129-
return bytes(v).decode(encoding, encodingErrors)
130-
131-
def is_string(v):
132-
return isinstance(v, str)
133-
134-
else:
135-
def b(v, encoding='utf-8', encodingErrors='strict'):
136-
if isinstance(v, unicode):
137-
# For python 2 encode unicode to bytes.
138-
return v.encode(encoding, encodingErrors)
139-
elif isinstance(v, bytes):
140-
# Already bytes.
141-
return v
142-
elif v is None:
143-
# Since we're dealing with text, interpret None as ""
144-
return ""
145-
else:
146-
# Force string representation.
147-
return unicode(v).encode(encoding, encodingErrors)
148-
149-
def u(v, encoding='utf-8', encodingErrors='strict'):
150-
if isinstance(v, bytes):
151-
# For python 2 decode bytes to unicode.
152-
return v.decode(encoding, encodingErrors)
153-
elif isinstance(v, unicode):
154-
# Already unicode.
155-
return v
156-
elif v is None:
157-
# Since we're dealing with text, interpret None as ""
158-
return u""
159-
else:
160-
# Force string representation.
161-
return bytes(v).decode(encoding, encodingErrors)
89+
def b(v, encoding='utf-8', encodingErrors='strict'):
90+
if isinstance(v, str):
91+
# For python 3 encode str to bytes.
92+
return v.encode(encoding, encodingErrors)
93+
elif isinstance(v, bytes):
94+
# Already bytes.
95+
return v
96+
elif v is None:
97+
# Since we're dealing with text, interpret None as ""
98+
return b""
99+
else:
100+
# Force string representation.
101+
return str(v).encode(encoding, encodingErrors)
102+
103+
def u(v, encoding='utf-8', encodingErrors='strict'):
104+
if isinstance(v, bytes):
105+
# For python 3 decode bytes to str.
106+
return v.decode(encoding, encodingErrors)
107+
elif isinstance(v, str):
108+
# Already str.
109+
return v
110+
elif v is None:
111+
# Since we're dealing with text, interpret None as ""
112+
return ""
113+
else:
114+
# Force string representation.
115+
return bytes(v).decode(encoding, encodingErrors)
162116

163-
def is_string(v):
164-
return isinstance(v, basestring)
117+
def is_string(v):
118+
return isinstance(v, str)
165119

166-
if sys.version_info[0:2] >= (3, 6):
167-
def pathlike_obj(path):
168-
if isinstance(path, os.PathLike):
169-
return os.fsdecode(path)
170-
else:
171-
return path
172-
else:
173-
def pathlike_obj(path):
174-
if is_string(path):
175-
return path
176-
elif hasattr(path, "__fspath__"):
177-
return path.__fspath__()
178-
else:
179-
try:
180-
return str(path)
181-
except:
182-
return path
120+
121+
def pathlike_obj(path):
122+
if isinstance(path, os.PathLike):
123+
return os.fsdecode(path)
124+
else:
125+
return path
183126

184127

185128
# Begin
@@ -452,7 +395,7 @@ def organize_polygon_rings(rings, return_errors=None):
452395
polys = [[ext] for ext in exteriors]
453396
return polys
454397

455-
class Shape(object):
398+
class Shape:
456399
def __init__(self, shapeType=NULL, points=None, parts=None, partTypes=None, oid=None):
457400
"""Stores the geometry of the different shape types
458401
specified in the Shapefile spec. Shape types are
@@ -823,9 +766,9 @@ def __dir__(self):
823766
"""
824767
default = list(dir(type(self))) # default list methods and attributes of this class
825768
fnames = list(self.__field_positions.keys()) # plus field names (random order if Python version < 3.6)
826-
return default + fnames
827-
828-
class ShapeRecord(object):
769+
return default + fnames
770+
771+
class ShapeRecord:
829772
"""A ShapeRecord object containing a shape along with its attributes.
830773
Provides the GeoJSON __geo_interface__ to return a Feature dictionary."""
831774
def __init__(self, shape=None, record=None):
@@ -874,7 +817,7 @@ class ShapefileException(Exception):
874817
"""An exception to handle shapefile specific problems."""
875818
pass
876819

877-
class Reader(object):
820+
class Reader:
878821
"""Reads the three files of a shapefile as a unit or
879822
separately. If one of the three files (.shp, .shx,
880823
.dbf) is missing no exception is thrown until you try
@@ -1756,7 +1699,7 @@ def iterShapeRecords(self, fields=None, bbox=None):
17561699
yield ShapeRecord(shape=shape, record=record)
17571700

17581701

1759-
class Writer(object):
1702+
class Writer:
17601703
"""Provides write support for ESRI Shapefiles."""
17611704
def __init__(self, target=None, shapeType=None, autoBalance=False, **kwargs):
17621705
self.target = target

test_shapefile.py

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,13 @@
22
This module tests the functionality of shapefile.py.
33
"""
44
# std lib imports
5+
import datetime
6+
import json
57
import os.path
6-
import sys
7-
if sys.version_info.major == 3:
8-
from pathlib import Path
8+
from pathlib import Path
99

1010
# third party imports
1111
import pytest
12-
import json
13-
import datetime
14-
if sys.version_info.major == 2:
15-
# required by pytest for python <36
16-
from pathlib2 import Path
1712

1813
# our imports
1914
import shapefile

0 commit comments

Comments
 (0)