o
    0Of                    @   s  d Z dZddlmZmZmZmZmZ ddlZddl	Z	ddl
Z
ddlZddlZddlZddlZddlmZ ddlZeeZdZdZdZdZd	Zd
ZdZdZdZdZdZdZ dZ!dZ"dZ#ddddddddddddd d!d"Z$dZ%dZ&d#Z'dZ(d$Z)d	Z*d%d&d'd(d)d*d+Z+e	j,d dkZ-e-re.Z/e0Z1dd,l2m3Z3m4Z4 dd-l5m6Z6 dd.l7m8Z8m9Z9 ndd/l:m1Z1 dd,l3m3Z3m4Z4 dd-l;m6Z6 dd.l;m8Z8m9Z9 dd0gZ<d1Z=e-rdkd4d5Z>dkd6d7Z?d8d9 Z@ndkd:d5Z>dkd;d7Z?d<d9 Z@e	j,dd# d=krd>d? ZAnd@d? ZAG dAdB dBejZBdldDdEZCdFdG ZDdHdI ZEdJdK ZFdLdM ZGdNdO ZHdPdQ ZIdldRdSZJdTdU ZKdmdVdWZLG dXdY dYeMZNG dZd[ d[eOZPG d\d] d]eMZQG d^d_ d_eOZRG d`da daeOZSG dbdc dceTZUG ddde deeMZVG dfdg dgeMZWdhdi ZXedjkr	 eX ZYe	ZeY dS dS )nz
shapefile.py
Provides read and write support for ESRI Shapefiles.
authors: jlawhead<at>geospatialpython.com
maintainer: karim.bahgat.norway<at>gmail.com
Compatible with Python versions 2.7-3.x
z2.3.1    )packunpackcalcsizeerrorStructN)dateT                                       NULLPOINTPOLYLINEPOLYGON
MULTIPOINTPOINTZ	POLYLINEZPOLYGONZMULTIPOINTZPOINTM	POLYLINEMPOLYGONMMULTIPOINTM
MULTIPATCH)r   r   r	   r
   r   r   r   r   r   r   r   r   r   r         TRIANGLE_STRIPTRIANGLE_FAN
OUTER_RING
INNER_RING
FIRST_RINGRING)r   r   r#   r	   r$   r
   )urlparse
urlunparse)	HTTPError)urlopenRequest)izip gJutf-8strictc                 C   @   t | tr| ||S t | tr| S | d u rdS t| ||S )N    )
isinstancestrencodebytesvencodingencodingErrors r>   B/home/ubuntu/webapp/venv/lib/python3.10/site-packages/shapefile.pybg      

r@   c                 C   r4   Nr1   )r6   r9   decoder7   r:   r>   r>   r?   uu   rA   rD   c                 C   
   t | tS N)r6   r7   r;   r>   r>   r?   	is_string      
rH   c                 C   r4   rB   )r6   unicoder8   r9   r:   r>   r>   r?   r@      rA   c                 C   r4   rB   )r6   r9   rC   rJ   r:   r>   r>   r?   rD      rA   c                 C   rE   rF   )r6   
basestringrG   r>   r>   r?   rH      rI   )r	      c                 C   s   t | tjrt| S | S rF   )r6   osPathLikefsdecodepathr>   r>   r?   pathlike_obj   s   
rR   c                 C   s8   t | r| S t| dr|  S zt| W S    |  Y S )N
__fspath__)rH   hasattrrS   r7   rP   r>   r>   r?   rR      s   

c                   @   s   e Zd ZdZdd ZdS )_ArrayzmConverts python tuples to lists of the appropriate type.
    Used to unpack different shapefile header parts.c                 C   s   t |  S rF   )r7   tolistselfr>   r>   r?   __repr__      z_Array.__repr__N)__name__
__module____qualname____doc__rY   r>   r>   r>   r?   rU      s    rU   Fc                    sl   t ttt|  dd \   d  d  t fddtdt| D }|r2|S |d S )a   Return the signed area enclosed by a ring using the linear time
    algorithm. A value >= 0 indicates a counter-clockwise oriented ring.
    A faster version is possible by setting 'fast' to True, which returns
    2x the area, e.g. if you're only interested in the sign of the area.
    Nr#   r   c                 3   s0    | ]} | |d   |d     V  qdS )r   Nr>   ).0ixsysr>   r?   	<genexpr>   s   . zsigned_area.<locals>.<genexpr>g       @)maplistzipappendsumrangelen)coordsfastarea2r>   ra   r?   signed_area   s   "ro   c                 C   s   t | dd}|dk S )zkReturns True if a polygon ring has clockwise orientation, determined
    by a negatively signed area. 
    Trm   r   )ro   )rl   rn   r>   r>   r?   is_cw   s   rq   c                 C   s   t t| S )z0Returns the input coords in reversed order.
    )rf   reversedrl   r>   r>   r?   rewind   s   rt   c                 C   s,   t |  \}}t|t|t|t|f}|S )z7Calculates and returns the bounding box of a ring.
    )rg   minmax)rl   rb   rc   bboxr>   r>   r?   	ring_bbox   s   rx   c                 C   s<   | \}}}}|\}}}}	||ko||ko||	ko||k}
|
S )zBTests whether two bounding boxes overlap, returning a boolean
    r>   )bbox1bbox2xmin1ymin1xmax1ymax1xmin2ymin2xmax2ymax2overlapr>   r>   r?   bbox_overlap       r   c                 C   s<   | \}}}}|\}}}}	||k o||ko||k o||	k}
|
S )zBTests whether bbox1 fully contains bbox2, returning a boolean
    r>   )ry   rz   r{   r|   r}   r~   r   r   r   r   containsr>   r>   r?   bbox_contains   r   r   c           
      C   s   |\}}| d }|d |k}d}| dd D ]C}|d |k}||krU|d |k}	|	|d |kkr6|	r5| }n|d |d | |d |d   |d |d    |krU| }|}|}q|S )a  Fast point-in-polygon crossings algorithm, MacMartin optimization.

    Adapted from code by Eric Haynes
    http://www.realtimerendering.com/resources/GraphicsGems//gemsiv/ptpoly_haines/ptinpoly.c
    
    Original description:
        Shoot a test ray along +X axis.  The strategy, from MacMartin, is to
        compare vertex Y values to the testing point's Y and quickly discard
        edges which are entirely to one side of the test ray.
    r   r   FNr>   )
rl   ptxtyvtx0yflag0inside_flagvtx1yflag1xflag0r>   r>   r?   ring_contains_point   s"   8r   c                    s  g } fdd}| D ]x}||vr| | t|dkr|d d |d d  |d d |d d   |d d |d d  |d d |d d   k}|s~||d g }t| }||kr~t| \}}	t|d t|	d }
}t |
|fr~|
|f  S |d qtd)	aM  Return a sample point guaranteed to be within a ring, by efficiently
    finding the first centroid of a coordinate triplet whose orientation
    matches the orientation of the ring and passes the point-in-ring test.
    The orientation of the ring is assumed to be clockwise, unless ccw
    (counter-clockwise) is set to True. 
    c                  3   s      D ]} | V  q d V  d S )Nr   r>   )r   rs   r>   r?   
itercoords%  s   zring_sample.<locals>.itercoordsr	   r   r   r#   g      @z5Unexpected error: Unable to find a ring sample point.)rh   rk   rq   rg   ri   r   pop	Exception)rl   ccwtripletr   r   is_straight_lineclosed_triplettriplet_ccwrb   rc   xmeanymeanr>   rs   r?   ring_sample  s$   

