def input_to_json_data(value, state=None):
    return conv.pipe(
        conv.make_input_to_json(),
        conv.test_isinstance(dict),
        conv.struct(
            dict(
                resultat_officiel=conv.pipe(
                    conv.test_isinstance(dict),
                    conv.uniform_mapping(
                        conv.pipe(
                            conv.test_isinstance(basestring),
                            conv.not_none,
                        ),
                        conv.pipe(
                            conv.test_isinstance(dict),
                            conv.struct(
                                dict(
                                    code=conv.pipe(
                                        conv.test_isinstance(basestring),
                                        conv.not_none,
                                    ),
                                    name=conv.pipe(
                                        conv.test_isinstance(basestring),
                                        conv.not_none,
                                    ),
                                    value=conv.pipe(
                                        conv.test_isinstance(float),
                                        conv.not_none,
                                    ),
                                ), ),
                            conv.not_none,
                        ),
                    ),
                    conv.not_none,
                ),
                scenario=conv.pipe(
                    conv.test_isinstance(dict),
                    conv.struct(
                        dict(
                            test_case=conv.pipe(
                                conv.test_isinstance(dict),
                                # For each entity convert its members from a dict to a list.
                                conv.uniform_mapping(
                                    conv.noop,
                                    conv.pipe(
                                        conv.test_isinstance(dict),
                                        conv.function(
                                            transform_entity_member_by_id_to_members
                                        ),
                                    ),
                                ),
                            ), ),
                        default=conv.noop,
                    ),
                    tax_benefit_system.Scenario.make_json_to_instance(
                        tax_benefit_system=tax_benefit_system),
                    conv.not_none,
                ),
            ), ),
    )(value, state=state or conv.default_state)
def input_to_json_data(value, state=None):
    return conv.pipe(
        conv.make_input_to_json(),
        conv.test_isinstance(dict),
        conv.struct(
            dict(
                resultat_officiel=conv.pipe(
                    conv.test_isinstance(dict),
                    conv.uniform_mapping(
                        conv.pipe(conv.test_isinstance(basestring), conv.not_none),
                        conv.pipe(
                            conv.test_isinstance(dict),
                            conv.struct(
                                dict(
                                    code=conv.pipe(conv.test_isinstance(basestring), conv.not_none),
                                    name=conv.pipe(conv.test_isinstance(basestring), conv.not_none),
                                    value=conv.pipe(conv.test_isinstance(float), conv.not_none),
                                )
                            ),
                            conv.not_none,
                        ),
                    ),
                    conv.not_none,
                ),
                scenario=conv.pipe(
                    conv.test_isinstance(dict),
                    conv.struct(
                        dict(
                            test_case=conv.pipe(
                                conv.test_isinstance(dict),
                                # For each entity convert its members from a dict to a list.
                                conv.uniform_mapping(
                                    conv.noop,
                                    conv.pipe(
                                        conv.test_isinstance(dict),
                                        conv.function(transform_entity_member_by_id_to_members),
                                    ),
                                ),
                            )
                        ),
                        default=conv.noop,
                    ),
                    tax_benefit_system.Scenario.make_json_to_instance(tax_benefit_system=tax_benefit_system),
                    conv.not_none,
                ),
            )
        ),
    )(value, state=state or conv.default_state)
Пример #3
0
 def make_json_to_array_by_period(self, period):
     return conv.condition(
         conv.test_isinstance(dict),
         conv.pipe(
             # Value is a dict of (period, value) couples.
             conv.uniform_mapping(
                 conv.pipe(
                     conv.function(periods.period),
                     conv.not_none,
                 ),
                 conv.pipe(
                     conv.make_item_to_singleton(),
                     conv.uniform_sequence(self.json_to_dated_python, ),
                     conv.empty_to_none,
                     conv.function(lambda cells_list: np.array(
                         cells_list, dtype=self.dtype)),
                 ),
                 drop_none_values=True,
             ),
             conv.empty_to_none,
         ),
         conv.pipe(
             conv.make_item_to_singleton(),
             conv.uniform_sequence(self.json_to_dated_python, ),
             conv.empty_to_none,
             conv.function(
                 lambda cells_list: np.array(cells_list, dtype=self.dtype)),
             conv.function(lambda array: {period: array}),
         ),
     )
