Skip to content
Commits on Source (5)
Changes
=======
2.4.0 (2018-05-21)
------------------
- Additional functional maps for GeoJSON entities
- https://github.com/frewsxcv/python-geojson/pull/112
2.3.0 (2017-09-18)
------------------
......
......@@ -21,7 +21,7 @@ This library contains:
Installation
------------
python-geojson is compatible with Python 2.6, 2.7, 3.3, 3.4, 3.5 and 3.6. It is listed on `PyPi as 'geojson'`_. The recommended way to install is via pip_:
python-geojson is compatible with Python 2.7, 3.3, 3.4, 3.5 and 3.6. It is listed on `PyPi as 'geojson'`_. The recommended way to install is via pip_:
.. code::
......@@ -288,7 +288,7 @@ coords
map_coords
~~~~~~~~~~
:code:`geojson.utils.map_coords` maps a function over all coordinate tuples and returns a geometry of the same type. Useful for translating a geometry in space or flipping coordinate order.
:code:`geojson.utils.map_coords` maps a function over all coordinate values and returns a geometry of the same type. Useful for scaling a geometry.
.. code:: python
......@@ -299,6 +299,34 @@ map_coords
>>> geojson.dumps(new_point, sort_keys=True) # doctest: +ELLIPSIS
'{"coordinates": [-57.905..., 18.62...], "type": "Point"}'
map_tuples
~~~~~~~~~~
:code:`geojson.utils.map_tuples` maps a function over all coordinates and returns a geometry of the same type. Useful for changing coordinate order or applying coordinate transforms.
.. code:: python
>>> import geojson
>>> new_point = geojson.utils.map_tuples(lambda c: (c[1], c[0]), geojson.Point((-115.81, 37.24)))
>>> geojson.dumps(new_point, sort_keys=True) # doctest: +ELLIPSIS
'{"coordinates": [37.24..., -115.81], "type": "Point"}'
map_geometries
~~~~~~~~~~
:code:`geojson.utils.map_geometries` maps a function over each geometry in the input.
.. code:: python
>>> import geojson
>>> new_point = geojson.utils.map_geometries(lambda g: geojson.MultiPoint([g["coordinates"]]), geojson.GeometryCollection([geojson.Point((-115.81, 37.24))]))
>>> geojson.dumps(new_point, sort_keys=True)
'{"geometries": [{"coordinates": [[-115.81, 37.24]], "type": "MultiPoint"}], "type": "GeometryCollection"}'
validation
~~~~~~~~~~
......
python-geojson (2.3.0-2) UNRELEASED; urgency=medium
python-geojson (2.4.0-1) unstable; urgency=medium
* Team upload.
* New upstream release.
* Update copyright-format URL to use HTTPS.
* Update Vcs-* URLs for Salsa.
* Bump Standards-Version to 4.1.4, no changes.
* Drop ancient X-Python-Version field.
* Add module import tests to autopkgtest configuration.
-- Bas Couwenberg <sebastic@debian.org> Sun, 21 Jan 2018 10:36:19 +0100
-- Bas Couwenberg <sebastic@debian.org> Tue, 22 May 2018 07:43:13 +0200
python-geojson (2.3.0-1) unstable; urgency=medium
......
# Test installability
Depends: @
Test-Command: /bin/true
# Test module import (Python 2)
Depends: python-all, python-geojson
Test-Command: set -e ; for py in $(pyversions -r 2>/dev/null) ; do cd "$ADTTMP" ; echo "Testing with $py:" ; $py -c "import geojson; print(geojson)" ; done
# Test module import (Python 3)
Depends: python3-all, python3-geojson
Test-Command: set -e ; for py in $(py3versions -r 2>/dev/null) ; do cd "$ADTTMP" ; echo "Testing with $py:" ; $py -c "import geojson; print(geojson)" ; done
__version__ = "2.3.0"
__version__ = "2.4.0"
__version_info__ = tuple(map(int, __version__.split(".")))
......@@ -112,11 +112,6 @@ class GeoJSON(dict):
raise AttributeError(
"{0} is not a GeoJSON type").format(type_)
geojson_factory = getattr(geojson.factory, type_)
if not issubclass(geojson_factory, GeoJSON):
raise TypeError("""\
Not a valid GeoJSON type:
%r (geojson_factory: %r, cls: %r)
""" % (type_, geojson_factory, cls))
instance = geojson_factory(**d)
except (AttributeError, KeyError) as invalid:
if strict:
......@@ -144,7 +139,3 @@ class GeoJSON(dict):
# make sure that each subclass implements it's own validation function
if self.__class__ != GeoJSON:
raise NotImplementedError(self.__class__)
# check for errors on own dict (self)
results = {key: obj.errors() for (key, obj) in self.iteritems()}
return {key: err for (key, err) in results.iteritems() if err}
......@@ -30,6 +30,29 @@ def map_coords(func, obj):
Returns the mapped coordinates from a Geometry after applying the provided
function to each dimension in tuples list (ie, linear scaling).
:param func: Function to apply to individual coordinate values
independently
:type func: function
:param obj: A geometry or feature to extract the coordinates from.
:type obj: Point, LineString, MultiPoint, MultiLineString, Polygon,
MultiPolygon
:return: The result of applying the function to each dimension in the
array.
:rtype: list
:raises ValueError: if the provided object is not GeoJSON.
"""
def tuple_func(coord):
return (func(coord[0]), func(coord[1]))
return map_tuples(tuple_func, obj)
def map_tuples(func, obj):
"""
Returns the mapped coordinates from a Geometry after applying the provided
function to each coordinate.
:param func: Function to apply to tuples
:type func: function
:param obj: A geometry or feature to extract the coordinates from.
......@@ -38,27 +61,70 @@ def map_coords(func, obj):
:return: The result of applying the function to each dimension in the
array.
:rtype: list
:raises ValueError: if the provided object is not a Geometry.
:raises ValueError: if the provided object is not GeoJSON.
"""
if obj['type'] == 'Point':
coordinates = tuple(map(func, obj['coordinates']))
coordinates = tuple(func(obj['coordinates']))
elif obj['type'] in ['LineString', 'MultiPoint']:
coordinates = [tuple(map(func, c)) for c in obj['coordinates']]
coordinates = [tuple(func(c)) for c in obj['coordinates']]
elif obj['type'] in ['MultiLineString', 'Polygon']:
coordinates = [[
tuple(map(func, c)) for c in curve]
tuple(func(c)) for c in curve]
for curve in obj['coordinates']]
elif obj['type'] == 'MultiPolygon':
coordinates = [[[
tuple(map(func, c)) for c in curve]
tuple(func(c)) for c in curve]
for curve in part]
for part in obj['coordinates']]
elif obj['type'] in ['Feature', 'FeatureCollection', 'GeometryCollection']:
return map_geometries(lambda g: map_tuples(func, g), obj)
else:
raise ValueError("Invalid geometry object %s" % repr(obj))
return {'type': obj['type'], 'coordinates': coordinates}
def map_geometries(func, obj):
"""
Returns the result of passing every geometry in the given geojson object
through func.
:param func: Function to apply to tuples
:type func: function
:param obj: A geometry or feature to extract the coordinates from.
:type obj: GeoJSON
:return: The result of applying the function to each geometry
:rtype: list
:raises ValueError: if the provided object is not geojson.
"""
simple_types = [
'Point',
'LineString',
'MultiPoint',
'MultiLineString',
'Polygon',
'MultiPolygon',
]
if obj['type'] in simple_types:
return func(obj)
elif obj['type'] == 'GeometryCollection':
geoms = [func(geom) if geom else None for geom in obj['geometries']]
return {'type': obj['type'], 'geometries': geoms}
elif obj['type'] == 'Feature':
geom = func(obj['geometry']) if obj['geometry'] else None
return {
'type': obj['type'],
'geometry': geom,
'properties': obj['properties'],
}
elif obj['type'] == 'FeatureCollection':
feats = [map_geometries(func, feat) for feat in obj['features']]
return {'type': obj['type'], 'features': feats}
else:
raise ValueError("Invalid GeoJSON object %s" % repr(obj))
def generate_random(featureType, numberVertices=3,
boundingBox=[-180.0, -90.0, 180.0, 90.0]):
"""
......
......@@ -21,7 +21,7 @@ def test_suite():
import doctest
try:
import unittest2 as unittest
except:
except ImportError:
import unittest
suite = unittest.TestLoader().discover("tests")
......
......@@ -55,3 +55,21 @@ class OperatorOverloadingTestCase(unittest.TestCase):
def test_delattr(self):
del self.point.coordinates
self.assertFalse(hasattr(self.point, 'coordinates'))
class BaseTestCase(unittest.TestCase):
def test_to_instance(self):
FAKE = 'fake'
self.assertEquals(FAKE, geojson.GeoJSON.to_instance(
None, (lambda: FAKE)))
with self.assertRaises(ValueError):
geojson.GeoJSON.to_instance({"type": "Not GeoJSON"}, strict=True)
def test_errors(self):
class Fake(geojson.GeoJSON):
pass
with self.assertRaises(NotImplementedError):
Fake().errors()
......@@ -140,3 +140,8 @@ class EncodingDecodingTest(unittest.TestCase):
def test_mapping(self):
self.assertEquals(to_mapping(geojson.Point([1, 2])),
{"coordinates": [1, 2], "type": "Point"})
def test_GeoJSON(self):
self.assertEquals(None, geojson.GeoJSON().__geo_interface__)
self.assertEquals({"type": "GeoJSON"}, to_mapping(geojson.GeoJSON()))