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 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 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 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)
Example #5
0
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
Example #6
0
class EstimationAdminView(BaseEditView):
    factory = Estimation
    schema = SQLAlchemySchemaNode(
        Estimation,
        title=u"Formulaire d'édition forcée de devis/factures/avoirs",
        help_msg=u"Les montants sont *10^5   10 000==1€",
    )
Example #7
0
 def group_schema(self, group, columns):
     columns = self.preprocessing(columns)
     includes = [x for x in columns]
     return SQLAlchemySchemaNode(self.table,
                                 name=group,
                                 title=group,
                                 includes=includes)
Example #8
0
 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)
Example #10
0
    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)
Example #11
0
 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
Example #12
0
    def test_validator_typedecorator_override(self):
        Base = declarative_base()

        def location_validator(value, node):
            """A dummy validator."""
            pass

        class LocationEnum(TypeDecorator):
            impl = Enum
            __colanderalchemy_config__ = {'validator': location_validator}

        class LocationString(TypeDecorator):
            impl = String
            __colanderalchemy_config__ = {'validator': location_validator}

        class House(Base):
            __tablename__ = 'house'
            id = Column(Integer, primary_key=True)
            door = Column(LocationEnum(['back', 'front']))
            window = Column(LocationString(128))

        schema = SQLAlchemySchemaNode(House)

        self.assertEqual(schema['door'].validator, location_validator)
        self.assertEqual(schema['window'].validator, location_validator)
Example #13
0
    def test_typedecorator_overwrite(self):
        key = SQLAlchemySchemaNode.sqla_info_key
        Base = declarative_base()

        class MyIntType(TypeDecorator):
            impl = Integer
            __colanderalchemy_config__ = {'typ': colander.String()}

        def string_validator(node, value):
            """A dummy validator."""
            pass

        class MyString(TypeDecorator):
            impl = Unicode
            __colanderalchemy_config__ = {'validator': string_validator}

        class World(Base):
            __tablename__ = 'world'
            id = Column(Integer, primary_key=True)
            not_a_number = Column(MyIntType)
            number = Column(MyIntType, info={key:
                                             {'typ': colander.Integer}})
            name = Column(MyString(5))

        world_schema = SQLAlchemySchemaNode(World)

        self.assertIsInstance(
            world_schema['not_a_number'].typ, colander.String)
        # should be overwritten by the key
        self.assertNotIsInstance(world_schema['number'].typ, colander.String)

        # test if validator is not overwritten by ColanderAlchemy
        self.assertEqual(world_schema['name'].validator, string_validator)
Example #14
0
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
Example #15
0
def test_task_line(config, request_with_config, estimation, unity, tva,
                   product, product_without_tva):
    from autonomie.models.task.task import TaskLine
    schema = SQLAlchemySchemaNode(TaskLine)
    request_with_config.context = estimation
    schema = schema.bind(request=request_with_config)
    value = {
        'description': u'test',
        'cost': 450,
        'quantity': 1,
        'unity': u'Mètre',
        'tva': 20.00,
        'product_id': product.id
    }
    assert schema.deserialize(value) == {
        'description': u'test',
        'cost': 45000000,
        'quantity': 1.0,
        'unity': u'Mètre',
        'tva': 2000,
        'product_id': product.id,
        'order': 1
    }
    value = {
        'description': u'test',
        'cost': 450,
        'quantity': 1,
        'unity': u'Mètre',
        'tva': 20.00,
        'product_id': product_without_tva.id
    }
    with pytest.raises(colander.Invalid):
        schema.deserialize(value)
Example #16
0
def test_task_line_group_lines(tva, unity):
    from autonomie.models.task.task import TaskLineGroup
    schema = SQLAlchemySchemaNode(TaskLineGroup, includes=('lines', ))
    schema = schema.bind()
    value = {'lines': []}
    with pytest.raises(colander.Invalid):
        schema.deserialize(value)

    value = {
        'lines': [{
            'cost': 15,
            'tva': 20,
            'description': u'description',
            'unity': u"Mètre",
            "quantity": 5,
        }]
    }
    assert schema.deserialize(value) == {
        'lines': [{
            'cost': 1500000,
            'tva': 2000,
            'description': u'description',
            'unity': u"Mètre",
            "quantity": 5.0,
            'order': 1
        }]
    }
