def userdata_doctype_view(userdata_model, request): """ View used to register doctypes status userdata_model The UserDatas model retrieved through traversal """ if 'submit' in request.params: schema = get_doctypes_form_schema(userdata_model)[0] appstruct = request.POST.items() appstruct = peppercorn.parse(appstruct) try: appstruct = schema.deserialize(appstruct) except colander.Invalid: logger.exception( "Error while validating doctype registration" ) else: node_schema = SQLAlchemySchemaNode(UserDatasSocialDocTypes) for data in appstruct.values(): model = node_schema.objectify(data) request.dbsession.merge(model) request.session.flash( u"Les informations saisies ont bien été enregistrées" ) return HTTPFound( request.route_path('userdata', id=userdata_model.id) )
def test_specify_order_fields(self): """ Test this issue: How to specify the order in which fields should be displayed ? #45 """ Base = declarative_base() # example taken from SQLAlchemy docs class MyClass(Base): __tablename__ = 'my_table' id = Column(Integer, primary_key=True) job_status = Column(String(50)) status = synonym("job_status") schema = SQLAlchemySchemaNode(MyClass, includes=['foo', 'job_status', 'id']) self.assertEqual(['job_status', 'id'], [x.name for x in schema]) self.assertNotIn('foo', schema) schema = SQLAlchemySchemaNode(MyClass, includes=['id', 'foo', 'job_status']) self.assertEqual(['id', 'job_status'], [x.name for x in schema]) self.assertNotIn('foo', schema)
def get_add_edit_schema(edit=False): """ Return a user add schema """ schema = SQLAlchemySchemaNode( User, includes=( 'civilite', 'firstname', 'lastname', 'email', ), ) if not edit: schema.add( colander.SchemaNode( colander.Boolean(), name='add_login', title=u"Créer des identifiants pour ce compte ?", description=u"Les identifiants permettront au titulaire de ce " u"compte de se connecter", ) ) set_widgets(schema) return schema
def _prep_schema(self): overrides = { 'person': { 'includes': ['name', 'surname', 'gender', 'addresses'], 'overrides': { 'addresses': { 'includes': ['street', 'city'], 'overrides': { 'city': { 'exclude': False } } } } }, } includes = ['email', 'enabled', 'created', 'timeout', 'person'] schema = SQLAlchemySchemaNode(Account, includes=includes, overrides=overrides) # Add a non-SQLAlchemy field schema.add(colander.SchemaNode( colander.String(), name='non_sql', missing=colander.drop )) return schema
def get_password_schema(): """ Return the schema for user password change """ schema = SQLAlchemySchemaNode( user.User, includes=('login', 'pwd',), title=u'Modification de mot de passe', validator=auth, ) schema.insert( 1, colander.SchemaNode( colander.String(), widget=deform.widget.PasswordWidget(), name='password', title=u'Mot de passe actuel', default=u'', ) ) schema['login'].widget = deform.widget.HiddenWidget() # Remove login validation schema['login'].validator = None return schema
def get_password_schema(): """ Return the schema for user password change """ schema = SQLAlchemySchemaNode( user.User, includes=( 'login', 'pwd', ), title=u'Modification de mot de passe', validator=auth, ) schema.insert( 1, colander.SchemaNode( colander.String(), widget=deform.widget.PasswordWidget(), name='password', title=u'Mot de passe actuel', default=u'', )) schema['login'].widget = deform.widget.HiddenWidget() # Remove login validation schema['login'].validator = None return schema
def test_dictify_with_null(self): """ Test SQLAlchemySchemaNode.dictify(obj) with null values and show that result is a valid appstruct for the given schema """ Base = declarative_base() class Sensor(Base): __tablename__ = 'sensor' sensor_id = Column(Integer, primary_key=True) institution_id = Column(Integer, nullable=True) sensor_label = Column(String, nullable=True) sensor = Sensor( sensor_id=3, institution_id=None, sensor_label=None, ) schema = SQLAlchemySchemaNode(Sensor) appstruct = schema.dictify(sensor) cstruct = schema.serialize(appstruct=appstruct) newappstruct = schema.deserialize(cstruct) newobj = schema.objectify(appstruct) self.assertEqual(appstruct, newappstruct) self.assertEqual(sensor.sensor_id, newobj.sensor_id) self.assertEqual(sensor.institution_id, newobj.institution_id) self.assertEqual(sensor.sensor_label, newobj.sensor_label)
def get_project_schema(): """ Return the project Edition/add form schema """ schema = SQLAlchemySchemaNode(Project, excludes=('_acl',)) schema['name'].missing = colander.required # Add a custom node to be able to associate existing customers customer_id_node = colander.SchemaNode( colander.Integer(), widget=deferred_customer_select, validator=deferred_customer_validator, default=deferred_default_customer, name='un client' ) customer_id_node.objectify = customer_objectify customer_id_node.dictify = customer_dictify schema.insert(3, colander.SchemaNode( colander.Sequence(), customer_id_node, widget=deform.widget.SequenceWidget(min_len=1), title=u"Clients", name='customers') ) return schema
def get_sequence_model_admin(model, title=u""): """ Return a schema for configuring sequence of models model The SQLAlchemy model to configure """ node_schema = SQLAlchemySchemaNode( model, widget=deform.widget.MappingWidget(template=TEMPLATES_URL + "clean_mapping.pt", )) node_schema.name = 'data' schema = colander.SchemaNode(colander.Mapping()) schema.add( colander.SchemaNode(colander.Sequence(), node_schema, widget=deform.widget.SequenceWidget( orderable=True, template=TEMPLATES_URL + "clean_sequence.pt", ), title=title, name='datas')) def dictify(models): return {'datas': [node_schema.dictify(model) for model in models]} def objectify(datas): return [node_schema.objectify(data) for data in datas] schema.dictify = dictify schema.objectify = objectify return schema
def userdata_doctype_view(userdata_model, request): """ View used to register doctypes status userdata_model The UserDatas model retrieved through traversal """ if 'submit' in request.params: schema = get_doctypes_form_schema(userdata_model)[0] appstruct = request.POST.items() appstruct = peppercorn.parse(appstruct) try: appstruct = schema.deserialize(appstruct) except colander.Invalid: logger.exception("Error while validating doctype registration") else: node_schema = SQLAlchemySchemaNode(UserDatasSocialDocTypes) for data in appstruct.values(): model = node_schema.objectify(data) request.dbsession.merge(model) request.session.flash( u"Les informations saisies ont bien été enregistrées") return HTTPFound(request.route_path('userdata', id=userdata_model.id))
def get_project_schema(): """ Return the project Edition/add form schema """ schema = SQLAlchemySchemaNode(Project, excludes=('_acl', )) schema['name'].missing = colander.required # Add a custom node to be able to associate existing customers customer_id_node = colander.SchemaNode( colander.Integer(), widget=deferred_customer_select, validator=deferred_customer_validator, default=deferred_default_customer, name='un client') customer_id_node.objectify = customer_objectify customer_id_node.dictify = customer_dictify schema.insert( 3, colander.SchemaNode(colander.Sequence(), customer_id_node, widget=deform.widget.SequenceWidget(min_len=1), title=u"Clients", name='customers')) return schema
def test_payment(mode, tva, bank): from autonomie.models.task.invoice import Payment schema = SQLAlchemySchemaNode(Payment) schema = schema.bind() value = { 'mode': mode.label, "amount": 12.5, "remittance_amount": u"Remittance", "date": NOW.isoformat(), "tva_id": tva.id, "bank_id": bank.id, "user_id": 5, "task_id": 5, } expected_value = { 'mode': mode.label, "amount": 1250000, "remittance_amount": u"Remittance", "date": NOW, "tva_id": tva.id, "bank_id": bank.id, "user_id": 5, "task_id": 5, } result = schema.deserialize(value) for key, value in expected_value.items(): assert result[key] == value
def get_password_schema(): """ Return the schema for user password change :returns: a colander Schema """ schema = SQLAlchemySchemaNode( Login, includes=('pwd_hash',), title=u'', ) set_widgets(schema) schema.insert( 0, colander.SchemaNode( colander.String(), widget=deform.widget.PasswordWidget(), name='password', title=u'Mot de passe actuel', default=u'', ) ) schema['pwd_hash'].title = u"Nouveau mot de passe" schema.validator = deferred_password_validator schema.after_bind = remove_actual_password_my_account return schema
def statistic_sheet_add_edit_view(context, request): """ View for adding editing statistics sheets """ post_datas = request.POST or request.json_body if 'title' in post_datas: schema = SQLAlchemySchemaNode(StatisticSheet, includes=('title',)) try: appstruct = schema.deserialize(request.POST) except colander.Invalid: logger.exception(u"Erreur à la création de la feuille de \ statistiques") else: if context.__name__ == 'statistic_sheet': sheet = schema.objectify(appstruct, context) sheet = request.dbsession.merge(sheet) else: sheet = schema.objectify(appstruct) request.dbsession.add(sheet) request.dbsession.flush() url = request.route_path('statistic', id=sheet.id) return dict(redirect=url) logger.debug(u"Invalid datas have been passed") raise HTTPClientError() logger.debug(u"Missing datas in the request") raise HTTPClientError()
def test_null_issues(self): """ Make sure nullable values are set properly when null #42 introduced an issue where values may not have been properly set if the value is supposed to be set to null """ Base = declarative_base() class Person(Base): __tablename__ = 'person' id = Column(Integer, primary_key=True) fullname = Column(String, nullable=True) age = Column(Integer, nullable=True) schema = SQLAlchemySchemaNode(Person) person = Person( id=7, fullname="Joe Smith", age=35, ) # dict coming from a form submission update_cstruct = { 'id': '7', 'fullname': '', 'age': '', } update_appstruct = schema.deserialize(update_cstruct) schema.objectify(update_appstruct, context=person) self.assertEqual(person.id, 7) self.assertEqual(person.fullname, None) self.assertEqual(person.age, None)
def statistic_sheet_add_edit_view(context, request): """ View for adding editing statistics sheets """ logger.info("Here we are") logger.info(request.POST) if 'title' in request.POST: schema = SQLAlchemySchemaNode(StatisticSheet, includes=('title',)) try: appstruct = schema.deserialize(request.POST) except colander.Invalid: logger.exception(u"Erreur à la création de la feuille de \ statistiques") else: if context.__name__ == 'statistic_sheet': sheet = schema.objectify(appstruct, context) sheet = request.dbsession.merge(sheet) else: sheet = schema.objectify(appstruct) request.dbsession.add(sheet) request.dbsession.flush() url = request.route_path('statistic', id=sheet.id) return HTTPFound(url) logger.debug(u"Invalid datas have been passed") raise HTTPClientError() logger.debug(u"Missing datas in the request") raise HTTPClientError()
def test_relationship_infinite_recursion(self): """Test to ensure infinite recursion does not occur when following backrefs """ # Unpatched, creating a bar or baz schema node causes infinite recursion schema = SQLAlchemySchemaNode(Bar) schema = SQLAlchemySchemaNode(Baz)
def get_doctypes_schema(userdatas_model): """ Build a form schema for doctypes registration :param obj userdatas_model: An instance of userdatas we're building the form for """ registered = userdatas_model.doctypes_registrations node_schema = SQLAlchemySchemaNode(UserDatasSocialDocTypes) node_schema.widget = deform.widget.MappingWidget( template="clean_mapping.pt" ) node_schema['status'].widget = deform.widget.CheckboxWidget() form_schema = colander.Schema() for index, entry in enumerate(registered): node = node_schema.clone() name = 'node_%s' % index node.name = name node.title = u'' node['status'].title = u'' node['status'].label = entry.doctype.label form_schema.add(node) return form_schema
def get_password_schema(): """ Return the schema for user password change :returns: a colander Schema """ schema = SQLAlchemySchemaNode( Login, includes=('pwd_hash', ), title=u'', validator=deferred_password_validator, ) set_widgets(schema) schema.insert( 0, colander.SchemaNode( colander.String(), widget=deform.widget.PasswordWidget(), name='password', title=u'Mot de passe actuel', default=u'', )) schema['pwd_hash'].title = u"Nouveau mot de passe" return schema
def test_payment_line_task_id(): from autonomie.models.task.estimation import PaymentLine schema = SQLAlchemySchemaNode(PaymentLine, includes=('task_id', )) value = {'task_id': 5} assert schema.deserialize(value) == value value = {} with pytest.raises(colander.Invalid): schema.deserialize(value)
def test_discount_line_description(): from autonomie.models.task.task import DiscountLine schema = SQLAlchemySchemaNode(DiscountLine, includes=('description', )) value = {'description': u"description"} assert schema.deserialize(value) == value value = {"description": u"<br /><p></p>\n"} with pytest.raises(colander.Invalid): schema.deserialize(value)
def test_task_line_group_task_id(): from autonomie.models.task.task import TaskLineGroup schema = SQLAlchemySchemaNode(TaskLineGroup, includes=('task_id', )) value = {'task_id': 5} assert schema.deserialize(value) == value value = {} with pytest.raises(colander.Invalid): schema.deserialize(value)
def test_default_clause(self): """Test proper handling of default and server_default values """ Base = declarative_base() def give_me_three(): return 3 class Patient(Base): __tablename__ = 'patient' # default= is equivalent to ColumnDefault() # server_default= is equivalent to DefaultClause() id = Column(BigInteger(unsigned=True), default=text("uuid_short()"), primary_key=True, autoincrement=False) received_timestamp = Column(TIMESTAMP, server_default=func.now(), nullable=False) some_number = Column(Integer, DefaultClause('3'), nullable=False) scalar_number = Column(Integer, default=3, nullable=False) pyfunc_test = Column(Integer, default=give_me_three, nullable=False) schema = SQLAlchemySchemaNode(Patient) ''' Conceivably you should be able to test DefaultClause for a scalar type value and use it as a default/missing in Colander. However, the value is interpreted by the backend engine and could be a interpreted by it in an unexpected way. For this reason we drop the value and let the backend handle it. ''' # from <FORM> result into SQLA; tests missing self.assertEqual(schema['id'].missing, colander.drop) self.assertEqual(schema['received_timestamp'].missing, colander.drop) self.assertEqual(schema['some_number'].missing, colander.drop) self.assertEqual(schema['scalar_number'].missing, 3) self.assertEqual(schema['pyfunc_test'].missing, 3) deserialized = schema.deserialize({}) self.assertIn('scalar_number', deserialized) self.assertEqual(deserialized['scalar_number'], 3) self.assertIn('pyfunc_test', deserialized) self.assertEqual(deserialized['pyfunc_test'], 3) # from SQLA result into <FORM>; tests default self.assertEqual(schema['id'].default, colander.null) self.assertEqual(schema['received_timestamp'].default, colander.null) self.assertEqual(schema['some_number'].default, colander.null) self.assertEqual(schema['scalar_number'].default, 3) self.assertEqual(schema['pyfunc_test'].default, 3) serialized = schema.serialize({}) self.assertIn('id', serialized) self.assertEqual(serialized['id'], colander.null) self.assertIn('received_timestamp', serialized) self.assertEqual(serialized['received_timestamp'], colander.null) self.assertIn('some_number', serialized) self.assertEqual(serialized['some_number'], colander.null) self.assertIn('scalar_number', serialized) self.assertEqual(serialized['scalar_number'], str(3)) self.assertIn('pyfunc_test', serialized) self.assertEqual(serialized['pyfunc_test'], str(3))
def test_clone(self): schema = SQLAlchemySchemaNode(Account, dummy='dummy', dummy2='dummy2') cloned = schema.clone() for attr in ['class_', 'includes', 'excludes', 'overrides']: self.assertEqual(getattr(schema, attr), getattr(cloned, attr)) self.assertEqual(cloned.kwargs, schema.kwargs) self.assertEqual([node.name for node in schema.children], [node.name for node in cloned.children])
def get_company_customer_schema(): """ return the schema for user add/edit regarding the current user's role """ schema = SQLAlchemySchemaNode(Customer) schema = _customize_schema(schema) schema['name'].missing = colander.required schema.after_bind = _customer_after_bind return schema
def test_payment_line_date(): import datetime from autonomie.models.task.estimation import PaymentLine schema = SQLAlchemySchemaNode(PaymentLine, includes=('date', )) schema = schema.bind() value = {'date': datetime.date.today().isoformat()} assert schema.deserialize(value) == {'date': datetime.date.today()} value = {} assert schema.deserialize(value) == value
def __init__(self, class_, includes=None, excludes=None, overrides=None, unknown='raise'): self.comparators = {} self.order_by_values = [] SQLAlchemySchemaNode.__init__(self, class_, includes, excludes, overrides, unknown)
def test_missing_mapping_configuration(self): """ Test to check ``missing`` is set to an SQLAlchemy-suitable value. """ schema = SQLAlchemySchemaNode(Account) self.assertEqual(schema['person_id'].missing, colander.null) self.assertEqual(schema['person'].missing, []) deserialized = schema.deserialize({'email': '*****@*****.**', 'timeout': '09:44:33'}) self.assertEqual(deserialized['person_id'], colander.null) self.assertEqual(deserialized['person'], [])
def test_context_billing_email_allowed_for_billing_email(self): from pyramid_bimt.views.user import deferred_user_billing_email_validator # noqa schema = SQLAlchemySchemaNode(User) self.request.context = User.by_email('*****@*****.**') self.request.POST['email'] = '*****@*****.**' validator = deferred_user_billing_email_validator( None, {'request': self.request}) self.assertFalse(validator(schema.get('email'), '*****@*****.**'))
def test_context_name_allowed_for_name(self): from pyramid_bimt.views.group import deferred_group_name_validator schema = SQLAlchemySchemaNode(Group) self.request.context = Group.by_name('enabled') self.request.POST['name'] = 'enabled' validator = deferred_group_name_validator(None, {'request': self.request}) self.assertFalse(validator(schema.get('name'), 'enabled'))
def test_context_product_id_allowed_for_product_id(self): from pyramid_bimt.views.group import deferred_group_product_id_validator # noqa schema = SQLAlchemySchemaNode(Group) self.request.context = Group.by_name('enabled') self.request.context.product_id = '123' self.request.POST['product_id'] = '123' validator = deferred_group_product_id_validator( None, {'request': self.request}) self.assertFalse(validator(schema.get('product_id'), '123'))
def test_imperative_colums_overrides(self): overrides = {'email': {'typ': colander.Integer}} account_schema = SQLAlchemySchemaNode(Account, overrides=overrides) self.assertTrue( isinstance(account_schema['email'].typ, colander.Integer)) overrides = {'email': {'name': 'Name'}} self.assertRaises(ValueError, SQLAlchemySchemaNode, Account, None, None, overrides) overrides = {'email': {'children': []}} # following shouldn't raise an exception allowing the test to pass SQLAlchemySchemaNode(Account, None, None, overrides)
def test_imperative_relationships_overrides(self): overrides = {'person': {'name': 'Name'}} self.assertRaises(ValueError, SQLAlchemySchemaNode, Account, None, None, overrides) overrides = {'person': {'typ': colander.Integer}} self.assertRaises(ValueError, SQLAlchemySchemaNode, Account, None, None, overrides) overrides = { 'person': { 'children': [], 'includes': ['id'] }, } schema = SQLAlchemySchemaNode(Account, overrides=overrides) self.assertEqual(schema['person'].children, []) overrides = { 'person': { 'includes': ['id'] }, } schema = SQLAlchemySchemaNode(Account, overrides=overrides) self.assertIn('id', schema['person']) self.assertEqual(len(schema['person'].children), 1) overrides = { 'person': { 'excludes': ['id'] }, } schema = SQLAlchemySchemaNode(Account, overrides=overrides) self.assertNotIn('id', schema['person']) overrides = { 'addresses': { 'overrides': { 'id': { 'typ': colander.Float } } } } overrides = { 'addresses': { 'overrides': { 'id': { 'typ': colander.String } } } } schema = SQLAlchemySchemaNode(Person, overrides=overrides) self.assertTrue( isinstance(schema['addresses'].children[0]['id'].typ, colander.String))
def get_individual_customer_schema(): """ return the schema for user add/edit regarding the current user's role """ excludes = ('name', 'tva_intracomm', 'function', 'registration') schema = SQLAlchemySchemaNode(Customer, excludes=excludes) schema = _customize_schema(schema) schema['firstname'].title = u"Prénom" schema['lastname'].title = u'Nom' schema['civilite'].missing = colander.required schema['lastname'].missing = colander.required schema.after_bind = _customer_after_bind return schema
def test_estimation_payment_lines(): from autonomie.models.task.estimation import Estimation schema = SQLAlchemySchemaNode(Estimation, includes=('payment_lines', )) schema = schema.bind() value = {'payment_lines': []} with pytest.raises(colander.Invalid): schema.deserialize(value) value = {} with pytest.raises(colander.Invalid): schema.deserialize(value) value = { 'payment_lines': [{ 'task_id': 5, 'date': datetime.date.today().isoformat(), 'amount': 12.5, 'description': u"Description" }] } expected_value = { 'payment_lines': [{ 'task_id': 5, 'date': datetime.date.today(), 'amount': 1250000, 'description': u"Description", 'order': 1 }] } assert schema.deserialize(value) == expected_value
def get_sequence_model_admin(model, title=u"", excludes=(), **kw): """ Return a schema for configuring sequence of models model The SQLAlchemy model to configure """ node_schema = SQLAlchemySchemaNode( model, widget=CleanMappingWidget(), excludes=excludes, ) node_schema.name = 'data' colanderalchemy_config = getattr(model, '__colanderalchemy_config__', {}) default_widget_options = dict( orderable=True, min_len=1, ) widget_options = colanderalchemy_config.get('seq_widget_options', {}) widget_options.update(kw.get('widget_options', {})) for key, value in widget_options.items(): default_widget_options[key] = value schema = colander.SchemaNode(colander.Mapping()) schema.add( colander.SchemaNode( colander.Sequence(), node_schema, widget=CleanSequenceWidget( **default_widget_options ), title=title, name='datas') ) def dictify(models): return {'datas': [node_schema.dictify(model) for model in models]} def objectify(datas): return [node_schema.objectify(data) for data in datas] schema.dictify = dictify schema.objectify = objectify return schema
def schema(self): return SQLAlchemySchemaNode(CompetenceGridSubItem, includes=( 'evaluation', 'id', 'comments', ))
def test_doc_example_deform(self): """ Test 'using ColanderAlchemy with Deform' example found in docs/source/deform.rst """ Base = declarative_base() class Phone(Base): __tablename__ = 'phones' person_id = Column(Integer, ForeignKey('persons.id'), primary_key=True) number = Column(Unicode(128), primary_key=True) location = Column(Enum('home', 'work')) class Person(Base): __tablename__ = 'persons' id = Column(Integer, primary_key=True) name = Column(Unicode(128), nullable=False) surname = Column(Unicode(128), nullable=False) phones = relationship(Phone) schema = SQLAlchemySchemaNode(Person) # because of naming clashes, we need to do this in another function def generate_colander(): class Phone(colander.MappingSchema): person_id = colander.SchemaNode(colander.Int()) number = colander.SchemaNode( colander.String(), validator=colander.Length(0, 128) ) location = colander.SchemaNode( colander.String(), validator=colander.OneOf(['home', 'work']), missing=colander.null ) class Phones(colander.SequenceSchema): phones = Phone(missing=[]) class Person(colander.MappingSchema): id = colander.SchemaNode(colander.Int(), missing=colander.drop) name = colander.SchemaNode( colander.String(), validator=colander.Length(0, 128) ) surname = colander.SchemaNode( colander.String(), validator=colander.Length(0, 128) ) phones = Phones(missing=[]) return Person() schema2 = generate_colander() self.is_equal_schema(schema, schema2)
def get_sequence_model_admin(model, title=u"", excludes=(), **kw): """ Return a schema for configuring sequence of models model The SQLAlchemy model to configure """ node_schema = SQLAlchemySchemaNode( model, widget=deform.widget.MappingWidget( template=TEMPLATES_URL + "clean_mapping.pt", ), excludes=excludes, ) node_schema.name = 'data' default_widget_options = dict( orderable=True, template=TEMPLATES_URL + "clean_sequence.pt", min_len=1, ) widget_options = kw.get('widget_options', {}) for key, value in widget_options.items(): default_widget_options[key] = value schema = colander.SchemaNode(colander.Mapping()) schema.add( colander.SchemaNode( colander.Sequence(), node_schema, widget=deform.widget.SequenceWidget( **default_widget_options ), title=title, name='datas') ) def dictify(models): return {'datas': [node_schema.dictify(model) for model in models]} def objectify(datas): return [node_schema.objectify(data) for data in datas] schema.dictify = dictify schema.objectify = objectify return schema
def get_user_schema(edit=False, permanent=True): """ Return the schema for adding/editing users edit Is this an edit form permanent Is this form related to permanent edition (managers or admins) """ if permanent: schema = SQLAlchemySchemaNode(user.User, excludes=('compte_tiers',)) else: schema = SQLAlchemySchemaNode(user.User) if permanent: schema.insert( 0, colander.SchemaNode( colander.Integer(), name='primary_group', validator=deferred_primary_group_validator, widget=deferred_primary_group_widget, title=u"Rôle de l'utilisateur", ) ) schema.add( CompanySchema( name='companies', title=u"Entreprise(s)", widget=deform.widget.SequenceWidget( add_subitem_text_template=u"Ajouter une entreprise" ) ) ) else: schema.add( colander.SchemaNode( colander.Set(), name="groups", validator=deferred_group_validator, widget=deferred_group_widget, title=u"Groupes de l'utilisateur", ) ) if edit: schema['login'].validator = deferred_login_validator schema['pwd'].missing = colander.drop else: schema['login'].validator = get_unique_login_validator() return schema
def get_doctypes_form_schema(userdatas_model): """ Returns a dynamically built form for doctypes registration """ registrations = userdatas_model.doctypes_registrations node_schema = SQLAlchemySchemaNode(UserDatasSocialDocTypes) appstruct = {} form_schema = colander.Schema() for index, registration in enumerate(registrations): node = node_schema.clone() name = 'node_%s' % index node.name = name node.title = u'' node['status'].title = registration.doctype.label form_schema.add(node) appstruct[name] = node_schema.dictify(registration) return form_schema, appstruct
def add_nodes(self, includes, excludes, overrides): SQLAlchemySchemaNode.add_nodes(self, includes, excludes, overrides) start = colander.SchemaNode(colander.Int(), name='start', title='Start', missing=0, default=0, validator=colander.Range(min=0)) limit = colander.SchemaNode(colander.Int(), name='limit', title='Limit', missing=25, default=25, validator=colander.Range(min=1)) values = [prop.key for prop in self.inspector.column_attrs] order_by = colander.SchemaNode(colander.String(), name='order_by', title='Order By', missing=values[0], default=values[0], validator=colander.OneOf(values)) direction_values = ['asc', 'desc'] validator = colander.OneOf(direction_values) direction = colander.SchemaNode(colander.String(), name='direction', title='Direction', missing='asc', default='asc', validator=validator) intersect = colander.SchemaNode(colander.Boolean(), name='intersect', title='Intersect Criterions', missing=True, default=True) self.order_by_values = values self.direction_values = direction_values self.add(start) self.add(limit) self.add(order_by) self.add(direction) self.add(intersect)
def test_dictify(self): import datetime overrides = { 'person': { 'includes': ['name', 'surname', 'gender', 'addresses'], 'overrides': { 'addresses': { 'includes': ['street', 'city'], 'overrides': { 'city': { 'exclude': False } } } } }, } includes = ['email', 'enabled', 'created', 'timeout', 'person'] schema = SQLAlchemySchemaNode(Account, includes=includes, overrides=overrides) #Add a non-SQLAlchemy field schema.add(colander.SchemaNode(colander.String, name='non_sql')) args = dict(street='My Street', city='My City') address = Address(**args) kws = dict(name='My Name', surname='My Surname', gender='M', addresses=[address]) person = Person(**kws) params = dict(email='*****@*****.**', enabled=True, created=datetime.datetime.now(), timeout=datetime.time(hour=00, minute=00), person=person) account = Account(**params) dictified = schema.dictify(account) kws['addresses'] = [args] params['person'] = kws self.assertEqual(dictified, params) for key in params: self.assertIn(key, dictified) if key == 'person': for k in kws: self.assertIn(k, dictified[key])
def test_defaultmissing_primarykey(self): """Ensure proper handling of empty values on primary keys """ Base = declarative_base() class User(Base): __tablename__ = 'user' # the follwing is automatically made autoincrement=True id = Column(Integer, primary_key=True) schema = SQLAlchemySchemaNode(User) # from <FORM> result into SQLA; tests missing self.assertEqual(schema['id'].missing, colander.drop) deserialized = schema.deserialize({}) self.assertNotIn('id', deserialized) # from SQLA result into <FORM>; tests default self.assertEqual(schema['id'].default, colander.null) serialized = schema.serialize({}) self.assertIn('id', serialized) self.assertEqual(serialized['id'], colander.null) class Widget(Base): __tablename__ = 'widget' id = Column(String, primary_key=True) schema = SQLAlchemySchemaNode(Widget) # from <FORM> result into SQLA; tests missing self.assertEqual(schema['id'].missing, colander.required) self.assertRaises(colander.Invalid, schema.deserialize, {}) # from SQLA result into <FORM>; tests default self.assertEqual(schema['id'].default, colander.null) serialized = schema.serialize({}) self.assertIn('id', serialized) self.assertEqual(serialized['id'], colander.null)
def get_sequence_model_admin(model, title=u""): """ Return a schema for configuring sequence of models model The SQLAlchemy model to configure """ node_schema = SQLAlchemySchemaNode( model, widget=deform.widget.MappingWidget( template=TEMPLATES_URL + "clean_mapping.pt", ) ) node_schema.name = 'data' schema = colander.SchemaNode(colander.Mapping()) schema.add( colander.SchemaNode( colander.Sequence(), node_schema, widget=deform.widget.SequenceWidget( orderable=True, template=TEMPLATES_URL + "clean_sequence.pt", ), title=title, name='datas') ) def dictify(models): return {'datas': [node_schema.dictify(model) for model in models]} def objectify(datas): return [node_schema.objectify(data) for data in datas] schema.dictify = dictify schema.objectify = objectify return schema
def get_add_edit_schema(edit=False): """ Add a form schema for login add/edit :returns: A colander form schema """ schema = SQLAlchemySchemaNode(Login) set_widgets(schema) schema.add( colander.SchemaNode( colander.String(), name="primary_group", validator=_deferred_primary_group_validator, widget=_deferred_primary_group_widget, title=u"Rôle de l'utilisateur", ) ) schema.add( colander.SchemaNode( colander.Set(), name="groups", validator=_deferred_group_validator, widget=_deferred_group_widget, title=u"Droits spécifiques", ) ) if edit: schema['login'].validator = _deferred_login_validator schema['pwd_hash'].missing = colander.drop schema['user_id'].validator = _deferred_user_id_validator else: schema['user_id'].validator = _get_unique_user_id_validator() schema['login'].validator = _get_unique_login_validator() return schema
def get_sequence_model_admin(model, title=u""): """ Return a schema for configuring sequence of models model The SQLAlchemy model to configure """ node_schema = SQLAlchemySchemaNode(model) node_schema.name = 'data' schema = colander.SchemaNode(colander.Mapping()) schema.add( colander.SchemaNode( colander.Sequence(), node_schema, widget=deform_widget.SequenceWidget( min_len=1, orderable=True, ), title=title, name='datas') ) return schema
def get_schema_from_relationship(self, prop, overrides): rel_node = SQLAlchemySchemaNode.get_schema_from_relationship(self, prop, overrides) if rel_node == None: return None name = prop.key if prop.uselist: comparators = [('', ''), ('contains', 'contains'), ('notcontains', 'not contains'), ('__eq__', '=='), ('__neq__', '!=')] default_comp = '__eq__' else: comparators = [('', ''), ('__eq__', '=='), ('__neq__', '!=')] default_comp = '__eq__' self.comparators[name] = comparators validator = colander.OneOf([v[0] for v in comparators if v[0]]) # Create the right node! rel_node.name = 'value' rel_node.title = rel_node.title.title() comp_node = colander.SchemaNode(colander.String(), name='comparator', title='Comparator', missing=default_comp, default=default_comp, validator=validator) mapping_name = '{}_criterion'.format(name) mapping_title = '{} Criterion'.format(title) return colander.SchemaNode(colander.Mapping(), rel_node, comp_node, name=mapping_name, title=mapping_title)
def get_admin_income_statement_measure_schema(total=False): """ Build the schema for income statement measure type edit/add Total types are more complex and can be : * The sum of categories * A list of account prefix (like the common type of measure_types) """ if total: schema = SQLAlchemySchemaNode( IncomeStatementMeasureType, includes=( "category_id", 'label', "account_prefix", 'is_total', 'order', ), ) schema['label'].validator = deferred_label_validator schema['is_total'].widget = deform.widget.HiddenWidget() schema.add_before( 'account_prefix', colander.SchemaNode( colander.String(), name="total_type", title=u"Cet indicateur est il définit comme :", widget=deform_extensions.RadioChoiceToggleWidget( values=( ( "categories", u"la somme des indicateurs de une ou plusieurs " u"catégories ?", "categories", ), ( "account_prefix", u"un groupement d'écritures ?", "account_prefix", ), ( "complex_total", u"le résultat d'une formule arithmétique basée sur " u"les catégories et les indicateurs ?", "complex_total", ), ) ), missing=colander.drop, ) ) schema['account_prefix'].missing = "" schema.add( colander.SchemaNode( colander.String(), name="complex_total", title=u"Combinaison complexe de catégories et d'indicateurs", description=deferred_complexe_total_description, validator=complex_total_validator, missing="" ) ) schema.add( colander.SchemaNode( CsvTuple(), name="categories", title=u"Somme des catégories", description=u"Représentera la somme des catégories " u"sélectionnées", widget=deferred_categories_widget, ) ) else: schema = SQLAlchemySchemaNode( IncomeStatementMeasureType, excludes=('is_total', "categories") ) schema['label'].validator = deferred_label_validator return schema
from sqlalchemy import Column, String, Text from colander import null from colanderalchemy import SQLAlchemySchemaNode from deform.widget import RichTextWidget, HiddenWidget, PasswordWidget from terms.server.schemata import Schema class Person(Schema): name = Column(String()) surname = Column(String()) password = Column(String()) PersonSchema = SQLAlchemySchemaNode(Person) PersonSchema.get('id').widget = HiddenWidget() PersonSchema.get('_id').widget = HiddenWidget() PersonSchema.get('ntype').widget = HiddenWidget() class PasswordWidget(PasswordWidget): def deserialize(self, field, pstruct): value = super(PasswordWidget, self).deserialize(field, pstruct) if isinstance(value, basestring) and len(value) == 60: return value try: return bcrypt.hashpw(value, bcrypt.gensalt()) except TypeError:
def get_schema_from_column(self, prop, overrides): col_node = SQLAlchemySchemaNode.get_schema_from_column(self, prop, overrides) col_node.missing = colander.null col_node.default = colander.null name = prop.key column = prop.columns[0] column_type = getattr(column.type, 'impl', column.type) type_ = colander.String() if isinstance(column_type, (Boolean, Enum)): comparators = [('', ''), ('__eq__', '=='), ('__neq__', '!=')] default_comp = '__eq__' elif isinstance(column_type, String): comparators = [('', ''), ('like', 'like'), ('ilike', 'ilike')] default_comp = 'like' elif isinstance(column_type, (Date, DateTime, Time)): comparators = [('', ''), ('__lt__', '<'), ('__lte__', '<='), ('__eq__', '=='), ('__neq__', '!='), ('__gte__', '>='), ('__gt__', '>')] default_comp = '__gte__' elif isinstance(column_type, (Float, Integer, Numeric)): comparators = [('', ''), ('__lt__', '<'), ('__lte__', '<='), ('__eq__', '=='), ('__neq__', '!='), ('__gte__', '>='), ('__gt__', '>')] default_comp = '__eq__' else: raise NotImplementedError('Unknown type: %s' % column_type) self.comparators[name] = comparators validator = colander.OneOf([v[0] for v in comparators if v[0]]) # Create right node! col_node.title = col_node.title.title() comp_node = colander.SchemaNode(colander.String(), name='comparator', title='Comparator', missing=default_comp, default=default_comp, validator=validator) mapping_name = '{}_criterion'.format(name) mapping_title = '' # '{} Criterion'.format(title) return colander.SchemaNode(colander.Mapping(), col_node, comp_node, name=mapping_name, title=mapping_title)