diff -Nru pyshp-2.0.1+ds/changelog.txt pyshp-2.1.0+ds/changelog.txt --- pyshp-2.0.1+ds/changelog.txt 2018-11-07 05:59:32.000000000 +0000 +++ pyshp-2.1.0+ds/changelog.txt 2019-02-15 20:12:21.000000000 +0000 @@ -1,4 +1,17 @@ +VERSION 2.1.0 + +2019-02-15 + New Features: + * Added back read/write support for unicode field names. + * Improved Record representation + * More support for geojson on Reader, ShapeRecord, ShapeRecords, and shapes() + + Bug fixes: + * Fixed error when reading optional m-values + * Fixed Record attribute autocomplete in Python 3 + * Misc readme cleanup + VERSION 2.0.1 2018-11-05 diff -Nru pyshp-2.0.1+ds/debian/changelog pyshp-2.1.0+ds/debian/changelog --- pyshp-2.0.1+ds/debian/changelog 2018-12-03 21:21:52.000000000 +0000 +++ pyshp-2.1.0+ds/debian/changelog 2019-02-16 07:26:49.000000000 +0000 @@ -1,3 +1,11 @@ +pyshp (2.1.0+ds-1) unstable; urgency=medium + + * Team upload. + * New upstream release. + * Bump Standards-Version to 4.3.0, no changes. + + -- Bas Couwenberg Sat, 16 Feb 2019 08:26:49 +0100 + pyshp (2.0.1+ds-1) unstable; urgency=medium * Team upload. diff -Nru pyshp-2.0.1+ds/debian/control pyshp-2.1.0+ds/debian/control --- pyshp-2.0.1+ds/debian/control 2018-11-05 13:04:50.000000000 +0000 +++ pyshp-2.1.0+ds/debian/control 2018-12-25 22:04:44.000000000 +0000 @@ -10,7 +10,7 @@ python-setuptools, python3-all, python3-setuptools -Standards-Version: 4.2.1 +Standards-Version: 4.3.0 Vcs-Browser: https://salsa.debian.org/debian-gis-team/pyshp Vcs-Git: https://salsa.debian.org/debian-gis-team/pyshp.git Homepage: https://github.com/GeospatialPython/pyshp diff -Nru pyshp-2.0.1+ds/PKG-INFO pyshp-2.1.0+ds/PKG-INFO --- pyshp-2.0.1+ds/PKG-INFO 2018-11-07 05:59:52.000000000 +0000 +++ pyshp-2.1.0+ds/PKG-INFO 2019-02-15 20:12:42.000000000 +0000 @@ -1,16 +1,15 @@ -Metadata-Version: 1.2 +Metadata-Version: 2.1 Name: pyshp -Version: 2.0.1 +Version: 2.1.0 Summary: Pure Python read/write support for ESRI Shapefile format Home-page: https://github.com/GeospatialPython/pyshp Author: Joel Lawhead Author-email: jlawhead@geospatialpython.com License: MIT -Download-URL: https://github.com/GeospatialPython/pyshp/archive/2.0.1.tar.gz -Description-Content-Type: text/markdown +Download-URL: https://github.com/GeospatialPython/pyshp/archive/2.1.0.tar.gz Description: # PyShp - The Python Shapefile Library (pyshp) reads and writes ESRI Shapefiles in pure Python. + The Python Shapefile Library (PyShp) reads and writes ESRI Shapefiles in pure Python. ![pyshp logo](http://4.bp.blogspot.com/_SBi37QEsCvg/TPQuOhlHQxI/AAAAAAAAAE0/QjFlWfMx0tQ/S350/GSP_Logo.png "PyShp") @@ -48,7 +47,7 @@ # Overview - The Python Shapefile Library (pyshp) provides read and write support for the + The Python Shapefile Library (PyShp) provides read and write support for the Esri Shapefile format. The Shapefile format is a popular Geographic Information System vector data format created by Esri. For more information about this format please read the well-written "ESRI Shapefile Technical @@ -65,9 +64,9 @@ Pyshp is compatible with Python 2.7-3.x. - This document provides examples for using pyshp to read and write shapefiles. However + This document provides examples for using PyShp to read and write shapefiles. However many more examples are continually added to the blog [http://GeospatialPython.com](http://GeospatialPython.com), - and by searching for pyshp on [https://gis.stackexchange.com](https://gis.stackexchange.com). + and by searching for PyShp on [https://gis.stackexchange.com](https://gis.stackexchange.com). Currently the sample census blockgroup shapefile referenced in the examples is available on the GitHub project site at [https://github.com/GeospatialPython/pyshp](https://github.com/GeospatialPython/pyshp). These @@ -84,6 +83,19 @@ # Version Changes + ## 2.1.0 + + ### New Features: + - Added back read/write support for unicode field names. + - Improved Record representation + - More support for geojson on Reader, ShapeRecord, ShapeRecords, and shapes() + + ### Bug fixes: + + - Fixed error when reading optional m-values + - Fixed Record attribute autocomplete in Python 3 + - Misc readme cleanup + ## 2.0.0 The newest version of PyShp, version 2.0 introduced some major new improvements. @@ -133,7 +145,7 @@ The examples below will use a shapefile created from the U.S. Census Bureau Blockgroups data set near San Francisco, CA and available in the git - repository of the pyshp GitHub site. + repository of the PyShp GitHub site. ## Reading Shapefiles @@ -173,7 +185,7 @@ You can also load shapefiles from any Python file-like object using keyword arguments to specify any of the three files. This feature is very powerful and - allows you to load shapefiles from a url, from a zip file, serialized object, + allows you to load shapefiles from a url, a zip file, a serialized object, or in some cases a database. @@ -182,8 +194,8 @@ >>> r = shapefile.Reader(shp=myshp, dbf=mydbf) Notice in the examples above the shx file is never used. The shx file is a - very simple fixed-record index for the variable length records in the shp - file. This file is optional for reading. If it's available pyshp will use the + very simple fixed-record index for the variable-length records in the shp + file. This file is optional for reading. If it's available PyShp will use the shx file to access shape records a little faster but will do just fine without it. @@ -198,8 +210,8 @@ 5 Shape types are represented by numbers between 0 and 31 as defined by the - shapefile specification and listed below. It is important to note that numbering system has - several reserved numbers which have not been used yet therefore the numbers of + shapefile specification and listed below. It is important to note that the numbering system has + several reserved numbers that have not been used yet, therefore the numbers of the existing shape types are not sequential: - NULL = 0 @@ -231,14 +243,22 @@ >>> sf.shapeTypeName == 'POLYGON' True - Other pieces of meta-data that we can check includes the number of features, - or the bounding box area the shapefile covers: + Other pieces of meta-data that we can check include the number of features + and the bounding box area the shapefile covers: >>> len(sf) 663 >>> sf.bbox [-122.515048, 37.652916, -122.327622, 37.863433] + + Finally, if you would prefer to work with the entire shapefile in a different + format, you can convert all of it to a GeoJSON dictionary, although you may lose + some information in the process, such as z- and m-values: + + + >>> sf.__geo_interface__['type'] + 'FeatureCollection' ### Reading Geometry @@ -272,7 +292,8 @@ >>> ['%.3f' % coord for coord in s.bbox] ['-122.450', '37.801', '-122.442', '37.808'] - Each shape record (except Points) contain the following attributes. Records of shapeType Point do not have a bounding box 'bbox'. + Each shape record (except Points) contains the following attributes. Records of + shapeType Point do not have a bounding box 'bbox'. >>> for name in dir(shapes[3]): @@ -330,7 +351,7 @@ >>> ['%.3f' % coord for coord in shape] ['-122.471', '37.787'] - In most cases, however, if you need to more than just type or bounds checking, you may want + In most cases, however, if you need to do more than just type or bounds checking, you may want to convert the geometry to the more human-readable [GeoJSON format](http://geojson.org), where lines and polygons are grouped for you: @@ -340,11 +361,17 @@ >>> geoj["type"] 'MultiPolygon' + The results from the shapes() method similiarly supports converting to GeoJSON: + + + >>> shapes.__geo_interface__['type'] + 'GeometryCollection' + ### Reading Records A record in a shapefile contains the attributes for each shape in the - collection of geometry. Records are stored in the dbf file. The link between + collection of geometries. Records are stored in the dbf file. The link between geometry and attributes is the foundation of all geographic information systems. This critical link is implied by the order of shapes and corresponding records in the shp geometry file and the dbf attribute file. @@ -459,30 +486,30 @@ >>> shapeRecs[3].record[1:3] ['060750601001', 4715] - Now let's read the first two points for that same record: - + The results from the shapeRecords() method is a list-like object that can be easily converted + to GeoJSON through the _\_geo_interface\_\_: - >>> points = shapeRecs[3].shape.points[0:2] - >>> len(points) - 2 + >>> shapeRecs.__geo_interface__['type'] + 'FeatureCollection' The shapeRecord() method reads a single shape/record pair at the specified index. To get the 4th shape record from the blockgroups shapefile use the third index: >>> shapeRec = sf.shapeRecord(3) + + Each individual shape record also supports the _\_geo_interface\_\_ to convert it to a GeoJSON: + + + >>> shapeRec.__geo_interface__['type'] + 'Feature' The blockgroup key and population count: >>> shapeRec.record[1:3] ['060750601001', 4715] - - >>> points = shapeRec.shape.points[0:2] - - >>> len(points) - 2 ## Writing Shapefiles @@ -676,17 +703,17 @@ >>> r = shapefile.Reader('shapefiles/test/dtype') >>> r.record(0) - [True] + Record #0: [True] >>> r.record(1) - [True] + Record #1: [True] >>> r.record(2) - [False] + Record #2: [False] >>> r.record(3) - [False] + Record #3: [False] >>> r.record(4) - [None] + Record #4: [None] >>> r.record(5) - [None] + Record #5: [None] You can also add attributes using keyword arguments where the keys are field names. @@ -750,8 +777,8 @@ **Adding a LineString shape** - For LineString shapefiles, each line shape consists of multiple lines. Line shapes must be given as a list of lines, - even if there is just one line. Also, each line must have at least two points. + For LineString shapefiles, each shape is given as a list of one or more linear features. + Each of the linear features must have at least two points. >>> w = shapefile.Writer('shapefiles/test/line') @@ -769,12 +796,13 @@ **Adding a Polygon shape** Similarly to LineString, Polygon shapes consist of multiple polygons, and must be given as a list of polygons. - The main difference being that polygons must have at least 4 points and the last point must be the same as the first. - It's also okay if you forget to do so, PyShp automatically checks and closes the polygons if you don't. + The main difference is that polygons must have at least 4 points and the last point must be the same as the first. + It's also okay if you forget to repeat the first point at the end; PyShp automatically checks and closes the polygons + if you don't. It's important to note that for Polygon shapefiles, your polygon coordinates must be ordered in a clockwise direction. If any of the polygons have holes, then the hole polygon coordinates must be ordered in a counterclockwise direction. - The direction of your polygons determines how shapefile readers will distinguish between polygons outlines and holes. + The direction of your polygons determines how shapefile readers will distinguish between polygon outlines and holes. >>> w = shapefile.Writer('shapefiles/test/polygon') @@ -832,7 +860,7 @@ >>> w.record("row", "two") >>> w.point(2, 2) - To help prevent accidental misalignment pyshp has an "auto balance" feature to + To help prevent accidental misalignment PyShp has an "auto balance" feature to make sure when you add either a shape or a record the two sides of the equation line up. This way if you forget to update an entry the shapefile will still be valid and handled correctly by most shapefile @@ -867,7 +895,7 @@ >>> w.recNum == w.shpNum True - If you do not use the autobalance or balance method and forget to manually + If you do not use the autoBalance() or balance() method and forget to manually balance the geometry and attributes the shapefile will be viewed as corrupt by most shapefile software. @@ -877,17 +905,18 @@ ## 3D and Other Geometry Types - Most shapefiles store conventional 2D points, lines, or polygons. But the shapefile format is also capable of storing - various other types of geometries as well, including complex 3D surfaces and objects. + Most shapefiles store conventional 2D points, lines, or polygons. But the shapefile format is also capable + of storing various other types of geometries as well, including complex 3D surfaces and objects. **Shapefiles with measurement (M) values** - Measured shape types are shapes that include a measurement value at each vertex, for instance speed measurements from a GPS device. - Shapes with measurement (M) values are added with following methods: "pointm", "multipointm", "linem", and "polygonm". - The M-values are specified by adding a third M value to each XY coordinate. Missing or unobserved M-values are specified with a None value, - or by simply omitting the third M-coordinate. - - + Measured shape types are shapes that include a measurement value at each vertex, for instance + speed measurements from a GPS device. Shapes with measurement (M) values are added with the following + methods: "pointm", "multipointm", "linem", and "polygonm". The M-values are specified by adding a + third M value to each XY coordinate. Missing or unobserved M-values are specified with a None value, + or by simply omitting the third M-coordinate. + + >>> w = shapefile.Writer('shapefiles/test/linem') >>> w.field('name', 'C') @@ -904,17 +933,17 @@ >>> r = shapefile.Reader('shapefiles/test/linem') - >>> r.mbox # the lower and upper bound of M values in the shapefile + >>> r.mbox # the lower and upper bound of M-values in the shapefile [0.0, 3.0] - >>> r.shape(0).m # flat list of M values + >>> r.shape(0).m # flat list of M-values [0.0, None, 3.0, None, 0.0, None, None] **Shapefiles with elevation (Z) values** Elevation shape types are shapes that include an elevation value at each vertex, for instance elevation from a GPS device. - Shapes with an elevation (Z) values are added with following methods: "pointz", "multipointz", "linez", and "polygonz". + Shapes with elevation (Z) values are added with the following methods: "pointz", "multipointz", "linez", and "polygonz". The Z-values are specified by adding a third Z value to each XY coordinate. Z-values do not support the concept of missing data, but if you omit the third Z-coordinate it will default to 0. Note that Z-type shapes also support measurement (M) values added as a fourth M-coordinate. This too is optional. @@ -926,7 +955,7 @@ >>> w.linez([ ... [[1,5,18],[5,5,20],[5,1,22],[3,3],[1,1]], # line with some omitted Z-values ... [[3,2],[2,6]], # line without any Z-values - ... [[3,2,15,0],[2,6,13,3],[1,9,14,2]] # line with both Z and M-values + ... [[3,2,15,0],[2,6,13,3],[1,9,14,2]] # line with both Z- and M-values ... ]) >>> w.record('linez1') @@ -937,17 +966,17 @@ >>> r = shapefile.Reader('shapefiles/test/linez') - >>> r.zbox # the lower and upper bound of Z values in the shapefile + >>> r.zbox # the lower and upper bound of Z-values in the shapefile [0.0, 22.0] - >>> r.shape(0).z # flat list of Z values + >>> r.shape(0).z # flat list of Z-values [18.0, 20.0, 22.0, 0.0, 0.0, 0.0, 0.0, 15.0, 13.0, 14.0] **3D MultiPatch Shapefiles** Multipatch shapes are useful for storing composite 3-Dimensional objects. A MultiPatch shape represents a 3D object made up of one or more surface parts. - Each surface in "parts" is defined by a list of XYZM values (Z and M values optional), and its corresponding type + Each surface in "parts" is defined by a list of XYZM values (Z and M values optional), and its corresponding type is given in the "partTypes" argument. The part type decides how the coordinate sequence is to be interpreted, and can be one of the following module constants: TRIANGLE_STRIP, TRIANGLE_FAN, OUTER_RING, INNER_RING, FIRST_RING, or RING. For instance, a TRIANGLE_STRIP may be used to represent the walls of a building, combined with a TRIANGLE_FAN to represent @@ -1011,7 +1040,7 @@ This means that as long as you are able to iterate through a source file without having to load everything into memory, such as a large CSV table or a large shapefile, you can - process and write any number of items, and even merging many different source files into a single + process and write any number of items, and even merge many different source files into a single large shapefile. If you need to edit or undo any of your writing you would have to read the file back in, one record at a time, make your changes, and write it back out. @@ -1075,6 +1104,7 @@ David A. Riggs davidh-ssec Evan Heidtmann + ezcitron geospatialpython Hannes Ignacio Martinez Vazquez @@ -1088,6 +1118,7 @@ Michal Čihař Mike Toews Nilo + pakoun Paulo Ernesto Raynor Vliegendhart Razzi Abuissa @@ -1108,3 +1139,4 @@ Classifier: Topic :: Software Development :: Libraries Classifier: Topic :: Software Development :: Libraries :: Python Modules Requires-Python: >= 2.7 +Description-Content-Type: text/markdown diff -Nru pyshp-2.0.1+ds/README.md pyshp-2.1.0+ds/README.md --- pyshp-2.0.1+ds/README.md 2018-11-07 05:59:32.000000000 +0000 +++ pyshp-2.1.0+ds/README.md 2019-02-15 20:12:21.000000000 +0000 @@ -1,6 +1,6 @@ # PyShp -The Python Shapefile Library (pyshp) reads and writes ESRI Shapefiles in pure Python. +The Python Shapefile Library (PyShp) reads and writes ESRI Shapefiles in pure Python. ![pyshp logo](http://4.bp.blogspot.com/_SBi37QEsCvg/TPQuOhlHQxI/AAAAAAAAAE0/QjFlWfMx0tQ/S350/GSP_Logo.png "PyShp") @@ -38,7 +38,7 @@ # Overview -The Python Shapefile Library (pyshp) provides read and write support for the +The Python Shapefile Library (PyShp) provides read and write support for the Esri Shapefile format. The Shapefile format is a popular Geographic Information System vector data format created by Esri. For more information about this format please read the well-written "ESRI Shapefile Technical @@ -55,9 +55,9 @@ Pyshp is compatible with Python 2.7-3.x. -This document provides examples for using pyshp to read and write shapefiles. However +This document provides examples for using PyShp to read and write shapefiles. However many more examples are continually added to the blog [http://GeospatialPython.com](http://GeospatialPython.com), -and by searching for pyshp on [https://gis.stackexchange.com](https://gis.stackexchange.com). +and by searching for PyShp on [https://gis.stackexchange.com](https://gis.stackexchange.com). Currently the sample census blockgroup shapefile referenced in the examples is available on the GitHub project site at [https://github.com/GeospatialPython/pyshp](https://github.com/GeospatialPython/pyshp). These @@ -74,6 +74,19 @@ # Version Changes +## 2.1.0 + +### New Features: +- Added back read/write support for unicode field names. +- Improved Record representation +- More support for geojson on Reader, ShapeRecord, ShapeRecords, and shapes() + +### Bug fixes: + +- Fixed error when reading optional m-values +- Fixed Record attribute autocomplete in Python 3 +- Misc readme cleanup + ## 2.0.0 The newest version of PyShp, version 2.0 introduced some major new improvements. @@ -123,7 +136,7 @@ The examples below will use a shapefile created from the U.S. Census Bureau Blockgroups data set near San Francisco, CA and available in the git -repository of the pyshp GitHub site. +repository of the PyShp GitHub site. ## Reading Shapefiles @@ -163,7 +176,7 @@ You can also load shapefiles from any Python file-like object using keyword arguments to specify any of the three files. This feature is very powerful and -allows you to load shapefiles from a url, from a zip file, serialized object, +allows you to load shapefiles from a url, a zip file, a serialized object, or in some cases a database. @@ -172,8 +185,8 @@ >>> r = shapefile.Reader(shp=myshp, dbf=mydbf) Notice in the examples above the shx file is never used. The shx file is a -very simple fixed-record index for the variable length records in the shp -file. This file is optional for reading. If it's available pyshp will use the +very simple fixed-record index for the variable-length records in the shp +file. This file is optional for reading. If it's available PyShp will use the shx file to access shape records a little faster but will do just fine without it. @@ -188,8 +201,8 @@ 5 Shape types are represented by numbers between 0 and 31 as defined by the -shapefile specification and listed below. It is important to note that numbering system has -several reserved numbers which have not been used yet therefore the numbers of +shapefile specification and listed below. It is important to note that the numbering system has +several reserved numbers that have not been used yet, therefore the numbers of the existing shape types are not sequential: - NULL = 0 @@ -221,14 +234,22 @@ >>> sf.shapeTypeName == 'POLYGON' True -Other pieces of meta-data that we can check includes the number of features, -or the bounding box area the shapefile covers: +Other pieces of meta-data that we can check include the number of features +and the bounding box area the shapefile covers: >>> len(sf) 663 >>> sf.bbox [-122.515048, 37.652916, -122.327622, 37.863433] + +Finally, if you would prefer to work with the entire shapefile in a different +format, you can convert all of it to a GeoJSON dictionary, although you may lose +some information in the process, such as z- and m-values: + + + >>> sf.__geo_interface__['type'] + 'FeatureCollection' ### Reading Geometry @@ -262,7 +283,8 @@ >>> ['%.3f' % coord for coord in s.bbox] ['-122.450', '37.801', '-122.442', '37.808'] -Each shape record (except Points) contain the following attributes. Records of shapeType Point do not have a bounding box 'bbox'. +Each shape record (except Points) contains the following attributes. Records of +shapeType Point do not have a bounding box 'bbox'. >>> for name in dir(shapes[3]): @@ -320,7 +342,7 @@ >>> ['%.3f' % coord for coord in shape] ['-122.471', '37.787'] -In most cases, however, if you need to more than just type or bounds checking, you may want +In most cases, however, if you need to do more than just type or bounds checking, you may want to convert the geometry to the more human-readable [GeoJSON format](http://geojson.org), where lines and polygons are grouped for you: @@ -330,11 +352,17 @@ >>> geoj["type"] 'MultiPolygon' +The results from the shapes() method similiarly supports converting to GeoJSON: + + + >>> shapes.__geo_interface__['type'] + 'GeometryCollection' + ### Reading Records A record in a shapefile contains the attributes for each shape in the -collection of geometry. Records are stored in the dbf file. The link between +collection of geometries. Records are stored in the dbf file. The link between geometry and attributes is the foundation of all geographic information systems. This critical link is implied by the order of shapes and corresponding records in the shp geometry file and the dbf attribute file. @@ -449,30 +477,30 @@ >>> shapeRecs[3].record[1:3] ['060750601001', 4715] -Now let's read the first two points for that same record: - +The results from the shapeRecords() method is a list-like object that can be easily converted +to GeoJSON through the _\_geo_interface\_\_: - >>> points = shapeRecs[3].shape.points[0:2] - >>> len(points) - 2 + >>> shapeRecs.__geo_interface__['type'] + 'FeatureCollection' The shapeRecord() method reads a single shape/record pair at the specified index. To get the 4th shape record from the blockgroups shapefile use the third index: >>> shapeRec = sf.shapeRecord(3) + +Each individual shape record also supports the _\_geo_interface\_\_ to convert it to a GeoJSON: + + + >>> shapeRec.__geo_interface__['type'] + 'Feature' The blockgroup key and population count: >>> shapeRec.record[1:3] ['060750601001', 4715] - - >>> points = shapeRec.shape.points[0:2] - - >>> len(points) - 2 ## Writing Shapefiles @@ -666,17 +694,17 @@ >>> r = shapefile.Reader('shapefiles/test/dtype') >>> r.record(0) - [True] + Record #0: [True] >>> r.record(1) - [True] + Record #1: [True] >>> r.record(2) - [False] + Record #2: [False] >>> r.record(3) - [False] + Record #3: [False] >>> r.record(4) - [None] + Record #4: [None] >>> r.record(5) - [None] + Record #5: [None] You can also add attributes using keyword arguments where the keys are field names. @@ -740,8 +768,8 @@ **Adding a LineString shape** -For LineString shapefiles, each line shape consists of multiple lines. Line shapes must be given as a list of lines, -even if there is just one line. Also, each line must have at least two points. +For LineString shapefiles, each shape is given as a list of one or more linear features. +Each of the linear features must have at least two points. >>> w = shapefile.Writer('shapefiles/test/line') @@ -759,12 +787,13 @@ **Adding a Polygon shape** Similarly to LineString, Polygon shapes consist of multiple polygons, and must be given as a list of polygons. -The main difference being that polygons must have at least 4 points and the last point must be the same as the first. -It's also okay if you forget to do so, PyShp automatically checks and closes the polygons if you don't. +The main difference is that polygons must have at least 4 points and the last point must be the same as the first. +It's also okay if you forget to repeat the first point at the end; PyShp automatically checks and closes the polygons +if you don't. It's important to note that for Polygon shapefiles, your polygon coordinates must be ordered in a clockwise direction. If any of the polygons have holes, then the hole polygon coordinates must be ordered in a counterclockwise direction. -The direction of your polygons determines how shapefile readers will distinguish between polygons outlines and holes. +The direction of your polygons determines how shapefile readers will distinguish between polygon outlines and holes. >>> w = shapefile.Writer('shapefiles/test/polygon') @@ -822,7 +851,7 @@ >>> w.record("row", "two") >>> w.point(2, 2) -To help prevent accidental misalignment pyshp has an "auto balance" feature to +To help prevent accidental misalignment PyShp has an "auto balance" feature to make sure when you add either a shape or a record the two sides of the equation line up. This way if you forget to update an entry the shapefile will still be valid and handled correctly by most shapefile @@ -857,7 +886,7 @@ >>> w.recNum == w.shpNum True -If you do not use the autobalance or balance method and forget to manually +If you do not use the autoBalance() or balance() method and forget to manually balance the geometry and attributes the shapefile will be viewed as corrupt by most shapefile software. @@ -867,17 +896,18 @@ ## 3D and Other Geometry Types -Most shapefiles store conventional 2D points, lines, or polygons. But the shapefile format is also capable of storing -various other types of geometries as well, including complex 3D surfaces and objects. +Most shapefiles store conventional 2D points, lines, or polygons. But the shapefile format is also capable +of storing various other types of geometries as well, including complex 3D surfaces and objects. **Shapefiles with measurement (M) values** -Measured shape types are shapes that include a measurement value at each vertex, for instance speed measurements from a GPS device. -Shapes with measurement (M) values are added with following methods: "pointm", "multipointm", "linem", and "polygonm". -The M-values are specified by adding a third M value to each XY coordinate. Missing or unobserved M-values are specified with a None value, -or by simply omitting the third M-coordinate. - - +Measured shape types are shapes that include a measurement value at each vertex, for instance +speed measurements from a GPS device. Shapes with measurement (M) values are added with the following +methods: "pointm", "multipointm", "linem", and "polygonm". The M-values are specified by adding a +third M value to each XY coordinate. Missing or unobserved M-values are specified with a None value, +or by simply omitting the third M-coordinate. + + >>> w = shapefile.Writer('shapefiles/test/linem') >>> w.field('name', 'C') @@ -894,17 +924,17 @@ >>> r = shapefile.Reader('shapefiles/test/linem') - >>> r.mbox # the lower and upper bound of M values in the shapefile + >>> r.mbox # the lower and upper bound of M-values in the shapefile [0.0, 3.0] - >>> r.shape(0).m # flat list of M values + >>> r.shape(0).m # flat list of M-values [0.0, None, 3.0, None, 0.0, None, None] **Shapefiles with elevation (Z) values** Elevation shape types are shapes that include an elevation value at each vertex, for instance elevation from a GPS device. -Shapes with an elevation (Z) values are added with following methods: "pointz", "multipointz", "linez", and "polygonz". +Shapes with elevation (Z) values are added with the following methods: "pointz", "multipointz", "linez", and "polygonz". The Z-values are specified by adding a third Z value to each XY coordinate. Z-values do not support the concept of missing data, but if you omit the third Z-coordinate it will default to 0. Note that Z-type shapes also support measurement (M) values added as a fourth M-coordinate. This too is optional. @@ -916,7 +946,7 @@ >>> w.linez([ ... [[1,5,18],[5,5,20],[5,1,22],[3,3],[1,1]], # line with some omitted Z-values ... [[3,2],[2,6]], # line without any Z-values - ... [[3,2,15,0],[2,6,13,3],[1,9,14,2]] # line with both Z and M-values + ... [[3,2,15,0],[2,6,13,3],[1,9,14,2]] # line with both Z- and M-values ... ]) >>> w.record('linez1') @@ -927,17 +957,17 @@ >>> r = shapefile.Reader('shapefiles/test/linez') - >>> r.zbox # the lower and upper bound of Z values in the shapefile + >>> r.zbox # the lower and upper bound of Z-values in the shapefile [0.0, 22.0] - >>> r.shape(0).z # flat list of Z values + >>> r.shape(0).z # flat list of Z-values [18.0, 20.0, 22.0, 0.0, 0.0, 0.0, 0.0, 15.0, 13.0, 14.0] **3D MultiPatch Shapefiles** Multipatch shapes are useful for storing composite 3-Dimensional objects. A MultiPatch shape represents a 3D object made up of one or more surface parts. -Each surface in "parts" is defined by a list of XYZM values (Z and M values optional), and its corresponding type +Each surface in "parts" is defined by a list of XYZM values (Z and M values optional), and its corresponding type is given in the "partTypes" argument. The part type decides how the coordinate sequence is to be interpreted, and can be one of the following module constants: TRIANGLE_STRIP, TRIANGLE_FAN, OUTER_RING, INNER_RING, FIRST_RING, or RING. For instance, a TRIANGLE_STRIP may be used to represent the walls of a building, combined with a TRIANGLE_FAN to represent @@ -1001,7 +1031,7 @@ This means that as long as you are able to iterate through a source file without having to load everything into memory, such as a large CSV table or a large shapefile, you can -process and write any number of items, and even merging many different source files into a single +process and write any number of items, and even merge many different source files into a single large shapefile. If you need to edit or undo any of your writing you would have to read the file back in, one record at a time, make your changes, and write it back out. @@ -1065,6 +1095,7 @@ David A. Riggs davidh-ssec Evan Heidtmann +ezcitron geospatialpython Hannes Ignacio Martinez Vazquez @@ -1078,6 +1109,7 @@ Michal Čihař Mike Toews Nilo +pakoun Paulo Ernesto Raynor Vliegendhart Razzi Abuissa diff -Nru pyshp-2.0.1+ds/setup.py pyshp-2.1.0+ds/setup.py --- pyshp-2.0.1+ds/setup.py 2018-11-07 05:59:32.000000000 +0000 +++ pyshp-2.1.0+ds/setup.py 2019-02-15 20:12:21.000000000 +0000 @@ -7,14 +7,14 @@ return data.decode('utf-8') setup(name='pyshp', - version='2.0.1', + version='2.1.0', description='Pure Python read/write support for ESRI Shapefile format', long_description=read_file('README.md'), long_description_content_type='text/markdown', author='Joel Lawhead', author_email='jlawhead@geospatialpython.com', url='https://github.com/GeospatialPython/pyshp', - download_url='https://github.com/GeospatialPython/pyshp/archive/2.0.1.tar.gz', + download_url='https://github.com/GeospatialPython/pyshp/archive/2.1.0.tar.gz', py_modules=['shapefile'], license='MIT', zip_safe=False, diff -Nru pyshp-2.0.1+ds/shapefile.py pyshp-2.1.0+ds/shapefile.py --- pyshp-2.0.1+ds/shapefile.py 2018-11-07 05:59:32.000000000 +0000 +++ pyshp-2.1.0+ds/shapefile.py 2019-02-15 20:12:21.000000000 +0000 @@ -2,11 +2,11 @@ shapefile.py Provides read and write support for ESRI Shapefiles. author: jlawheadgeospatialpython.com -version: 2.0.1 +version: 2.1.0 Compatible with Python versions 2.7-3.x """ -__version__ = "2.0.1" +__version__ = "2.1.0" from struct import pack, unpack, calcsize, error, Struct import os @@ -457,8 +457,8 @@ """ return dict((f, self[i]) for f, i in self.__field_positions.items()) - def __str__(self): - return 'Record #{} '.format(self.__oid) + def __repr__(self): + return 'Record #{}: {}'.format(self.__oid, list(self)) def __dir__(self): """ @@ -467,15 +467,51 @@ :return: List of method names and fields """ - attrs = [attr for attr in vars(type(self)) if not attr.startswith('_')] - return attrs + self.__field_positions.values() # plus field names (random order) + default = list(dir(type(self))) # default list methods and attributes of this class + fnames = list(self.__field_positions.keys()) # plus field names (random order) + return default + fnames class ShapeRecord(object): - """A ShapeRecord object containing a shape along with its attributes.""" + """A ShapeRecord object containing a shape along with its attributes. + Provides the GeoJSON __geo_interface__ to return a Feature dictionary.""" def __init__(self, shape=None, record=None): self.shape = shape self.record = record + @property + def __geo_interface__(self): + return {'type': 'Feature', + 'properties': self.record.as_dict(), + 'geometry': self.shape.__geo_interface__} + +class Shapes(list): + """A class to hold a list of Shape objects. Subclasses list to ensure compatibility with + former work and allows to use all the optimazations of the builtin list. + In addition to the list interface, this also provides the GeoJSON __geo_interface__ + to return a GeometryCollection dictionary. """ + + def __repr__(self): + return 'Shapes: {}'.format(list(self)) + + @property + def __geo_interface__(self): + return {'type': 'GeometryCollection', + 'geometries': [g.__geo_interface__ for g in self]} + +class ShapeRecords(list): + """A class to hold a list of ShapeRecord objects. Subclasses list to ensure compatibility with + former work and allows to use all the optimazations of the builtin list. + In addition to the list interface, this also provides the GeoJSON __geo_interface__ + to return a FeatureCollection dictionary. """ + + def __repr__(self): + return 'ShapeRecords: {}'.format(list(self)) + + @property + def __geo_interface__(self): + return {'type': 'FeatureCollection', + 'features': [f.__geo_interface__ for f in self]} + class ShapefileException(Exception): """An exception to handle shapefile specific problems.""" pass @@ -585,9 +621,7 @@ features = [] for feat in self.iterShapeRecords(): fdict = {'type': 'Feature', - 'properties': dict(*zip(fieldnames, - list(feat.record) - )), + 'properties': dict(zip(fieldnames,feat.record)), 'geometry': feat.shape.__geo_interface__} features.append(fdict) return {'type': 'FeatureCollection', @@ -748,14 +782,18 @@ record.z = _Array('d', unpack("<%sd" % nPoints, f.read(nPoints * 8))) # Read m extremes and values if shapeType in (13,15,18,23,25,28,31): - (mmin, mmax) = unpack("<2d", f.read(16)) + if next - f.tell() >= 16: + (mmin, mmax) = unpack("<2d", f.read(16)) # Measure values less than -10e38 are nodata values according to the spec - record.m = [] - for m in _Array('d', unpack("<%sd" % nPoints, f.read(nPoints * 8))): - if m > NODATA: - record.m.append(m) - else: - record.m.append(None) + if next - f.tell() >= nPoints * 8: + record.m = [] + for m in _Array('d', unpack("<%sd" % nPoints, f.read(nPoints * 8))): + if m > NODATA: + record.m.append(m) + else: + record.m.append(None) + else: + record.m = [None for _ in range(nPoints)] # Read a single point if shapeType in (1,11,21): record.points = [_Array('d', unpack("<2d", f.read(16)))] @@ -763,8 +801,11 @@ if shapeType == 11: record.z = list(unpack("= 8: + (m,) = unpack(" NODATA: record.m = [m] @@ -822,7 +863,7 @@ shp.seek(0,2) self.shpLength = shp.tell() shp.seek(100) - shapes = [] + shapes = Shapes() while shp.tell() < self.shpLength: shapes.append(self.__shape()) return shapes @@ -856,9 +897,9 @@ else: idx = len(fieldDesc[name]) - 1 fieldDesc[name] = fieldDesc[name][:idx] - fieldDesc[name] = u(fieldDesc[name], "ascii") + fieldDesc[name] = u(fieldDesc[name], self.encoding, self.encodingErrors) fieldDesc[name] = fieldDesc[name].lstrip() - fieldDesc[1] = u(fieldDesc[1], "ascii") + fieldDesc[1] = u(fieldDesc[1], 'ascii') self.fields.append(fieldDesc) terminator = dbf.read(1) if terminator != b"\r": @@ -994,9 +1035,8 @@ def shapeRecords(self): """Returns a list of combination geometry/attribute records for all records in a shapefile.""" - shapeRecords = [] - return [ShapeRecord(shape=rec[0], record=rec[1]) \ - for rec in zip(self.shapes(), self.records())] + return ShapeRecords([ShapeRecord(shape=rec[0], record=rec[1]) \ + for rec in zip(self.shapes(), self.records())]) def iterShapeRecords(self): """Returns a generator of combination geometry/attribute records for @@ -1269,7 +1309,7 @@ year -= 1900 # Remove deletion flag placeholder from fields for field in self.fields: - if str(field[0]).startswith("Deletion"): + if field[0].startswith("Deletion"): self.fields.remove(field) numRecs = self.recNum numFields = len(self.fields) @@ -1284,10 +1324,10 @@ # Field descriptors for field in self.fields: name, fieldType, size, decimal = field - name = b(name, 'ascii', self.encodingErrors) + name = b(name, self.encoding, self.encodingErrors) name = name.replace(b' ', b'_') name = name.ljust(11).replace(b' ', b'\x00') - fieldType = b(fieldType, 'ascii', self.encodingErrors) + fieldType = b(fieldType, 'ascii') size = int(size) fld = pack('<11sc4xBB14x', name, fieldType, size, decimal) f.write(fld) @@ -1833,7 +1873,7 @@ # run tests runner = doctest.DocTestRunner(checker=Py23DocChecker(), verbose=verbosity) with open("README.md","rb") as fobj: - test = doctest.DocTestParser().get_doctest(string=fobj.read().decode("utf8"), globs={}, name="README", filename="README.md", lineno=0) + test = doctest.DocTestParser().get_doctest(string=fobj.read().decode("utf8").replace('\r\n','\n'), globs={}, name="README", filename="README.md", lineno=0) failure_count, test_count = runner.run(test) # print results Binary files /tmp/tmpjq_CG8/UAyC3EPdtw/pyshp-2.0.1+ds/shapefiles/test/balancing.dbf and /tmp/tmpjq_CG8/2Xrw34AU6Z/pyshp-2.1.0+ds/shapefiles/test/balancing.dbf differ Binary files /tmp/tmpjq_CG8/UAyC3EPdtw/pyshp-2.0.1+ds/shapefiles/test/contextwriter.dbf and /tmp/tmpjq_CG8/2Xrw34AU6Z/pyshp-2.1.0+ds/shapefiles/test/contextwriter.dbf differ Binary files /tmp/tmpjq_CG8/UAyC3EPdtw/pyshp-2.0.1+ds/shapefiles/test/dtype.dbf and /tmp/tmpjq_CG8/2Xrw34AU6Z/pyshp-2.1.0+ds/shapefiles/test/dtype.dbf differ Binary files /tmp/tmpjq_CG8/UAyC3EPdtw/pyshp-2.0.1+ds/shapefiles/test/line.dbf and /tmp/tmpjq_CG8/2Xrw34AU6Z/pyshp-2.1.0+ds/shapefiles/test/line.dbf differ Binary files /tmp/tmpjq_CG8/UAyC3EPdtw/pyshp-2.0.1+ds/shapefiles/test/linem.dbf and /tmp/tmpjq_CG8/2Xrw34AU6Z/pyshp-2.1.0+ds/shapefiles/test/linem.dbf differ Binary files /tmp/tmpjq_CG8/UAyC3EPdtw/pyshp-2.0.1+ds/shapefiles/test/linez.dbf and /tmp/tmpjq_CG8/2Xrw34AU6Z/pyshp-2.1.0+ds/shapefiles/test/linez.dbf differ Binary files /tmp/tmpjq_CG8/UAyC3EPdtw/pyshp-2.0.1+ds/shapefiles/test/multipatch.dbf and /tmp/tmpjq_CG8/2Xrw34AU6Z/pyshp-2.1.0+ds/shapefiles/test/multipatch.dbf differ Binary files /tmp/tmpjq_CG8/UAyC3EPdtw/pyshp-2.0.1+ds/shapefiles/test/multipoint.dbf and /tmp/tmpjq_CG8/2Xrw34AU6Z/pyshp-2.1.0+ds/shapefiles/test/multipoint.dbf differ Binary files /tmp/tmpjq_CG8/UAyC3EPdtw/pyshp-2.0.1+ds/shapefiles/test/onlydbf.dbf and /tmp/tmpjq_CG8/2Xrw34AU6Z/pyshp-2.1.0+ds/shapefiles/test/onlydbf.dbf differ Binary files /tmp/tmpjq_CG8/UAyC3EPdtw/pyshp-2.0.1+ds/shapefiles/test/point.dbf and /tmp/tmpjq_CG8/2Xrw34AU6Z/pyshp-2.1.0+ds/shapefiles/test/point.dbf differ Binary files /tmp/tmpjq_CG8/UAyC3EPdtw/pyshp-2.0.1+ds/shapefiles/test/polygon.dbf and /tmp/tmpjq_CG8/2Xrw34AU6Z/pyshp-2.1.0+ds/shapefiles/test/polygon.dbf differ Binary files /tmp/tmpjq_CG8/UAyC3EPdtw/pyshp-2.0.1+ds/shapefiles/test/shapetype.dbf and /tmp/tmpjq_CG8/2Xrw34AU6Z/pyshp-2.1.0+ds/shapefiles/test/shapetype.dbf differ Binary files /tmp/tmpjq_CG8/UAyC3EPdtw/pyshp-2.0.1+ds/shapefiles/test/testfile.dbf and /tmp/tmpjq_CG8/2Xrw34AU6Z/pyshp-2.1.0+ds/shapefiles/test/testfile.dbf differ