def get_introspection_data(cls, tax_benefit_system): """ Get instrospection data about the code of the variable. :returns: (comments, source file path, source code, start line number) :rtype: tuple """ comments = inspect.getcomments(cls) # Handle dynamically generated variable classes or Jupyter Notebooks, which have no source. try: absolute_file_path = inspect.getsourcefile(cls) except TypeError: source_file_path = None else: source_file_path = absolute_file_path.replace( tax_benefit_system.get_package_metadata()['location'], '') try: source_lines, start_line_number = inspect.getsourcelines(cls) # Python 2 backward compatibility if isinstance(source_lines[0], bytes): source_lines = [ source_line.decode('utf-8') for source_line in source_lines ] source_code = textwrap.dedent(''.join(source_lines)) except (IOError, TypeError): source_code, start_line_number = None, None return comments, to_unicode(source_file_path), to_unicode( source_code), start_line_number
def build_entity(entity): formatted_doc = to_unicode(entity.doc.strip()) formatted_entity = { 'plural': entity.plural, 'description': to_unicode(entity.label), 'documentation': formatted_doc } if not entity.is_person: formatted_entity['roles'] = { role.key: build_role(role) for role in entity.roles } return formatted_entity
def test_decomposition(print_decomposition = False): simulation = tax_benefit_system.new_scenario().init_single_entity( period = "2013-01", parent1 = dict( effectif_entreprise = 3000, exposition_accident = "tres_eleve", code_postal_entreprise = "75001", ratio_alternants = .025, salaire_de_base = {"2013": 12 * 3000}, taille_entreprise = "de_20_a_249", categorie_salarie = "prive_non_cadre", ), menage = dict( zone_apl = "zone_1", ), ).new_simulation() xml_file_path = os.path.join( decompositions_directory, "fiche_de_paie_decomposition.xml" ) decomposition_json = decompositions.get_decomposition_json( tax_benefit_system, xml_file_path = xml_file_path) simulations = [simulation] response = decompositions.calculate(simulations, decomposition_json) if print_decomposition: logger.debug(to_unicode( json.dumps(response, encoding = 'utf-8', ensure_ascii = False, indent = 2) ))
def trace(tax_benefit_system, input_data): simulation = Simulation(tax_benefit_system=tax_benefit_system, simulation_json=input_data, trace=True) requested_computations = dpath.util.search(input_data, '*/*/*/*', afilter=lambda t: t is None, yielded=True) for computation in requested_computations: path = computation[0] entity_plural, entity_id, variable_name, period = path.split('/') simulation.calculate(variable_name, period) trace = deepcopy(simulation.tracer.trace) for vector_key, vector_trace in trace.items(): value = vector_trace['value'].tolist() if isinstance(value[0], Enum): value = [item.name for item in value] if isinstance(value[0], bytes): value = [to_unicode(item) for item in value] vector_trace['value'] = value return { "trace": trace, "entitiesDescription": {entity.plural: entity.ids for entity in simulation.entities.values()}, "requestedCalculations": list(simulation.tracer.requested_calculations) }
def test_decomposition(print_decomposition=False): simulation = tax_benefit_system.new_scenario().init_single_entity( period="2013-01", parent1=dict( effectif_entreprise=3000, exposition_accident="tres_eleve", code_postal_entreprise="75001", ratio_alternants=.025, salaire_de_base={"2013": 12 * 3000}, taille_entreprise="de_20_a_249", categorie_salarie="prive_non_cadre", ), menage=dict(zone_apl="zone_1", ), ).new_simulation() xml_file_path = os.path.join(decompositions_directory, "fiche_de_paie_decomposition.xml") decomposition_json = decompositions.get_decomposition_json( tax_benefit_system, xml_file_path=xml_file_path) simulations = [simulation] response = decompositions.calculate(simulations, decomposition_json) if print_decomposition: logger.debug( to_unicode( json.dumps(response, encoding='utf-8', ensure_ascii=False, indent=2)))
def test_response_data(): entities = json.loads(entities_response.data.decode('utf-8')) test_documentation = to_unicode( openfisca_country_template.entities.Household.doc.strip()) assert_equal( entities['household'], { 'description': 'All the people in a family or group who live together in the same place.', 'documentation': test_documentation, 'plural': 'households', 'roles': { 'child': { 'description': 'Other individuals living in the household.', 'plural': 'children', }, 'parent': { 'description': 'The one or two adults in charge of the household.', 'plural': 'parents', 'max': 2, } } })
def _generate_tests_from_file(tax_benefit_system, path_to_file, options): filename = os.path.splitext(os.path.basename(path_to_file))[0] name_filter = options.get('name_filter') if isinstance(name_filter, str): name_filter = to_unicode(name_filter) verbose = options.get('verbose') only_variables = options.get('only_variables') ignore_variables = options.get('ignore_variables') tests = _parse_test_file(tax_benefit_system, path_to_file) for test_index, (path_to_file, name, period_str, test) in enumerate(tests, 1): if name_filter is not None and name_filter not in filename \ and name_filter not in (test.get('name', '')) \ and name_filter not in (test.get('keywords', [])): continue keywords = test.get('keywords', []) title = "{}: {}{} - {}".format( os.path.basename(path_to_file), '[{}] '.format(', '.join(keywords)) if keywords else '', name, period_str, ) def check(): try: _run_test(period_str, test, verbose, only_variables, ignore_variables, options) except Exception: log.error(title) raise yield unittest.FunctionTestCase(check)
def calculate(tax_benefit_system, input_data): simulation = SimulationBuilder().build_from_entities(tax_benefit_system, input_data) requested_computations = dpath.util.search(input_data, '*/*/*/*', afilter = lambda t: t is None, yielded = True) computation_results = {} for computation in requested_computations: path = computation[0] entity_plural, entity_id, variable_name, period = path.split('/') variable = tax_benefit_system.get_variable(variable_name) result = simulation.calculate(variable_name, period) entity = simulation.get_entity(plural = entity_plural) entity_index = entity.ids.index(entity_id) if variable.value_type == Enum: entity_result = result.decode()[entity_index].name elif variable.value_type == float: entity_result = float(str(result[entity_index])) # To turn the float32 into a regular float without adding confusing extra decimals. There must be a better way. elif variable.value_type == str: entity_result = to_unicode(result[entity_index]) # From bytes to unicode else: entity_result = result.tolist()[entity_index] dpath.util.new(computation_results, path, entity_result) dpath.merge(input_data, computation_results) return input_data
def __init__(self, path, message, code=None): self.error = {} dpath_path = '/'.join([str(item) for item in path]) message = to_unicode(message) message = message.strip(os.linesep).replace(os.linesep, ' ') dpath.util.new(self.error, dpath_path, message) self.code = code Exception.__init__(self, str(self.error).encode('utf-8'))
def to_json_dict(self): if not isinstance(self[1], str): self[1] = to_unicode(self[1]) return collections.OrderedDict(( ('unit', self[0]), ('start', self[1]), ('size', self[2]), ))
def calculate(): tax_benefit_system = data['tax_benefit_system'] request.on_json_loading_failed = handle_invalid_json input_data = request.get_json() try: simulation = Simulation(tax_benefit_system=tax_benefit_system, simulation_json=input_data) except SituationParsingError as e: abort(make_response(jsonify(e.error), e.code or 400)) except UnicodeEncodeError as e: abort( make_response( jsonify({ "error": "'" + e[1] + "' is not a valid ASCII value." }), 400)) requested_computations = dpath.util.search(input_data, '*/*/*/*', afilter=lambda t: t is None, yielded=True) results = {} try: for computation in requested_computations: path = computation[0] entity_plural, entity_id, variable_name, period = path.split( '/') variable = tax_benefit_system.get_variable(variable_name) result = simulation.calculate(variable_name, period) entity = simulation.get_entity(plural=entity_plural) entity_index = entity.ids.index(entity_id) if variable.value_type == Enum: entity_result = result.decode()[entity_index].name elif variable.value_type == float: entity_result = float( str(result[entity_index]) ) # To turn the float32 into a regular float without adding confusing extra decimals. There must be a better way. elif variable.value_type == str: entity_result = to_unicode( result[entity_index]) # From bytes to unicode else: entity_result = result.tolist()[entity_index] dpath.util.new(results, path, entity_result) except UnicodeEncodeError as e: abort( make_response( jsonify({ "error": "'" + e[1] + "' is not a valid ASCII value." }), 400)) dpath.util.merge(input_data, results) return jsonify(input_data)
def internal_server_error(e): message = to_unicode(e.args[0]) if type(e) == UnicodeEncodeError or type(e) == UnicodeDecodeError: response = jsonify({"error": "Internal server error: '" + e[1] + "' is not a valid ASCII value."}) elif message: response = jsonify({"error": "Internal server error: " + message.strip(os.linesep).replace(os.linesep, ' ')}) else: response = jsonify({"error": "Internal server error: " + str(e)}) response.status_code = 500 return response
def __str__(self): """Transform period to a string. >>> to_unicode(period(YEAR, 2014)) '2014' >>> to_unicode(period(YEAR, '2014-2')) 'year:2014-02' >>> to_unicode(period(MONTH, '2014-2')) '2014-02' >>> to_unicode(period(YEAR, 2012, size = 2)) 'year:2012:2' >>> to_unicode(period(MONTH, 2012, size = 2)) 'month:2012-01:2' >>> to_unicode(period(MONTH, 2012, size = 12)) '2012' >>> to_unicode(period(YEAR, '2012-3', size = 2)) 'year:2012-03:2' >>> to_unicode(period(MONTH, '2012-3', size = 2)) 'month:2012-03:2' >>> to_unicode(period(MONTH, '2012-3', size = 12)) 'year:2012-03' """ unit, start_instant, size = self if unit == ETERNITY: return 'ETERNITY' year, month, day = start_instant # 1 year long period if (unit == MONTH and size == 12 or unit == YEAR and size == 1): if month == 1: # civil year starting from january return to_unicode(year) else: # rolling year return '{}:{}-{:02d}'.format(YEAR, year, month) # simple month if unit == MONTH and size == 1: return '{}-{:02d}'.format(year, month) # several civil years if unit == YEAR and month == 1: return '{}:{}:{}'.format(unit, year, size) if unit == DAY: if size == 1: return '{}-{:02d}-{:02d}'.format(year, month, day) else: return '{}:{}-{:02d}-{:02d}:{}'.format(unit, year, month, day, size) # complex period return '{}:{}-{:02d}:{}'.format(unit, year, month, size)
def suggest(self): """Returns a dict of suggestions and modifies self.test_case applying those suggestions.""" test_case = self.test_case if test_case is None: return None period_start_date = self.period.start.date period_start_year = self.period.start.year suggestions = dict() for individu in test_case['individus']: individu_id = individu['id'] if individu.get('age') is None and individu.get('age_en_mois') is None and individu.get('date_naissance') is None: # Add missing date_naissance date to person (a parent is 40 years old and a child is 10 years old. is_parent = any(individu_id in famille['parents'] for famille in test_case['familles']) birth_year = period_start_year - 40 if is_parent else period_start_year - 10 date_naissance = datetime.date(birth_year, 1, 1) individu['date_naissance'] = date_naissance suggestions.setdefault('test_case', {}).setdefault('individus', {}).setdefault(individu_id, {})[ 'date_naissance'] = date_naissance.isoformat() if individu.get('activite') is None: if find_age(individu, period_start_date) < 16: individu['activite'] = TypesActivite.etudiant suggestions.setdefault('test_case', {}).setdefault('individus', {}).setdefault(individu_id, {})[ 'activite'] = TypesActivite.etudiant individu_by_id = { individu['id']: individu for individu in test_case['individus'] } for foyer_fiscal in test_case['foyers_fiscaux']: if len(foyer_fiscal['declarants']) == 1 and foyer_fiscal['personnes_a_charge']: # Suggest "parent isolé" when foyer_fiscal contains a single "declarant" with "personnes_a_charge". if foyer_fiscal.get('caseT') is None: suggestions.setdefault('test_case', {}).setdefault('foyers_fiscaux', {}).setdefault( foyer_fiscal['id'], {})['caseT'] = foyer_fiscal['caseT'] = True elif len(foyer_fiscal['declarants']) == 2: # Suggest "PACSé" or "Marié" instead of "Célibataire" when foyer_fiscal contains 2 "declarants" without # "statut_marital". statut_marital = TypesStatutMarital.pacse # PACSé for individu_id in foyer_fiscal['declarants']: individu = individu_by_id[individu_id] if individu.get('statut_marital') == TypesStatutMarital.marie: # Marié statut_marital = TypesStatutMarital.marie for individu_id in foyer_fiscal['declarants']: individu = individu_by_id[individu_id] if individu.get('statut_marital') is None: individu['statut_marital'] = statut_marital suggestions.setdefault('test_case', {}).setdefault('individus', {}).setdefault(individu_id, {})[ 'statut_marital'] = to_unicode(statut_marital) return suggestions or None
def period(self, unit, size = 1): """Create a new period starting at instant. >>> instant(2014).period('month') Period(('month', Instant((2014, 1, 1)), 1)) >>> instant('2014-2').period('year', 2) Period(('year', Instant((2014, 2, 1)), 2)) >>> instant('2014-2-3').period('day', size = 2) Period(('day', Instant((2014, 2, 3)), 2)) """ assert unit in ('day', 'month', 'year'), 'Invalid unit: {} of type {}'.format(unit, type(unit)) assert isinstance(size, int) and size >= 1, 'Invalid size: {} of type {}'.format(size, type(size)) return Period((to_unicode(unit), self, size))
def load_variable(self, variable_class, update=False): name = to_unicode(variable_class.__name__) # Check if a Variable with the same name is already registered. baseline_variable = self.get_variable(name) if baseline_variable and not update: raise VariableNameConflict( 'Variable "{}" is already defined. Use `update_variable` to replace it.' .format(name)) variable = variable_class(baseline_variable=baseline_variable) self.variables[variable.name] = variable return variable
def replace_variable(self, variable): """ Replaces an existing OpenFisca variable in the tax and benefit system by a new one. The new variable must have the same name than the replaced one. If no variable with the given name exists in the tax and benefit system, no error will be raised and the new variable will be simply added. :param Variable variable: New variable to add. Must be a subclass of Variable. """ name = to_unicode(variable.__name__) if self.variables.get(name) is not None: del self.variables[name] self.load_variable(variable, update=False)
def __init__(self, baseline): """ :param baseline: Baseline TaxBenefitSystem. """ self.baseline = baseline self.parameters = baseline.parameters self._parameters_at_instant_cache = baseline._parameters_at_instant_cache self.variables = baseline.variables.copy() self.decomposition_file_path = baseline.decomposition_file_path self.Scenario = baseline.Scenario self.key = to_unicode(self.__class__.__name__) if not hasattr(self, 'apply'): raise Exception("Reform {} must define an `apply` function".format(self.key)) self.apply()
def build_formula(formula, country_package_metadata, source_file_path, tax_benefit_system): source_code, start_line_number = inspect.getsourcelines(formula) # Python 2 backward compatibility if isinstance(source_code[0], bytes): source_code = [ source_line.decode('utf-8') for source_line in source_code ] source_code = textwrap.dedent(''.join(source_code)) api_formula = { 'source': build_source_url(country_package_metadata, source_file_path, start_line_number, source_code), 'content': to_unicode(source_code), } if formula.__doc__: api_formula['documentation'] = to_unicode( textwrap.dedent(formula.__doc__)) return api_formula
def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('--array-length', default=1000, type=int, help="length of the array") parser.add_argument('--calculate-time', default=0.1, type=float, help="time taken by the calculation in seconds") global args args = parser.parse_args() print(to_unicode(args).encode('utf-8')) test_all_notations()
def _parse_test_file(tax_benefit_system, yaml_path): filename = os.path.splitext(os.path.basename(yaml_path))[0] with open(yaml_path) as yaml_file: try: tests = yaml.load(yaml_file, Loader=Loader) except yaml.scanner.ScannerError: log.error("{} is not a valid YAML file".format(yaml_path).encode('utf-8')) raise tests, error = conv.pipe( conv.make_item_to_singleton(), conv.uniform_sequence( conv.noop, drop_none_items = True, ), )(tests) if error is not None: embedding_error = conv.embed_error(tests, 'errors', error) assert embedding_error is None, embedding_error raise ValueError("Error in test {}:\n{}".format(yaml_path, yaml.dump(tests, Dumper=Dumper, allow_unicode = True, default_flow_style = False, indent = 2, width = 120))) for test in tests: current_tax_benefit_system = tax_benefit_system if test.get('reforms'): reforms = test.pop('reforms') if not isinstance(reforms, list): reforms = [reforms] for reform_path in reforms: current_tax_benefit_system = current_tax_benefit_system.apply_reform(reform_path) try: test, error = scenarios.make_json_or_python_to_test( tax_benefit_system = current_tax_benefit_system )(test) except Exception: log.error("{} is not a valid OpenFisca test file".format(yaml_path).encode('utf-8')) raise if error is not None: embedding_error = conv.embed_error(test, 'errors', error) assert embedding_error is None, embedding_error raise ValueError("Error in test {}:\n{}\nYaml test content: \n{}\n".format( yaml_path, error, yaml.dump(test, Dumper=Dumper, allow_unicode = True, default_flow_style = False, indent = 2, width = 120))) yield yaml_path, test.get('name') or filename, to_unicode(test['scenario'].period), test
def set_reference(self, reference): if reference: if isinstance(reference, basestring_type): reference = [to_unicode(reference)] elif isinstance(reference, list): pass elif isinstance(reference, tuple): reference = list(reference) else: raise TypeError( 'The reference of the variable {} is a {} instead of a String or a List of Strings.' .format(self.name, type(reference))) for element in reference: if not isinstance(element, basestring_type): raise TypeError( 'The reference of the variable {} is a {} instead of a String or a List of Strings.' .format(self.name, type(reference))) return reference
def test_encoding_period_id(): simulation_json = json.dumps({ "persons": { "bill": { "salary": { "2017": 60000 } }, "bell": { "salary": { "2017": 60000 } } }, "households": { "_": { "parents": ["bill", "bell"], "housing_tax": { "à": 400 }, "accommodation_size": { "2017-01": 300 }, "housing_occupancy_status": { "2017-01": "tenant" } } } }) # No UnicodeDecodeError response = post_json(simulation_json) assert_equal(response.status_code, BAD_REQUEST) response_json = json.loads(response.data.decode('utf-8')) # In Python 3, there is no encoding issue. if "Expected a period" not in to_unicode(response.data): assert_in( "'à' is not a valid ASCII value.", response_json['error'] )
def trace(): tax_benefit_system = data['tax_benefit_system'] request.on_json_loading_failed = handle_invalid_json input_data = request.get_json() try: simulation = Simulation(tax_benefit_system=tax_benefit_system, simulation_json=input_data, trace=True) except SituationParsingError as e: abort(make_response(jsonify(e.error), e.code or 400)) requested_computations = dpath.util.search(input_data, '*/*/*/*', afilter=lambda t: t is None, yielded=True) for computation in requested_computations: path = computation[0] entity_plural, entity_id, variable_name, period = path.split('/') simulation.calculate(variable_name, period) trace = deepcopy(simulation.tracer.trace) for vector_key, vector_trace in trace.items(): value = vector_trace['value'].tolist() if isinstance(value[0], Enum): value = [item.name for item in value] if isinstance(value[0], bytes): value = [to_unicode(item) for item in value] vector_trace['value'] = value return jsonify({ "trace": trace, "entitiesDescription": { entity.plural: entity.ids for entity in simulation.entities.values() }, "requestedCalculations": list(simulation.tracer.requested_calculations) })
def _generate_tests_from_file(tax_benefit_system, path_to_file, options): filename = os.path.splitext(os.path.basename(path_to_file))[0] name_filter = options.get('name_filter') if isinstance(name_filter, str): name_filter = to_unicode(name_filter) verbose = options.get('verbose') tests = _parse_test_file(tax_benefit_system, path_to_file, options) for test_index, (simulation, test) in enumerate(tests, 1): if name_filter is not None and name_filter not in filename \ and name_filter not in (test.get('name', '')) \ and name_filter not in (test.get('keywords', [])): continue keywords = test.get('keywords', []) title = "{}: {}{} - {}".format( os.path.basename(path_to_file), '[{}] '.format(', '.join(keywords)) if keywords else '', test.get('name'), test.get('period'), ) test.update({'options': options}) def check(): try: _run_test(simulation, test) except Exception: log.error(title) raise finally: if verbose: print("Computation log:") simulation.tracer.print_computation_log() yield unittest.FunctionTestCase(check)
def set_label(self, label): if label: return to_unicode(label)
def __init__(self, baseline_variable=None): self.name = to_unicode(self.__class__.__name__) attr = { name: value for name, value in self.__class__.__dict__.items() if not name.startswith('__') } self.baseline_variable = baseline_variable self.value_type = self.set(attr, 'value_type', required=True, allowed_values=VALUE_TYPES.keys()) self.dtype = VALUE_TYPES[self.value_type]['dtype'] self.json_type = VALUE_TYPES[self.value_type]['json_type'] if self.value_type == Enum: self.possible_values = self.set(attr, 'possible_values', required=True, setter=self.set_possible_values) if self.value_type == str: self.max_length = self.set(attr, 'max_length', allowed_type=int) if self.max_length: self.dtype = '|S{}'.format(self.max_length) if self.value_type == Enum: self.default_value = self.set(attr, 'default_value', allowed_type=self.possible_values, required=True) else: self.default_value = self.set( attr, 'default_value', allowed_type=self.value_type, default=VALUE_TYPES[self.value_type].get('default')) self.entity = self.set(attr, 'entity', required=True, setter=self.set_entity) self.definition_period = self.set(attr, 'definition_period', required=True, allowed_values=(DAY, MONTH, YEAR, ETERNITY)) self.label = self.set(attr, 'label', allowed_type=basestring_type, setter=self.set_label) self.end = self.set(attr, 'end', allowed_type=basestring_type, setter=self.set_end) self.reference = self.set(attr, 'reference', setter=self.set_reference) self.cerfa_field = self.set(attr, 'cerfa_field', allowed_type=(basestring_type, dict)) self.unit = self.set(attr, 'unit', allowed_type=basestring_type) self.documentation = self.set(attr, 'documentation', allowed_type=basestring_type, setter=self.set_documentation) self.set_input = self.set_set_input(attr.pop('set_input', None)) self.calculate_output = self.set_calculate_output( attr.pop('calculate_output', None)) self.is_period_size_independent = self.set( attr, 'is_period_size_independent', allowed_type=bool, default=VALUE_TYPES[self.value_type]['is_period_size_independent']) self.base_function = self.set_base_function( attr.pop('base_function', None)) formulas_attr, unexpected_attrs = _partition( attr, lambda name, value: name.startswith(FORMULA_NAME_PREFIX)) self.formulas = self.set_formulas(formulas_attr) if unexpected_attrs: raise ValueError( 'Unexpected attributes in definition of variable "{}": {!r}'. format(self.name, ', '.join(sorted(unexpected_attrs.keys())))) self.is_neutralized = False
def test_several_months(): assert to_unicode(Period((MONTH, first_jan, 3))) == 'month:2014-01:3' assert to_unicode(Period((MONTH, first_march, 3))) == 'month:2014-03:3'
def attribute_groupless_persons_to_entities(self, test_case, period, groupless_individus): individus_without_famille = groupless_individus['familles'] individus_without_menage = groupless_individus['menages'] individus_without_foyer_fiscal = groupless_individus['foyers_fiscaux'] individu_by_id = { individu['id']: individu for individu in test_case['individus'] } # Affecte à une famille chaque individu qui n'appartient à aucune d'entre elles. new_famille = dict( enfants = [], parents = [], ) new_famille_id = None for individu_id in individus_without_famille[:]: # Tente d'affecter l'individu à une famille d'après son foyer fiscal. foyer_fiscal, foyer_fiscal_role = find_foyer_fiscal_and_role(test_case, individu_id) if foyer_fiscal_role == u'declarants' and len(foyer_fiscal[u'declarants']) == 2: for declarant_id in foyer_fiscal[u'declarants']: if declarant_id != individu_id: famille, other_role = find_famille_and_role(test_case, declarant_id) if other_role == u'parents' and len(famille[u'parents']) == 1: # Quand l'individu n'est pas encore dans une famille, mais qu'il est déclarant # dans un foyer fiscal, qu'il y a un autre déclarant dans ce même foyer fiscal # et que cet autre déclarant est seul parent dans sa famille, alors ajoute # l'individu comme autre parent de cette famille. famille[u'parents'].append(individu_id) individus_without_famille.remove(individu_id) break elif foyer_fiscal_role == u'personnes_a_charge' and foyer_fiscal[u'declarants']: for declarant_id in foyer_fiscal[u'declarants']: famille, other_role = find_famille_and_role(test_case, declarant_id) if other_role == u'parents': # Quand l'individu n'est pas encore dans une famille, mais qu'il est personne à charge # dans un foyer fiscal, qu'il y a un déclarant dans ce foyer fiscal et que ce déclarant # est parent dans sa famille, alors ajoute l'individu comme enfant de cette famille. famille[u'enfants'].append(individu_id) individus_without_famille.remove(individu_id) break if individu_id in individus_without_famille: # L'individu n'est toujours pas affecté à une famille. # Tente d'affecter l'individu à une famille d'après son ménage. menage, menage_role = find_menage_and_role(test_case, individu_id) if menage_role == u'personne_de_reference': conjoint_id = menage[u'conjoint'] if conjoint_id is not None: famille, other_role = find_famille_and_role(test_case, conjoint_id) if other_role == u'parents' and len(famille[u'parents']) == 1: # Quand l'individu n'est pas encore dans une famille, mais qu'il est personne de # référence dans un ménage, qu'il y a un conjoint dans ce ménage et que ce # conjoint est seul parent dans sa famille, alors ajoute l'individu comme autre # parent de cette famille. famille[u'parents'].append(individu_id) individus_without_famille.remove(individu_id) elif menage_role == u'conjoint': personne_de_reference_id = menage[u'personne_de_reference'] if personne_de_reference_id is not None: famille, other_role = find_famille_and_role(test_case, personne_de_reference_id) if other_role == u'parents' and len(famille[u'parents']) == 1: # Quand l'individu n'est pas encore dans une famille, mais qu'il est conjoint # dans un ménage, qu'il y a une personne de référence dans ce ménage et que # cette personne est seul parent dans une famille, alors ajoute l'individu comme # autre parent de cette famille. famille[u'parents'].append(individu_id) individus_without_famille.remove(individu_id) elif menage_role == u'enfants' and (menage['personne_de_reference'] is not None or menage[u'conjoint'] is not None): for other_id in (menage['personne_de_reference'], menage[u'conjoint']): if other_id is None: continue famille, other_role = find_famille_and_role(test_case, other_id) if other_role == u'parents': # Quand l'individu n'est pas encore dans une famille, mais qu'il est enfant dans un # ménage, qu'il y a une personne à charge ou un conjoint dans ce ménage et que # celui-ci est parent dans une famille, alors ajoute l'individu comme enfant de # cette famille. famille[u'enfants'].append(individu_id) individus_without_famille.remove(individu_id) break if individu_id in individus_without_famille: # L'individu n'est toujours pas affecté à une famille. individu = individu_by_id[individu_id] age = find_age(individu, period.start.date) if len(new_famille[u'parents']) < 2 and (age is None or age >= 18): new_famille[u'parents'].append(individu_id) else: new_famille[u'enfants'].append(individu_id) if new_famille_id is None: new_famille[u'id'] = new_famille_id = to_unicode(uuid.uuid4()) test_case[u'familles'].append(new_famille) individus_without_famille.remove(individu_id) # Affecte à un foyer fiscal chaque individu qui n'appartient à aucun d'entre eux. new_foyer_fiscal = dict( declarants = [], personnes_a_charge = [], ) new_foyer_fiscal_id = None for individu_id in individus_without_foyer_fiscal[:]: # Tente d'affecter l'individu à un foyer fiscal d'après sa famille. famille, famille_role = find_famille_and_role(test_case, individu_id) if famille_role == u'parents' and len(famille[u'parents']) == 2: for parent_id in famille[u'parents']: if parent_id != individu_id: foyer_fiscal, other_role = find_foyer_fiscal_and_role(test_case, parent_id) if other_role == u'declarants' and len(foyer_fiscal[u'declarants']) == 1: # Quand l'individu n'est pas encore dans un foyer fiscal, mais qu'il est parent # dans une famille, qu'il y a un autre parent dans cette famille et que cet autre # parent est seul déclarant dans son foyer fiscal, alors ajoute l'individu comme # autre déclarant de ce foyer fiscal. foyer_fiscal[u'declarants'].append(individu_id) individus_without_foyer_fiscal.remove(individu_id) break elif famille_role == u'enfants' and famille[u'parents']: for parent_id in famille[u'parents']: foyer_fiscal, other_role = find_foyer_fiscal_and_role(test_case, parent_id) if other_role == u'declarants': # Quand l'individu n'est pas encore dans un foyer fiscal, mais qu'il est enfant dans une # famille, qu'il y a un parent dans cette famille et que ce parent est déclarant dans # son foyer fiscal, alors ajoute l'individu comme personne à charge de ce foyer fiscal. foyer_fiscal[u'personnes_a_charge'].append(individu_id) individus_without_foyer_fiscal.remove(individu_id) break if individu_id in individus_without_foyer_fiscal: # L'individu n'est toujours pas affecté à un foyer fiscal. # Tente d'affecter l'individu à un foyer fiscal d'après son ménage. menage, menage_role = find_menage_and_role(test_case, individu_id) if menage_role == u'personne_de_reference': conjoint_id = menage[u'conjoint'] if conjoint_id is not None: foyer_fiscal, other_role = find_foyer_fiscal_and_role(test_case, conjoint_id) if other_role == u'declarants' and len(foyer_fiscal[u'declarants']) == 1: # Quand l'individu n'est pas encore dans un foyer fiscal, mais qu'il est personne de # référence dans un ménage, qu'il y a un conjoint dans ce ménage et que ce # conjoint est seul déclarant dans un foyer fiscal, alors ajoute l'individu comme # autre déclarant de ce foyer fiscal. foyer_fiscal[u'declarants'].append(individu_id) individus_without_foyer_fiscal.remove(individu_id) elif menage_role == u'conjoint': personne_de_reference_id = menage[u'personne_de_reference'] if personne_de_reference_id is not None: foyer_fiscal, other_role = find_foyer_fiscal_and_role(test_case, personne_de_reference_id) if other_role == u'declarants' and len(foyer_fiscal[u'declarants']) == 1: # Quand l'individu n'est pas encore dans un foyer fiscal, mais qu'il est conjoint # dans un ménage, qu'il y a une personne de référence dans ce ménage et que # cette personne est seul déclarant dans un foyer fiscal, alors ajoute l'individu # comme autre déclarant de ce foyer fiscal. foyer_fiscal[u'declarants'].append(individu_id) individus_without_foyer_fiscal.remove(individu_id) elif menage_role == u'enfants' and (menage['personne_de_reference'] is not None or menage[u'conjoint'] is not None): for other_id in (menage['personne_de_reference'], menage[u'conjoint']): if other_id is None: continue foyer_fiscal, other_role = find_foyer_fiscal_and_role(test_case, other_id) if other_role == u'declarants': # Quand l'individu n'est pas encore dans un foyer fiscal, mais qu'il est enfant dans # un ménage, qu'il y a une personne à charge ou un conjoint dans ce ménage et que # celui-ci est déclarant dans un foyer fiscal, alors ajoute l'individu comme # personne à charge de ce foyer fiscal. foyer_fiscal[u'declarants'].append(individu_id) individus_without_foyer_fiscal.remove(individu_id) break if individu_id in individus_without_foyer_fiscal: # L'individu n'est toujours pas affecté à un foyer fiscal. individu = individu_by_id[individu_id] age = find_age(individu, period.start.date) if len(new_foyer_fiscal[u'declarants']) < 2 and (age is None or age >= 18): new_foyer_fiscal[u'declarants'].append(individu_id) else: new_foyer_fiscal[u'personnes_a_charge'].append(individu_id) if new_foyer_fiscal_id is None: new_foyer_fiscal[u'id'] = new_foyer_fiscal_id = to_unicode(uuid.uuid4()) test_case[u'foyers_fiscaux'].append(new_foyer_fiscal) individus_without_foyer_fiscal.remove(individu_id) # Affecte à un ménage chaque individu qui n'appartient à aucun d'entre eux. # Si le ménage n'a pas de personne de référence, et que le premier parent n'a pas de ménage, on le déclare comme personne de référence. famille = test_case.get('familles') and test_case['familles'][0] menage = test_case.get('menages') and test_case['menages'][0] if famille and menage: parent_1 = famille['parents'][0] if not menage.get('personne_de_reference') and parent_1 in individus_without_menage: menage['personne_de_reference'] = parent_1 individus_without_menage.remove(parent_1) new_menage = dict( autres = [], conjoint = None, enfants = [], personne_de_reference = None, ) new_menage_id = None for individu_id in individus_without_menage[:]: # Tente d'affecter l'individu à un ménage d'après sa famille. famille, famille_role = find_famille_and_role(test_case, individu_id) if famille_role == u'parents' and len(famille[u'parents']) == 2: for parent_id in famille[u'parents']: if parent_id != individu_id: menage, other_role = find_menage_and_role(test_case, parent_id) if other_role == u'personne_de_reference' and menage[u'conjoint'] is None: # Quand l'individu n'est pas encore dans un ménage, mais qu'il est parent # dans une famille, qu'il y a un autre parent dans cette famille et que cet autre # parent est personne de référence dans un ménage et qu'il n'y a pas de conjoint # dans ce ménage, alors ajoute l'individu comme conjoint de ce ménage. menage[u'conjoint'] = individu_id individus_without_menage.remove(individu_id) elif other_role == u'conjoint' and menage[u'personne_de_reference'] is None: # Quand l'individu n'est pas encore dans un ménage, mais qu'il est parent # dans une famille, qu'il y a un autre parent dans cette famille et que cet autre # parent est conjoint dans un ménage et qu'il n'y a pas de personne de référence # dans ce ménage, alors ajoute l'individu comme personne de référence de ce ménage. menage[u'personne_de_reference'] = individu_id individus_without_menage.remove(individu_id) break elif famille_role == u'enfants' and famille[u'parents']: for parent_id in famille[u'parents']: menage, other_role = find_menage_and_role(test_case, parent_id) if other_role in (u'personne_de_reference', u'conjoint'): # Quand l'individu n'est pas encore dans un ménage, mais qu'il est enfant dans une # famille, qu'il y a un parent dans cette famille et que ce parent est personne de # référence ou conjoint dans un ménage, alors ajoute l'individu comme enfant de ce # ménage. menage[u'enfants'].append(individu_id) individus_without_menage.remove(individu_id) break if individu_id in individus_without_menage: # L'individu n'est toujours pas affecté à un ménage. # Tente d'affecter l'individu à un ménage d'après son foyer fiscal. foyer_fiscal, foyer_fiscal_role = find_foyer_fiscal_and_role(test_case, individu_id) if foyer_fiscal_role == u'declarants' and len(foyer_fiscal[u'declarants']) == 2: for declarant_id in foyer_fiscal[u'declarants']: if declarant_id != individu_id: menage, other_role = find_menage_and_role(test_case, declarant_id) if other_role == u'personne_de_reference' and menage[u'conjoint'] is None: # Quand l'individu n'est pas encore dans un ménage, mais qu'il est déclarant # dans un foyer fiscal, qu'il y a un autre déclarant dans ce foyer fiscal et que # cet autre déclarant est personne de référence dans un ménage et qu'il n'y a # pas de conjoint dans ce ménage, alors ajoute l'individu comme conjoint de ce # ménage. menage[u'conjoint'] = individu_id individus_without_menage.remove(individu_id) elif other_role == u'conjoint' and menage[u'personne_de_reference'] is None: # Quand l'individu n'est pas encore dans un ménage, mais qu'il est déclarant # dans une foyer fiscal, qu'il y a un autre déclarant dans ce foyer fiscal et # que cet autre déclarant est conjoint dans un ménage et qu'il n'y a pas de # personne de référence dans ce ménage, alors ajoute l'individu comme personne # de référence de ce ménage. menage[u'personne_de_reference'] = individu_id individus_without_menage.remove(individu_id) break elif foyer_fiscal_role == u'personnes_a_charge' and foyer_fiscal[u'declarants']: for declarant_id in foyer_fiscal[u'declarants']: menage, other_role = find_menage_and_role(test_case, declarant_id) if other_role in (u'personne_de_reference', u'conjoint'): # Quand l'individu n'est pas encore dans un ménage, mais qu'il est personne à charge # dans un foyer fiscal, qu'il y a un déclarant dans ce foyer fiscal et que ce # déclarant est personne de référence ou conjoint dans un ménage, alors ajoute # l'individu comme enfant de ce ménage. menage[u'enfants'].append(individu_id) individus_without_menage.remove(individu_id) break if individu_id in individus_without_menage: # L'individu n'est toujours pas affecté à un ménage. if new_menage[u'personne_de_reference'] is None: new_menage[u'personne_de_reference'] = individu_id elif new_menage[u'conjoint'] is None: new_menage[u'conjoint'] = individu_id else: new_menage[u'enfants'].append(individu_id) if new_menage_id is None: new_menage[u'id'] = new_menage_id = to_unicode(uuid.uuid4()) test_case[u'menages'].append(new_menage) individus_without_menage.remove(individu_id) return test_case
def json_default(self): default = self.default_value if default is not None: to_unicode(default) return default
def test_several_days(): assert to_unicode(Period((DAY, first_jan, 3))) == 'day:2014-01-01:3' assert to_unicode(Period((DAY, first_march, 3))) == 'day:2014-03-01:3'
def json_default(self): default = np.array(self.default_value, self.dtype) return to_unicode(default)
def test_day(): assert to_unicode(Period((DAY, first_jan, 1))) == '2014-01-01'