`

r   c                    s   t  fdd|D S )zFReturns True if all vertexes in coords2 are fully inside coords1.
    c                 3   s    | ]}t  |V  qd S rF   )r   )r_   p2coords1r>   r?   rd   L  s    z%ring_contains_ring.<locals>.<genexpr>)all)r   coords2r>   r   r?   ring_contains_ringI  s   r   c                    s  g  g }| D ]}t |r | q|| qt dkr* d g| }|g}|S t dkr=|sDg } D ]
}|g}|| q7|S tdd tt|D }dd  D }| D ]}	t||	 }
t|D ]\}}t||
rx||	 | qhq\|	 D ]2\}	}t|dkrt ||	  }t
||	 |d}g }|D ]}t | |}|r|| q|||	< q~|	 D ]\}	}t|dkrt| fddd	d }|g||	< qg }t|	 D ]\}	}|s||	 ||	= qqg }t D ]+\}}|g}g }t|	 D ]\}	}|d |kr|||	  q||7 }|| q|D ]}	||	 }|g}|| q|r;|d
ur;t||d< |S |d
urHt||d< | dd  D }|S )a  Organize a list of coordinate rings into one or more polygons with holes.
    Returns a list of polygons, where each polygon is composed of a single exterior
    ring, and one or more interior holes. If a return_errors dict is provided (optional), 
    any errors encountered will be added to it. 

    Rings must be closed, and cannot intersect each other (non-self-intersecting polygon).
    Rings are determined as exteriors if they run in clockwise direction, or interior
    holes if they run in counter-clockwise direction. This method is used to construct
    GeoJSON (multi)polygons from the shapefile polygon shape type, which does not
    explicitly store the structure of the polygons beyond exterior/interior ring orientation. 
    r   r   c                 S   s   g | ]}|g fqS r>   r>   )r_   hole_ir>   r>   r?   
<listcomp>{      z*organize_polygon_rings.<locals>.<listcomp>c                 S      g | ]}t |qS r>   )rx   )r_   ringr>   r>   r?   r   |  r   )r   c                    s   t t |  ddS )NTrp   )absro   )x	exteriorsr>   r?   <lambda>  r   z(organize_polygon_rings.<locals>.<lambda>)keyNpolygon_orphaned_holespolygon_only_holesc                 S   s   g | ]}|gqS r>   r>   )r_   extr>   r>   r?   r         )rq   rh   rk   dictxrangekeysrx   	enumerater   itemsr   r   sortedrf   )ringsreturn_errorsholesr   polypolysr   hole_exteriorsexterior_bboxesr   	hole_bboxext_iext_bboxexterior_candidatesr   hole_samplenew_exterior_candidateshole_in_exteriororphan_holes
poly_holesr>   r   r?   organize_polygon_ringsN  s   




r   c                   @   sX   e Zd ZeddddfddZedd Zedd Zedd	 Z	ed
d Z
dd ZdS )ShapeNc                 C   sF   || _ |pg | _|pg | _|r|| _i | _|dur|| _dS d| _dS )aa  Stores the geometry of the different shape types
        specified in the Shapefile spec. Shape types are
        usually point, polyline, or polygons. Every shape type
        except the "Null" type contains points at some level for
        example vertices in a polygon. If a shape type has
        multiple shapes containing points within a single
        geometry record then those shapes are called parts. Parts
        are designated by their starting index in geometry record's
        list of shapes. For MultiPatch geometry, partTypes designates
        the patch type of each of the parts. 
        N)	shapeTypepointsparts	partTypes_errors_Shape__oid)rX   r   r   r   r   oidr>   r>   r?   __init__  s   



zShape.__init__c              	   C   s|  | j tttfv rt| jdkrdt dS dt| jd dS | j ttt	fv r>t| jdkr3dg dS ddd | jD dS | j t
ttfv rt| jdkrRdg dS t| jdkrddd	d | jD dS d }g }| jD ]}|d krt|}qk|d
d | j|| D  |}qk|dd | j|d  D  d|dS | j tttfv r5t| jdkrdg dS g }tt| jD ]0}| j| }z	| j|d  }W n ty   t| j}Y nw dd | j|| D }|| qt|| j}	tr"| jr"d| j}
| jdd }|r|
d }t| | jdd }|r"|
d }t| t|	dkr0d|	d dS d|	dS tdt| j   )Nr   Point)typecoordinates
MultiPointc                 S   r   r>   tupler_   r   r>   r>   r?   r     r   z+Shape.__geo_interface__.<locals>.<listcomp>
LineStringr   c                 S   r   r>   r   r   r>   r>   r?   r     r   c                 S   r   r>   r   r   r>   r>   r?   r     r   c                 S   r   r>   r   r   r>   r>   r?   r     r   MultiLineStringPolygonc                 S   r   r>   r   r   r>   r>   r?   r   ,  r   zAPossible issue encountered when converting Shape #{} to GeoJSON: r   a^  Shapefile format requires that all polygon interior holes be contained by an exterior ring, but the Shape contained interior holes (defined by counter-clockwise orientation in the shapefile format) that were orphaned, i.e. not contained by any exterior rings. The rings were still included but were encoded as GeoJSON exterior rings instead of holes.r   a  Shapefile format requires that polygons contain at least one exterior ring, but the Shape was entirely made up of interior holes (defined by counter-clockwise orientation in the shapefile format). The rings were still included but were encoded as GeoJSON exterior rings instead of holes.MultiPolygonz1Shape type "%s" cannot be represented as GeoJSON.)r   r   r   r   rk   r   r   r   r!   r   r   r   r   r   rh   r   r    r   r   
IndexErrorr   r   VERBOSEformatr   getloggerwarningr   SHAPETYPE_LOOKUP)rX   psr   partr   r`   startendr   r   headerorphansmsg
only_holesr>   r>   r?   __geo_interface__  s~   






zShape.__geo_interface__c                 C   sB  t  }| r	| d nd}|dkrt}n0|dkrt}n)|dkr t}n"|dkr't}n|dkr.t}n|dkr5t}n|dkr<t}ntd	| ||_|dkrU| d
 g|_dg|_	|S |dv rd| d
 |_dg|_	|S |dv rg }g }d}t
| d
 D ]-\}}|dkrt|st|}n|dkrt|rt|}|| || |t|7 }qt||_||_	|S |dv rg }g }d}| d
 D ]}	||	 || |t|	7 }q||_||_	|S |dv rg }g }d}| d
 D ]6}
t
|
D ]/\}}|dkrt|st|}n|dkrt|rt|}|| || |t|7 }qq||_||_	|S )Nr   Nullr   r   r   r   r   r   z*Cannot create Shape from GeoJSON type '%s'r   r   )r   r   )r   r   r   r   r   r   r   r   r   r   r   rq   rt   extendrh   rk   )geojshapegeojTyper   r   r   indexr`   ext_or_hole
linestringpolygonr>   r>   r?   _from_geojsonT  s   5
2








zShape._from_geojsonc                 C      | j S )z9The index position of the shape in the original shapefile)r   rW   r>   r>   r?   r        z	Shape.oidc                 C   
   t | j S rF   r   r   rW   r>   r>   r?   shapeTypeName     
zShape.shapeTypeNamec                 C   s   d | j| jS )NzShape #{}: {})r   r   r   rW   r>   r>   r?   rY        zShape.__repr__)r[   r\   r]   r   r   propertyr   staticmethodr   r   r   rY   r>   r>   r>   r?   r     s    
p
Q

r   c                   @   s`   e Zd ZdZdddZdd Zdd Zd	d
 Zdd Ze	dd Z
dddZdd Zdd ZdS )_Recordat  
    A class to hold a record. Subclasses list to ensure compatibility with
    former work and to reuse all the optimizations of the builtin list.
    In addition to the list interface, the values of the record
    can also be retrieved using the field's name. For example if the dbf contains
    a field ID at position 0, the ID can be retrieved with the position, the field name
    as a key, or the field name as an attribute.

    >>> # Create a Record with one field, normally the record is created by the Reader class
    >>> r = _Record({'ID': 0}, [0])
    >>> print(r[0])
    >>> print(r['ID'])
    >>> print(r.ID)
    Nc                 C   s,   || _ |dur|| _nd| _t| | dS )z
        A Record should be created by the Reader class

        :param field_positions: A dict mapping field names to field positions
        :param values: A sequence of values
        :param oid: The object id, an int (optional)
        Nr   )_Record__field_positions_Record__oidrf   r   )rX   field_positionsvaluesr   r>   r>   r?   r     s
   z_Record.__init__c                 C   sP   z| j | }t| |W S  ty   td| ty'   td|w )a  
        __getattr__ is called if an attribute is used that does
        not exist in the normal sense. For example r=Record(...), r.ID
        calls r.__getattr__('ID'), but r.index(5) calls list.index(r, 5)
        :param item: The field name, used as attribute
        :return: Value of the field
        :raises: AttributeError, if item is not a field of the shapefile
                and IndexError, if the field exists but the field's 
                corresponding value in the Record does not exist
        {} is not a field namez4{} found as a field but not enough values available.)r  rf   __getitem__KeyErrorAttributeErrorr   r   rX   itemr   r>   r>   r?   __getattr__  s   