Пример #4
0
    def json_or_python_to_input_variables(value, state=None):
        if value is None:
            return value, None
        if state is None:
            state = conv.default_state

        input_variables, errors = conv.pipe(
            conv.test_isinstance(dict),
            conv.uniform_mapping(
                conv.pipe(
                    conv.test_isinstance(basestring_type),
                    conv.not_none,
                ),
                conv.noop,
            ),
        )(value, state=state)

        if errors is not None:
            return input_variables, errors

        for input_variable_name in input_variables.keys():
            if input_variable_name not in variables_name:
                # We only import VariableNotFound here to avoid a circular dependency in imports
                from .taxbenefitsystems import VariableNotFound
                raise VariableNotFound(input_variable_name, tax_benefit_system)

        input_variables, errors = conv.pipe(
            make_json_or_python_to_array_by_period_by_variable_name(
                tax_benefit_system, period),
            conv.empty_to_none,
        )(value, state=state)
        if errors is not None:
            return input_variables, errors
        if input_variables is None:
            return input_variables, None

        count_by_entity_key = {}
        errors = {}
        for variable_name, array_by_period in input_variables.items():
            column = tax_benefit_system.get_variable(variable_name)
            entity_key = column.entity.key
            entity_count = count_by_entity_key.get(entity_key, 0)
            for variable_period, variable_array in array_by_period.items():
                if entity_count == 0:
                    count_by_entity_key[entity_key] = entity_count = len(
                        variable_array)
                elif len(variable_array) != entity_count:
                    errors[column.name] = state._(
                        "Array has not the same length as other variables of entity {}: {} instead of {}"
                    ).format(column.name, len(variable_array), entity_count)

        return input_variables, errors or None
Пример #5
0
 def json_to_python(self):
     return conv.condition(
         conv.test_isinstance(dict),
         conv.pipe(
             # Value is a dict of (period, value) couples.
             conv.uniform_mapping(
                 conv.pipe(
                     conv.function(periods.period),
                     conv.not_none,
                 ),
                 self.json_to_dated_python,
             ), ),
         self.json_to_dated_python,
     )
