Skip to content

Commit 9e4e554

Browse files
authored
Merge pull request #349 from JamesParrott/pyshp-3.0.0
Avoid a # type ignore directive, improve comments & docstrings, and delete commented code blocks
2 parents 666f2cc + a04f1c8 commit 9e4e554

File tree

1 file changed

+23
-32
lines changed

1 file changed

+23
-32
lines changed

src/shapefile.py

Lines changed: 23 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,10 @@ class GeoJSONFeatureCollection(TypedDict):
323323

324324

325325
class GeoJSONFeatureCollectionWithBBox(GeoJSONFeatureCollection):
326-
# bbox is technically optional under the spec
326+
# bbox is technically optional under the spec but this seems
327+
# a very minor improvement that would require NotRequired
328+
# from the typing-extensions backport for Python 3.9
329+
# (PyShp's resisted having any other dependencies so far!)
327330
bbox: list[float]
328331

329332

@@ -717,6 +720,11 @@ def __init__(
717720
are designated by their starting index in geometry record's
718721
list of shapes. For MultiPatch geometry, partTypes designates
719722
the patch type of each of the parts.
723+
Lines allows the points-lists and parts to be denoted together
724+
in one argument. It is intended for multiple point shapes
725+
(polylines, polygons and multipatches) but if used as a length-1
726+
nested list for a multipoint (instead of points for some reason)
727+
PyShp will not complain, as multipoints only have 1 part internally.
720728
"""
721729

722730
# Preserve previous behaviour for anyone who set self.shapeType = None
@@ -732,7 +740,6 @@ def __init__(
732740
default_points: PointsT = []
733741
default_parts: list[int] = []
734742

735-
# Make sure polygon rings (parts) are closed
736743
if lines is not None:
737744
if self.shapeType in Polygon_shapeTypes:
738745
lines = list(lines)
@@ -1055,7 +1062,7 @@ def __repr__(self):
10551062
class NullShape(Shape):
10561063
# Shape.shapeType = NULL already,
10571064
# to preserve handling of default args in Shape.__init__
1058-
# Repeated for clarity.
1065+
# Repeated for the avoidance of doubt.
10591066
def __init__(
10601067
self,
10611068
oid: Optional[int] = None,
@@ -1100,8 +1107,8 @@ def write_to_byte_stream(
11001107

11011108
class _CanHaveBBox(Shape):
11021109
"""As well as setting bounding boxes, we also utilize the
1103-
fact that this mixin applies to all the shapes that are
1104-
not a single point.
1110+
fact that this mixin only applies to all the shapes that are
1111+
not a single point (polylines, polygons, multipatches and multipoints).
11051112
"""
11061113

11071114
@staticmethod
@@ -1185,10 +1192,6 @@ def from_byte_stream(
11851192
b_io, nParts
11861193
)
11871194

1188-
# else:
1189-
# parts = None
1190-
# partTypes = None
1191-
11921195
if nPoints:
11931196
kwargs["points"] = cast(
11941197
PointsT, cls._read_points_from_byte_stream(b_io, nPoints)
@@ -1204,25 +1207,7 @@ def from_byte_stream(
12041207
b_io, nPoints, next_shape
12051208
)
12061209

1207-
# else:
1208-
# points = None
1209-
# zbox, zs = None, None
1210-
# mbox, ms = None, None
1211-
12121210
return ShapeClass(**kwargs)
1213-
# return ShapeClass(
1214-
# shapeType=shapeType,
1215-
# # Mypy 1.17.1 doesn't figure out that an Optional[list[Point2D]] is an Optional[list[PointT]]
1216-
# points=cast(Optional[PointsT], points),
1217-
# parts=parts,
1218-
# partTypes=partTypes,
1219-
# oid=oid,
1220-
# m=ms,
1221-
# z=zs,
1222-
# bbox=shape_bbox,
1223-
# mbox=mbox,
1224-
# zbox=zbox,
1225-
# )
12261211

12271212
@staticmethod
12281213
def write_to_byte_stream(
@@ -1231,7 +1216,7 @@ def write_to_byte_stream(
12311216
i: int,
12321217
) -> int:
12331218
# We use static methods here and below,
1234-
# to support s only being an instance of a the
1219+
# to support s only being an instance of the
12351220
# Shape base class (with shapeType set)
12361221
# i.e. not necessarily one of our newer shape specific
12371222
# sub classes.
@@ -2327,6 +2312,10 @@ def __init__(
23272312
# Close and delete the temporary zipfile
23282313
try:
23292314
zipfileobj.close()
2315+
# TODO Does catching all possible exceptions really increase
2316+
# the chances of closing the zipfile successully, or does it
2317+
# just mean .close() failures will still fail, but fail
2318+
# silently?
23302319
except: # noqa: E722
23312320
pass
23322321
# Try to load shapefile
@@ -3550,15 +3539,16 @@ def shape(
35503539
# Check is shape or import from geojson
35513540
if not isinstance(s, Shape):
35523541
if hasattr(s, "__geo_interface__"):
3553-
s = s.__geo_interface__ # type: ignore [assignment]
3542+
shape_dict = cast(dict, s.__geo_interface__)
35543543
if isinstance(s, dict):
3555-
s = Shape._from_geojson(s)
3544+
shape_dict = s
35563545
else:
35573546
raise TypeError(
35583547
"Can only write Shape objects, GeoJSON dictionaries, "
35593548
"or objects with the __geo_interface__, "
35603549
f"not: {s}"
35613550
)
3551+
s = Shape._from_geojson(shape_dict)
35623552
# Write to file
35633553
offset, length = self.__shpRecord(s)
35643554
if self.shx:
@@ -3600,7 +3590,8 @@ def __shpRecord(self, s: Shape) -> tuple[int, int]:
36003590
# Record number, Content length place holder
36013591
b_io.write(pack(">2i", self.shpNum, -1))
36023592

3603-
# Track number of content bytes written. Excluding self.shpNum and length t.b.c.
3593+
# Track number of content bytes written, excluding
3594+
# self.shpNum and length (t.b.c.)
36043595
n = 0
36053596

36063597
n += b_io.write(pack("<i", s.shapeType))
@@ -3962,7 +3953,7 @@ def _filter_network_doctests(
39623953

39633954
def _replace_remote_url(
39643955
old_url: str,
3965-
# Default port of Python http.server and Python 2's SimpleHttpServer
3956+
# Default port of Python http.server
39663957
port: int = 8000,
39673958
scheme: str = "http",
39683959
netloc: str = "localhost",

0 commit comments

Comments
 (0)