z_Record.__getattr__c                 C   sP   | drt| ||S z| j| }t| ||W S  ty'   td|w )z
        Sets a value of a field attribute
        :param key: The field name
        :param value: the value of that field
        :return: None
        :raises: AttributeError, if key is not a field of the shapefile
        _r  )
startswithrf   __setattr__r  __setitem__r  r	  r   rX   r   valuer   r>   r>   r?   r    s   

z_Record.__setattr__c                 C   sj   zt | |W S  ty#   z| j| }W n ty    d}Y nw Y nw |dur.t | |S td|)z
        Extends the normal list item access with
        access using a fieldname

        For example r['ID'], r[0]
        :param item: Either the position of the value or the name of a field
        :return: the value of the field
        Nz'"{}" is not a field name and not an int)rf   r  	TypeErrorr  r  r   r   r
  r>   r>   r?   r    s   	z_Record.__getitem__c                 C   sT   zt | ||W S  ty)   | j|}|dur"t | || Y S td|w )z
        Extends the normal list item access with
        access using a fieldname

        For example r['ID']=2, r[0]=2
        :param key: Either the position of the value or the name of a field
        :param value: the new value of the field
        Nz%{} is not a field name and not an int)rf   r  r  r  r   r   r   r  r>   r>   r?   r  	  s   	z_Record.__setitem__c                 C   r   )z:The index position of the record in the original shapefile)r  rW   r>   r>   r?   r     r   z_Record.oidFc                    sX   t  fdd j D }|r*| D ]\}}t|tr)d|j|j|j||< q|S )zi
        Returns this Record as a dictionary using the field names as keys
        :return: dict
        c                 3   s     | ]\}}| | fV  qd S rF   r>   )r_   fr`   rW   r>   r?   rd   %      z"_Record.as_dict.<locals>.<genexpr>{:04d}{:02d}{:02d})	r   r  r   r6   r   r   yearmonthday)rX   date_stringsdctkr;   r>   rW   r?   as_dict   s   
z_Record.as_dictc                 C   s   d | jt| S )NzRecord #{}: {})r   r  rf   rW   r>   r>   r?   rY   ,  s   z_Record.__repr__c                 C   s&   t tt| }t | j }|| S )z
        Helps to show the field names in an interactive environment like IPython.
        See: http://ipython.readthedocs.io/en/stable/config/integrating.html

        :return: List of method names and fields
        )rf   dirr   r  r   )rX   defaultfnamesr>   r>   r?   __dir__/  s   z_Record.__dir__rF   F)r[   r\   r]   r^   r   r  r  r  r  r   r   r  rY   r!  r>   r>   r>   r?   r    s    


r  c                   @   s&   e Zd ZdZdddZedd ZdS )ShapeRecordzA ShapeRecord object containing a shape along with its attributes.
    Provides the GeoJSON __geo_interface__ to return a Feature dictionary.Nc                 C   s   || _ || _d S rF   r   record)rX   r   r%  r>   r>   r?   r   =  s   
zShapeRecord.__init__c                 C   s.   d| j jdd| jjtkrd dS | jjdS )NFeatureT)r  )r   
propertiesgeometry)r%  r  r   r   r   r   rW   r>   r>   r?   r   A  s   zShapeRecord.__geo_interface__NN)r[   r\   r]   r^   r   r   r   r>   r>   r>   r?   r#  :  s
    
r#  c                   @   $   e Zd ZdZdd Zedd ZdS )Shapesa$  A class to hold a list of Shape objects. Subclasses list to ensure compatibility with
    former work and to reuse all the optimizations of the builtin list.
    In addition to the list interface, this also provides the GeoJSON __geo_interface__
    to return a GeometryCollection dictionary.c                 C      d t| S )Nz
Shapes: {}r   rf   rW   r>   r>   r?   rY   M     zShapes.__repr__c                 C      ddd | D d}|S )NGeometryCollectionc                 S      g | ]}|j qS r>   r   )r_   r   r>   r>   r?   r   U  r   z,Shapes.__geo_interface__.<locals>.<listcomp>)r   
geometriesr>   rX   
collectionr>   r>   r?   r   P  s   zShapes.__geo_interface__Nr[   r\   r]   r^   rY   r   r   r>   r>   r>   r?   r+  G  
    r+  c                   @   r*  )ShapeRecordsa)  A class to hold a list of ShapeRecord objects. Subclasses list to ensure compatibility with
    former work and to reuse all the optimizations of the builtin list.
    In addition to the list interface, this also provides the GeoJSON __geo_interface__
    to return a FeatureCollection dictionary.c                 C   r,  )NzShapeRecords: {}r-  rW   r>   r>   r?   rY   ^  r.  zShapeRecords.__repr__c                 C   r/  )NFeatureCollectionc                 S   r1  r>   r2  )r_   shaperecr>   r>   r?   r   d  r   z2ShapeRecords.__geo_interface__.<locals>.<listcomp>)r   featuresr>   r4  r>   r>   r?   r   a  s   zShapeRecords.__geo_interface__Nr6  r>   r>   r>   r?   r8  X  r7  r8  c                   @   s   e Zd ZdZdS )ShapefileExceptionz3An exception to handle shapefile specific problems.N)r[   r\   r]   r^   r>   r>   r>   r?   r<  g  s    r<  c                   @   sF  e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	e
dd Ze
dd ZdHddZdd Zdd Zdd Zdd Zdd Zdd  Zd!d" Zd#d$ ZdId%d&Zd'd( Zd)d* ZdHd+d,ZdJd.d/ZdHd0d1ZdHd2d3Zd4d5 ZdHd6d7ZdHd8d9ZdHd:d;Z dJd<d=Z!dHd>d?Z"dHd@dAZ#dKdBdCZ$dIdDdEZ%dIdFdGZ&dS )LReaderac  Reads the three files of a shapefile as a unit or
    separately.  If one of the three files (.shp, .shx,
    .dbf) is missing no exception is thrown until you try
    to call a method that depends on that particular file.
    The .shx index file is used if available for efficiency
    but is not required to read the geometry from the .shp
    file. The "shapefile" argument in the constructor is the
    name of the file you want to open, and can be the path
    to a shapefile on a local filesystem, inside a zipfile, 
    or a url. 

    You can instantiate a Reader without specifying a shapefile
    and then specify one later with the load() method.

    Only the shapefile headers are read upon loading. Content
    within each file is only accessed when required and as
    efficiently as possible. Shapefiles are usually not large
    but they can be.
    c              	   O   s.  d | _ d | _d | _g | _d| _g | _d | _d | _d | _g | _	d| _
i | _|dd| _|dd| _t|dkrt|d }t|rd|v r<|ddkrVtd	| |dr`|}d }n|d |dd
  }||dd
 d d  }|drt|ddid}t|}tjdddd}||  |d nt|dd}t |dj}	|sdd |	! D }
t|
dkrtdt|
dkr|
d }ntd|
 t"j#$|d }dD ]1}z*|	|d | }tjddd}||  |d t%| || | j&| W q   Y qW d    n	1 sw   Y  z|'  W n   Y | j s0| jr6| (  d S td| |drt)|}|d }t"j#$|\}}t"j#*|}dD ]K}z>t+|}|d | |d< t,|}t|ddid}t|}tjddd}||  |d t%| || | j&| W qZ t-y   Y qZw | j s| jr| (  d S td| | (| d S d|. v rEt/|d d r|d | _ z| j d W n% t0t1j2fy   t13| j  | _ Y nw t"j#$|d \}}| 4| d!|. v rEt/|d! d r6|d! | _z| jd W n% t0t1j2fy5   t13| j | _Y nw t"j#$|d! \}}| 5| d"|. v rt/|d" d rx|d" | _z| jd W n% t0t1j2fyw   t13| j | _Y nw t"j#$|d" \}}| 6| | j s| jr| (  d S d S )#NzNot specifiedr   r<   r2   r=   r3   z.zipr   z:Reading from multiple nested zipfiles is not supported: %sr$   httpz
