|
3 | 3 | Provides read and write support for ESRI Shapefiles.
|
4 | 4 | authors: jlawhead<at>geospatialpython.com
|
5 | 5 | maintainer: karim.bahgat.norway<at>gmail.com
|
6 |
| -Compatible with Python versions 2.7-3.x |
| 6 | +Compatible with Python versions >= 3.8 |
7 | 7 | """
|
8 | 8 |
|
9 | 9 | __version__ = "2.3.1"
|
10 | 10 |
|
11 |
| -from struct import pack, unpack, calcsize, error, Struct |
| 11 | +import array |
| 12 | +from datetime import date |
| 13 | +import io |
| 14 | +import logging |
12 | 15 | import os
|
| 16 | +from struct import pack, unpack, calcsize, error, Struct |
13 | 17 | import sys
|
14 |
| -import time |
15 |
| -import array |
16 | 18 | import tempfile
|
17 |
| -import logging |
18 |
| -import io |
19 |
| -from datetime import date |
| 19 | +import time |
20 | 20 | import zipfile
|
21 | 21 |
|
| 22 | +from urllib.error import HTTPError |
| 23 | +from urllib.parse import urlparse, urlunparse |
| 24 | +from urllib.request import urlopen, Request |
| 25 | + |
22 | 26 | # Create named logger
|
23 | 27 | logger = logging.getLogger(__name__)
|
24 | 28 |
|
|
74 | 78 | 5: 'RING'}
|
75 | 79 |
|
76 | 80 |
|
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 | + |
97 | 84 | # Helpers
|
98 | 85 |
|
99 | 86 | MISSING = [None,'']
|
100 | 87 | NODATA = -10e38 # as per the ESRI shapefile spec, only used for m-values.
|
101 | 88 |
|
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) |
162 | 116 |
|
163 |
| - def is_string(v): |
164 |
| - return isinstance(v, basestring) |
| 117 | +def is_string(v): |
| 118 | + return isinstance(v, str) |
165 | 119 |
|
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 |
183 | 126 |
|
184 | 127 |
|
185 | 128 | # Begin
|
@@ -452,7 +395,7 @@ def organize_polygon_rings(rings, return_errors=None):
|
452 | 395 | polys = [[ext] for ext in exteriors]
|
453 | 396 | return polys
|
454 | 397 |
|
455 |
| -class Shape(object): |
| 398 | +class Shape: |
456 | 399 | def __init__(self, shapeType=NULL, points=None, parts=None, partTypes=None, oid=None):
|
457 | 400 | """Stores the geometry of the different shape types
|
458 | 401 | specified in the Shapefile spec. Shape types are
|
@@ -823,9 +766,9 @@ def __dir__(self):
|
823 | 766 | """
|
824 | 767 | default = list(dir(type(self))) # default list methods and attributes of this class
|
825 | 768 | 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: |
829 | 772 | """A ShapeRecord object containing a shape along with its attributes.
|
830 | 773 | Provides the GeoJSON __geo_interface__ to return a Feature dictionary."""
|
831 | 774 | def __init__(self, shape=None, record=None):
|
@@ -874,7 +817,7 @@ class ShapefileException(Exception):
|
874 | 817 | """An exception to handle shapefile specific problems."""
|
875 | 818 | pass
|
876 | 819 |
|
877 |
| -class Reader(object): |
| 820 | +class Reader: |
878 | 821 | """Reads the three files of a shapefile as a unit or
|
879 | 822 | separately. If one of the three files (.shp, .shx,
|
880 | 823 | .dbf) is missing no exception is thrown until you try
|
@@ -1756,7 +1699,7 @@ def iterShapeRecords(self, fields=None, bbox=None):
|
1756 | 1699 | yield ShapeRecord(shape=shape, record=record)
|
1757 | 1700 |
|
1758 | 1701 |
|
1759 |
| -class Writer(object): |
| 1702 | +class Writer: |
1760 | 1703 | """Provides write support for ESRI Shapefiles."""
|
1761 | 1704 | def __init__(self, target=None, shapeType=None, autoBalance=False, **kwargs):
|
1762 | 1705 | self.target = target
|
|
0 commit comments