@@ -128,15 +128,14 @@ def b(
128128 if isinstance (v , str ):
129129 # For python 3 encode str to bytes.
130130 return v .encode (encoding , encodingErrors )
131- elif isinstance (v , bytes ):
131+ if isinstance (v , bytes ):
132132 # Already bytes.
133133 return v
134- elif v is None :
134+ if v is None :
135135 # Since we're dealing with text, interpret None as ""
136136 return b""
137- else :
138- # Force string representation.
139- return str (v ).encode (encoding , encodingErrors )
137+ # Force string representation.
138+ return str (v ).encode (encoding , encodingErrors )
140139
141140
142141def u (
@@ -145,15 +144,14 @@ def u(
145144 if isinstance (v , bytes ):
146145 # For python 3 decode bytes to str.
147146 return v .decode (encoding , encodingErrors )
148- elif isinstance (v , str ):
147+ if isinstance (v , str ):
149148 # Already str.
150149 return v
151- elif v is None :
150+ if v is None :
152151 # Since we're dealing with text, interpret None as ""
153152 return ""
154- else :
155- # Force string representation.
156- return bytes (v ).decode (encoding , encodingErrors )
153+ # Force string representation.
154+ return bytes (v ).decode (encoding , encodingErrors )
157155
158156
159157def is_string (v : Any ) -> bool :
@@ -163,8 +161,8 @@ def is_string(v: Any) -> bool:
163161def pathlike_obj (path : Any ) -> Any :
164162 if isinstance (path , os .PathLike ):
165163 return os .fsdecode (path )
166- else :
167- return path
164+
165+ return path
168166
169167
170168# Begin
@@ -193,8 +191,8 @@ def signed_area(
193191 area2 = sum (xs [i ] * (ys [i + 1 ] - ys [i - 1 ]) for i in range (1 , len (coords )))
194192 if fast :
195193 return area2
196- else :
197- return area2 / 2.0
194+
195+ return area2 / 2.0
198196
199197
200198def is_cw (coords : Coords ) -> bool :
@@ -374,7 +372,7 @@ def organize_polygon_rings(
374372 # multiple exteriors, ie multi-polygon, have to group holes with correct exterior
375373 # shapefile format does not specify which holes belong to which exteriors
376374 # so have to do efficient multi-stage checking of hole-to-exterior containment
377- elif len (exteriors ) > 1 :
375+ if len (exteriors ) > 1 :
378376 # exit early if no holes
379377 if not holes :
380378 polys = []
@@ -457,13 +455,12 @@ def organize_polygon_rings(
457455 return polys
458456
459457 # no exteriors, be nice and assume due to incorrect winding order
460- else :
461- if return_errors is not None :
462- return_errors ["polygon_only_holes" ] = len (holes )
463- exteriors = holes
464- # add as single exterior without any holes
465- polys = [[ext ] for ext in exteriors ]
466- return polys
458+ if return_errors is not None :
459+ return_errors ["polygon_only_holes" ] = len (holes )
460+ exteriors = holes
461+ # add as single exterior without any holes
462+ polys = [[ext ] for ext in exteriors ]
463+ return polys
467464
468465
469466class GeoJSON_Error (Exception ):
@@ -515,107 +512,111 @@ def __geo_interface__(self) -> GeoJsonShapeT:
515512 # however, it does allow geometry types with 'empty' coordinates to be interpreted as null-geometries
516513 return {"type" : "Point" , "coordinates" : ()}
517514 # return {"type": "Point", "coordinates": tuple()} #type: ignore
518- else :
519- return {"type" : "Point" , "coordinates" : self .points [0 ]}
520- # return {"type": "Point", "coordinates": tuple(self.points[0])} # type: ignore
521- elif self .shapeType in [MULTIPOINT , MULTIPOINTM , MULTIPOINTZ ]:
515+
516+ return {"type" : "Point" , "coordinates" : self .points [0 ]}
517+ # return {"type": "Point", "coordinates": tuple(self.points[0])} # type: ignore
518+
519+ if self .shapeType in [MULTIPOINT , MULTIPOINTM , MULTIPOINTZ ]:
522520 if len (self .points ) == 0 :
523521 # the shape has no coordinate information, i.e. is 'empty'
524522 # the geojson spec does not define a proper null-geometry type
525523 # however, it does allow geometry types with 'empty' coordinates to be interpreted as null-geometries
526524 return {"type" : "MultiPoint" , "coordinates" : []}
527- else :
528- # multipoint
529- return {
530- "type" : "MultiPoint" ,
531- "coordinates" : self .points ,
532- # "coordinates": [tuple(p) for p in self.points], #type: ignore
533- }
534- elif self .shapeType in [POLYLINE , POLYLINEM , POLYLINEZ ]:
525+
526+ # multipoint
527+ return {
528+ "type" : "MultiPoint" ,
529+ "coordinates" : self .points ,
530+ # "coordinates": [tuple(p) for p in self.points], #type: ignore
531+ }
532+
533+ if self .shapeType in [POLYLINE , POLYLINEM , POLYLINEZ ]:
535534 if len (self .parts ) == 0 :
536535 # the shape has no coordinate information, i.e. is 'empty'
537536 # the geojson spec does not define a proper null-geometry type
538537 # however, it does allow geometry types with 'empty' coordinates to be interpreted as null-geometries
539538 return {"type" : "LineString" , "coordinates" : []}
540- elif len (self .parts ) == 1 :
539+
540+ if len (self .parts ) == 1 :
541541 # linestring
542542 return {
543543 "type" : "LineString" ,
544544 "coordinates" : self .points ,
545545 # "coordinates": [tuple(p) for p in self.points], #type: ignore
546546 }
547- else :
548- # multilinestring
549- ps = None
550- coordinates = []
551- for part in self .parts :
552- if ps is None :
553- ps = part
554- continue
555- else :
556- # coordinates.append([tuple(p) for p in self.points[ps:part]])
557- coordinates .append ([p for p in self .points [ps :part ]])
558- ps = part
559547
560- # coordinates.append([tuple(p) for p in self.points[part:]])
561- coordinates .append ([p for p in self .points [part :]]) # pylint: disable=undefined-loop-variable
548+ # multilinestring
549+ ps = None
550+ coordinates = []
551+ for part in self .parts :
552+ if ps is None :
553+ ps = part
554+ continue
555+ else :
556+ # coordinates.append([tuple(p) for p in self.points[ps:part]])
557+ coordinates .append ([p for p in self .points [ps :part ]])
558+ ps = part
559+
560+ # coordinates.append([tuple(p) for p in self.points[part:]])
561+ coordinates .append ([p for p in self .points [part :]]) # pylint: disable=undefined-loop-variable
562562
563- return {"type" : "MultiLineString" , "coordinates" : coordinates }
564- elif self .shapeType in [POLYGON , POLYGONM , POLYGONZ ]:
563+ return {"type" : "MultiLineString" , "coordinates" : coordinates }
564+
565+ if self .shapeType in [POLYGON , POLYGONM , POLYGONZ ]:
565566 if len (self .parts ) == 0 :
566567 # the shape has no coordinate information, i.e. is 'empty'
567568 # the geojson spec does not define a proper null-geometry type
568569 # however, it does allow geometry types with 'empty' coordinates to be interpreted as null-geometries
569570 return {"type" : "Polygon" , "coordinates" : []}
570- else :
571- # get all polygon rings
572- rings = []
573- for i in range (len (self .parts )):
574- # get indexes of start and end points of the ring
575- start = self .parts [i ]
576- try :
577- end = self .parts [i + 1 ]
578- except IndexError :
579- end = len (self .points )
580-
581- # extract the points that make up the ring
582- # ring = [tuple(p) for p in self.points[start:end]]
583- ring = [p for p in self .points [start :end ]]
584- rings .append (ring )
585-
586- # organize rings into list of polygons, where each polygon is defined as list of rings.
587- # the first ring is the exterior and any remaining rings are holes (same as GeoJSON).
588- polys = organize_polygon_rings (rings , self ._errors )
589-
590- # if VERBOSE is True, issue detailed warning about any shape errors
591- # encountered during the Shapefile to GeoJSON conversion
592- if VERBOSE and self ._errors :
593- header = f"Possible issue encountered when converting Shape #{ self .oid } to GeoJSON: "
594- orphans = self ._errors .get ("polygon_orphaned_holes" , None )
595- if orphans :
596- msg = (
597- header
598- + "Shapefile format requires that all polygon interior holes be contained by an exterior ring, \
571+
572+ # get all polygon rings
573+ rings = []
574+ for i in range (len (self .parts )):
575+ # get indexes of start and end points of the ring
576+ start = self .parts [i ]
577+ try :
578+ end = self .parts [i + 1 ]
579+ except IndexError :
580+ end = len (self .points )
581+
582+ # extract the points that make up the ring
583+ # ring = [tuple(p) for p in self.points[start:end]]
584+ ring = [p for p in self .points [start :end ]]
585+ rings .append (ring )
586+
587+ # organize rings into list of polygons, where each polygon is defined as list of rings.
588+ # the first ring is the exterior and any remaining rings are holes (same as GeoJSON).
589+ polys = organize_polygon_rings (rings , self ._errors )
590+
591+ # if VERBOSE is True, issue detailed warning about any shape errors
592+ # encountered during the Shapefile to GeoJSON conversion
593+ if VERBOSE and self ._errors :
594+ header = f"Possible issue encountered when converting Shape #{ self .oid } to GeoJSON: "
595+ orphans = self ._errors .get ("polygon_orphaned_holes" , None )
596+ if orphans :
597+ msg = (
598+ header
599+ + "Shapefile format requires that all polygon interior holes be contained by an exterior ring, \
599600 but the Shape contained interior holes (defined by counter-clockwise orientation in the shapefile format) that were \
600601 orphaned, i.e. not contained by any exterior rings. The rings were still included but were \
601602 encoded as GeoJSON exterior rings instead of holes."
602- )
603- logger .warning (msg )
604- only_holes = self ._errors .get ("polygon_only_holes" , None )
605- if only_holes :
606- msg = (
607- header
608- + "Shapefile format requires that polygons contain at least one exterior ring, \
603+ )
604+ logger .warning (msg )
605+ only_holes = self ._errors .get ("polygon_only_holes" , None )
606+ if only_holes :
607+ msg = (
608+ header
609+ + "Shapefile format requires that polygons contain at least one exterior ring, \
609610 but the Shape was entirely made up of interior holes (defined by counter-clockwise orientation in the shapefile format). The rings were \
610611 still included but were encoded as GeoJSON exterior rings instead of holes."
611- )
612- logger .warning (msg )
612+ )
613+ logger .warning (msg )
613614
614- # return as geojson
615- if len (polys ) == 1 :
616- return {"type" : "Polygon" , "coordinates" : polys [0 ]}
617- else :
618- return {"type" : "MultiPolygon" , "coordinates" : polys }
615+ # return as geojson
616+ if len (polys ) == 1 :
617+ return {"type" : "Polygon" , "coordinates" : polys [0 ]}
618+
619+ return {"type" : "MultiPolygon" , "coordinates" : polys }
619620
620621 else :
621622 raise GeoJSON_Error (
0 commit comments