示例#1
0
    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
示例#2
0
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)
            ))
示例#4
0
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)))
示例#6
0
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,
                }
            }
        })
示例#7
0
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)
示例#8
0
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
示例#9
0
 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]),
     ))
示例#11
0
    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)
示例#12
0
文件: app.py 项目: bzg/openfisca-core
 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
示例#13
0
    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)
示例#14
0
    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
示例#15
0
    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)
示例#18
0
 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()
示例#19
0
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()
示例#21
0
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
示例#22
0
    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
示例#23
0
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']
            )
示例#24
0
    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)
        })
示例#25
0
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)
示例#26
0
 def set_label(self, label):
     if label:
         return to_unicode(label)
示例#27
0
    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
示例#28
0
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'
示例#29
0
    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
示例#30
0
 def json_default(self):
     default = self.default_value
     if default is not None:
         to_unicode(default)
     return default
示例#31
0
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'
示例#32
0
 def json_default(self):
     default = np.array(self.default_value, self.dtype)
     return to_unicode(default)
示例#33
0
def test_day():
    assert to_unicode(Period((DAY, first_jan, 1))) == '2014-01-01'