Пример #6
0
def make_json_or_python_to_test(tax_benefit_system):
    validate = conv.struct(
        dict(
            itertools.chain(
                dict(
                    absolute_error_margin=conv.pipe(
                        conv.test_isinstance((float, int)),
                        conv.test_greater_or_equal(0),
                    ),
                    axes=make_json_or_python_to_axes(tax_benefit_system),
                    description=conv.pipe(
                        conv.test_isinstance(basestring_type),
                        conv.cleanup_line,
                    ),
                    input_variables=conv.pipe(
                        conv.test_isinstance(dict),
                        conv.uniform_mapping(
                            conv.pipe(
                                conv.test_isinstance(basestring_type),
                                conv.not_none,
                            ),
                            conv.noop,
                        ),
                        conv.empty_to_none,
                    ),
                    keywords=conv.pipe(
                        conv.make_item_to_singleton(),
                        conv.test_isinstance(list),
                        conv.uniform_sequence(
                            conv.pipe(
                                conv.test_isinstance(basestring_type),
                                conv.cleanup_line,
                            ),
                            drop_none_items=True,
                        ),
                        conv.empty_to_none,
                    ),
                    name=conv.pipe(
                        conv.test_isinstance(basestring_type),
                        conv.cleanup_line,
                    ),
                    output_variables=conv.test_isinstance(dict),
                    period=conv.pipe(
                        conv.function(periods.period),
                        conv.not_none,
                    ),
                    relative_error_margin=conv.pipe(
                        conv.test_isinstance((float, int)),
                        conv.test_greater_or_equal(0),
                    ),
                ).items(),
                ((entity.plural,
                  conv.pipe(
                      conv.make_item_to_singleton(),
                      conv.test_isinstance(list),
                  )) for entity in tax_benefit_system.entities),
            )), )

    def json_or_python_to_test(value, state=None):
        if value is None:
            return value, None
        if state is None:
            state = conv.default_state
        value, error = conv.pipe(
            conv.test_isinstance(dict),
            validate,
        )(value, state=state)
        if error is not None:
            return value, error

        value, error = conv.struct(
            dict(output_variables=make_json_or_python_to_input_variables(
                tax_benefit_system, value['period']), ),
            default=conv.noop,
        )(value, state=state)
        if error is not None:
            return value, error

        test_case = value.copy()
        absolute_error_margin = test_case.pop('absolute_error_margin')
        axes = test_case.pop('axes')
        description = test_case.pop('description')
        input_variables = test_case.pop('input_variables')
        keywords = test_case.pop('keywords')
        name = test_case.pop('name')
        output_variables = test_case.pop('output_variables')
        period = test_case.pop('period')
        relative_error_margin = test_case.pop('relative_error_margin')

        if test_case is not None and all(
                entity_members is None
                for entity_members in test_case.values()):
            test_case = None

        scenario, error = tax_benefit_system.Scenario.make_json_to_instance(
            repair=True, tax_benefit_system=tax_benefit_system)(dict(
                axes=axes,
                input_variables=input_variables,
                period=period,
                test_case=test_case,
            ),
                                                                state=state)
        if error is not None:
            return scenario, error

        return {
            key: value
            for key, value in dict(
                absolute_error_margin=absolute_error_margin,
                description=description,
                keywords=keywords,
                name=name,
                output_variables=output_variables,
                relative_error_margin=relative_error_margin,
                scenario=scenario,
            ).items() if value is not None
        }, None

    return json_or_python_to_test
        def json_or_python_to_test_case(value, state = None):
            if value is None:
                return value, None
            if state is None:
                state = conv.default_state

            column_by_name = self.tax_benefit_system.column_by_name

            # First validation and conversion step
            test_case, error = conv.pipe(
                conv.test_isinstance(dict),
                conv.struct(
                    dict(
                        familles = conv.pipe(
                            conv.condition(
                                conv.test_isinstance(list),
                                conv.pipe(
                                    conv.uniform_sequence(
                                        conv.test_isinstance(dict),
                                        drop_none_items = True,
                                        ),
                                    conv.function(lambda values: collections.OrderedDict(
                                        (value.pop('id', index), value)
                                        for index, value in enumerate(values)
                                        )),
                                    ),
                                ),
                            conv.test_isinstance(dict),
                            conv.uniform_mapping(
                                conv.pipe(
                                    conv.test_isinstance((basestring, int)),
                                    conv.not_none,
                                    ),
                                conv.pipe(
                                    conv.test_isinstance(dict),
                                    conv.struct(
                                        dict(itertools.chain(
                                            dict(
                                                enfants = conv.pipe(
                                                    conv.test_isinstance(list),
                                                    conv.uniform_sequence(
                                                        conv.test_isinstance((basestring, int)),
                                                        drop_none_items = True,
                                                        ),
                                                    conv.default([]),
                                                    ),
                                                parents = conv.pipe(
                                                    conv.test_isinstance(list),
                                                    conv.uniform_sequence(
                                                        conv.test_isinstance((basestring, int)),
                                                        drop_none_items = True,
                                                        ),
                                                    conv.default([]),
                                                    ),
                                                ).iteritems(),
                                            (
                                                (column.name, column.json_to_python)
                                                for column in column_by_name.itervalues()
                                                if column.entity == 'fam'
                                                ),
                                            )),
                                        drop_none_values = True,
                                        ),
                                    ),
                                drop_none_values = True,
                                ),
                            conv.default({}),
                            ),
                        individus = conv.pipe(
                            conv.condition(
                                conv.test_isinstance(list),
                                conv.pipe(
                                    conv.uniform_sequence(
                                        conv.test_isinstance(dict),
                                        drop_none_items = True,
                                        ),
                                    conv.function(lambda values: collections.OrderedDict(
                                        (value.pop('id', index), value)
                                        for index, value in enumerate(values)
                                        )),
                                    ),
                                ),
                            conv.test_isinstance(dict),
                            conv.uniform_mapping(
                                conv.pipe(
                                    conv.test_isinstance((basestring, int)),
                                    conv.not_none,
                                    ),
                                conv.pipe(
                                    conv.test_isinstance(dict),
                                    conv.struct(
                                        dict(
                                            (column.name, column.json_to_python)
                                            for column in column_by_name.itervalues()
                                            if column.entity == 'ind' and column.name not in (
                                                'idfam', 'idfoy', 'idmen', 'quifam', 'quifoy', 'quimen')
                                            ),
                                        drop_none_values = True,
                                        ),
                                    ),
                                drop_none_values = True,
                                ),
                            conv.empty_to_none,
                            conv.not_none,
                            ),
                        ),
                    ),
                )(value, state = state)
            if error is not None:
                return test_case, error

            # Second validation step
            familles_individus_id = list(test_case['individus'].iterkeys())
            test_case, error = conv.struct(
                dict(
                    familles = conv.uniform_mapping(
                        conv.noop,
                        conv.struct(
                            dict(
                                enfants = conv.uniform_sequence(conv.test_in_pop(familles_individus_id)),
                                parents = conv.uniform_sequence(conv.test_in_pop(familles_individus_id)),
                                ),
                            default = conv.noop,
                            ),
                        ),
                    ),
                default = conv.noop,
                )(test_case, state = state)

            remaining_individus_id = set(familles_individus_id)
            if remaining_individus_id:
                if error is None:
                    error = {}
                for individu_id in remaining_individus_id:
                    error.setdefault('individus', {})[individu_id] = state._(u"Individual is missing from {}").format(
                        state._(u' & ').join(
                            word
                            for word in [
                                u'familles' if individu_id in familles_individus_id else None,
                                ]
                            if word is not None
                            ))
            if error is not None:
                return test_case, error

            return test_case, error