User-agentzwMozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36)headerszw+bT)modesuffixdeleterb)r@  rc                 S   s   g | ]	}| d r|qS ).shp)endswith)r_   namer>   r>   r?   r     s    
z#Reader.__init__.<locals>.<listcomp>z'Zipfile does not contain any shapefileszZipfile contains more than one shapefile: %s. Please specify the full                                     path to the shapefile you would like to open.)shpshxdbf.)r@  rB  z'No shp or dbf file found in zipfile: %sr#   z#No shp or dbf file found at url: %srH  readrI  rJ  )7rH  rI  rJ  _files_to_close	shapeName_offsets	shpLength
numRecords	numShapesfields_Reader__dbfHdrLength_Reader__fieldLookupr   r<   r=   rk   rR   rH   countr<  rF  findr  r/   r.   tempfileNamedTemporaryFilewriterL  seekopenzipfileZipFilenamelistrM   rQ   splitextsetattrrh   closeloadr+   basenamerf   r,   r-   r   rT   	NameErrorioUnsupportedOperationBytesIOload_shpload_shxload_dbf)rX   argskwargsrQ   zpath	shapefilereqresp
zipfileobjarchive
shapefilesr   memberfileobjurlinfourlpathr  _urlinfo_pathbaseNamer>   r>   r?   r     s   













zReader.__init__c                 C   sT   dg}| j r|dt| t| j  | jr%|dt| t| j d|S )zC
        Use some general info on the shapefile as __str__
        zshapefile Readerz    {} shapes (type '{}')z    {} records ({} fields)
)	rH  rh   r   rk   r   r   rJ  rS  join)rX   infor>   r>   r?   __str__D  s   
zReader.__str__c                 C      | S z1
        Enter phase of context manager.
        r>   rW   r>   r>   r?   	__enter__Q     zReader.__enter__c                 C      |    dS )zD
        Exit phase of context manager, close opened files.
        Nrb  rX   exc_typeexc_valexc_tbr>   r>   r?   __exit__W     zReader.__exit__c           	      C   s   | j r| jdu r|   | jS | jrz| jr!| jdu r|   | jS | jdu rw| j}| }|dd | }|d t	dj
}g }| }||k rj|| ||d\}}|dd|  7 }|| ||k sKt|| _|| _|| | jS dS )z6Returns the number of shapes/records in the shapefile.Nr   r#   d   >2ir   )rJ  rQ  _Reader__dbfHeaderrH  rI  rR  _Reader__shxHeadertellr[  r   r   rh   rL  rk   rO  )	rX   rH  
checkpointrP  r   offsetsposrecNum	recLengthr>   r>   r?   __len__]  s:   








zReader.__len__c                 c   s    |   D ]}|V  qdS )z5Iterates through the shapes/records in the shapefile.N)iterShapeRecords)rX   r:  r>   r>   r?   __iter__  s   zReader.__iter__c                 C   s    |   }|j}t| j|d< |S )Nrw   )shapeRecordsr   rf   rw   )rX   shaperecordsfcollectionr>   r>   r?   r     s   zReader.__geo_interface__c                 C   r   rF   r   rW   r>   r>   r?   r     r   zReader.shapeTypeNameNc                 C   s   |r*t j|\}}|| _| | | | | | | js*| js*t	d||f | jr1| 
  | jr8|   | jrA|   dS dS )zOpens a shapefile from a filename or file-like
        object. Normally this method would be called by the
        constructor with the file name as an argument.z Unable to open %s.dbf or %s.shp.N)rM   rQ   r`  rN  ri  rj  rk  rH  rJ  r<  _Reader__shpHeaderr  rI  r  )rX   ro  rN  r   r>   r>   r?   rc    s   


zReader.loadc                 C      d}zt d||f d| _| j| j W dS  ty@   zt d|| f d| _| j| j W Y dS  ty?   Y Y dS w w )zX
        Attempts to load file with .shp extension as both lower and upper case
        rH  %s.%srC  N)r\  rH  rM  rh   IOErrorupper)rX   shapefile_nameshp_extr>   r>   r?   ri       zReader.load_shpc                 C   r  )zX
        Attempts to load file with .shx extension as both lower and upper case
        rI  r  rC  N)r\  rI  rM  rh   r  r  )rX   r  shx_extr>   r>   r?   rj    r  zReader.load_shxc                 C   r  )zX
        Attempts to load file with .dbf extension as both lower and upper case
        rJ  r  rC  N)r\  rJ  rM  rh   r  r  )rX   r  dbf_extr>   r>   r?   rk    r  zReader.load_dbfc                 C      |    d S rF   r  rW   r>   r>   r?   __del__  rZ   zReader.__del__c              	   C   s@   | j D ]}t|drz|  W q ty   Y qw qg | _ d S )Nrb  )rM  rT   rb  r  )rX   	attributer>   r>   r?   rb    s   


zReader.closec                 C   sD   |st d| jr| jdu r|   | jr t| jdkr |   |S )zqChecks to see if the requested shapefile file object is
        available. If not a ShapefileException is raised.z:Shapefile Reader requires a shapefile or file-like object.Nr   )r<  rH  rP  rc  rJ  rk   rS  )rX   r  r>   r>   r?   __getFileObj  s   zReader.__getFileObjc                 C   s>   | j r| j d }t||krtd|dk rt| j | }|S )zqProvides list-like handling of a record index with a clearer
        error message if the index is out of bounds.r   z#Shape or Record index out of range.r   )rQ  r   r   rj   )rX   r`   rmaxr>   r>   r?   __restrictIndex  s   
zReader.__restrictIndexc                 C   s   | j std| j }|d td|dd d | _|d td|dd | _td	td
|d| _td	td|d| _	g | _
td	td|dD ]}|tkr_| j
| qR| j
d qRdS )z.Reads the header information from a .shp file.zMShapefile Reader requires a shapefile or file-like object. (no shp file found   >ir$   r   r#       <id<4d<2d   N)rH  r<  r[  r   rL  rP  r   rU   rw   zboxmboxNODATArh   )rX   rH  mr>   r>   r?   __shpHeader   s   

zReader.__shpHeaderc                 C   s  |  | j}t|d}d } } } } }	}
td|d\}}| d|  }td|dd }||_|dkr>g |_n!|d	v r_td
td|d|_	|dur_t
||j	s_|| dS |dv rmtd|dd }|d	v r{td|dd }|rtdtd| ||d |_|dkrtdtd| ||d |_|rtdd|  |d| }ttt|fd  |_|dv rtd|d\}}td
td| ||d |_|dv r1||  dkrtd|d\}	}
||  |d kr'g |_td
td| ||d D ]}|tkr|j| q|jd qn
dd t|D |_|dv rCtd
td|dg|_|dkrSttd|d|_|dv r{||  dkrktd|d\}nt}|tkrw|g|_ndg|_|| |S )z8Returns the header info and geometry for a single shape.)r   Nr  r   r#   r  r$   r   
r	   r
   r   r   r   r   r   r   r   r   r  r  r  r	   r
   r   r   r   r   r   r`   z<%sir   <%sdr  r   r   r   r   r  r   r   r   r   r   r   r   c                 S      g | ]}d qS rF   r>   r_   r  r>   r>   r?   r   O      z"Reader.__shape.<locals>.<listcomp>r   r   r   r   <d)r   r   )_Reader__getFileObjrH  r   r   rL  r  r   r   rU   rw   r   r[  r   r   rf   r0   iterzr  r  rh   rj   )rX   r   rw   r  r%  nPartsnPointszminzmaxmminmmaxr  r  nextr   flatr  r>   r>   r?   __shape  sh   

   
"






zReader.__shapec                 C   sF   | j }|s	td|d td|dd d d }|d | _d	S )
z.Reads the header information from a .shx file.MShapefile Reader requires a shapefile or file-like object. (no shx file foundr  r  r$   r   r#   r  r   N)rI  r<  r[  r   rL  rR  )rX   rI  shxRecordLengthr>   r>   r?   __shxHeaderg  s   
zReader.__shxHeaderc                 C   sf   | j }|s	td|d td|d| j d }tjdkr$|  dd |d	d	d D | _	d	S )
z1Reads the shape offset positions from a .shx filer  r  r`   r#   r$   bigc                 S   s   g | ]}d | qS r#   r>   )r_   elr>   r>   r?   r   |  r   z'Reader.__shxOffsets.<locals>.<listcomp>N)
rI  r<  r[  rU   rL  rR  sys	byteorderbyteswaprO  )rX   rI  
shxRecordsr>   r>   r?   __shxOffsetsq  s   

