can't adapt type 'EnumValue'
I have a SQLAlchemy model with this column:
status = Column(
Enum('SUBSCRIBED', 'UNSUBSCRIBED', 'UNCONFIRMED',
name='status_choices', native_enum=False),
Then spyne.model.complex.TableModel around that model is used for a service.
When a value for that column comes from a SOAP client i get this:
ProgrammingError: (ProgrammingError) can't adapt type 'EnumValue' 'INSERT INTO ...
I tried to register a psycopg2 adapter for spyne.model.enum.Enum.EnumValue but it's a dynamically created class...
Hi,
There's no test for it, so I'm not surprised.... Can you provide a test case? It'd make my job much easier.
Best,
I looked in the tests, but where can i find tests that test Spyne+SQLAlchemy+Postgres?
So, if this is not enough for you, I think you can take it from here.
I could not check the changes - i pulled the repo but could not find commit d4697752568bd80db02e1dd6bac9de1641c67a7a
But i found another bug with enums:
62 def __cmp__(self, other):
63 import ipdb; import pprint; ipdb.set_trace()
---> 64 return isinstance(self, type(other)) and cmp(self.__value, other.__value)
65
66 def __invert__(self):
67 return values[maximum - self.__value]
68
69 def __nonzero__(self):
ipdb> self
SUBSCRIBED
ipdb> other
u'UNSUBSCRIBED'
ipdb> isinstance(self, type(other)) and cmp(self.__value, other.__value)
False
ipdb> isinstance(self, type(other))
False
ipdb> cmp(self.__value, other.__value)
*** AttributeError: 'EnumValue' object has no attribute '__value'
ipdb>
I.e. when SQLAlchemy pulls current data from database and compares value from db with value of the field from SOAP request, it will always say it's not equal:
/home/vic/projects/.venv/apilib/local/lib/python2.7/site-packages/sqlalchemy/orm/attributes.py(1278)from_scalar_attribute()
1276 return cls((), [current], ())
1277 # don't let ClauseElement expressions here trip things up
-> 1278 elif attribute.is_equal(current, original) is True:
1279 return cls((), [current], ())
1280 else:
/home/vic/projects/.venv/apilib/local/lib/python2.7/site-packages/sqlalchemy/types.py(203)compare_values()
201 """Compare two values for equality."""
202
--> 203 return x == y
204
205 def get_dbapi_type(self, dbapi):
> /home/vic/projects/apigateway/apigateway/spyne_injection.py(64)__cmp__()
62 def __cmp__(self, other):
63 import ipdb; import pprint; ipdb.set_trace()
---> 64 return isinstance(self, type(other)) and cmp(self.__value, other.__value)
65
66 def __invert__(self):
Also, using __cmp__ is wrong here:
> /home/vic/projects/apigateway/apigateway/spyne_injection.py(64)__cmp__()
62 def __cmp__(self, other):
63 import ipdb; import pprint; ipdb.set_trace()
---> 64 return isinstance(self, type(other)) and cmp(self.__value, other.__value)
65
66 def __invert__(self):
ipdb> n
--Return--
False
> /home/vic/projects/apigateway/apigateway/spyne_injection.py(64)__cmp__()
63 import ipdb; import pprint; ipdb.set_trace()
---> 64 return isinstance(self, type(other)) and cmp(self.__value, other.__value)
65
ipdb>
--Return--
True
> /home/vic/projects/.venv/apilib/local/lib/python2.7/site-packages/sqlalchemy/types.py(203)compare_values()
202
--> 203 return x == y
204
because if types differ, it returns False which is 0, which means that values are equal (http://docs.python.org/2/reference/datamodel.html#object.cmp)
you're right that __cmp__ implementation has always been wrong here. can you please write tests for these so I can fix this?
Thanks
@plq , hi Burak!
Sorry, I don't have time for this (got a lot of urgent work to do) and the unittests look quite complex to me. I removed all ENums from my SQLALchemy models and replaced them with strings with check constraints.
I would suggest removing enum support from Spyne, as it looks like no one used it anyway - this is what i did in our monkey-patching code for spyne.
would you now?
enums are there because they're there in the Xml schema standard. so they work just fine. just apparently not with sqlalchemy. I'll eventually fix this.
thanks for your time