This is an automated email from the git hooks/post-receive script. sebastic pushed a commit to branch master in repository python-shapely.
commit 5faff2115a2de564aab062462f6d084960365631 Author: Bas Couwenberg <sebas...@xs4all.nl> Date: Sun Oct 11 11:03:32 2015 +0200 Imported Upstream version 1.5.13 --- CHANGES.txt | 8 ++ setup.py | 2 +- shapely/__init__.py | 2 +- shapely/{libgeos.py => _buildcfg.py} | 73 +++++++++------- shapely/geometry/base.py | 4 +- shapely/geometry/polygon.py | 2 +- shapely/geos.py | 161 +++++++++++++++++++++++++++++++++-- tests/__init__.py | 4 +- tests/test_dlls.py | 6 +- tests/test_hash.py | 24 +++++- 10 files changed, 234 insertions(+), 52 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 3257c36..e353755 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,6 +1,14 @@ Changes ======= +1.5.13 (2015-10-09) +------------------- +- Restore setup and runtime discovery and loading of GEOS shared library to + state at version 1.5.9 (#326). +- On OS X we try to reuse any GEOS shared library that may have been loaded + via import of Fiona or Rasterio in order to avoid a bug involving the + GEOS AbstractSTRtree (#324, #327). + 1.5.12 (2015-08-27) ------------------- - Remove configuration of root logger from libgeos.py (#312). diff --git a/setup.py b/setup.py index 34d7969..abe841a 100755 --- a/setup.py +++ b/setup.py @@ -35,7 +35,7 @@ from distutils.version import StrictVersion as Version # Get geos_version from GEOS dynamic library, which depends on # GEOS_LIBRARY_PATH and/or GEOS_CONFIG environment variables -from shapely.libgeos import geos_version_string, geos_version, \ +from shapely._buildcfg import geos_version_string, geos_version, \ geos_config, get_geos_config logging.basicConfig() diff --git a/shapely/__init__.py b/shapely/__init__.py index da34e60..1d51ed9 100644 --- a/shapely/__init__.py +++ b/shapely/__init__.py @@ -1 +1 @@ -__version__ = "1.5.12" +__version__ = "1.5.13" diff --git a/shapely/libgeos.py b/shapely/_buildcfg.py similarity index 81% rename from shapely/libgeos.py rename to shapely/_buildcfg.py index e35a854..d692b9d 100644 --- a/shapely/libgeos.py +++ b/shapely/_buildcfg.py @@ -19,9 +19,14 @@ import subprocess import sys +# Add message handler to this module's logger log = logging.getLogger(__name__) +ch = logging.StreamHandler() +log.addHandler(ch) + if 'all' in sys.warnoptions: - log.level = logging.DEBUG + # show GEOS messages in console with: python -W all + log.setLevel(logging.DEBUG) # The main point of this module is to load a dynamic library to this variable @@ -124,23 +129,37 @@ if not lgeos and geos_config: # Platform-specific attempts, and build `free` object -def load_dll(libname, fallbacks=[]): - '''Load GEOS dynamic library''' +def load_dll(libname, fallbacks=None): lib = find_library(libname) + dll = None if lib is not None: try: - return CDLL(lib) - except OSError: - pass - for name in fallbacks: - try: - return CDLL(name) + log.debug("Trying `CDLL(%s)`", lib) + dll = CDLL(lib) except OSError: - # move on to the next fallback + log.warn("Failed `CDLL(%s)`", lib) pass - raise OSError( - "Could not find library %s or load any of its variants %s" % ( - libname, fallbacks)) + + if not dll and fallbacks is not None: + for name in fallbacks: + try: + log.debug("Trying `CDLL(%s)`", name) + dll = CDLL(name) + except OSError: + # move on to the next fallback + log.warn("Failed `CDLL(%s)`", name) + pass + + if dll: + log.debug("Library path: %r", lib or name) + log.debug("DLL: %r", dll) + return dll + else: + # No shared library was loaded. Raise OSError. + raise OSError( + "Could not find library {0} or load any of its variants {1}".format( + libname, fallbacks or [])) + if sys.platform.startswith('linux'): if not lgeos: @@ -152,24 +171,18 @@ if sys.platform.startswith('linux'): elif sys.platform == 'darwin': if not lgeos: - # First test to see if this is a delocated wheel with a GEOS dylib. - geos_whl_dylib = os.path.abspath(os.path.join( - os.path.dirname(__file__), '.dylibs/libgeos_c.1.dylib')) - if os.path.exists(geos_whl_dylib): - lgeos = CDLL(geos_whl_dylib) + if hasattr(sys, 'frozen'): + # .app file from py2app + alt_paths = [os.path.join(os.environ['RESOURCEPATH'], + '..', 'Frameworks', 'libgeos_c.dylib')] else: - if hasattr(sys, 'frozen'): - # .app file from py2app - alt_paths = [os.path.join(os.environ['RESOURCEPATH'], - '..', 'Frameworks', 'libgeos_c.dylib')] - else: - alt_paths = [ - # The Framework build from Kyng Chaos - "/Library/Frameworks/GEOS.framework/Versions/Current/GEOS", - # macports - '/opt/local/lib/libgeos_c.dylib', - ] - lgeos = load_dll('geos_c', fallbacks=alt_paths) + alt_paths = [ + # The Framework build from Kyng Chaos + "/Library/Frameworks/GEOS.framework/Versions/Current/GEOS", + # macports + '/opt/local/lib/libgeos_c.dylib', + ] + lgeos = load_dll('geos_c', fallbacks=alt_paths) free = load_dll('c', fallbacks=['/usr/lib/libc.dylib']).free free.argtypes = [c_void_p] diff --git a/shapely/geometry/base.py b/shapely/geometry/base.py index 6498e06..42d821f 100644 --- a/shapely/geometry/base.py +++ b/shapely/geometry/base.py @@ -270,7 +270,7 @@ class BaseGeometry(object): def __ne__(self, other): return not self.__eq__(other) - __hash__ = object.__hash__ + __hash__ = None # Array and ctypes interfaces # --------------------------- @@ -773,7 +773,7 @@ class BaseMultipartGeometry(BaseGeometry): def __ne__(self, other): return not self.__eq__(other) - __hash__ = object.__hash__ + __hash__ = None def svg(self, scale_factor=1., color=None): """Returns a group of SVG elements for the multipart geometry. diff --git a/shapely/geometry/polygon.py b/shapely/geometry/polygon.py index 7c7c0cb..945a108 100644 --- a/shapely/geometry/polygon.py +++ b/shapely/geometry/polygon.py @@ -264,7 +264,7 @@ class Polygon(BaseGeometry): def __ne__(self, other): return not self.__eq__(other) - __hash__ = object.__hash__ + __hash__ = None @property def ctypes(self): diff --git a/shapely/geos.py b/shapely/geos.py index c767d72..976173b 100644 --- a/shapely/geos.py +++ b/shapely/geos.py @@ -2,33 +2,178 @@ Proxies for libgeos, GEOS-specific exceptions, and utilities """ +import os import re import sys import atexit import logging import threading -from ctypes import CDLL, cdll, pointer, string_at, cast, POINTER +from ctypes import CDLL, cdll, pointer, string_at, cast, POINTER, DEFAULT_MODE from ctypes import c_void_p, c_size_t, c_char_p, c_int, c_float from ctypes.util import find_library from .ctypes_declarations import prototype, EXCEPTION_HANDLER_FUNCTYPE -from .libgeos import lgeos as _lgeos, geos_version from . import ftools # Add message handler to this module's logger LOG = logging.getLogger(__name__) +ch = logging.StreamHandler() +LOG.addHandler(ch) if 'all' in sys.warnoptions: # show GEOS messages in console with: python -W all - logging.basicConfig() -else: - # no handler messages shown - class NullHandler(logging.Handler): - def emit(self, record): + LOG.setLevel(logging.DEBUG) + + +# Find and load the GEOS and C libraries +# If this ever gets any longer, we'll break it into separate modules + +def load_dll(libname, fallbacks=None, mode=DEFAULT_MODE): + lib = find_library(libname) + dll = None + if lib is not None: + try: + LOG.debug("Trying `CDLL(%s)`", lib) + dll = CDLL(lib, mode=mode) + except OSError: + LOG.warn("Failed `CDLL(%s)`", lib) pass - LOG.addHandler(NullHandler()) + if not dll and fallbacks is not None: + for name in fallbacks: + try: + LOG.debug("Trying `CDLL(%s)`", name) + dll = CDLL(name, mode=mode) + except OSError: + # move on to the next fallback + LOG.warn("Failed `CDLL(%s)`", name) + pass + + if dll: + LOG.debug("Library path: %r", lib or name) + LOG.debug("DLL: %r", dll) + return dll + else: + # No shared library was loaded. Raise OSError. + raise OSError( + "Could not find lib {0} or load any of its variants {1}.".format( + libname, fallbacks or [])) + +_lgeos = None + +if sys.platform.startswith('linux'): + _lgeos = load_dll('geos_c', fallbacks=['libgeos_c.so.1', 'libgeos_c.so']) + free = load_dll('c').free + free.argtypes = [c_void_p] + free.restype = None + +elif sys.platform == 'darwin': + # First: have we already loaded GEOS through a Fiona or Rasterio? + # If so, let's obtain a handle to it instead of loading this module's + # copy to side step the mysterious issue described at + # https://github.com/Toblerity/Shapely/issues/324. + geos_mod = sys.modules.get('fiona') or sys.modules.get('rasterio') + if geos_mod: + dll_path = os.path.join( + os.path.dirname(geos_mod.__file__), '.dylibs', + 'libgeos_c.1.dylib') + try: + _lgeos = CDLL(dll_path, mode=(DEFAULT_MODE | 16)) + except OSError: + LOG.debug("GEOS DLL in fiona or rasterio .dylibs not found.") + alt_paths = [ + # The Framework build from Kyng Chaos + "/Library/Frameworks/GEOS.framework/Versions/Current/GEOS", + # macports + '/opt/local/lib/libgeos_c.dylib', + ] + _lgeos = load_dll('geos_c', fallbacks=alt_paths, + mode=(DEFAULT_MODE | 16)) + if _lgeos: + LOG.debug("Found %r already loaded, using it.", _lgeos) + + # If neither fiona nor rasterio have been imported, or if the block + # above failed to assign _lgeos, we will locate and load the GEOS + # DLL. + if not _lgeos: + # Test to see if we have a delocated wheel with a GEOS dylib. + geos_whl_dylib = os.path.abspath(os.path.join(os.path.dirname( + __file__), '.dylibs/libgeos_c.1.dylib')) + if os.path.exists(geos_whl_dylib): + _lgeos = CDLL(geos_whl_dylib) + LOG.debug("Found GEOS DLL: %r, using it.", _lgeos) + + else: + if hasattr(sys, 'frozen'): + try: + # .app file from py2app + alt_paths = [os.path.join(os.environ['RESOURCEPATH'], + '..', 'Frameworks', 'libgeos_c.dylib')] + except KeyError: + # binary from pyinstaller + alt_paths = [ + os.path.join(sys.executable, 'libgeos_c.dylib')] + else: + alt_paths = [ + # The Framework build from Kyng Chaos + "/Library/Frameworks/GEOS.framework/Versions/Current/GEOS", + # macports + '/opt/local/lib/libgeos_c.dylib', + ] + _lgeos = load_dll('geos_c', fallbacks=alt_paths) + + free = load_dll('c').free + free.argtypes = [c_void_p] + free.restype = None + +elif sys.platform == 'win32': + try: + egg_dlls = os.path.abspath(os.path.join(os.path.dirname(__file__), + "DLLs")) + wininst_dlls = os.path.abspath(os.__file__ + "../../../DLLs") + original_path = os.environ['PATH'] + os.environ['PATH'] = "%s;%s;%s" % \ + (egg_dlls, wininst_dlls, original_path) + _lgeos = CDLL("geos.dll") + except (ImportError, WindowsError, OSError): + raise + + def free(m): + try: + cdll.msvcrt.free(m) + except WindowsError: + # XXX: See http://trac.gispython.org/projects/PCL/ticket/149 + pass + +elif sys.platform == 'sunos5': + _lgeos = load_dll('geos_c', fallbacks=['libgeos_c.so.1', 'libgeos_c.so']) + free = CDLL('libc.so.1').free + free.argtypes = [c_void_p] + free.restype = None +else: # other *nix systems + _lgeos = load_dll('geos_c', fallbacks=['libgeos_c.so.1', 'libgeos_c.so']) + free = load_dll('c', fallbacks=['libc.so.6']).free + free.argtypes = [c_void_p] + free.restype = None + + +def _geos_version(): + # extern const char GEOS_DLL *GEOSversion(); + GEOSversion = _lgeos.GEOSversion + GEOSversion.restype = c_char_p + GEOSversion.argtypes = [] + #define GEOS_CAPI_VERSION "@VERSION@-CAPI-@CAPI_VERSION@" + geos_version_string = GEOSversion() + if sys.version_info[0] >= 3: + geos_version_string = geos_version_string.decode('ascii') + res = re.findall(r'(\d+)\.(\d+)\.(\d+)', geos_version_string) + assert len(res) == 2, res + geos_version = tuple(int(x) for x in res[0]) + capi_version = tuple(int(x) for x in res[1]) + return geos_version_string, geos_version, capi_version + +geos_version_string, geos_version, geos_capi_version = _geos_version() # If we have the new interface, then record a baseline so that we know what diff --git a/tests/__init__.py b/tests/__init__.py index cf0c6b2..396da18 100755 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,6 +1,6 @@ import sys -from shapely.libgeos import geos_version_string -from shapely.geos import lgeos, WKTWriter + +from shapely.geos import geos_version_string, lgeos, WKTWriter from shapely import speedups diff --git a/tests/test_dlls.py b/tests/test_dlls.py index 55db556..306e94f 100644 --- a/tests/test_dlls.py +++ b/tests/test_dlls.py @@ -1,8 +1,8 @@ -from . import unittest - -from shapely.libgeos import load_dll import sys +from . import unittest +from shapely.geos import load_dll + class LoadingTestCase(unittest.TestCase): diff --git a/tests/test_hash.py b/tests/test_hash.py index 97f5919..712974c 100644 --- a/tests/test_hash.py +++ b/tests/test_hash.py @@ -3,19 +3,35 @@ from shapely.geometry import Point, MultiPoint, Polygon, GeometryCollection def test_point(): g = Point(0, 0) - assert hash(g) + try: + assert hash(g) + return False + except TypeError: + return True def test_multipoint(): g = MultiPoint([(0, 0)]) - assert hash(g) + try: + assert hash(g) + return False + except TypeError: + return True def test_polygon(): g = Point(0, 0).buffer(1.0) - assert hash(g) + try: + assert hash(g) + return False + except TypeError: + return True def test_collection(): g = GeometryCollection([Point(0, 0)]) - assert hash(g) + try: + assert hash(g) + return False + except TypeError: + return True -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/python-shapely.git _______________________________________________ Pkg-grass-devel mailing list Pkg-grass-devel@lists.alioth.debian.org http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-grass-devel