[Git][debian-gis-team/python-rtree][master] 5 commits: New upstream version 0.9.4
Bas Couwenberg
gitlab at salsa.debian.org
Wed Feb 12 11:15:05 GMT 2020
Bas Couwenberg pushed to branch master at Debian GIS Project / python-rtree
Commits:
7b189e4d by Bas Couwenberg at 2020-02-12T05:51:20+01:00
New upstream version 0.9.4
- - - - -
d5c86f77 by Bas Couwenberg at 2020-02-12T05:51:21+01:00
Update upstream source from tag 'upstream/0.9.4'
Update to upstream version '0.9.4'
with Debian dir eaf4afdafdf184d3ddf63122606cc2b2f4db1485
- - - - -
060473e7 by Bas Couwenberg at 2020-02-12T05:51:33+01:00
New upstream release.
- - - - -
f04fa0d8 by Bas Couwenberg at 2020-02-12T06:03:29+01:00
Update Source, Comment & Files-Excluded for GitHub releases.
- - - - -
d5e53e07 by Bas Couwenberg at 2020-02-12T06:03:29+01:00
Set distribution to unstable.
- - - - -
14 changed files:
- .travis.yml
- README.md
- ci/azp/conda.yml
- ci/azp/docker.yml
- ci/azp/linux-1604-pip.yml
- ci/azp/linux-1804-pip.yml
- ci/azp/osx.yml
- ci/azp/win.yml
- debian/changelog
- debian/copyright
- rtree/__init__.py
- rtree/core.py
- rtree/index.py
- tests/test_index.py
Changes:
=====================================
.travis.yml
=====================================
@@ -19,7 +19,9 @@ addons:
- libspatialindex-c3
install:
+ - pip install flake8
- pip install -e .
script:
+ - flake8 --ignore=E501 --exclude=rtree/__init__.py rtree/
- python -m pytest --doctest-modules rtree tests/test_*
=====================================
README.md
=====================================
@@ -2,6 +2,7 @@ Rtree
=====
[](https://travis-ci.org/Toblerity/rtree)
+[](https://badge.fury.io/py/Rtree)
Python bindings for libspatialindex 1.8.3.
=====================================
ci/azp/conda.yml
=====================================
@@ -27,11 +27,12 @@ jobs:
- bash: |
source activate rtree
- conda install --yes --quiet --name rtree python=$PYTHON_VERSION libspatialindex=$SIDX_VERSION
+ conda install --yes --quiet --name rtree -c conda-forge python=$PYTHON_VERSION libspatialindex=$SIDX_VERSION
displayName: Install Anaconda packages
- bash: |
source activate rtree
- pip install pytest numpy
+ pip install flake8 pytest numpy
+ flake8 --ignore=E501 --exclude=rtree/__init__.py rtree/
python -m pytest --doctest-modules rtree tests/test_*
- displayName: pytest
+ displayName: Lint with Flake8 and run unit tests
=====================================
ci/azp/docker.yml
=====================================
@@ -36,6 +36,7 @@ jobs:
sudo update-locale LANG=en_US.UTF-8
export LANG="en_US.UTF-8"
export LC_ALL="en_US.UTF-8"
- pip install pytest numpy
+ pip install flake8 pytest numpy
+ flake8 --ignore=E501 --exclude=rtree/__init__.py rtree/
python -m pytest --doctest-modules rtree tests/test_*
- displayName: 'Run pytest'
+ displayName: Lint with Flake8 and run unit tests
=====================================
ci/azp/linux-1604-pip.yml
=====================================
@@ -14,6 +14,7 @@ jobs:
displayName: pip install
- bash: |
- pip3 install pytest numpy
+ pip3 install flake8 pytest numpy
+ flake8 --ignore=E501 --exclude=rtree/__init__.py rtree/
python3 -m pytest --doctest-modules rtree tests/test_*
- displayName: pytest
+ displayName: Lint with Flake8 and run unit tests
=====================================
ci/azp/linux-1804-pip.yml
=====================================
@@ -14,6 +14,7 @@ jobs:
displayName: pip install
- bash: |
- pip3 install pytest numpy
+ pip3 install flake8 pytest numpy
+ flake8 --ignore=E501 --exclude=rtree/__init__.py rtree/
python3 -m pytest --doctest-modules rtree tests/test_*
- displayName: pytest
+ displayName: Lint with Flake8 and run unit tests
=====================================
ci/azp/osx.yml
=====================================
@@ -40,11 +40,12 @@ jobs:
- bash: |
source activate rtree
- conda install --yes --quiet --name rtree python=$PYTHON_VERSION libspatialindex=$SIDX_VERSION
+ conda install --yes --quiet --name rtree -c conda-forge python=$PYTHON_VERSION libspatialindex=$SIDX_VERSION
displayName: Install Anaconda packages
- bash: |
source activate rtree
- pip install pytest numpy
+ pip install flake8 pytest numpy
+ flake8 --ignore=E501 --exclude=rtree/__init__.py rtree/
python -m pytest --doctest-modules rtree tests/test_*
- displayName: pytest
+ displayName: Lint with Flake8 and run unit tests
=====================================
ci/azp/win.yml
=====================================
@@ -29,11 +29,12 @@ jobs:
- script: |
call activate rtree
- conda install --yes --quiet --name rtree python=%PYTHON_VERSION% libspatialindex=%SIDX_VERSION%
+ conda install --yes --quiet --name rtree -c conda-forge python=%PYTHON_VERSION% libspatialindex=%SIDX_VERSION%
displayName: Install Anaconda packages
- script: |
call activate rtree
- pip install pytest numpy
+ pip install flake8 pytest numpy
+ flake8 --ignore=E501 --exclude=rtree/__init__.py rtree/
python -m pytest --doctest-modules rtree tests
- displayName: pytest
+ displayName: Lint with Flake8 and run unit tests
=====================================
debian/changelog
=====================================
@@ -1,8 +1,10 @@
-python-rtree (0.9.3-2) UNRELEASED; urgency=medium
+python-rtree (0.9.4-1) unstable; urgency=medium
+ * New upstream release.
* Bump Standards-Version to 4.5.0, no changes.
+ * Update Source, Comment & Files-Excluded for GitHub releases.
- -- Bas Couwenberg <sebastic at debian.org> Sat, 25 Jan 2020 11:09:37 +0100
+ -- Bas Couwenberg <sebastic at debian.org> Wed, 12 Feb 2020 05:52:09 +0100
python-rtree (0.9.3-1) unstable; urgency=medium
=====================================
debian/copyright
=====================================
@@ -1,12 +1,7 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: Rtree
Upstream-Contact: Howard Butler <hobu.inc at gmail.com>
-Source: http://pypi.debian.net/rtree/
-Comment: The upstream sources are repacked to excluded the Rtree.egg-info
- directory that is automatically removed by dh_clean.
-Files-Excluded: Rtree.egg-info/*
- docs/build/*
- tests/*.pyc
+Source: https://github.com/Toblerity/rtree
Files: *
Copyright: 2011, Howard Butler, Brent Pedersen, Sean Gilles, and others.
=====================================
rtree/__init__.py
=====================================
@@ -2,4 +2,4 @@ from .index import Rtree
from .core import rt
-__version__ = '0.9.3'
+__version__ = '0.9.4'
=====================================
rtree/core.py
=====================================
@@ -107,8 +107,6 @@ if os.name == 'nt':
os.environ['PATH'] = oldenv
return None
-
-
base_name = 'spatialindex_c'
if '64' in platform.architecture()[0]:
arch = '64'
@@ -328,23 +326,25 @@ try:
rt.Index_Flush.restype = None
rt.Index_Flush.errcheck = check_void_done
- rt.Index_Contains_obj.argtypes = [ctypes.c_void_p,
- ctypes.POINTER(ctypes.c_double),
- ctypes.POINTER(ctypes.c_double),
- ctypes.c_uint32,
- ctypes.POINTER(
- ctypes.POINTER(ctypes.c_void_p)),
- ctypes.POINTER(ctypes.c_uint64)]
+ rt.Index_Contains_obj.argtypes = [
+ ctypes.c_void_p,
+ ctypes.POINTER(ctypes.c_double),
+ ctypes.POINTER(ctypes.c_double),
+ ctypes.c_uint32,
+ ctypes.POINTER(ctypes.POINTER(ctypes.c_void_p)),
+ ctypes.POINTER(ctypes.c_uint64)
+ ]
rt.Index_Contains_obj.restype = ctypes.c_int
rt.Index_Contains_obj.errcheck = check_return
- rt.Index_Contains_id.argtypes = [ctypes.c_void_p,
- ctypes.POINTER(ctypes.c_double),
- ctypes.POINTER(ctypes.c_double),
- ctypes.c_uint32,
- ctypes.POINTER(
- ctypes.POINTER(ctypes.c_int64)),
- ctypes.POINTER(ctypes.c_uint64)]
+ rt.Index_Contains_id.argtypes = [
+ ctypes.c_void_p,
+ ctypes.POINTER(ctypes.c_double),
+ ctypes.POINTER(ctypes.c_double),
+ ctypes.c_uint32,
+ ctypes.POINTER(ctypes.POINTER(ctypes.c_int64)),
+ ctypes.POINTER(ctypes.c_uint64)
+ ]
rt.Index_Contains_id.restype = ctypes.c_int
rt.Index_Contains_id.errcheck = check_return
=====================================
rtree/index.py
=====================================
@@ -5,24 +5,8 @@ import pprint
from . import core
-try:
- import cPickle as pickle
-except ImportError:
- import pickle
+import pickle
-import sys
-if sys.version_info[0] == 2:
- range = xrange
- string_types = basestring
-elif sys.version_info[0] == 3:
- string_types = str
-
-
-def string_output(s):
- if sys.version_info[0] == 2:
- return s
- elif sys.version_info[0] == 3:
- return s.decode('UTF-8')
RT_Memory = 0
RT_Disk = 1
@@ -61,10 +45,12 @@ def _get_bounds(handle, bounds_fn, interleaved):
if (dimension.value == 0):
return None
- mins = ctypes.cast(pp_mins, ctypes.POINTER(ctypes.c_double
- * dimension.value))
- maxs = ctypes.cast(pp_maxs, ctypes.POINTER(ctypes.c_double
- * dimension.value))
+ mins = ctypes.cast(
+ pp_mins, ctypes.POINTER(ctypes.c_double * dimension.value)
+ )
+ maxs = ctypes.cast(
+ pp_maxs, ctypes.POINTER(ctypes.c_double * dimension.value)
+ )
results = [mins.contents[i] for i in range(dimension.value)]
results += [maxs.contents[i] for i in range(dimension.value)]
@@ -94,7 +80,7 @@ def _get_data(handle):
class Index(object):
"""An R-Tree, MVR-Tree, or TPR-Tree indexing object"""
- def __init__(self, *args, **kwargs):
+ def __init__(self, *args, **kwargs):
"""Creates a new index
:param filename:
@@ -161,7 +147,7 @@ class Index(object):
>>> idx = index.Index(properties=p)
>>> idx # doctest: +ELLIPSIS
- <rtree.index.Index object at 0x...>
+ rtree.index.Index(bounds=[1.7976931348623157e+308, 1.7976931348623157e+308, -1.7976931348623157e+308, -1.7976931348623157e+308], size=0)
Insert an item into the index::
@@ -220,7 +206,7 @@ class Index(object):
basename = None
storage = None
if args:
- if isinstance(args[0], string_types) or isinstance(args[0], bytes):
+ if isinstance(args[0], str) or isinstance(args[0], bytes):
# they sent in a filename
basename = args[0]
# they sent in a filename, stream
@@ -283,7 +269,6 @@ class Index(object):
else:
self.properties.storage = RT_Memory
-
ps = kwargs.get('pagesize', None)
if ps:
self.properties.pagesize = int(ps)
@@ -299,6 +284,15 @@ class Index(object):
for item in stream:
self.insert(*item)
+ def get_size(self):
+ try:
+ return self.count(self.bounds)
+ except core.RTreeError:
+ return 0
+
+ def __repr__(self):
+ return 'rtree.index.Index(bounds={}, size={})'.format(self.bounds, self.get_size())
+
def __getstate__(self):
state = self.__dict__.copy()
del state["handle"]
@@ -386,7 +380,6 @@ class Index(object):
# return serialized to keep it alive for the pointer.
return size, ctypes.cast(p, ctypes.POINTER(ctypes.c_uint8)), serialized
-
def set_result_limit(self, value):
return core.rt.Index_SetResultSetOffset(self.handle, value)
@@ -463,7 +456,7 @@ class Index(object):
p_mins, p_maxs = self.get_coordinate_pointers(coordinates)
pv_mins, pv_maxs = self.get_coordinate_pointers(velocities)
# End time isn't used
- t_start, t_end = self._get_time_doubles((time, time+1))
+ t_start, t_end = self._get_time_doubles((time, time + 1))
data = ctypes.c_ubyte(0)
size = 0
if obj is not None:
@@ -529,7 +522,6 @@ class Index(object):
return p_num_results.value
-
def _countTP(self, coordinates, velocities, times):
p_mins, p_maxs = self.get_coordinate_pointers(coordinates)
pv_mins, pv_maxs = self.get_coordinate_pointers(velocities)
@@ -777,7 +769,7 @@ class Index(object):
yield self.loads(data)
core.rt.Index_DestroyObjResults(its, num_results)
- except: # need to catch all exceptions, not just rtree.
+ except Exception: # need to catch all exceptions, not just rtree.
core.rt.Index_DestroyObjResults(its, num_results)
raise
@@ -790,7 +782,7 @@ class Index(object):
for i in range(num_results):
yield items.contents[i]
core.rt.Index_Free(its)
- except:
+ except Exception:
core.rt.Index_Free(its)
raise
@@ -854,6 +846,12 @@ class Index(object):
return self._nearest_obj(coordinates, num_results, objects)
p_mins, p_maxs = self.get_coordinate_pointers(coordinates)
+ # p_num_results is an input and output for C++ lib
+ # as an input it says "get n closest neighbors"
+ # but if multiple neighbors are at the same distance, both will be returned
+ # so the number of returned neighbors may be > p_num_results
+ # thus p_num_results.contents.value gets set as an output by the C++ lib
+ # to indicate the actual number of results for _get_ids to use
p_num_results = ctypes.pointer(ctypes.c_uint64(num_results))
it = ctypes.pointer(ctypes.c_int64())
@@ -865,10 +863,9 @@ class Index(object):
ctypes.byref(it),
p_num_results)
- return self._get_ids(it, min(num_results,p_num_results.contents.value))
+ return self._get_ids(it, p_num_results.contents.value)
- def _nearestTP(self, coordinates, velocities, times, num_results=1,
- objects=False):
+ def _nearestTP(self, coordinates, velocities, times, num_results=1, objects=False):
p_mins, p_maxs = self.get_coordinate_pointers(coordinates)
pv_mins, pv_maxs = self.get_coordinate_pointers(velocities)
t_start, t_end = self._get_time_doubles(times)
@@ -907,13 +904,17 @@ class Index(object):
bounds = property(get_bounds)
def delete(self, id, coordinates):
- """Deletes items from the index with the given ``'id'`` within the
- specified coordinates.
+ """Deletes an item from the index with the given ``'id'`` and
+ coordinates given by the ``coordinates`` sequence. As the index can
+ contain multiple items with the same ID and coordinates, deletion
+ is not guaranteed to delete all items in the index with the given ID
+ and coordinates.
:param id: long integer
- A long integer that is the identifier for this index entry. IDs
- need not be unique to be inserted into the index, and it is up
- to the user to ensure they are unique if this is a requirement.
+ A long integer ID for the entry, which need not be unique. The
+ index can contain multiple entries with identical IDs and
+ coordinates. Uniqueness of items should be enforced at the
+ application level by the user.
:param coordinates: sequence or array
Dimension * 2 coordinate pairs, representing the min
@@ -1045,8 +1046,8 @@ class Index(object):
# this code assumes the coords are not interleaved.
# xmin, xmax, ymin, ymax, zmin, zmax
for i in range(dimension):
- mins[i] = coordinates[i*2]
- maxs[i] = coordinates[(i*2)+1]
+ mins[i] = coordinates[i * 2]
+ maxs[i] = coordinates[(i * 2) + 1]
p_mins[0] = ctypes.cast(mins, ctypes.POINTER(ctypes.c_double))
p_maxs[0] = ctypes.cast(maxs, ctypes.POINTER(ctypes.c_double))
@@ -1140,6 +1141,7 @@ class Index(object):
return output
+
# An alias to preserve backward compatibility
Rtree = Index
@@ -1204,8 +1206,8 @@ class Handle(object):
try:
if self._ptr is not None:
- self._destroy(self._ptr)
- self._ptr = None
+ self._destroy(self._ptr)
+ self._ptr = None
except AttributeError:
pass
@@ -1235,10 +1237,11 @@ class IndexHandle(Handle):
try:
core.rt.Index_Flush
if self._ptr is not None:
- core.rt.Index_Flush(self._ptr)
+ core.rt.Index_Flush(self._ptr)
except AttributeError:
pass
+
class IndexStreamHandle(IndexHandle):
_create = core.rt.Index_CreateWithStream
@@ -1515,11 +1518,10 @@ class Property(object):
"""Reinsert factor"""
def get_filename(self):
- s = core.rt.IndexProperty_GetFileName(self.handle)
- return string_output(s)
+ return core.rt.IndexProperty_GetFileName(self.handle).decode()
def set_filename(self, value):
- if isinstance(value, string_types):
+ if isinstance(value, str):
value = value.encode('utf-8')
return core.rt.IndexProperty_SetFileName(self.handle, value)
@@ -1527,11 +1529,10 @@ class Property(object):
"""Index filename for disk storage"""
def get_dat_extension(self):
- s = core.rt.IndexProperty_GetFileNameExtensionDat(self.handle)
- return string_output(s)
+ return core.rt.IndexProperty_GetFileNameExtensionDat(self.handle).decode()
def set_dat_extension(self, value):
- if isinstance(value, string_types):
+ if isinstance(value, str):
value = value.encode('utf-8')
return core.rt.IndexProperty_SetFileNameExtensionDat(
self.handle, value)
@@ -1540,11 +1541,10 @@ class Property(object):
"""Extension for .dat file"""
def get_idx_extension(self):
- s = core.rt.IndexProperty_GetFileNameExtensionIdx(self.handle)
- return string_output(s)
+ return core.rt.IndexProperty_GetFileNameExtensionIdx(self.handle).decode()
def set_idx_extension(self, value):
- if isinstance(value, string_types):
+ if isinstance(value, str):
value = value.encode('utf-8')
return core.rt.IndexProperty_SetFileNameExtensionIdx(
self.handle, value)
@@ -1836,7 +1836,7 @@ class RtreeContainer(Rtree):
>>> idx = index.RtreeContainer(properties=p)
>>> idx # doctest: +ELLIPSIS
- <rtree.index.RtreeContainer object at 0x...>
+ rtree.index.RtreeContainer(bounds=[1.7976931348623157e+308, 1.7976931348623157e+308, -1.7976931348623157e+308, -1.7976931348623157e+308], size=0)
Insert an item into the index::
@@ -1854,7 +1854,7 @@ class RtreeContainer(Rtree):
[34.37768294..., 26.73758537..., 49.37768294..., 41.73758537...]
"""
if args:
- if isinstance(args[0], string_types) \
+ if isinstance(args[0], str) \
or isinstance(args[0], bytes) \
or isinstance(args[0], ICustomStorage):
raise ValueError('%s supports only in-memory indexes'
@@ -1862,6 +1862,15 @@ class RtreeContainer(Rtree):
self._objects = {}
return super(RtreeContainer, self).__init__(*args, **kwargs)
+ def get_size(self):
+ try:
+ return self.count(self.bounds)
+ except core.RTreeError:
+ return 0
+
+ def __repr__(self):
+ return 'rtree.index.RtreeContainer(bounds={}, size={})'.format(self.bounds, self.get_size())
+
def __contains__(self, obj):
return id(obj) in self._objects
@@ -1974,11 +1983,11 @@ class RtreeContainer(Rtree):
49.3776829412, 41.7375853734])]
"""
- if bbox == False:
+ if bbox is False:
for id in super(RtreeContainer,
self).intersection(coordinates, bbox):
yield self._objects[id][1]
- elif bbox == True:
+ elif bbox is True:
for value in super(RtreeContainer,
self).intersection(coordinates, bbox):
value.object = self._objects[value.id][1]
@@ -1988,7 +1997,7 @@ class RtreeContainer(Rtree):
raise ValueError(
"valid values for the bbox argument are True and False")
- def nearest(self, coordinates, num_results = 1, bbox=False):
+ def nearest(self, coordinates, num_results=1, bbox=False):
"""Returns the ``k``-nearest objects to the given coordinates
in increasing distance order.
@@ -2022,11 +2031,11 @@ class RtreeContainer(Rtree):
>>> idx.insert(object(), (34.37, 26.73, 49.37, 41.73))
>>> hits = idx.nearest((0, 0, 10, 10), 3, bbox=True)
"""
- if bbox == False:
+ if bbox is False:
for id in super(RtreeContainer,
self).nearest(coordinates, num_results, bbox):
yield self._objects[id][1]
- elif bbox == True:
+ elif bbox is True:
for value in super(RtreeContainer,
self).nearest(coordinates, num_results, bbox):
value.object = self._objects[value.id][1]
=====================================
tests/test_index.py
=====================================
@@ -340,6 +340,38 @@ class IndexNearest(IndexTestCase):
idx.add(i, (start, 1, stop, 1))
hits = sorted(idx.nearest((13, 0, 20, 2), 3))
self.assertEqual(hits, [3, 4, 5])
+
+ def test_nearest_equidistant(self):
+ """Test that if records are equidistant, both are returned."""
+ point = (0, 0)
+ small_box = (-10, -10, 10, 10)
+ large_box = (-50, -50, 50, 50)
+
+ idx = index.Index()
+ idx.insert(0, small_box)
+ idx.insert(1, large_box)
+ self.assertEqual(list(idx.nearest(point, 2)), [0, 1])
+ self.assertEqual(list(idx.nearest(point, 1)), [0, 1])
+
+ idx.insert(2, (0, 0))
+ self.assertEqual(list(idx.nearest(point, 2)), [0, 1, 2])
+ self.assertEqual(list(idx.nearest(point, 1)), [0, 1, 2])
+
+ idx = index.Index()
+ idx.insert(0, small_box)
+ idx.insert(1, large_box)
+ idx.insert(2, (50, 50)) # point on top right vertex of large_box
+ point = (51, 51) # right outside of large_box
+ self.assertEqual(list(idx.nearest(point, 2)), [1, 2])
+ self.assertEqual(list(idx.nearest(point, 1)), [1, 2])
+
+ idx = index.Index()
+ idx.insert(0, small_box)
+ idx.insert(1, large_box)
+ idx.insert(2, (51, 51)) # point right outside on top right vertex of large_box
+ point = (51, 52) # shifted 1 unit up from the point above
+ self.assertEqual(list(idx.nearest(point, 2)), [2, 1])
+ self.assertEqual(list(idx.nearest(point, 1)), [2])
def test_nearest_object(self):
View it on GitLab: https://salsa.debian.org/debian-gis-team/python-rtree/compare/6a17f875b2ae3d849b162736bb3fce3de885597c...d5e53e0774299c15cd75d15bda12fa4724357480
--
View it on GitLab: https://salsa.debian.org/debian-gis-team/python-rtree/compare/6a17f875b2ae3d849b162736bb3fce3de885597c...d5e53e0774299c15cd75d15bda12fa4724357480
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20200212/80411372/attachment-0001.html>
More information about the Pkg-grass-devel
mailing list