diff --git a/README.md b/README.md index 380ffd2..96ee555 100644 --- a/README.md +++ b/README.md @@ -142,7 +142,7 @@ method. >>> len(list(sf.iterShapes())) 663 -Each shape record contains the following attributes: +Each shape record (except Points) contain the following attributes. Records of shapeType Point do not have a bounding box 'bbox'. >>> for name in dir(shapes[3]): diff --git a/changelog.txt b/changelog.txt index 9ff0a00..f7785ee 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,9 @@ +VERSION 1.2.12 + +2017-08-24 Karim Bahgat + * Fixed errors caused by strict value type checking, as introduced in v1.2.11. Now more lenient by attempting force conversion of values to match the field type. + * Allow reading file-like objects without seek method (such as ZipFile or urllib.urlopen). + VERSION 1.2.11 2017-04-29 Karim Bahgat diff --git a/setup.py b/setup.py index 9acd4f7..09a667b 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ from setuptools import setup setup(name='pyshp', - version='1.2.11', + version='1.2.12', description='Pure Python read/write support for ESRI Shapefile format', long_description=open('README.md').read(), author='Joel Lawhead', diff --git a/shapefile.py b/shapefile.py index 3724ddb..8b0fff4 100644 --- a/shapefile.py +++ b/shapefile.py @@ -2,12 +2,12 @@ shapefile.py Provides read and write support for ESRI Shapefiles. author: jlawheadgeospatialpython.com -date: 2017/04/29 -version: 1.2.11 +date: 2018/09/8 +version: 1.2.13 Compatible with Python versions 2.7-3.x """ -__version__ = "1.2.11" +__version__ = "1.2.13" from struct import pack, unpack, calcsize, error, Struct import os @@ -522,11 +522,19 @@ def __record(self): #not parseable as float, set to None value = None else: + # force to int try: - value = int(value) + # first try to force directly to int. + # forcing a large int to float and back to int + # will lose information and result in wrong nr. + value = int(value) except ValueError: - #not parseable as int, set to None - value = None + # forcing directly to int failed, so was probably a float. + try: + value = int(float(value)) + except ValueError: + #not parseable as int, set to None + value = None elif typ == 'D': # date: 8 bytes - date stored as a string in the format YYYYMMDD. if value.count(b('0')) == len(value): # QGIS NULL is all '0' chars @@ -945,8 +953,18 @@ def __dbfRecords(self): if value in MISSING: value = str("*"*size) # QGIS NULL elif not deci: + # force to int + try: + # first try to force directly to int. + # forcing a large int to float and back to int + # will lose information and result in wrong nr. + value = int(value) + except ValueError: + # forcing directly to int failed, so was probably a float. + value = int(float(value)) value = format(value, "d")[:size].rjust(size) # caps the size if exceeds the field size else: + value = float(value) value = format(value, ".%sf"%deci)[:size].rjust(size) # caps the size if exceeds the field size elif fieldType == "D": # date: 8 bytes - date stored as a string in the format YYYYMMDD. @@ -971,8 +989,8 @@ def __dbfRecords(self): else: value = b(' ') # unknown is set to space else: - # anything else is forced to string - value = str(value)[:size].ljust(size) + # anything else is forced to byte string + value = b(value)[:size].ljust(size) if len(value) != size: raise ShapefileException( "Shapefile Writer unable to pack incorrect sized value"