def validate_node_json(node, state = None):
    if node is None:
        return None, None
    state = conv.add_ancestor_to_state(state, node)

    validated_node, error = conv.test_isinstance(dict)(node, state = state)
    if error is not None:
        conv.remove_ancestor_from_state(state, node)
        return validated_node, error

    validated_node, errors = conv.struct(
        {
            '@context': conv.pipe(
                conv.test_isinstance(basestring),
                conv.make_input_to_url(full = True),
                conv.test_equals(u'http://openfisca.fr/contexts/legislation.jsonld'),
                ),
            '@type': conv.pipe(
                conv.test_isinstance(basestring),
                conv.cleanup_line,
                conv.test_in((u'Node', u'Parameter', u'Scale')),
                conv.not_none,
                ),
            'comment': conv.pipe(
                conv.test_isinstance(basestring),
                conv.cleanup_text,
                ),
            'description': conv.pipe(
                conv.test_isinstance(basestring),
                conv.cleanup_line,
                ),
            },
        constructor = collections.OrderedDict,
        default = conv.noop,
        drop_none_values = 'missing',
        keep_value_order = True,
        )(validated_node, state = state)
    if errors is not None:
        conv.remove_ancestor_from_state(state, node)
        return validated_node, errors

    validated_node.pop('@context', None)  # Remove optional @context everywhere. It will be added to root node later.
    node_converters = {
        '@type': conv.noop,
        'comment': conv.noop,
        'description': conv.noop,
        }
    node_type = validated_node['@type']
    if node_type == u'Node':
        node_converters.update(dict(
            children = conv.pipe(
                conv.test_isinstance(dict),
                conv.uniform_mapping(
                    conv.pipe(
                        conv.test_isinstance(basestring),
                        conv.cleanup_line,
                        conv.not_none,
                        ),
                    conv.pipe(
                        validate_node_json,
                        conv.not_none,
                        ),
                    ),
                conv.empty_to_none,
                conv.not_none,
                ),
            ))
    elif node_type == u'Parameter':
        node_converters.update(dict(
            format = conv.pipe(
                conv.test_isinstance(basestring),
                conv.input_to_slug,
                conv.test_in([
                    'boolean',
                    'float',
                    'integer',
                    'rate',
                    ]),
                ),
            unit = conv.pipe(
                conv.test_isinstance(basestring),
                conv.input_to_slug,
                conv.test_in(units),
                ),
            values = conv.pipe(
                conv.test_isinstance(list),
                conv.uniform_sequence(
                    validate_value_json,
                    drop_none_items = True,
                    ),
                make_validate_values_json_dates(require_consecutive_dates = True),
                conv.empty_to_none,
                conv.not_none,
                ),
            ))
    else:
        assert node_type == u'Scale'
        node_converters.update(dict(
            option = conv.pipe(
                conv.test_isinstance(basestring),
                conv.input_to_slug,
                conv.test_in((
                    'contrib',
                    'main-d-oeuvre',
                    'noncontrib',
                    )),
                ),
            slices = conv.pipe(
                conv.test_isinstance(list),
                conv.uniform_sequence(
                    validate_slice_json,
                    drop_none_items = True,
                    ),
                validate_slices_json_dates,
                conv.empty_to_none,
                conv.not_none,
                ),
            unit = conv.pipe(
                conv.test_isinstance(basestring),
                conv.input_to_slug,
                conv.test_in((
                    'currency',
                    )),
                ),
            ))
    validated_node, errors = conv.struct(
        node_converters,
        constructor = collections.OrderedDict,
        drop_none_values = 'missing',
        keep_value_order = True,
        )(validated_node, state = state)

    conv.remove_ancestor_from_state(state, node)
    return validated_node, errors
