Use with Automap?
Hello,
Sorry if this is the wrong place to ask this question. I'm pretty new to github.
I want to use alchemyjsonschema with automap. My setup is similar to the example code shown here. When I try using
factory = SchemaFactory(SingleModelWalker)
result = factory(someTable)
I get an <class 'AttributeError'>. someTable is of type <class 'sqlalchemy.ext.automap.someTable'>
Any advice? Thanks
Was able to solve my own issue somewhat. I need to predefine the class and then reflect it again, then it works:
class someTable(Base):
__tablename__ = "someTable"
# reflect in to override the predefined classes
Base.prepare(engine=engine, reflect=True)
Was hoping to avoid having to do that.
oh, i see.
these tests are passed in my local's environment. (but, i found another bug for required field of related table, of course, this is out of context of this issue)
https://gist.github.com/podhmo/cf12f3e6874ba3628b3f867b9ea65d04
when generated classes don't have __tablename__ property, above error is occured. maybe.
I could not reproduce same error (using automap then AttributeError is raised). if you can, please, give me a simple set enable to reproduce it.
Thanks for looking into that. I realised my problem only comes when I try to use it on a query. Maybe this is false usage, if so, I'm sorry about that.
I wrote this up to illustrate my problem. The first test works, second one will not:
import sqlalchemy, unittest
from sqlalchemy.ext.automap import automap_base
from sqlalchemy import create_engine
from collections import OrderedDict
from alchemyjsonschema import SchemaFactory
from alchemyjsonschema import SingleModelWalker
class Test(unittest.TestCase):
def setUp(self):
self.Base = automap_base()
self.engine = create_engine("postgresql://postgres:testpw@localhost:5432/testdb")
self.Base.prepare(self.engine, reflect=True)
self.session = sqlalchemy.orm.Session(self.engine)
def test_will_work(self):
TestTable = self.Base.classes.test_table
factory = SchemaFactory(SingleModelWalker)
result = factory(TestTable)
expected_result = {
'type': 'object',
'title': 'test_table',
'properties': OrderedDict([('firstnumber', {
'type': 'integer'
}), ('secondnumber', {
'type': 'integer'
}), ('bez', {
'type': 'string',
'maxLength': 50
})]),
'required': ['firstnumber', 'secondnumber']
}
self.assertEqual(result, expected_result)
def test_wont_work(self):
TestTable = self.Base.classes.test_table
row = self.session.query(TestTable).first()
factory = SchemaFactory(SingleModelWalker)
result = factory(row)
expected_result = {
'type': 'object',
'title': 'test_table',
'properties': OrderedDict([('firstnumber', {
'type': 'integer',
'value': 1
}), ('secondnumber', {
'type': 'integer',
'value': 1
}), ('bez', {
'type': 'string',
'maxLength': 50,
'value': 'test'
})]),
'required': ['firstnumber', 'secondnumber']
}
self.assertEqual(result, expected_result)
def tearDown(self):
self.session.rollback()
if __name__ == "__main__":
unittest.main()
DB table looks like:
Table "public.test_table"
Column | Type | Modifiers | Storage | Stats target | Description
-------------+-----------------------+-----------+----------+--------------+-------------
firstnumber | integer | not null | plain | |
secondnumber | integer | not null | plain | |
bez | character varying(50) | | extended | |
Indexes:
"test_table_pkey" PRIMARY KEY, btree (firstnumber, secondnumber)
Thanks!
No problem. I hope it helps.
ah, I haven't expected passing a instance of defined model class. but, if will be able to passing a instance, it is also convenience, maybe.
two phase action is good for this.
- build schema from model class
- add value from model instance
from alchemyjsonschema import emit_value
schema = factory(row.__class__)
schema = emit_value(schema, row)
Ok, sounds good. Thanks for your help