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)
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}), ), )
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
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, )
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