Skip to content

Commit a8def9f

Browse files
authored
Merge pull request geoalchemy#192 from elemoine/unpickling
Fix the geom unpickling process
2 parents 65b1177 + 18d2b59 commit a8def9f

File tree

3 files changed

+45
-24
lines changed

3 files changed

+45
-24
lines changed

geoalchemy2/elements.py

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from sqlalchemy.ext.compiler import compiles
1212

1313

14-
class _SpatialElement(object):
14+
class _SpatialElement(functions.Function):
1515
"""
1616
The base class for :class:`geoalchemy2.elements.WKTElement` and
1717
:class:`geoalchemy2.elements.WKBElement`.
@@ -43,6 +43,13 @@ def __init__(self, data, srid=-1, extended=False, use_st_prefix=True):
4343
self.data = data
4444
self.extended = extended
4545
self.use_st_prefix = use_st_prefix
46+
if self.extended:
47+
args = [self.geom_from_extended_version, self.data]
48+
else:
49+
args = [self.geom_from, self.data, self.srid]
50+
if not self.use_st_prefix:
51+
args[0] = args[0].lstrip('ST_')
52+
functions.Function.__init__(self, *args)
4653

4754
def __str__(self):
4855
return self.desc
@@ -68,23 +75,30 @@ def __getattr__(self, name):
6875

6976
def __getstate__(self):
7077
state = {
71-
'data': str(self),
7278
'srid': self.srid,
79+
'data': str(self),
7380
'extended': self.extended,
81+
'use_st_prefix': self.use_st_prefix,
82+
'name': self.name,
7483
}
7584
return state
7685

7786
def __setstate__(self, state):
78-
self.srid = state['srid']
79-
self.extended = state['extended']
87+
self.__dict__.update(state)
8088
self.data = self._data_from_desc(state['data'])
89+
args = [self.name, self.data]
90+
if not self.extended:
91+
args.append(self.srid)
92+
# we need to call Function.__init__ to properly initialize SQLAlchemy's
93+
# internal states
94+
functions.Function.__init__(self, *args)
8195

8296
@staticmethod
8397
def _data_from_desc(desc):
8498
raise NotImplementedError()
8599

86100

87-
class WKTElement(_SpatialElement, functions.Function):
101+
class WKTElement(_SpatialElement):
88102
"""
89103
Instances of this class wrap a WKT or EWKT value.
90104
@@ -93,17 +107,10 @@ class WKTElement(_SpatialElement, functions.Function):
93107
wkt_element_1 = WKTElement('POINT(5 45)')
94108
wkt_element_2 = WKTElement('POINT(5 45)', srid=4326)
95109
wkt_element_3 = WKTElement('SRID=4326;POINT(5 45)', extended=True)
96-
97110
"""
98111

99-
def __init__(self, *args, **kwargs):
100-
_SpatialElement.__init__(self, *args, **kwargs)
101-
if self.extended:
102-
f = "ST_GeomFromEWKT" if self.use_st_prefix else "GeomFromEWKT"
103-
args = (f, self.data)
104-
else:
105-
args = ("ST_GeomFromText", self.data, self.srid)
106-
functions.Function.__init__(self, *args)
112+
geom_from = 'ST_GeomFromText'
113+
geom_from_extended_version = 'ST_GeomFromEWKT'
107114

108115
@property
109116
def desc(self):
@@ -117,7 +124,7 @@ def _data_from_desc(desc):
117124
return desc
118125

119126

120-
class WKBElement(_SpatialElement, functions.Function):
127+
class WKBElement(_SpatialElement):
121128
"""
122129
Instances of this class wrap a WKB or EWKB value.
123130
@@ -129,14 +136,8 @@ class WKBElement(_SpatialElement, functions.Function):
129136
using the :func:`geoalchemy2.shape.from_shape` function.
130137
"""
131138

132-
def __init__(self, *args, **kwargs):
133-
_SpatialElement.__init__(self, *args, **kwargs)
134-
if self.extended:
135-
f = "ST_GeomFromEWKB" if self.use_st_prefix else "GeomFromEWKB"
136-
args = (f, self.data)
137-
else:
138-
args = ("ST_GeomFromWKB", self.data, self.srid)
139-
functions.Function.__init__(self, *args)
139+
geom_from = 'ST_GeomFromWKB'
140+
geom_from_extended_version = 'ST_GeomFromEWKB'
140141

141142
@property
142143
def desc(self):

tests/test_elements.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@ def test_pickle_unpickle(self):
4646
assert unpickled.srid == 3
4747
assert unpickled.extended is True
4848
assert unpickled.data == 'POINT(1 2)'
49+
assert unpickled.name == 'ST_GeomFromEWKT'
50+
f = unpickled.ST_Buffer(2)
51+
eq_sql(f, 'ST_Buffer('
52+
'ST_GeomFromEWKT(:ST_GeomFromEWKT_1), '
53+
':ST_Buffer_1)')
54+
assert f.compile().params == {
55+
u'ST_Buffer_1': 2,
56+
u'ST_GeomFromEWKT_1': 'POINT(1 2)',
57+
}
4958

5059

5160
class TestExtendedWKTElement():
@@ -152,6 +161,15 @@ def test_pickle_unpickle(self):
152161
assert unpickled.srid == 3
153162
assert unpickled.extended is True
154163
assert unpickled.data == b'\x01\x02'
164+
assert unpickled.name == 'ST_GeomFromEWKB'
165+
f = unpickled.ST_Buffer(2)
166+
eq_sql(f, 'ST_Buffer('
167+
'ST_GeomFromEWKB(:ST_GeomFromEWKB_1), '
168+
':ST_Buffer_1)')
169+
assert f.compile().params == {
170+
u'ST_Buffer_1': 2,
171+
u'ST_GeomFromEWKB_1': b'\x01\x02',
172+
}
155173

156174

157175
class TestExtendedWKBElement():

tests/test_functional.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,9 +280,11 @@ def test_pickle_unpickle(self):
280280

281281
pickled = pickle.dumps(lake)
282282
unpickled = pickle.loads(pickled)
283-
assert unpickled.geom.extended
284283
assert unpickled.geom.srid == 4326
285284
assert str(unpickled.geom) == data_desc
285+
assert unpickled.geom.extended
286+
assert unpickled.geom.use_st_prefix
287+
assert unpickled.geom.name == 'ST_GeomFromEWKB'
286288

287289

288290
class TestCallFunction():

0 commit comments

Comments
 (0)