zReader.__shxOffsetsc                 C   s.   | j }|r	|dkrdS | js|   | j| S )zbReturns the offset in a .shp file for a shape based on information
        in the .shx index file.N)rI  rO  _Reader__shxOffsets)rX   r`   rI  r>   r>   r?   __shapeIndex~  s   
zReader.__shapeIndexr   c           
      C   s   |  | j}| |}| |}|s_|dd | }|d tdj}d}| }||k rS||kr5n||d\}}	|dd|	  7 }|| |d7 }||k s0||kr_t	d
|||| | j||dS )	zReturns a shape object for a shape in the geometry
        record file.
        If the 'bbox' arg is given (list or tuple of xmin,ymin,xmax,ymax), 
        returns None if the shape is not within that region. 
        r   r#   r  r  r   r   zFShape index {} is out of bounds; the .shp file only contains {} shapesr   rw   )r  rH  _Reader__restrictIndex_Reader__shapeIndexr[  r  r   r   rL  r<  r   _Reader__shape)
rX   r`   rw   rH  offsetrP  r   _ir  r  r>   r>   r?   r     s,   





zReader.shapec                 C   s   t  }|| j|d |S )zReturns all shapes in a shapefile.
        To only read shapes within a given spatial region, specify the 'bbox'
        arg as a list or tuple of xmin,ymin,xmax,ymax. 
        rw   )r+  r   
iterShapes)rX   rw   shapesr>   r>   r?   r    s   zReader.shapesc                 c   s    |  | j}|dd | }|d | jr/t| jD ]}| j||d}|r,|V  qdS d}g }| }||k rX|| | j||d}| }|rP|V  |d7 }||k s;|t|ks`J || _|| _	dS )zReturns a generator of shapes in a shapefile. Useful
        for handling large shapefiles.
        To only read shapes within a given spatial region, specify the 'bbox'
        arg as a list or tuple of xmin,ymin,xmax,ymax. 
        r   r#   r  r  r   N)
r  rH  r[  r  rR  r   r  rh   rk   rO  )rX   rw   rH  rP  r`   r   r  r  r>   r>   r?   r    s4   
	
	
zReader.iterShapesc                 C   sr  | j std| j }|d td|d\| _| _| _| jd d }t|D ]S}t	td|d}d}d}d|| v rF|| 
d}nt|| d }|| d	| ||< t|| | j| j||< ||  ||< t|d d
|d< | j| q(|d}|dkrtd| jdd tdd t| jD | _dd | jdd	 D }| |\}	}
}|| _|
| _d	S )zzReads a dbf header. Xbase-related code borrows heavily from ActiveState Python Cookbook Recipe 362715 by Raymond HettingerzNShapefile Reader requires a shapefile or file-like object. (no dbf file found)r   z<xxxxLHH20xr  !   <11sc4xBB14x    r   Nascii   zAShapefile dbf header lacks expected terminator. (likely corrupt?))DeletionFlagCr   r   c                 s        | ]\}}|d  |fV  qdS r   Nr>   r_   r`   r  r>   r>   r?   rd     r  z%Reader.__dbfHeader.<locals>.<genexpr>c                 S   s   g | ]}|d  qS r   r>   )r_   r  r>   r>   r?   r     r   z&Reader.__dbfHeader.<locals>.<listcomp>)rJ  r<  r[  r   rL  rQ  rT  _Reader__recordLengthrj   rf   r   rk   rD   r<   r=   lstriprS  rh   insertr   r   rU  _Reader__recordFields_Reader__fullRecStruct_Reader__fullRecLookup)rX   rJ  	numFieldsfield	fieldDescrG  idx
terminator
fieldnamesfieldTuples	recLookup	recStructr>   r>   r?   __dbfHeader  s8   


zReader.__dbfHeaderc                    s   | j du r	|   dd | jD } dur" fddt| j|D }d|}t|}|| jk r=|d7 }|d7 }|| jk s0||fS )zCalculates the format and size of a .dbf record. Optional 'fields' arg 
        specifies which fieldnames to unpack and which to ignore. Note that this
        always includes the DeletionFlag at index 0, regardless of the 'fields' arg. 
        Nc                 S   s   g | ]}d |d  qS )z%dsr#   r>   )r_   	fieldinfor>   r>   r?   r     s    z&Reader.__recordFmt.<locals>.<listcomp>c                    s8   g | ]\}}|d   v s|d  dkr|nd|d  qS )r   r  z%dxr#   r>   )r_   r   coderS  r>   r?   r     s    
r1   r   r   )rQ  r  rS  rg   r}  r   r  )rX   rS  structcodesfmtfmtSizer>   r  r?   __recordFmt  s    





zReader.__recordFmtc           	      C   s   |durPt t|}| j|d\}}t|}|D ]}|| jvs#|dkr*td|qg }| jdd D ]}|d }||v rC|| q4t	dd t
|D }n| jdd }| j}| j}|||fS )	aF  Returns the necessary info required to unpack a record's fields,
        restricted to a subset of fieldnames 'fields' if specified. 
        Returns a list of field info tuples, a name-index lookup dict, 
        and a Struct instance for unpacking these fields. Note that DeletionFlag
        is not a valid field. 
        Nr  r  z"{}" is not a valid field namer   r   c                 s   r  r  r>   r  r>   r>   r?   rd   =  r  z(Reader.__recordFields.<locals>.<genexpr>)rf   set_Reader__recordFmtr   rU  
ValueErrorr   rS  rh   r   r   r  r  )	rX   rS  r  r  r  rG  r  r   r  r>   r>   r?   __recordFields$  s&   

zReader.__recordFieldsc                 C   s  |  | j}|||j}|d dkrdS |dd }t|t|kr1tdt|t|g }t||D ]\\}}	}
}}|	dv r|	dd }|
dd	}|d	krXd}n|rlzt|}W n tyk   d}Y nw zt|}W n ty   ztt|}W n ty   d}Y nw Y now |	d
kr|
dd	
dd	
dd	sd}nYz"t|dd t|dd t|dd }}}t|||}W n6   t| }Y n+|	dkr|dkrd}n |dv rd}n|dv rd}nd}nt|| j| j}| d}|| q8t|||S )zReads and returns a dbf record row as a list of values. Requires specifying
        a list of field info tuples 'fieldTuples', a record name-index dict 'recLookup', 
        and a Struct instance 'recStruct' for unpacking these fields. 
        r       Nr   znNumber of record values ({}) is different from the requested                             number of fields ({})NFr     *r5   D   0r$   rL   r   Ls   YyTt1Ts   NnFf0F )r  rJ  r   rL  sizerk   r<  r   rg   splitreplacefloatr	  intr   rD   stripr<   r=   rstriprh   r  )rX   r  r  r  r   r  recordContentsr%  rG  typr  decir  yr  r  r>   r>   r?   __recordE  sh   4zReader.__recordc                 C   sn   |  | j}| jdu r|   | |}| j}|d || j||   | |\}}}| j	||||dS )zReturns a specific dbf record based on the supplied index.
        To only read some of the fields, specify the 'fields' arg as a
        list of one or more fieldnames. 
        Nr   r   r  r  r  )
r  rJ  rQ  r  r  r  r[  rT  r  _Reader__record)rX   r`   rS  r  recSizer  r  r  r>   r>   r?   r%    s   


zReader.recordc           	      C   sr   | j du r	|   g }| | j}|| j | |\}}}t| j D ]}| j||||d}|r6|	| q$|S )zReturns all records in a dbf file. 
        To only read some of the fields, specify the 'fields' arg as a
        list of one or more fieldnames.
        Nr   )
rQ  r  r  rJ  r[  rT  r  rj   r!  rh   )	rX   rS  recordsr  r  r  r  r`   rD  r>   r>   r?   r#    s   

zReader.recordsc                 c   sl    | j du r
|   | | j}|| j | |\}}}t| j D ]}| j||||d}|r3|V  q#dS )zReturns a generator of records in a dbf file.
        Useful for large shapefiles or dbf files.
        To only read some of the fields, specify the 'fields' arg as a
        list of one or more fieldnames.
        Nr   )	rQ  r  r  rJ  r[  rT  r  r   r!  )rX   rS  r  r  r  r  r`   rD  r>   r>   r?   iterRecords  s   
