Fixed #27830 -- Used distutils.version.LooseVersion for version parsing.
This commit is contained in:
parent
e7dc39fb65
commit
08bda82c23
|
@ -11,6 +11,7 @@ from django.core.exceptions import ImproperlyConfigured
|
|||
from django.db.backends.postgresql.operations import DatabaseOperations
|
||||
from django.db.utils import ProgrammingError
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.version import get_version_tuple
|
||||
|
||||
from .adapter import PostGISAdapter
|
||||
from .models import PostGISGeometryColumns, PostGISSpatialRefSys
|
||||
|
@ -109,7 +110,6 @@ class PostGISOperations(BaseSpatialOperations, DatabaseOperations):
|
|||
postgis = True
|
||||
geography = True
|
||||
geom_func_prefix = 'ST_'
|
||||
version_regex = re.compile(r'^(?P<major>\d)\.(?P<minor1>\d)\.(?P<minor2>\d+)')
|
||||
|
||||
Adapter = PostGISAdapter
|
||||
|
||||
|
@ -353,18 +353,8 @@ class PostGISOperations(BaseSpatialOperations, DatabaseOperations):
|
|||
Return the PostGIS version as a tuple (version string, major,
|
||||
minor, subminor).
|
||||
"""
|
||||
# Getting the PostGIS version
|
||||
version = self.postgis_lib_version()
|
||||
m = self.version_regex.match(version)
|
||||
|
||||
if m:
|
||||
major = int(m.group('major'))
|
||||
minor1 = int(m.group('minor1'))
|
||||
minor2 = int(m.group('minor2'))
|
||||
else:
|
||||
raise Exception('Could not parse PostGIS version string: %s' % version)
|
||||
|
||||
return (version, major, minor1, minor2)
|
||||
return (version,) + get_version_tuple(version)
|
||||
|
||||
def proj_version_tuple(self):
|
||||
"""
|
||||
|
|
|
@ -3,8 +3,6 @@ SQL functions reference lists:
|
|||
https://web.archive.org/web/20130407175746/https://www.gaia-gis.it/gaia-sins/spatialite-sql-4.0.0.html
|
||||
https://www.gaia-gis.it/gaia-sins/spatialite-sql-4.2.1.html
|
||||
"""
|
||||
import re
|
||||
|
||||
from django.contrib.gis.db.backends.base.operations import (
|
||||
BaseSpatialOperations,
|
||||
)
|
||||
|
@ -16,6 +14,7 @@ from django.contrib.gis.measure import Distance
|
|||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.db.backends.sqlite3.operations import DatabaseOperations
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.version import get_version_tuple
|
||||
|
||||
|
||||
class SpatiaLiteDistanceOperator(SpatialOperator):
|
||||
|
@ -35,7 +34,6 @@ class SpatiaLiteDistanceOperator(SpatialOperator):
|
|||
class SpatiaLiteOperations(BaseSpatialOperations, DatabaseOperations):
|
||||
name = 'spatialite'
|
||||
spatialite = True
|
||||
version_regex = re.compile(r'^(?P<major>\d)\.(?P<minor1>\d)\.(?P<minor2>\d+)')
|
||||
|
||||
Adapter = SpatiaLiteAdapter
|
||||
|
||||
|
@ -189,16 +187,7 @@ class SpatiaLiteOperations(BaseSpatialOperations, DatabaseOperations):
|
|||
minor, subminor).
|
||||
"""
|
||||
version = self.spatialite_version()
|
||||
|
||||
m = self.version_regex.match(version)
|
||||
if m:
|
||||
major = int(m.group('major'))
|
||||
minor1 = int(m.group('minor1'))
|
||||
minor2 = int(m.group('minor2'))
|
||||
else:
|
||||
raise Exception('Could not parse SpatiaLite version string: %s' % version)
|
||||
|
||||
return (version, major, minor1, minor2)
|
||||
return (version,) + get_version_tuple(version)
|
||||
|
||||
def spatial_aggregate_name(self, agg_name):
|
||||
"""
|
||||
|
|
|
@ -8,7 +8,7 @@ from ctypes import byref, c_int, c_uint
|
|||
from django.contrib.gis.geos import prototypes as capi
|
||||
from django.contrib.gis.geos.error import GEOSException
|
||||
from django.contrib.gis.geos.geometry import GEOSGeometry, LinearGeometryMixin
|
||||
from django.contrib.gis.geos.libgeos import geos_version_info, get_pointer_arr
|
||||
from django.contrib.gis.geos.libgeos import geos_version_tuple, get_pointer_arr
|
||||
from django.contrib.gis.geos.linestring import LinearRing, LineString
|
||||
from django.contrib.gis.geos.point import Point
|
||||
from django.contrib.gis.geos.polygon import Polygon
|
||||
|
@ -115,7 +115,7 @@ class MultiLineString(LinearGeometryMixin, GeometryCollection):
|
|||
|
||||
@property
|
||||
def closed(self):
|
||||
if geos_version_info()['version'] < '3.5':
|
||||
if geos_version_tuple() < (3, 5):
|
||||
raise GEOSException("MultiLineString.closed requires GEOS >= 3.5.0.")
|
||||
return super().closed
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ from ctypes.util import find_library
|
|||
from django.contrib.gis.geos.error import GEOSException
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.utils.functional import SimpleLazyObject
|
||||
from django.utils.version import get_version_tuple
|
||||
|
||||
logger = logging.getLogger('django.contrib.gis')
|
||||
|
||||
|
@ -199,3 +200,8 @@ def geos_version_info():
|
|||
raise GEOSException('Could not parse version info string "%s"' % ver)
|
||||
return {key: m.group(key) for key in (
|
||||
'version', 'release_candidate', 'capi_version', 'major', 'minor', 'subminor')}
|
||||
|
||||
|
||||
def geos_version_tuple():
|
||||
"""Return the GEOS version as a tuple (major, minor, subminor)."""
|
||||
return get_version_tuple(geos_version_info()['version'])
|
||||
|
|
|
@ -14,6 +14,7 @@ from django.db.backends.base.base import BaseDatabaseWrapper
|
|||
from django.db.utils import DatabaseError as WrappedDatabaseError
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.safestring import SafeText
|
||||
from django.utils.version import get_version_tuple
|
||||
|
||||
try:
|
||||
import psycopg2 as Database
|
||||
|
@ -25,7 +26,7 @@ except ImportError as e:
|
|||
|
||||
def psycopg2_version():
|
||||
version = psycopg2.__version__.split(' ', 1)[0]
|
||||
return tuple(int(v) for v in version.split('.') if v.isdigit())
|
||||
return get_version_tuple(version)
|
||||
|
||||
|
||||
PSYCOPG2_VERSION = psycopg2_version()
|
||||
|
|
|
@ -2,6 +2,7 @@ import datetime
|
|||
import functools
|
||||
import os
|
||||
import subprocess
|
||||
from distutils.version import LooseVersion
|
||||
|
||||
|
||||
def get_version(version=None):
|
||||
|
@ -77,3 +78,17 @@ def get_git_changeset():
|
|||
except ValueError:
|
||||
return None
|
||||
return timestamp.strftime('%Y%m%d%H%M%S')
|
||||
|
||||
|
||||
def get_version_tuple(version):
|
||||
"""
|
||||
Return a tuple of version numbers (e.g. (1, 2, 3)) from the version
|
||||
string (e.g. '1.2.3').
|
||||
"""
|
||||
loose_version = LooseVersion(version)
|
||||
version_numbers = []
|
||||
for item in loose_version.version:
|
||||
if not isinstance(item, int):
|
||||
break
|
||||
version_numbers.append(item)
|
||||
return tuple(version_numbers)
|
||||
|
|
|
@ -323,13 +323,12 @@ class PostgreSQLTests(TestCase):
|
|||
|
||||
def test_correct_extraction_psycopg2_version(self):
|
||||
from django.db.backends.postgresql.base import psycopg2_version
|
||||
version_path = 'django.db.backends.postgresql.base.Database.__version__'
|
||||
|
||||
with mock.patch(version_path, '2.6.9'):
|
||||
self.assertEqual(psycopg2_version(), (2, 6, 9))
|
||||
with mock.patch('psycopg2.__version__', '4.2.1 (dt dec pq3 ext lo64)'):
|
||||
self.assertEqual(psycopg2_version(), (4, 2, 1))
|
||||
|
||||
with mock.patch(version_path, '2.5.dev0'):
|
||||
self.assertEqual(psycopg2_version(), (2, 5))
|
||||
with mock.patch('psycopg2.__version__', '4.2b0.dev1 (dt dec pq3 ext lo64)'):
|
||||
self.assertEqual(psycopg2_version(), (4, 2))
|
||||
|
||||
|
||||
class DateQuotingTest(TestCase):
|
||||
|
|
|
@ -12,7 +12,7 @@ from django.contrib.gis.geos import (
|
|||
MultiLineString, MultiPoint, MultiPolygon, Point, Polygon, fromfile,
|
||||
fromstr,
|
||||
)
|
||||
from django.contrib.gis.geos.libgeos import geos_version_info
|
||||
from django.contrib.gis.geos.libgeos import geos_version_tuple
|
||||
from django.contrib.gis.shortcuts import numpy
|
||||
from django.template import Context
|
||||
from django.template.engine import Engine
|
||||
|
@ -670,11 +670,11 @@ class GEOSTest(SimpleTestCase, TestDataMixin):
|
|||
self.assertFalse(ls_not_closed.closed)
|
||||
self.assertTrue(ls_closed.closed)
|
||||
|
||||
if geos_version_info()['version'] >= '3.5':
|
||||
if geos_version_tuple() >= (3, 5):
|
||||
self.assertFalse(MultiLineString(ls_closed, ls_not_closed).closed)
|
||||
self.assertTrue(MultiLineString(ls_closed, ls_closed).closed)
|
||||
|
||||
with mock.patch('django.contrib.gis.geos.collections.geos_version_info', lambda: {'version': '3.4.9'}):
|
||||
with mock.patch('django.contrib.gis.geos.libgeos.geos_version_info', lambda: {'version': '3.4.9'}):
|
||||
with self.assertRaisesMessage(GEOSException, "MultiLineString.closed requires GEOS >= 3.5.0."):
|
||||
MultiLineString().closed
|
||||
|
||||
|
@ -1305,6 +1305,10 @@ class GEOSTest(SimpleTestCase, TestDataMixin):
|
|||
self.assertEqual(m.group('version'), v_geos)
|
||||
self.assertEqual(m.group('capi_version'), v_capi)
|
||||
|
||||
def test_geos_version_tuple(self):
|
||||
with mock.patch('django.contrib.gis.geos.libgeos.geos_version_info', lambda: {'version': '3.4.9'}):
|
||||
self.assertEqual(geos_version_tuple(), (3, 4, 9))
|
||||
|
||||
def test_from_gml(self):
|
||||
self.assertEqual(
|
||||
GEOSGeometry('POINT(0 0)'),
|
||||
|
|
|
@ -68,6 +68,12 @@ class TestPostGISVersionCheck(unittest.TestCase):
|
|||
actual = ops.postgis_version_tuple()
|
||||
self.assertEqual(expect, actual)
|
||||
|
||||
def test_version_loose_tuple(self):
|
||||
expect = ('1.2.3b1.dev0', 1, 2, 3)
|
||||
ops = FakePostGISOperations(expect[0])
|
||||
actual = ops.postgis_version_tuple()
|
||||
self.assertEqual(expect, actual)
|
||||
|
||||
def test_valid_version_numbers(self):
|
||||
versions = [
|
||||
('1.3.0', 1, 3, 0),
|
||||
|
@ -81,15 +87,6 @@ class TestPostGISVersionCheck(unittest.TestCase):
|
|||
actual = ops.spatial_version
|
||||
self.assertEqual(version[1:], actual)
|
||||
|
||||
def test_invalid_version_numbers(self):
|
||||
versions = ['nope', '123']
|
||||
|
||||
for version in versions:
|
||||
with self.subTest(version=version):
|
||||
ops = FakePostGISOperations(version)
|
||||
with self.assertRaises(Exception):
|
||||
ops.spatial_version
|
||||
|
||||
def test_no_version_number(self):
|
||||
ops = FakePostGISOperations()
|
||||
with self.assertRaises(ImproperlyConfigured):
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from django import get_version
|
||||
from django.test import SimpleTestCase
|
||||
from django.utils.version import get_version_tuple
|
||||
|
||||
|
||||
class VersionTests(SimpleTestCase):
|
||||
|
@ -22,3 +23,8 @@ class VersionTests(SimpleTestCase):
|
|||
)
|
||||
for ver_tuple, ver_string in tuples_to_strings:
|
||||
self.assertEqual(get_version(ver_tuple), ver_string)
|
||||
|
||||
def test_get_version_tuple(self):
|
||||
self.assertEqual(get_version_tuple('1.2.3'), (1, 2, 3))
|
||||
self.assertEqual(get_version_tuple('1.2.3b2'), (1, 2, 3))
|
||||
self.assertEqual(get_version_tuple('1.2.3b2.dev0'), (1, 2, 3))
|
||||
|
|
Loading…
Reference in New Issue