@@ -323,7 +323,10 @@ class GeoJSONFeatureCollection(TypedDict):
323323
324324
325325class 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):
10551062class 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
11011108class _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
39633954def _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