def test_empty_spec(): """ GIVEN empty specification WHEN init_model_factory is called with the specification THEN KeyError is raised. """ with pytest.raises( openapi_sqlalchemy.exceptions.MalformedSpecificationError): openapi_sqlalchemy.init_model_factory(base=None, spec={})
def test_schema(): """ GIVEN valid specification with single property WHEN return value of init_model_factory is called with the name of the schema THEN a SQLAlchemy model with a single property is returned. """ model_factory = openapi_sqlalchemy.init_model_factory( base=mock.MagicMock, spec={ "components": { "schemas": { "Table": { "properties": { "column": { "type": "integer" } }, "x-tablename": "table", "type": "object", } } } }, ) model = model_factory(name="Table") # Checking model assert model.__tablename__ == "table" assert hasattr(model, "column") assert isinstance(model.column.type, sqlalchemy.Integer)
def test_database_indexes(engine, index: str): """ GIVEN specification with a schema with an integer and given index WHEN schema is created THEN no exceptions get raised. """ # Defining specification column_schema = {"type": "integer", index: True} spec = { "components": { "schemas": { "Table": { "properties": { "id": { "type": "integer", "x-primary-key": True }, "column": column_schema, }, "x-tablename": "table", "type": "object", } } } } # Creating model factory base = declarative.declarative_base() model_factory = openapi_sqlalchemy.init_model_factory(spec=spec, base=base) model_factory(name="Table") # Creating models base.metadata.create_all(engine)
def test_cache_same(mocked_model_factory: mock.MagicMock): """ GIVEN valid specification and mocked model_factory WHEN return value of init_model_factory is called multiple times with the same name THEN mocked model_factory is called once. """ model_factory = openapi_sqlalchemy.init_model_factory( base=mock.MagicMock, spec={"components": { "schemas": {} }}) model_factory(name="table 1") model_factory(name="table 1") assert mocked_model_factory.call_count == 1
def test_cache_diff(mocked_model_factory: mock.MagicMock): """ GIVEN valid specification and mocked model_factory WHEN return value of init_model_factory is called with different names THEN mocked model_factory is called the same number of times the return value is called. """ model_factory = openapi_sqlalchemy.init_model_factory( base=mock.MagicMock, spec={"components": { "schemas": {} }}) model_factory(name="table 1") model_factory(name="table 2") assert mocked_model_factory.call_count == 2
def test_database_autoincrement(engine, sessionmaker): """ GIVEN specification with a schema with an autoincrement id column WHEN schema is created, values inserted without id column THEN the data is returned as it was inserted with autogenerated value. """ # Defining specification spec = { "components": { "schemas": { "Table": { "properties": { "id": { "type": "integer", "x-primary-key": True, "x-autoincrement": True, }, "name": { "type": "string" }, }, "x-tablename": "table", "type": "object", } } } } # Creating model factory base = declarative.declarative_base() model_factory = openapi_sqlalchemy.init_model_factory(spec=spec, base=base) model = model_factory(name="Table") # Creating models base.metadata.create_all(engine) # Creating instance of model and ref_model model_instance = model(name="table name 1") session = sessionmaker() session.add(model_instance) session.flush() # Querying session queried_model = session.query(model).first() assert queried_model.id == 1 assert queried_model.name == "table name 1"
def test_database_types(engine, sessionmaker, type_: str, format_: typing.Optional[str], value: typing.Any): """ GIVEN specification with a schema with a given type column and a value for that column WHEN schema is created and an instance is added to the session THEN the instance is returned when the session is queried for it. """ # Defining specification column_schema = {"type": type_, "x-primary-key": True} if format_ is not None: column_schema["format"] = format_ spec = { "components": { "schemas": { "Table": { "properties": { "column": column_schema }, "x-tablename": "table", "type": "object", } } } } # Creating model factory base = declarative.declarative_base() model_factory = openapi_sqlalchemy.init_model_factory(spec=spec, base=base) model = model_factory(name="Table") # Creating models base.metadata.create_all(engine) # Creating model instance model_instance = model(column=value) session = sessionmaker() session.add(model_instance) session.flush() # Querying session queried_model = session.query(model).first() assert queried_model.column == value
def test_database_not_autoincrement(engine, sessionmaker): """ GIVEN specification with a schema with autoincrement disabled id column WHEN schema is created, values inserted without id column THEN exception is raised. """ # Defining specification spec = { "components": { "schemas": { "Table": { "properties": { "id": { "type": "integer", "x-primary-key": True, "x-autoincrement": False, }, "name": { "type": "string" }, }, "x-tablename": "table", "type": "object", } } } } # Creating model factory base = declarative.declarative_base() model_factory = openapi_sqlalchemy.init_model_factory(spec=spec, base=base) model = model_factory(name="Table") # Creating models base.metadata.create_all(engine) # Creating instance of model and ref_model model_instance = model(name="table name 1") session = sessionmaker() session.add(model_instance) with pytest.raises(sqlalchemy.orm.exc.FlushError): session.flush()
def test_database_feature(engine, sessionmaker, spec): """ GIVEN specification with a schema that has a $ref on a column WHEN schema is created and an instance is added to the session THEN the instance is returned when the session is queried for it. """ # Creating model factory base = declarative.declarative_base() model_factory = openapi_sqlalchemy.init_model_factory(spec=spec, base=base) model = model_factory(name="Table") # Creating models base.metadata.create_all(engine) # Creating model instance model_instance = model(column=1) session = sessionmaker() session.add(model_instance) session.flush() # Querying session queried_model = session.query(model).first() assert queried_model.column == 1
from sqlalchemy.ext.declarative import declarative_base from yaml import safe_load from openapi_sqlalchemy import init_model_factory Base = declarative_base() with open("ref-model-example-spec.yml") as spec_file: SPEC = safe_load(spec_file) MODEL_FACTORY = init_model_factory(base=Base, spec=SPEC) Employee = MODEL_FACTORY(name="Employee")
def test_database_many_to_one_relationship(engine, sessionmaker): """ GIVEN specification with a schema with an object relationship WHEN schema is created, values inserted in both tables and queried THEN the data is returned as it was inserted. """ # Defining specification spec = { "components": { "schemas": { "RefTable": { "properties": { "id": { "type": "integer", "x-primary-key": True }, "name": { "type": "string" }, }, "x-tablename": "ref_table", "x-backref": "tables", "type": "object", }, "Table": { "properties": { "id": { "type": "integer", "x-primary-key": True }, "name": { "type": "string" }, "ref_table": { "$ref": "#/components/schemas/RefTable" }, }, "x-tablename": "table", "type": "object", }, } } } # Creating model factory base = declarative.declarative_base() model_factory = openapi_sqlalchemy.init_model_factory(spec=spec, base=base) model = model_factory(name="Table") ref_model = model_factory(name="RefTable") # Creating models base.metadata.create_all(engine) # Creating instance of model and ref_model ref_model_instance = ref_model(id=11, name="ref table name 1") model_instance = model(id=12, name="table name 1", ref_table=ref_model_instance) session = sessionmaker() session.add(ref_model_instance) session.add(model_instance) session.flush() # Querying session queried_model = session.query(model).first() assert queried_model.id == 12 assert queried_model.name == "table name 1" assert queried_model.ref_table_id == 11 assert queried_model.ref_table.id == 11 assert queried_model.ref_table.name == "ref table name 1" queried_ref_model = session.query(ref_model).first() assert queried_ref_model.id == 11 assert queried_ref_model.name == "ref table name 1" assert len(queried_ref_model.tables) == 1 assert queried_ref_model.tables[0].id == 12