Example #17
0
class CancelInvoiceAdminView(BaseEditView):
    factory = CancelInvoice
    schema = SQLAlchemySchemaNode(
        CancelInvoice,
        title=u"Formulaire d'édition forcée de devis/factures/avoirs",
        help_msg=u"Les montants sont *10^5   10 000==1€",
    )
Example #18
0
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
Example #19
0
    def test_example_typedecorator_overwrite(self):
        Base = declarative_base()

        class Email(TypeDecorator):
            impl = Unicode
            __colanderalchemy_config__ = {'validator': colander.Email}

        class User(Base):
            __tablename__ = 'user'
            id = Column(Integer, primary_key=True)
            email = Column(Email, nullable=False)
            second_email = Column(Email)

        schema = SQLAlchemySchemaNode(User)

        # because of naming clashes, we need to do this in another function
        def generate_colander():
            class User(colander.MappingSchema):
                id = colander.SchemaNode(colander.Integer(),
                                         missing=colander.drop)
                email = colander.SchemaNode(colander.String(),
                                            validator=colander.Email())
                second_email = colander.SchemaNode(colander.String(),
                                                   validator=colander.Email(),
                                                   missing=colander.null)

            return User()

        schema2 = generate_colander()

        self.is_equal_schema(schema, schema2)
Example #20
0
class AdminInvoice(BaseEditView):
    """
    Vue pour l'administration de factures ?token=admin

    Vue accessible aux utilisateurs admin
    """
    schema = SQLAlchemySchemaNode(Invoice)
Example #21
0
class BloodPressureCrudViews(IndividualRecordCRUDView, CRUDView):
    model = BloodPressure
    schema = SQLAlchemySchemaNode(BloodPressure,
                                  includes=[
                                      'time', 'systolic', 'diastolic',
                                      colander.SchemaNode(colander.Float(),
                                                          name='heart_rate',
                                                          title='Heart rate',
                                                          missing=None)
                                  ])

    title = 'blood pressure'
    url_path = '/blood_pressure'
    list_display = ('time', 'systolic', 'diastolic', heart_rate)

    def get_list_query(self):
        query = super(BloodPressureCrudViews, self).get_list_query()

        return query.order_by(BloodPressure.time.desc())

    def dictify(self, obj):

        appstruct = super(BloodPressureCrudViews, self).dictify(obj)

        if obj.heart_rate is not None:
            appstruct['heart_rate'] = obj.heart_rate.rate

        return appstruct
Example #22
0
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
Example #23
0
    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)
Example #24
0
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
Example #25
0
    def test_aliased_view(self):
        """tests aliased view that was broken in 0.3.1
        """
        Base = declarative_base()

        class Person(Base):
            __tablename__ = 'person'

            id = Column(Integer, primary_key=True)
            parent_id = Column(Integer, ForeignKey('person.id'))

        class ParentView(Base):
            _parent_table = Person.__table__
            _child_table = aliased(_parent_table)

            __mapper_args__ = {
                'primary_key': [_child_table.c.id],
                'include_properties': [_child_table.c.id],
            }

            __table__ = _parent_table.join(
                _child_table,
                _child_table.c.parent_id == _parent_table.c.id
            )

        schema = SQLAlchemySchemaNode(ParentView)
        self.assertIn('id', schema)
Example #26
0
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()
Example #27
0
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
Example #28
0
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
Example #29
0
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
Example #30
0
class HeightWeightCrudViews(IndividualRecordCRUDView, CRUDView):
    model = HeightWeight
    schema = SQLAlchemySchemaNode(
        HeightWeight, includes=['time', 'weight', 'height', notes_schema])
    url_path = '/height_weight'
    list_display = ('time', 'weight', 'height', bmi, notes)

    def get_list_query(self):
        query = super(HeightWeightCrudViews, self).get_list_query()
        query = query.outerjoin(HeightWeight.notes)
        query = query.with_entities(HeightWeight.id, HeightWeight.time,
                                    HeightWeight.weight, HeightWeight.height,
                                    HeightWeight.bmi, Note.text)

        return query.order_by(HeightWeight.time.desc())

    def dictify(self, obj):
        """
        Serialize a HeightWeightCrudViews object to a dict
        """

        # Default serialization for built-in fields
        appstruct = super(HeightWeightCrudViews, self).dictify(obj)

        if obj.notes is not None:
            appstruct['notes'] = obj.notes.text

        return appstruct