zReader.iterRecordsc                 C   s:   |  |}| j||d}|r| j||d}t||dS dS )a^  Returns a combination geometry and attribute record for the
        supplied record index. 
        To only read some of the fields, specify the 'fields' arg as a
        list of one or more fieldnames. 
        If the 'bbox' arg is given (list or tuple of xmin,ymin,xmax,ymax), 
        returns None if the shape is not within that region. 
        r  r  r$  N)r  r   r%  r#  )rX   r`   rS  rw   r   r%  r>   r>   r?   shapeRecord  s   
zReader.shapeRecordc                 C   s   t | j||dS )a`  Returns a list of combination geometry/attribute records for
        all records in a shapefile.
        To only read some of the fields, specify the 'fields' arg as a
        list of one or more fieldnames. 
        To only read entries within a given spatial region, specify the 'bbox'
        arg as a list or tuple of xmin,ymin,xmax,ymax. 
        )rS  rw   )r8  r  )rX   rS  rw   r>   r>   r?   r    s   zReader.shapeRecordsc                 c   st    |du rt |  | j|dD ]\}}t||dV  qdS | j|dD ]}|r7| j|j|d}t||dV  q$dS )ae  Returns a generator of combination geometry/attribute records for
        all records in a shapefile.
        To only read some of the fields, specify the 'fields' arg as a
        list of one or more fieldnames. 
        To only read entries within a given spatial region, specify the 'bbox'
        arg as a list or tuple of xmin,ymin,xmax,ymax. 
        Nr  r$  r  )r`   rS  )r0   r  r$  r#  r%  r   )rX   rS  rw   r   r%  r>   r>   r?   r    s   zReader.iterShapeRecordsrF   r)  r  )r   NN)'r[   r\   r]   r^   r   r  r  r  r  r  r   r   r   rc  ri  rj  rk  r  rb  r  r  r  r  r  r  r  r   r  r  r  r  r  r!  r%  r#  r$  r%  r  r  r>   r>   r>   r?   r=    sN     "1





O



%
	*
*

!
T




