def test_exclude_schema(self, req, dbsession, check_csrf_token): """ It should exlude general forms used by the study (editing) """ from datetime import date from webob.multidict import MultiDict from occams import models as datastore from occams import models x = datastore.Schema(name='x', title=u'x', publish_date=date.today()) y = datastore.Schema(name='y', title=u'Y', publish_date=date.today()) study = models.Study(name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today(), schemata=set([x])) dbsession.add_all([x, y, study]) dbsession.flush() req.GET = MultiDict() res = self._call_fut(study, req) assert 1 == len(res['schemata']) assert 'y' == res['schemata'][0]['name']
def test_update_cycles(self, req, dbsession, check_csrf_token): """ It should also update cycle versions """ from datetime import date, timedelta from occams import models as datastore from occams import models today = date.today() tomorrow = today + timedelta(days=1) v1 = datastore.Schema(name=u'test', title=u'', publish_date=today) v2 = datastore.Schema(name=u'test', title=u'', publish_date=tomorrow) cycle = models.Cycle(name=u'wk-001', title=u'WK-001', schemata=set([v1])) study = models.Study(name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', cycles=[cycle], schemata=set([v1]), consent_date=date.today()) dbsession.add_all([study, v1, v2]) dbsession.flush() req.json_body = {'schema': v1.name, 'versions': [v2.id]} self._call_fut(study, req) assert v2 in study.schemata # v2 should have been passed on to the cycle using it as well assert v2 in cycle.schemata
def test_schema_publish_date_unique(dbsession): """ It should enforce unique publish dates """ from datetime import date import sqlalchemy.exc from occams import models # First version dbsession.add( models.Schema(name='Foo', title=u'Foo', publish_date=date(2014, 3, 31))) dbsession.flush() # Draft version dbsession.add(models.Schema(name='Foo', title=u'Foo', publish_date=None)) dbsession.flush() # Add another published schema (not on the same date) # Publish, not on the same date dbsession.add( models.Schema(name='Foo', title=u'Foo', publish_date=date(2014, 4, 1))) dbsession.flush() # New version, same date (wrong) dbsession.add( models.Schema(name='Foo', title=u'Foo', publish_date=date(2014, 4, 1))) with pytest.raises(sqlalchemy.exc.IntegrityError): dbsession.flush()
def test_exclude_schema_used_versions(self, req, dbsession, check_csrf_token): """ It should exclude general versions already used by the form (editing) """ from datetime import date, timedelta from webob.multidict import MultiDict from occams import models as datastore from occams import models today = date.today() tomorrow = today + timedelta(days=1) y0 = datastore.Schema(name='y', title=u'Y', publish_date=today) y1 = datastore.Schema(name='y', title=u'Y', publish_date=tomorrow) study = models.Study(name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today(), schemata=set([y0])) dbsession.add_all([y0, y1, study]) dbsession.flush() req.GET = MultiDict() res = self._call_fut(study, req) assert 1 == len(res['schemata']) assert str(tomorrow) == res['schemata'][0]['publish_date']
def test_enable(self, req, dbsession, check_csrf_token): """ It should successfully add a schema to a cycle """ from datetime import date from occams import models as datastore from occams import models schema = datastore.Schema(name='test', title=u'Test', publish_date=date.today()) cycle = models.Cycle(name='week-1', title=u'Week 1', week=1) study = models.Study(name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today(), cycles=[cycle], schemata=set([schema])) dbsession.add_all([study, schema]) dbsession.flush() req.json_body = { 'schema': schema.name, 'cycle': cycle.id, 'enabled': True } self._call_fut(study, req) assert schema in cycle.schemata
def test_success(self, req, dbsession, check_csrf_token): """ It should remove the schema from the study and cascade to its cycles """ from datetime import date from occams import models as datastore from occams import models schema = datastore.Schema(name='test', title=u'', publish_date=date.today()) cycle = models.Cycle(name='week-1', title=u'Week 1', week=1, schemata=set([schema])) study = models.Study(name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today(), cycles=[cycle], schemata=set([schema])) dbsession.add_all([study, schema]) dbsession.flush() req.matchdict = {'schema': schema.name} self._call_fut(study, req) assert schema not in study.schemata assert schema not in cycle.schemata
def test_fail_if_termination_schema(self, req, dbsession, check_csrf_token): """ It should not allow termination schemata to be used as study schemata """ from datetime import date from pyramid.httpexceptions import HTTPBadRequest from occams import models as datastore from occams import models schema = datastore.Schema(name='test', title=u'', publish_date=date.today()) study = models.Study(name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today(), termination_schema=schema) dbsession.add_all([study, schema]) dbsession.flush() req.json_body = {'schema': schema.name, 'versions': [schema.id]} with pytest.raises(HTTPBadRequest) as excinfo: self._call_fut(study, req) assert 'already a termination form' in \ excinfo.value.json['errors']['schema'].lower()
def test_fail_if_not_same_schema(self, req, dbsession, check_csrf_token): """ It should fail if the schema and versions do not match """ from datetime import date from pyramid.httpexceptions import HTTPBadRequest from occams import models as datastore from occams import models schema = datastore.Schema(name='test', title=u'', publish_date=date.today()) study = models.Study(name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today()) dbsession.add_all([study, schema]) dbsession.flush() req.json_body = {'schema': u'otherform', 'versions': [schema.id]} with pytest.raises(HTTPBadRequest) as excinfo: self._call_fut(study, req) assert 'Incorrect versions' in \ excinfo.value.json['errors']['versions']
def test_fail_if_not_published(self, req, dbsession, check_csrf_token): """ It should fail if the schema is not published """ from datetime import date from pyramid.httpexceptions import HTTPBadRequest from occams import models as datastore from occams import models schema = datastore.Schema(name='test', title=u'') study = models.Study(name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today()) dbsession.add_all([study, schema]) dbsession.flush() dbsession.execute(models.patient_schema_table.insert().values( {'schema_id': schema.id})) req.json_body = {'schema': schema.name, 'versions': [schema.id]} with pytest.raises(HTTPBadRequest) as excinfo: self._call_fut(study, req) assert 'not published' in \ excinfo.value.json['errors']['versions-0']
def test_choice_defaults(dbsession): """ It should set choice defaults """ from occams import models schema = models.Schema(name=u'Foo', title=u'Foo') attribute = models.Attribute(schema=schema, name=u'foo', title=u'Enter Foo', type=u'choice', order=0) choice1 = models.Choice(attribute=attribute, name='001', title=u'Foo', order=0) choice2 = models.Choice(attribute=attribute, name='002', title=u'Bar', order=1) choice3 = models.Choice(attribute=attribute, name='003', title=u'Baz', order=2) dbsession.add_all([schema, attribute, choice1, choice2, choice3]) dbsession.flush() count = dbsession.query(models.Choice).count() assert count, 3 == 'Did not find any choices'
def test_list_not_include_private(self, dbsession): """ It should not include private data if specified. Note this is not the same as de-identification) """ from datetime import date from occams import models as datastore from occams.exports.schema import SchemaPlan schema = datastore.Schema(name=u'contact', title=u'Contact Details', publish_date=date.today(), attributes={ 'foo': datastore.Attribute(name='foo', title=u'', type='string', order=0, is_private=True) }) dbsession.add_all([schema]) dbsession.flush() plans = SchemaPlan.list_all(dbsession, include_private=True) assert len(plans) == 1 plans = SchemaPlan.list_all(dbsession, include_private=False) assert len(plans) == 0
def test_add_to_patient(self, req, dbsession): from datetime import date from occams import models schema = models.Schema(name=u'schema', title=u'Schema', publish_date=date.today()) study = models.Study(name='some-study', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today(), schemata=set([schema])) site = models.Site(name=u'somewhere', title=u'Somewhere') patient = models.Patient(pid=u'12345', site=site) dbsession.add_all([study, patient]) dbsession.flush() req.method = 'POST' req.matchdict = {'patient': patient} req.json_body = { 'schema': schema.id, 'collect_date': str(date.today()), } factory = models.FormFactory(req) factory.__parent__ = patient self._call_fut(factory, req) contexts = dbsession.query(models.Context).all() assert len(contexts) == 1 assert contexts[0].entity.schema == schema
def test_entity_force_date(dbsession): """ It should maintain a date object for date types. (Sometimes applications will blindly assign datetimes...) """ from datetime import date, datetime from occams import models schema = models.Schema(name=u'Foo', title=u'', publish_date=date(2000, 1, 1)) s1 = models.Attribute(schema=schema, name='s1', title=u'Section 1', type='section', order=0) entity = models.Entity(schema=schema) # Do simple values simpleName = 'choicesimple' schema.attributes[simpleName] = models.Attribute(schema=schema, parent_attribute=s1, title=u'', type='date', is_required=False, order=1) now = datetime.now() today = now.date() entity[simpleName] = now dbsession.flush() assert isinstance(entity[simpleName], date) assert today == entity[simpleName]
def test_file(self, req, dbsession): """ It should return the json rows for the codebook fragment """ from datetime import date from webob.multidict import MultiDict from occams import models from occams.exports.schema import SchemaPlan dbsession.add(models.Schema( name=u'aform', title=u'', publish_date=date.today(), attributes={ u'myfield': models.Attribute( name=u'myfield', title=u'', type=u'string', order=0 ) } )) dbsession.flush() req.GET = MultiDict([('file', 'aform')]) req.registry.settings['studies.export.plans'] = [SchemaPlan.list_all] res = self._call_fut(models.ExportFactory(req), req) assert res is not None
def test_basic(self, req, dbsession, check_csrf_token): """ It should allow adding a schema to a study """ from datetime import date from occams import models as datastore from occams import models schema = datastore.Schema(name='test', title=u'', publish_date=date.today()) study = models.Study(name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today()) dbsession.add_all([study, schema]) dbsession.flush() req.json_body = {'schema': schema.name, 'versions': [schema.id]} self._call_fut(study, req) assert schema in study.schemata
def test_attribute_unique_case_insensitive(dbsession): """ It should enforce case-insensitive attributes """ from datetime import date import sqlalchemy.exc from occams import models schema = models.Schema(name='Foo', title=u'Foo', publish_date=date(2014, 3, 31)) schema.attributes['MyAttr'] = models.Attribute(name=u'MyAttr', title=u'My Attribute', type=u'string', order=0) dbsession.add(schema) dbsession.flush() schema.attributes['myattr'] = models.Attribute(name=u'myattr', title=u'My Attribute 2', type=u'string', order=1) with pytest.raises(sqlalchemy.exc.IntegrityError): dbsession.flush()
def test_schema_has_private(dbsession): """ It should be able to determine if a schema has private attributes """ from datetime import date from occams import models schema = models.Schema(name='Foo', title=u'Foo', publish_date=date(2014, 3, 31), attributes={ 'not_private': models.Attribute(name='not_private', title=u'', type='string', is_private=False, order=0) }) dbsession.add(schema) dbsession.flush() assert not schema.has_private schema.attributes['is_private'] = models.Attribute(name='is_private', title=u'', type='string', is_private=True, order=1) assert schema.has_private
def test_build_report_expected_metadata_columns(dbsession): """ It should always include entity metdata in the final report query """ from datetime import date from occams import models, reporting today = date.today() schema = models.Schema(name=u'A', title=u'A', publish_date=today) dbsession.add(schema) dbsession.flush() report = reporting.build_report(dbsession, u'A') assert u'id' in report.c assert u'form_name' in report.c assert u'form_publish_date' in report.c assert u'state' in report.c assert u'collect_date' in report.c assert u'not_done' in report.c assert u'create_date' in report.c assert u'create_user' in report.c assert u'modify_date' in report.c assert u'modify_user' in report.c
def check_report_column_type(dbsession, ds_type, sa_type): """ It should normalize datastore types to SQL types """ from datetime import date from occams import models, reporting schema = models.Schema(name=u'A', title=u'A', publish_date=date.today(), attributes={ 's1': models.Attribute(name=u's1', title=u'S1', type='section', order=0, attributes={ 'a': models.Attribute( name=u'a', title=u'', type=ds_type, order=1) }) }) dbsession.add(schema) dbsession.flush() report = reporting.build_report(dbsession, u'A') column_type = dbsession.query(report.c.a).column_descriptions[0]['type'] assert isinstance(column_type, sa_type), \ '%s did not covert to %s, got %s' \ % (ds_type, str(sa_type), column_type)
def test_datadict_multiple_choice(dbsession): """ It should retain answer choices in the columns dictionary """ from copy import deepcopy from datetime import date, timedelta from six import iterkeys from occams import models, reporting today = date.today() schema1 = models.Schema(name=u'A', title=u'A', publish_date=today, attributes={ 's1': models.Attribute( name=u's1', title=u'S1', type='section', order=0, attributes={ 'a': models.Attribute( name=u'a', title=u'', type='string', is_collection=True, order=1, choices={ '001': models.Choice(name=u'001', title=u'Foo', order=0), '002': models.Choice(name=u'002', title=u'Bar', order=1) }) }) }) dbsession.add(schema1) dbsession.flush() columns = reporting.build_columns(dbsession, u'A') assert 'a' in columns assert sorted(['001', '002']) == sorted(iterkeys(columns['a'].choices)) schema2 = deepcopy(schema1) schema2.publish_date = today + timedelta(1) schema2.attributes['s1'].attributes['a'].choices['003'] = \ models.Choice(name=u'003', title=u'Baz', order=3) dbsession.add(schema2) dbsession.flush() columns = reporting.build_columns(dbsession, u'A') assert sorted(['001', '002', '003']) == \ sorted(iterkeys(columns['a'].choices))
def test_copy_schema_basic(dbsession): """ It should let the user copy schemata """ from copy import deepcopy from occams import models schema = models.Schema(name='Foo', title=u'Foo', attributes={ 'section1': models.Attribute( name=u'section1', title=u'Section 1', type='section', order=0, attributes={ 'foo': models.Attribute( name='foo', title=u'Enter Foo', type='choice', order=1, choices={ '001': models.Choice(name='001', title=u'Foo', order=0), '002': models.Choice(name='002', title=u'Bar', order=1), '003': models.Choice(name='003', title=u'Baz', order=2) }, ) }) }) dbsession.add(schema) dbsession.flush() schema_copy = deepcopy(schema) dbsession.add(schema_copy) dbsession.flush() # The ones that matter for checksums assert schema.name == schema_copy.name attribute = schema.attributes['foo'] for prop in ('name', 'title', 'description', 'type', 'is_collection', 'is_required'): attribute_copy = schema_copy.attributes['foo'] assert getattr(attribute, prop) == getattr(attribute_copy, prop) for choice in schema.attributes['foo'].choices.values(): choice_copy = schema_copy.attributes['foo'].choices[choice.name] for prop in ('name', 'title', 'order'): assert getattr(choice, prop) == getattr(choice_copy, prop)
def test_success(self, req, dbsession, check_csrf_token): """ It should allow removal of entities from a visit. """ from datetime import date, timedelta from pyramid.httpexceptions import HTTPOk from occams import models as datastore from occams import models cycle = models.Cycle(name='week-1', title=u'', week=1) schema = datastore.Schema( name=u'sample', title=u'', publish_date=date.today()) study = models.Study( name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today(), cycles=[cycle], schemata=set([schema])) site = models.Site(name=u'ucsd', title=u'UCSD') default_state = ( dbsession.query(datastore.State) .filter_by(name=u'pending-entry') .one()) t_a = date.today() + timedelta(days=5) patient_a = models.Patient(site=site, pid=u'12345') visit_a = models.Visit( patient=patient_a, cycles=[cycle], visit_date=t_a) entity_a_1 = datastore.Entity( schema=schema, collect_date=t_a, state=default_state) entity_a_2 = datastore.Entity( schema=schema, collect_date=t_a, state=default_state) entity_a_3 = datastore.Entity( schema=schema, collect_date=t_a, state=default_state) list(map(visit_a.entities.add, [entity_a_1, entity_a_2, entity_a_3])) dbsession.add_all([visit_a, study]) dbsession.flush() req.json_body = { 'forms': [entity_a_2.id, entity_a_3.id] } res = self._call_fut(visit_a['forms'], req) # refresh the session so we can get a correct listing dbsession.expunge_all() visit_a = dbsession.query(models.Visit).get(visit_a.id) assert isinstance(res, HTTPOk) assert sorted([e.id for e in [entity_a_1]]) == \ sorted([e.id for e in visit_a.entities])
def test_valid_upload(self, req, dbsession, check_csrf_token): """ It should be able to upload a perfectly valid CSV """ import tempfile import csv from datetime import date from occams import models as datastore from occams import models schema = datastore.Schema(name='rand', title=u'Rand', publish_date=date.today(), attributes={ 'criteria': datastore.Attribute(name='criteria', title=u'Criteria', type='string', order=0) }) study = models.Study(name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', is_randomized=True, randomization_schema=schema, consent_date=date.today()) dbsession.add_all([study]) dbsession.flush() class DummyUpload: pass with tempfile.NamedTemporaryFile(prefix='nose-', suffix='.exe') as fp: upload = DummyUpload() upload.file = fp upload.filename = fp.name # forget the schema keys writer = csv.writer(fp) writer.writerow( [u'ARM', u'STRATA', u'BLOCKID', u'RANDID', u'CRITERIA']) # noqa writer.writerow( [u'UCSD', u'hints', u'1234567', u'987654', u'is smart']) # noqa fp.flush() req.POST = {'upload': upload} self._call_fut(study, req) stratum = dbsession.query(models.Stratum).one() entity = dbsession.query(datastore.Entity).one() assert stratum.arm.name == 'UCSD' assert entity in stratum.entities assert entity['criteria'] == 'is smart'
def test_add_category_to_schema(dbsession): """ Scheamta should be taggable via categories """ from occams import models schema = models.Schema(name='Foo', title=u'') dbsession.add(schema) dbsession.flush() assert len(schema.categories) == 0 category1 = models.Category(name='Tests', title=u'Test Schemata') schema.categories.add(category1) dbsession.flush() assert len(schema.categories) == 1 assert len(category1.schemata) == 1 assert sorted([s.name for s in category1.schemata]) == sorted(['Foo']) schema.categories.add(category1) dbsession.flush() assert len(schema.categories) == 1 assert len(category1.schemata) == 1 category2 = models.Category(name='Bars', title=u'Bar Schemata') schema.categories.add(category2) assert len(schema.categories) == 2 assert sorted([c.name for c in schema.categories]) == \ sorted(['Tests', 'Bars']) assert sorted([s.name for s in category2.schemata]) == sorted(['Foo']) # Now try a common use case: get all schema of a certain cateogry # First we'll need a second schema of the same category of another schema2 = models.Schema(name='Bar', title=u'') schema2.categories.add(category2) dbsession.add(schema2) dbsession.flush() # Now we want all the schemata of a certain category schemata = (dbsession.query(models.Schema).join( models.Schema.categories).filter_by(name='Bars')) # Should be the ones we just marked assert sorted([s.name for s in schemata]) == \ sorted(['Foo', 'Bar'])
def test_datadict_duplicate_vocabulary_term(dbsession): """ It should use the most recent version of a choice label """ from copy import deepcopy from datetime import date, timedelta from six import itervalues from occams import models, reporting today = date.today() schema1 = models.Schema(name=u'A', title=u'A', publish_date=today, attributes={ 's1': models.Attribute( name=u's1', title=u'S1', type='section', order=0, attributes={ 'a': models.Attribute( name=u'a', title=u'', type='string', is_collection=True, order=1, choices={ '001': models.Choice(name=u'001', title=u'Foo', order=0), '002': models.Choice(name=u'002', title=u'Bar', order=1) }) }) }) schema2 = deepcopy(schema1) schema2.state = u'published' schema2.publish_date = today + timedelta(1) for choice in itervalues(schema2.attributes['s1'].attributes['a'].choices): choice.title = 'New ' + choice.title dbsession.add_all([schema1, schema2]) dbsession.flush() columns = reporting.build_columns(dbsession, u'A') assert '001' in columns['a'].choices assert '002' in columns['a'].choices assert 'New Foo' == columns['a'].choices['001'] assert 'New Bar' == columns['a'].choices['002']
def test_include_not_retracted_form( self, req, dbsession, check_csrf_token): """ It should not use retracted forms, even if there are the most recent """ from datetime import date, timedelta from occams import models as datastore from occams import models t0 = date.today() t1 = t0 + timedelta(days=1) t2 = t1 + timedelta(days=1) study = models.Study( name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today()) cycle1 = models.Cycle(name='week-1', title=u'', week=1) cycle1.schemata.update([ datastore.Schema(name='form1', title=u'', publish_date=t0), datastore.Schema(name='form1', title=u'', publish_date=t2, retract_date=t2)]) study.cycles.append(cycle1) patient = models.Patient( site=models.Site(name=u'ucsd', title=u'UCSD'), pid=u'12345') dbsession.add_all([patient, study]) dbsession.flush() req.json_body = { 'cycles': [cycle1.id], 'visit_date': str(t2), 'include_forms': True } res = self._call_fut(patient['visits'], req) assert 1 == len(res['entities']) assert str(t0) == res['entities'][0]['schema']['publish_date']
def test_schema_unique_case_insensitive(dbsession): """ It should enforce case-insensitive schemata """ from datetime import date import sqlalchemy.exc from occams import models dbsession.add( models.Schema(name='Foo', title=u'Foo', publish_date=date(2014, 3, 31))) dbsession.flush() dbsession.add( models.Schema(name='foo', title=u'Foo', publish_date=date(2014, 3, 31))) with pytest.raises(sqlalchemy.exc.IntegrityError): dbsession.flush()
def test_cascade_forms(self, req, dbsession, check_csrf_token): """ It should remove all visit-associated forms. """ from datetime import date from occams import models as datastore from occams import models schema = datastore.Schema( name=u'sample', title=u'Some Sample', publish_date=date.today()) study = models.Study( name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today()) cycle = models.Cycle( name=u'week-10', title=u'Week 10', week=10) study.cycles.append(cycle) patient = models.Patient( site=models.Site(name=u'ucsd', title=u'UCSD'), pid=u'12345') enrollment = models.Enrollment( study=study, patient=patient, consent_date=date.today()) visit = models.Visit( patient=patient, cycles=[cycle], visit_date=date.today()) visit.entities.add(datastore.Entity( schema=schema, collect_date=date.today())) dbsession.add_all([patient, enrollment, study, visit]) dbsession.flush() visit_id = visit.id self._call_fut(visit, req) assert dbsession.query(models.Visit).get(visit_id) is None assert 0 == dbsession.query(datastore.Entity).count()
def test_term(self, req, dbsession, check_csrf_token): """ It should filter schemata by title or publish_date """ from datetime import date from webob.multidict import MultiDict from occams import models as datastore from occams import models dbsession.add_all([ datastore.Schema(name='v', title=u'V', publish_date=date.today()), datastore.Schema(name='xyz', title=u'XYZ', publish_date=date.today()) ]) dbsession.flush() req.GET = MultiDict([('term', 'x')]) res = self._call_fut(models.StudyFactory(req), req) assert 'xyz' == res['schemata'][0]['name']
def test_choice_constraint(dbsession): """ It should validate against choice constraints """ from datetime import date from occams import models from occams.exc import ConstraintError schema = models.Schema(name=u'Foo', title=u'', publish_date=date(2000, 1, 1)) s1 = models.Attribute(schema=schema, name='s1', title=u'Section 1', type='section', order=0) models.Attribute(schema=schema, parent_attribute=s1, name=u'test', title=u'', type=u'choice', is_required=False, order=0, choices={ '001': models.Choice(name=u'001', title=u'Foo', order=0), '002': models.Choice(name=u'002', title=u'Bar', order=1), '003': models.Choice(name=u'003', title=u'Baz', order=2) }) dbsession.add(schema) dbsession.flush() entity = models.Entity(schema=schema) dbsession.add(entity) entity['test'] = None entity['test'] = u'002' dbsession.flush() entry = (dbsession.query(models.ValueChoice).filter( models.ValueChoice.value.has(name=u'002')).one()) assert entry.value.name == '002' # Should not be able to set it to something outside of the specified # choice constraints with pytest.raises(ConstraintError): entity['test'] = u'999'