def validate_node_json(node, state=None):
    if node is None:
        return None, None
    state = conv.add_ancestor_to_state(state, node)

    validated_node, error = conv.test_isinstance(dict)(node, state=state)
    if error is not None:
        conv.remove_ancestor_from_state(state, node)
        return validated_node, error

    validated_node, errors = conv.struct(
        {
            '@context':
            conv.pipe(
                conv.test_isinstance(basestring),
                conv.make_input_to_url(full=True),
                conv.test_equals(
                    u'http://openfisca.fr/contexts/legislation.jsonld'),
            ),
            '@type':
            conv.pipe(
                conv.test_isinstance(basestring),
                conv.cleanup_line,
                conv.test_in((u'Node', u'Parameter', u'Scale')),
                conv.not_none,
            ),
            'comment':
            conv.pipe(
                conv.test_isinstance(basestring),
                conv.cleanup_text,
            ),
            'description':
            conv.pipe(
                conv.test_isinstance(basestring),
                conv.cleanup_line,
            ),
        },
        constructor=collections.OrderedDict,
        default=conv.noop,
        drop_none_values='missing',
        keep_value_order=True,
    )(validated_node, state=state)
    if errors is not None:
        conv.remove_ancestor_from_state(state, node)
        return validated_node, errors

    validated_node.pop(
        '@context', None
    )  # Remove optional @context everywhere. It will be added to root node later.
    node_converters = {
        '@type': conv.noop,
        'comment': conv.noop,
        'description': conv.noop,
    }
    node_type = validated_node['@type']
    if node_type == u'Node':
        node_converters.update(
            dict(children=conv.pipe(
                conv.test_isinstance(dict),
                conv.uniform_mapping(
                    conv.pipe(
                        conv.test_isinstance(basestring),
                        conv.cleanup_line,
                        conv.not_none,
                    ),
                    conv.pipe(
                        validate_node_json,
                        conv.not_none,
                    ),
                ),
                conv.empty_to_none,
                conv.not_none,
            ), ))
    elif node_type == u'Parameter':
        node_converters.update(
            dict(
                format=conv.pipe(
                    conv.test_isinstance(basestring),
                    conv.input_to_slug,
                    conv.test_in([
                        'boolean',
                        'float',
                        'integer',
                        'rate',
                    ]),
                ),
                unit=conv.pipe(
                    conv.test_isinstance(basestring),
                    conv.input_to_slug,
                    conv.test_in(units),
                ),
                values=conv.pipe(
                    conv.test_isinstance(list),
                    conv.uniform_sequence(
                        validate_value_json,
                        drop_none_items=True,
                    ),
                    make_validate_values_json_dates(
                        require_consecutive_dates=True),
                    conv.empty_to_none,
                    conv.not_none,
                ),
            ))
    else:
        assert node_type == u'Scale'
        node_converters.update(
            dict(
                option=conv.pipe(
                    conv.test_isinstance(basestring),
                    conv.input_to_slug,
                    conv.test_in((
                        'contrib',
                        'main-d-oeuvre',
                        'noncontrib',
                    )),
                ),
                slices=conv.pipe(
                    conv.test_isinstance(list),
                    conv.uniform_sequence(
                        validate_slice_json,
                        drop_none_items=True,
                    ),
                    validate_slices_json_dates,
                    conv.empty_to_none,
                    conv.not_none,
                ),
                unit=conv.pipe(
                    conv.test_isinstance(basestring),
                    conv.input_to_slug,
                    conv.test_in(('currency', )),
                ),
            ))
    validated_node, errors = conv.struct(
        node_converters,
        constructor=collections.OrderedDict,
        drop_none_values='missing',
        keep_value_order=True,
    )(validated_node, state=state)

    conv.remove_ancestor_from_state(state, node)
    return validated_node, errors