r=  c                   @   sV  e Zd ZdZdVddZdd Zdd	 Zd
d Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd Zedd Zdd Zdd Zd d! ZdWd#d$Zd%d& Zd'd( Zd)d* Zd+d, Zd-d. Zd/d0 Zd1d2 Zd3d4 Zd5d6 ZdXd7d8ZdYd:d;Zd<d= Z d>d? Z!d@dA Z"dBdC Z#dDdE Z$dFdG Z%dHdI Z&dJdK Z'dLdM Z(dNdO Z)dPdQ Z*dZdTdUZ+dS )[Writerz+Provides write support for ESRI Shapefiles.NFc                 K   s  || _ || _g | _|| _d  | _ | _| _g | _|rYt|}t	|s.t
dt|t|| tj|d d | _| tj|d d | _| tj|d d | _n=|dsh|dsh|dr|d|d|d}}}|r| || _|r| || _|r| || _nt
d	| jr| jd
 | jr| jd
 d| _d| _d | _d | _d | _d| _|dd| _|dd| _d S )NzHThe target filepath {} must be of type str/unicode or path-like, not {}.r   rE  z.shxz.dbfrH  rI  rJ  zYEither the target filepath, or any of shp, shx, or dbf must be set to create a shapefile.sd   9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999r<   r2   r=   r3   )targetautoBalancerS  r   rH  rI  rJ  rM  rR   rH   r   r   reprr   _Writer__getFileObjrM   rQ   r`  r   rZ  r  shpNum_bbox_zbox_mboxdeletionFlagr   r<   r=   )rX   r'  r   r(  rm  rH  rI  rJ  r>   r>   r?   r     sB   "zWriter.__init__c                 C   s   t | j| jS )zReturns the current number of features written to the shapefile. 
        If shapes and records are unbalanced, the length is considered the highest
        of the two.)rv   r  r+  rW   r>   r>   r?   r  #  s   zWriter.__len__c                 C   r  r  r>   rW   r>   r>   r?   r  )  r  zWriter.__enter__c                 C   r  )zT
        Exit phase of context manager, finish writing and close the files.
        Nr  r  r>   r>   r?   r  /  r  zWriter.__exit__c                 C   r  rF   r  rW   r>   r>   r?   r  5  rZ   zWriter.__del__c              	   C   sl  | j ot| j do| j j }| jot| jdo| jj }| jo)t| jdo(| jj }| j rK|rK| jrK|rK| jr;|   | j| jkrKt	d| j| jf | j rX|rX| j
| j dd | jre|re| j
| jdd | jrn|rn|   | j | j| jfD ]}t|drt|dr|jsz|  W qv ty   Y qvw qv| jD ]}t|drz|  W q ty   Y qw qg | _dS )	zL
        Write final shp, shx, and dbf headers, close opened files.
        closedzpWhen saving both the dbf and shp file, the number of records (%s) must correspond with the number of shapes (%s)rH  )
headerTyperI  flushrb  N)rH  rT   r0  rI  rJ  r(  balancer  r+  r<  _Writer__shapefileHeader_Writer__dbfHeaderr2  r  rM  rb  )rX   shp_openshx_opendbf_openr  r>   r>   r?   rb  8  sB   






zWriter.closec                 C   s^   |st dt|dr|S tj|d }|r"tj|s"t| t|d}| j	| |S )z*Safety handler to verify file-like objectszNo file-like object available.rZ  r   zwb+)
r<  rT   rM   rQ   r  existsmakedirsr\  rM  rh   )rX   r  pthfpr>   r>   r?   r  d  s   


zWriter.__getFileObjc                 C   s:   | j  }| j dd | j  }|d }| j | |S )z+Calculates the file length of the shp file.r   r#   )rH  r  r[  )rX   r   r  r>   r>   r?   __shpFileLengthr  s   

zWriter.__shpFileLengthc                 C   s   g }g }t |jdkr#tt|j d d \}}|| || ntd|j t|t|t|t|g}| j	rdt|d | j	d t|d | j	d t|d | j	d t|d | j	d g| _	|S || _	|S )Nr   r#   zjCannot create bbox. Expected a valid shape with at least one point. Got a shape of type '%s' and 0 points.r   r	   )
rk   r   rf   rg   r   r   r   ru   rv   r,  )rX   sr   r  pxpyrw   r>   r>   r?   __bbox  s   
NzWriter.__bboxc              	   C   s   g }|j D ]}z	||d  W q ty   |d Y qw t|t|g}| jrAt|d | jd t|d | jd g| _|S || _|S )Nr#   r   r   )r   rh   r   ru   rv   r-  )rX   r>  r  r   r  r>   r>   r?   __zbox  s   
*zWriter.__zboxc              	   C   s   |j dv rdnd}g }|jD ]}z|| d ur|||  W q ty(   Y qw |s0|t t|t|g}| jrRt|d | jd t|d | jd g| _|S || _|S )N)r   r   r   r   r   r	   r#   r   r   )r   r   rh   r   r  ru   rv   r.  )rX   r>  mposr  r   r  r>   r>   r?   __mbox  s$   

*zWriter.__mboxc                 C   r   rF   r   rW   r>   r>   r?   r     r   zWriter.shapeTypeNamec                 C   r   )zReturns the current bounding box for the shapefile which is
        the lower-left and upper-right corners. It does not contain the
        elevation or measure extremes.)r,  rW   r>   r>   r?   rw     s   zWriter.bboxc                 C   r   )z1Returns the current z extremes for the shapefile.)r-  rW   r>   r>   r?   r       zWriter.zboxc                 C   r   )z1Returns the current m extremes for the shapefile.)r.  rW   r>   r>   r?   r    rE  zWriter.mboxrH  c              
   C   s  |  |}|d |tddddddd |dkr&|td|   n|dkr9|tdd| jd  d	  | jd
u rAt| _|tdd| j | jdkruz|  }|d
u r]g d}|tdg|R   W n t	yt   t
dw |tddddd | jdv r|  }|d
u rddg}nddg}| jdv r|  }|d
u rddg}nddg}z|td|d |d |d |d  W d
S  t	y   t
dw )zWrites the specified header type to the specified file-like object.
        Several of the shapefile formats are so similar that a single generic
        method to read or write them is warranted.r   z>6ii
'  rH  r  rI  r  r   r#   Nz<2ii  )r   r   r   r   r  z8Failed to write shapefile bounding box. Floats required.)r   r   r   r   )	r   r   r   r   r   r   r   r   r   r   zHFailed to write shapefile elevation and measure values. Floats required.)r*  r[  rZ  r   _Writer__shpFileLengthr+  r   r   rw   r   r<  r  r  )rX   fileObjr1  r  rw   r  r  r>   r>   r?   __shapefileHeader  sJ   





,zWriter.__shapefileHeaderc              	   C   s:  |  | j}|d d}t dd \}}}|d8 }dd | jD }|s*td| j}t|}|d d	 }	|	d
kr?tdt	dd |D d }
t
d||||||	|
}|| |D ]9}|\}}}}t|| j| j}|dd}|dd ddd}t|d}t|}t
d||||}|| q\|d dS )z,Writes the dbf header and field descriptors.r   r	   Nil  c                 S   s   g | ]
}|d  dkr|qS )r   r  r>   r_   r  r>   r>   r?   r         z&Writer.__dbfHeader.<locals>.<listcomp>z3Shapefile dbf file must contain at least one field.r  r  i  z3Shapefile dbf header length exceeds maximum length.c                 S   s   g | ]}t |d  qS r  )r  rI  r>   r>   r?   r     s    r   z<BBBBLHH20xr     _
   r   r  r  r  r  )r*  rJ  r[  time	localtimerS  r<  r  rk   ri   r   rZ  r@   r<   r=   r  ljustr  )rX   r  versionr  r  r  rS  numRecsr  headerLengthrecordLengthr   r  rG  	fieldTyper  decimalfldr>   r>   r?   r    s<   


zWriter.__dbfHeaderc                 C   s~   | j r| j| jk r|   t|ts+t|dr|j}t|tr%t	|}nt
d| | |\}}| jr=| || d S d S )Nr   zbCan only write Shape objects, GeoJSON dictionaries, or objects with the __geo_interface__, not: %r)r(  r  r+  r3  r6   r   rT   r   r   r   r   _Writer__shpRecordrI  _Writer__shxRecord)rX   r>  r  lengthr>   r>   r?   r   0  s   


zWriter.shapec                    s  |  | j   }|  jd7  _ td| jd   }| jd u r-|jtkr-|j| _|jtkrB|j| jkrBtd|j| jf  td|j |jdv rU| 	| |jdv ryz tdg| 	|R   W n t
yx   td	| j w |jd
v r tdt|j |jdv r tdt|j |jd
v r|jD ]
} td| q|jdkr|jD ]
} td| q|jdv rz fdd|jD  W n t
y   td| j w |jdv r9z tdg| |R   W n t
y   td| j w z$t|dr tdt|j g|jR   n
 fdd|jD  W n t
y8   td| j w |jdv rz tdg| |R   W n t
y^   td| j w z4t|dr} tdt|j gdd |jD R   n|jdv rdnd fdd|jD  W n t
y   td| j w |jdv rz td|jd d |jd d  W n t
y   td| j w |jdkr4| | t|drz|jsd |_ td!|jd  W n@ t
y   td"| j w z!t|jd dk r|jd d  td!|jd d  W n t
y3   td"| j w |jd#v r| | t|drrz|jrR|jd d u rVtf|_ td$|jd  W n^ t
yq   td%| j w z?|jdkr{dndt|jd d k r|jd t n|jd  d u rt|jd <  td$|jd   W n t
y   td%| j w   }|| d } |d&   td'|  | ||fS )(Nr   r  r   z@The shape's type (%s) must match the type of the shapefile (%s).r  r  r  r  z<Failed to write bounding box for record %s. Expected floats.r  r   c              	      s*   g | ]}  td g|dd R  qS )r  Nr#   )rZ  r   r   r  r>   r?   r   m  s   * z&Writer.__shpRecord.<locals>.<listcomp>z6Failed to write points for record %s. Expected floats.r  r  zBFailed to write elevation extremes for record %s. Expected floats.r  r  c                    s0   g | ]}  td t|dkr|d ndqS )r  r#   r   )rZ  r   rk   r   rZ  r>   r?   r   }  s   0 z@Failed to write elevation values for record %s. Expected floats.r  z?Failed to write measure extremes for record %s. Expected floatsr  c                 S   s   g | ]
}|d ur
|nt qS rF   )r  )r_   r  r>   r>   r?   r     rJ  r	   r#   c                    s<   g | ]}  td t|kr| dur| ntqS )r  N)rZ  r   rk   r  r   r  rC  r>   r?   r     s   < z=Failed to write measure values for record %s. Expected floatsz5Failed to write point for record %s. Expected floats.r   r  r  z?Failed to write elevation value for record %s. Expected floats.)r   r   z<1dz=Failed to write measure value for record %s. Expected floats.r$   r  )r*  rH  r  r+  rZ  r   r   r   r   _Writer__bboxr   r<  rk   r   r   r   _Writer__zboxrT   r  _Writer__mboxr  rh   r  r[  )rX   r>  r  r   r   ptfinishrY  r>   r[  r?   __shpRecordC  s   


 






 $ .*


zWriter.__shpRecordc                 C   sP   |  | j}z|td|d  W n ty   tdw |td| dS )zWrites the shx records.r  r#   zThe .shp file has reached its file size limit > 4294967294 bytes (4.29 GB). To fix this, break up your file into multiple smaller ones.N)r*  rI  rZ  r   r   r<  )rX   r  rY  r  r>   r>   r?   __shxRecord  s   zWriter.__shxRecordc                 O   s   | j r| j| jkr|   tdd | jD }|r/t|}t||k r.|d t||k s#n<|rbg }| jD ]*}|d dkr?q6|d |v r[||d  }|du rU|d q6|| q6|d q6n	dd t	|D }| 
| dS )	a  Creates a dbf attribute record. You can submit either a sequence of
        field values or keyword arguments of field names and values. Before
        adding records you must add fields for the record values using the
        field() method. If the record values exceed the number of fields the
        extra ones won't be added. In the case of using keyword arguments to specify
        field/value pairs only fields matching the already registered fields
        will be added.c                 s   s     | ]}|d  dkrdV  qdS )r   r  r   Nr>   rI  r>   r>   r?   rd     r  z Writer.record.<locals>.<genexpr>r1   r   r  Nc                 S   r  )r1   r>   r  r>   r>   r?   r     r  z!Writer.record.<locals>.<listcomp>)r(  r  r+  r3  ri   rS  rf   rk   rh   rj   _Writer__dbfRecord)rX   
recordList
recordDict
fieldCountr%  r  valr>   r>   r?   r%    s.   	

zWriter.recordc           	   	   C   s  |  | j}| jdkr|   |d |  jd7  _dd | jD }t||D ]\\}}}}}| }t|}|dv r}|t	v rEd| }n|sjzt|}W n t
y\   tt|}Y nw t|dd	| |}nyt|}t|d
| d	| |}nf|dkrt|trd|j|j|j}nRt|trt|dkrdj| }nA|t	v rd}n:t|rt|dkrn/td|dkr|t	v rd}n |dv rd}n|dv rd}nd}nt|| j| jd	| |}t|tst|d| j}t||krtdt|||f || q(d	S )zWrites the dbf records.r   r  r   c                 s   s     | ]}|d  dkr|V  qdS )r   r  Nr>   rI  r>   r>   r?   rd   
	  r  z%Writer.__dbfRecord.<locals>.<genexpr>r  r  r  Nz.%sfr  r  r	   s   00000000r   zaDate values must be either a datetime.date object, a list, a YYYYMMDD string, or a missing value.r  )Tr      T)Fr      Fr  zZShapefile Writer unable to pack incorrect sized value (size %d) into field '%s' (size %d).)r*  rJ  r  r5  rZ  rS  rg   r  r  MISSINGr	  r  r   rjustr6   r   r  r  r  rf   rk   rH   r<  r@   r<   r=   rO  r9   )	rX   r%  r  rS  	fieldNamerT  r  r  r  r>   r>   r?   __dbfRecord  sd   




zWriter.__dbfRecordc                 C   sH   | j | jkr|   | j | jks| j | jk r"|   | j | jk sdS dS )zAdds corresponding empty attributes or null geometry records depending
        on which type of record was created to make sure all three files
        are in synch.N)r  r+  nullr%  rW   r>   r>   r?   r3  C	  s   zWriter.balancec                 C   s   |  tt dS )zCreates a null shape.N)r   r   r   rW   r>   r>   r?   rn  M	  s   zWriter.nullc                 C   s*   t }t|}|j||g | | dS )zCreates a POINT shape.N)r   r   r   rh   r   )rX   r   r  r   
pointShaper>   r>   r?   pointR	  s   zWriter.pointc                 C   s,   t }t|}|j|||g | | dS )z[Creates a POINTM shape.
        If the m (measure) value is not set, it defaults to NoData.N)r   r   r   rh   r   )rX   r   r  r  r   ro  r>   r>   r?   pointmY	  s   zWriter.pointmr   c                 C   s.   t }t|}|j||||g | | dS )zCreates a POINTZ shape.
        If the z (elevation) value is not set, it defaults to 0.
        If the m (measure) value is not set, it defaults to NoData.N)r   r   r   rh   r   )rX   r   r  r  r  r   ro  r>   r>   r?   pointza	  s   zWriter.pointzc                 C      t }|g}| j||d dS )zBCreates a MULTIPOINT shape.
        Points is a list of xy values.r   r   N)r   _shapepartsrX   r   r   r>   r>   r?   
multipointk	  s   zWriter.multipointc                 C   rs  )zCreates a MULTIPOINTM shape.
        Points is a list of xym values.
        If the m (measure) value is not included, it defaults to None (NoData).rt  N)r!   ru  rv  r>   r>   r?   multipointmr	  s   zWriter.multipointmc                 C   rs  )zCreates a MULTIPOINTZ shape.
        Points is a list of xyzm values.
        If the z (elevation) value is not included, it defaults to 0.
        If the m (measure) value is not included, it defaults to None (NoData).rt  N)r   ru  rv  r>   r>   r?   multipointzz	  s   zWriter.multipointzc                 C      t }| j||d dS )zfCreates a POLYLINE shape.
        Lines is a collection of lines, each made up of a list of xy values.rt  N)r   ru  rX   linesr   r>   r>   r?   line	  s   zWriter.linec                 C   rz  )zCreates a POLYLINEM shape.
        Lines is a collection of lines, each made up of a list of xym values.
        If the m (measure) value is not included, it defaults to None (NoData).rt  N)r   ru  r{  r>   r>   r?   linem	  s   zWriter.linemc                 C   rz  )zCreates a POLYLINEZ shape.
        Lines is a collection of lines, each made up of a list of xyzm values.
        If the z (elevation) value is not included, it defaults to 0.
        If the m (measure) value is not included, it defaults to None (NoData).rt  N)r   ru  r{  r>   r>   r?   linez	     zWriter.linezc                 C   rz  )a  Creates a POLYGON shape.
        Polys is a collection of polygons, each made up of a list of xy values.
        Note that for ordinary polygons the coordinates must run in a clockwise direction.
        If some of the polygons are holes, these must run in a counterclockwise direction.rt  N)r   ru  rX   r   r   r>   r>   r?   r   	  r  zWriter.polyc                 C   rz  )ap  Creates a POLYGONM shape.
        Polys is a collection of polygons, each made up of a list of xym values.
        Note that for ordinary polygons the coordinates must run in a clockwise direction.
        If some of the polygons are holes, these must run in a counterclockwise direction.
        If the m (measure) value is not included, it defaults to None (NoData).rt  N)r    ru  r  r>   r>   r?   polym	  s   zWriter.polymc                 C   rz  )a  Creates a POLYGONZ shape.
        Polys is a collection of polygons, each made up of a list of xyzm values.
        Note that for ordinary polygons the coordinates must run in a clockwise direction.
        If some of the polygons are holes, these must run in a counterclockwise direction.
        If the z (elevation) value is not included, it defaults to 0.
        If the m (measure) value is not included, it defaults to None (NoData).rt  N)r   ru  r  r>   r>   r?   polyz	  s   zWriter.polyzc                 C   sp   t }t|}g |_g |_|D ]}|jt|j |D ]}t|ts&t|}|j| qq||_| 	| dS )a  Creates a MULTIPATCH shape.
        Parts is a collection of 3D surface patches, each made up of a list of xyzm values.
        PartTypes is a list of types that define each of the surface patches.
        The types can be any of the following module constants: TRIANGLE_STRIP,
        TRIANGLE_FAN, OUTER_RING, INNER_RING, FIRST_RING, or RING.
        If the z (elevation) value is not included, it defaults to 0.
        If the m (measure) value is not included, it defaults to None (NoData).N)
r"   r   r   r   rh   rk   r6   rf   r   r   )rX   r   r   r   	polyShaper   rp  r>   r>   r?   
multipatch	  s   
zWriter.multipatchc                 C   s   t |}g |_g |_|dv r"|D ]}|d |d kr!||d  q|D ]}|jt|j |D ]}t|ts<t|}|j| q1q$| | dS )zInternal method for adding a shape that has multiple collections of points (parts):
        lines, polygons, and multipoint shapes.
        )r
   r   r   r   r   r   N)r   r   r   rh   rk   r6   rf   r   )rX   r   r   r  r   rp  r>   r>   r?   ru  	  s    
zWriter._shapepartsr  50c                 C   sP   |dkr	d}d}n|dkrd}d}t | jdkrtd| j||||f dS )	z-Adds a dbf field descriptor to the shapefile.r  8r   r  1i  z8Shapefile Writer reached maximum number of fields: 2046.N)rk   rS  r<  rh   )rX   rG  rT  r  rU  r>   r>   r?   r  	  s   zWriter.field)NNF)rH  rF   r  )r  r  r   ),r[   r\   r]   r^   r   r  r  r  r  rb  r*  rF  r\  r]  r^  r   r   rw   r  r  r4  r5  r   rW  rX  r%  rc  r3  rn  rp  rq  rr  rw  rx  ry  r}  r~  r  r   r  r  r  ru  r  r>   r>   r>   r?   r&    sV    
',

:# 	#E




		r&  c                     s   dd l  d _| dd}|dkrtd dd lG  fddd j} j| |d}tdd	}  j	|
 d
ddi dddd}W d    n1 sRw   Y  ||\}}|rg|d |S |dkrqtd |S |dkrz|| |S )Nr   r   verbosezRunning doctests...c                       s&   e Zd Z fddZ fddZdS )ztest.<locals>.Py23DocCheckerc                    s@   t jd dkrdd|}dd|} j| |||}|S )Nr   r#   zu'(.*?)'z'\1'zu"(.*?)"z"\1")r  version_infosubOutputCheckercheck_output)rX   wantgotoptionflagsresdoctestrer>   r?   r  O
  s
   z)test.<locals>.Py23DocChecker.check_outputc                    s    j d d S )NT)r  	summarizerW   )r  r>   r?   r  U
  r   z&test.<locals>.Py23DocChecker.summarizeN)r[   r\   r]   r  r  r>   r  r>   r?   Py23DocCheckerN
  s    r  )checkerr  z	README.mdrC  utf8z
r|  README)stringglobsrG  filenamelinenoTzAll test passed successfully)r  NORMALIZE_WHITESPACEr   printr  r  DocTestRunnerr\  DocTestParserget_doctestrL  rC   r  runr  )rm  	verbosityr  runnerfobjtestfailure_count
test_countr>   r  r?   r  E
  s*   ,

r  __main__)r2   r3   r"  rF   )[r^   __version__structr   r   r   r   r   rM   r  rM  arrayrX  loggingrf  datetimer   r]  	getLoggerr[   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r   r%   r&   r'   r(   r)   r*   PARTTYPE_LOOKUPr  PYTHON3rj   r   rg   r0   urllib.parser+   r,   urllib.errorr-   urllib.requestr.   r/   	itertoolsurllib2rj  r  r@   rD   rH   rR   rU   ro   rq   rt   rx   r   r   r   r   r   r   objectr   rf   r  r#  r+  r8  r   r<  r=  r&  r  r  exitr>   r>   r>   r?   <module>   s    








*,
y l 	(      q      Q
$