示例#1
0
def test_different_os_positive(mocked_run_osie, slug):
    handler = mocked_run_osie

    d = copy.deepcopy(cacher_provisioning)
    dpath.new(d, "instance/operating_system_version/os_slug", slug)
    c = (
        d["id"],
        d["instance"]["id"],
        tinkerbell,
        handler.host_state_dir,
        "flavor-runner.sh",
        ("-M", "/statedir/metadata"),
        {"PACKET_BOOTDEV_MAC": ""},
    )

    stamp = handler.statedir + "disks-partioned-image-extracted"
    metadata = handler.statedir + "metadata"
    cleanup = handler.statedir + "cleanup.sh"

    open(stamp, "w").close()
    handler.handle_provisioning(d)

    handlers.remove_statefile.assert_called()
    handlers.remove_statefile.call_args[0][0] == stamp
    assert not os.path.exists(stamp)
    assert not os.path.exists(cleanup)
    assert handlers.write_statefile.call_count == 2
    assert handlers.write_statefile.call_args_list[0][0][0] == metadata
    assert handlers.write_statefile.call_args_list[1][0][0] == metadata
    assert os.path.exists(metadata)
    assert handler.run_osie.call_args_list == [call(*c), call(*c)]
示例#2
0
def test_existence_of_loop_sh(mocked_run_osie):
    handler = mocked_run_osie

    cleanup = handler.statedir + "cleanup.sh"
    loop = handler.statedir + "loop.sh"
    metadata = handler.statedir + "metadata"
    stamp = handler.statedir + "disks-partioned-image-extracted"

    open(loop, "w").close()
    os.chmod(loop, 0o700)
    d = copy.deepcopy(cacher_provisioning)
    dpath.new(d, "instance/operating_system_version/os_slug", "freebsd_11_1")
    c = (
        d["id"],
        d["instance"]["id"],
        tinkerbell,
        handler.host_state_dir,
        "flavor-runner.sh",
        ("-M", "/statedir/metadata"),
        {"PACKET_BOOTDEV_MAC": ""},
    )

    assert handler.handle_provisioning(d)

    assert os.path.exists(loop)
    assert not os.path.exists(stamp)
    assert not os.path.exists(cleanup)

    assert handlers.write_statefile.call_count == 2
    assert handlers.write_statefile.call_args_list[0][0][0] == metadata
    assert handlers.write_statefile.call_args_list[1][0][0] == metadata
    assert os.path.exists(metadata)
    handler.run_osie.assert_called_with(*c)
示例#3
0
def params_unprepare_from_saved(fields, copy_to_legacy=False):
    """
    Unescape all section and param names for hyper params and configuration
    If copy_to_legacy is set then copy hyperparams and configuration data to the legacy location for the old clients
    """
    for param_field in ("hyperparams", "configuration"):
        params = safe_get(fields, param_field)
        if params:
            unescaped_params = {
                ParameterKeyEscaper.unescape(key): {
                    ParameterKeyEscaper.unescape(k): v for k, v in value.items()
                }
                if isinstance(value, dict)
                else value
                for key, value in params.items()
            }
            dpath.set(fields, param_field, unescaped_params)

    if copy_to_legacy:
        for new_params_field, old_params_field, use_sections in (
            (f"hyperparams", "execution/parameters", True),
            (f"configuration", "execution/model_desc", False),
        ):
            legacy_params = _get_legacy_params(
                safe_get(fields, new_params_field), with_sections=use_sections
            )
            if legacy_params:
                dpath.new(
                    fields,
                    old_params_field,
                    {_get_full_param_name(p): p["value"] for p in legacy_params},
                )
示例#4
0
def build_definitions_context(definitions: Dict[str, DictNode], definitions_raw: Dict[str, List[Tuple[int, str]]]) -> \
        Dict[str, Dict[str, Any]]:
    definitions_context: Dict[str, Dict[str, Any]] = {}
    definitions = deepcopy(definitions)
    # iterate on the files
    for file_path, resources in definitions.items():

        for resource in resources:
            if resource.get("kind") == "List":
                resources.extend(item for item in resource.get("items", []) if item)
                resources.remove(resource)

        # iterate on the resources
        for resource in resources:
            if is_invalid_k8_definition(resource):
                continue
            resource_id = get_resource_id(resource)
            if not resource_id:
                continue
            start_line = resource["__startline__"]
            end_line = min(resource["__endline__"], len(definitions_raw[file_path]))
            first_line_index = 0
            # skip empty lines
            while not str.strip(definitions_raw[file_path][first_line_index][1]):
                first_line_index += 1
            # check if the file is a json file
            if str.strip(definitions_raw[file_path][first_line_index][1])[0] == "{":
                start_line += 1
                end_line += 1
            else:
                # add resource comments to definition lines
                current_line = str.strip(definitions_raw[file_path][start_line - 1][1])
                while not current_line or current_line[0] == YAML_COMMENT_MARK:
                    start_line -= 1
                    current_line = str.strip(definitions_raw[file_path][start_line - 1][1])

                # remove next resource comments from definition lines
                current_line = str.strip(definitions_raw[file_path][end_line - 1][1])
                while not current_line or current_line[0] == YAML_COMMENT_MARK:
                    end_line -= 1
                    current_line = str.strip(definitions_raw[file_path][end_line - 1][1])

            code_lines = definitions_raw[file_path][start_line - 1: end_line]
            dpath.new(
                definitions_context,
                [file_path, resource_id],
                {"start_line": start_line, "end_line": end_line, "code_lines": code_lines},
            )

            skipped_checks = get_skipped_checks(resource)
            dpath.new(
                definitions_context,
                [file_path, resource_id, "skipped_checks"],
                skipped_checks,
            )
    return definitions_context
示例#5
0
def params_prepare_for_save(fields: dict, previous_task: Task = None):
    """
    If legacy hyper params or configuration is passed then replace the corresponding section in the new structure
    Escape all the section and param names for hyper params and configuration to make it mongo sage
    """
    for old_params_field, new_params_field, default_section in (
        ("execution/parameters", "hyperparams", hyperparams_default_section),
        ("execution/model_desc", "configuration", None),
    ):
        legacy_params = safe_get(fields, old_params_field)
        if legacy_params is None:
            continue

        if (
            not safe_get(fields, new_params_field)
            and previous_task
            and previous_task[new_params_field]
        ):
            previous_data = previous_task.to_proper_dict().get(new_params_field)
            removed = _remove_legacy_params(
                previous_data, with_sections=default_section is not None
            )
            if not legacy_params and not removed:
                # if we only need to delete legacy fields from the db
                # but they are not there then there is no point to proceed
                continue

            fields_update = {new_params_field: previous_data}
            params_unprepare_from_saved(fields_update)
            fields.update(fields_update)

        for full_name, value in legacy_params.items():
            section, name = split_param_name(full_name, default_section)
            new_path = list(filter(None, (new_params_field, section, name)))
            new_param = dict(name=name, type=hyperparams_legacy_type, value=str(value))
            if section is not None:
                new_param["section"] = section
            dpath.new(fields, new_path, new_param)
        dpath.delete(fields, old_params_field)

    for param_field in ("hyperparams", "configuration"):
        params = safe_get(fields, param_field)
        if params:
            escaped_params = {
                ParameterKeyEscaper.escape(key): {
                    ParameterKeyEscaper.escape(k): v for k, v in value.items()
                }
                if isinstance(value, dict)
                else value
                for key, value in params.items()
            }
            dpath.set(fields, param_field, escaped_params)
示例#6
0
    def add(self, key: str, value: Any) -> Any:
        """Overwrite or add config value.

        Args:
            key: Key to set
            value: Value to add or update too

        Returns:
            Updated config

        """
        dpath.new(self._config, key, value)
        self.log.debug(f"added config value [{key}] -> {value}")
        return self.sync()
示例#7
0
def my_path(my_dictionary: dict = None, path=None, value=None):
    items = path.split('/')
    # if the last character is a digit
    if items[-1].isdigit():
        items.pop()
        new_path = "/".join(items)
        # Check the element before the digit is already in the dictionary
        if dpath.search(my_dictionary, new_path):
            # Is it a list ?
            if isinstance(dpath.get(my_dictionary, new_path), list):
                dpath.new(my_dictionary, path, value)
            else:
                raise ValueError("The following entry can not be added: {}. "
                                 "This is not a list".format(
                                     my_dictionary[items[-2]]))
        # Not in the dictionary
        else:
            dpath.new(my_dictionary, new_path, [])
            dpath.new(my_dictionary, path, value)
    else:
        if dpath.search(my_dictionary, path):
            # Set the new value
            dpath.set(my_dictionary, path, value)
        else:
            dpath.new(my_dictionary, path, value)
    return my_dictionary
示例#8
0
def test_provisioning(handler, path, value):
    d = copy.deepcopy(cacher_provisioning)
    hwid = d["id"]
    iid = d["instance"]["id"]
    c = (
        hwid,
        iid,
        tinkerbell,
        handler.host_state_dir,
        "flavor-runner.sh",
        ("-M", "/statedir/metadata"),
        {
            "PACKET_BOOTDEV_MAC": ""
        },
    )

    if path:
        dpath.new(d, path, value)

    num_calls_write_statefile = 1
    has_user_data = False
    if path == "instance/userdata" and value:
        has_user_data = True
        num_calls_write_statefile += 1

        args = c[-2] + ("-u", "/statedir/userdata")
        c = c[:-2] + (args, ) + c[-1:]

    handler.handle_provisioning(d)

    handler.phone_home.assert_called_with({
        "type":
        "provisioning.104.01",
        "body":
        "Device connected to DHCP system"
    })
    handler.run_osie.assert_called_with(*c)
    handler.wipe.assert_not_called()
    assert handlers.write_statefile.call_count == num_calls_write_statefile
    assert (
        handlers.write_statefile.call_args_list[0][0][0] == handler.statedir +
        "metadata")
    assert os.path.isfile(handler.statedir + "metadata")
    if has_user_data:
        assert os.path.isfile(handler.statedir + "userdata")
        assert (handlers.write_statefile.call_args_list[1][0][0] ==
                handler.statedir + "userdata")
示例#9
0
def set_preferences(call, company_id, req_model):
    # type: (APICall, str, SetPreferencesRequest) -> Dict
    assert isinstance(call, APICall)
    changes = req_model.preferences

    def invalid_key(_, key, __):
        if not isinstance(key, str):
            return True
        elif key.startswith("$") or "." in key:
            raise errors.bad_request.FieldsValueError(
                f"Key {key} is invalid. Keys cannot start with '$' or contain '.'."
            )
        return True

    remap(changes, visit=invalid_key)

    base_preferences = get_user_preferences(call)
    new_preferences = deepcopy(base_preferences)
    for key, value in changes.items():
        try:
            dpath.new(new_preferences, key, value, separator=".")
        except Exception:
            log.exception(
                'invalid preferences update for user "{}": key=`%s`, value=`%s`',
                key,
                value,
            )
            raise errors.bad_request.InvalidPreferencesUpdate(key=key,
                                                              value=value)

    if new_preferences == base_preferences:
        updated, fields = 0, {}
    else:
        with translate_errors_context("updating user preferences"):
            updated = User.objects(id=call.identity.user,
                                   company=company_id).update(
                                       upsert=False,
                                       preferences=dumps(new_preferences))

    return {
        "updated": updated,
        "fields": {
            "preferences": new_preferences
        } if updated else {},
    }
示例#10
0
def test_provisioning_mismatch_preinstalled(handler, path, value):
    d = copy.deepcopy(cacher_provisioning)
    dpath.new(d, path, value)
    c = (
        d["id"],
        d["instance"]["id"],
        tinkerbell,
        handler.host_state_dir,
        "flavor-runner.sh",
        ("-M", "/statedir/metadata"),
        {
            "PACKET_BOOTDEV_MAC": ""
        },
    )

    if path == "instance/userdata" and value:
        args = c[-2] + ("-u", "/statedir/userdata")
        c = c[:-2] + (args, ) + c[-1:]

    handler.handle_provisioning(d)

    handler.phone_home.assert_not_called()
    handler.run_osie.assert_called_with(*c)
    handler.wipe.assert_called_with(d)

    metadata = handler.statedir + "metadata"
    cleanup = handler.statedir + "cleanup.sh"
    userdata = handler.statedir + "userdata"

    assert os.path.isfile(cleanup)
    assert stat.S_IMODE(os.stat(cleanup).st_mode) == 0o700
    assert open(cleanup).read() == "#!/usr/bin/env sh\nreboot\n"

    assert os.path.isfile(metadata)
    assert handlers.write_statefile.call_args_list[0][0][0] == metadata
    assert handlers.write_statefile.call_args_list[-1][0][0] == cleanup

    handlers.remove_statefile.assert_not_called()
    write_satefile_count = 2
    if path == "instance/userdata" and value:
        assert os.path.isfile(userdata)
        write_satefile_count += 1
        assert handlers.write_statefile.call_args_list[1][0][0] == userdata

    assert handlers.write_statefile.call_count == write_satefile_count
示例#11
0
 def _upgrade_task_data(task_data: dict):
     for old_param_field, new_param_field, default_section in (
         ("execution/parameters", "hyperparams", hyperparams_default_section),
         ("execution/model_desc", "configuration", None),
     ):
         legacy = safe_get(task_data, old_param_field)
         if not legacy:
             continue
         for full_name, value in legacy.items():
             section, name = split_param_name(full_name, default_section)
             new_path = list(filter(None, (new_param_field, section, name)))
             if not safe_get(task_data, new_path):
                 new_param = dict(
                     name=name, type=hyperparams_legacy_type, value=str(value)
                 )
                 if section is not None:
                     new_param["section"] = section
                 dpath.new(task_data, new_path, new_param)
         dpath.delete(task_data, old_param_field)
示例#12
0
        def merge_projection_result(result):
            for ref_field_name, data in ref_projection.items():
                res = data.get('res')
                if not res:
                    self._expand_reference_fields(cls, result,
                                                  [ref_field_name])
                    continue
                ref_ids = self._search(cls,
                                       result,
                                       ref_field_name,
                                       only_values=False)
                if not ref_ids:
                    continue
                for path, value in ref_ids:
                    obj = res.get(value) or {'id': value}
                    dpath.new(result, path, obj, separator='.')

            # any reference field not projected should be expanded
            do_expand_reference_ids(result, skip_fields=list(ref_projection))
 def _assign_definition_value(self, var_name, var_value, var_assignments):
     assignment_regex = self._generate_var_evaluation_regex(var_name)
     var_file = var_assignments['var_file']
     for (assignment_file,
          assignments) in var_assignments['definitions'].items():
         # Save evaluation information in context
         for assignment_obj in assignments:
             definition_path = assignment_obj.get('definition_path')
             entry_expression = assignment_obj.get('definition_expression')
             definition_name = assignment_obj.get('definition_name')
             context_path, _ = self._extract_context_path(definition_path)
             dpath.new(self.definitions_context[assignment_file],
                       f'evaluations/{var_name}/var_file', var_file)
             dpath.new(self.definitions_context[assignment_file],
                       f'evaluations/{var_name}/value', var_value)
             dpath.new(self.definitions_context[assignment_file],
                       f'evaluations/{var_name}/definitions', assignments)
             evaluated_value = str(var_value)
             evaluated_definition = re.sub(assignment_regex,
                                           evaluated_value,
                                           entry_expression)
             dpath.set(self.tf_definitions[assignment_file],
                       definition_path, evaluated_definition)
             self.logger.debug(
                 f'Evaluated definition {definition_name} in file {assignment_file}: default value of variable {var_file}: '
                 f'{var_name} to "{evaluated_value}"')
示例#14
0
    def _assign_definition_value(self, var_name, var_value, var_assignments):
        assignment_regex = self._generate_var_evaluation_regex(var_name)
        var_file = var_assignments['var_file']
        var_value_string = str(var_value)
        for (assignment_file, assignments) in var_assignments['definitions'].items():
            # Save evaluation information in context
            for assignment_obj in assignments:
                definition_path = assignment_obj.get('definition_path')
                entry_expression = assignment_obj.get('definition_expression')
                definition_name = assignment_obj.get('definition_name')
                context_path, _ = self._extract_context_path(definition_path)
                if assignment_file in self.definitions_context.keys():
                    dpath.new(self.definitions_context[assignment_file], f'evaluations/{var_name}/var_file',
                              var_file)
                    dpath.new(self.definitions_context[assignment_file], f'evaluations/{var_name}/value',
                              var_value)
                    dpath.new(self.definitions_context[assignment_file],
                              f'evaluations/{var_name}/definitions',
                              assignments)
                if self._is_variable_only_expression(assignment_regex, entry_expression):
                    # Preserve the original type of the variable if not part of a composite expression
                    evaluated_definition = var_value
                else:
                    evaluated_definition = re.sub(assignment_regex, var_value_string, entry_expression)

                dpath.set(self.tf_definitions[assignment_file], definition_path, evaluated_definition)
                self.logger.debug(
                    f'Evaluated definition {definition_name} in file {assignment_file}: default value of variable {var_file}: '
                    f'{var_name} to "{var_value_string}"')
示例#15
0
    def add_result(self, result_id, result):

        try:
            registered = self._registers.get(result_id, None)
            if registered is None:
                raise FrklException(
                    msg=
                    "Result for id '{}' not registered, this is most likely a bug."
                    .format(result_id))

            value_template = registered.get("value", None)
            if value_template is not None:
                new_value = replace_strings_in_obj(
                    value_template,
                    replacement_dict={"__result__": result},
                    jinja_env=DEFAULT_RUN_CONFIG_JINJA_ENV,
                )
            else:
                new_value = result

            target = registered.get("target", None)
            if target is None:
                if not isinstance(result, Mapping):
                    raise FrklException(
                        msg="Can't merge result id '{}'".format(result_id),
                        reason=
                        "Value for result-id '{}' not a mapping, and no 'target' provided.",
                        solution=
                        "Either provide a 'target' value, or use the 'value' template to convert the result.",
                    )
                dict_merge(self._result, new_value, copy_dct=False)
            else:
                temp = {}
                dpath.new(temp, target, new_value, separator=".")
                dict_merge(self._result, temp, copy_dct=False)
        except (Exception) as e:
            log.error("Could not register result '{}': {}".format(
                result_id, e))
示例#16
0
    def parse_section_title(self, cell, current_section=None):
        if not isinstance(cell.internal_value, str):
            raise SheetParsingError(
                "Enable to parse summary: Unexpected value in cell '{}'".
                format(cell.coordinate))
        description = ''.join(cell.internal_value.split('.')[1:]).strip()
        key = slugify(description, stopwords=True)
        path = f"subparams/{current_section}/subparams/{key}" if current_section else f"subparams/{key}"
        if dpath.search(self.sections, path):
            raise SheetParsingError(
                "Name collision: section '{}' alredy exists.".format(path))
        dpath.new(self.sections, path, {
            'description': description,
            'metadata': {
                'order': []
            }
        })

        # Keep track of the order
        order_path = f'subparams/{current_section}/metadata/order' if current_section else 'metadata/order'
        dpath.get(self.sections, order_path).append(key)

        return path
    def _assign_definition_value(self, definition_type, var_name, var_value,
                                 var_assignments):
        """
        assigns var_value to variable var_name in tf_definitions
        :param definition_type: the entity's block type
        :param var_name: variable name
        :param var_value: variable value
        :param var_assignments: variable assignments
        """
        assignment_regex = self._generate_evaluation_regex(
            definition_type, var_name)
        var_file = var_assignments['var_file']
        var_value_string = str(var_value)
        for (assignment_file,
             assignments) in var_assignments['definitions'].items():
            # Save evaluation information in context
            for assignment_obj in assignments:
                definition_path = assignment_obj.get('definition_path')
                entry_expression = assignment_obj.get('definition_expression')
                definition_name = assignment_obj.get('definition_name')
                if not isinstance(entry_expression, str):
                    # Example of unsupported evaluation:
                    # cidr_blocks = local.ip_ranges.ipv4Prefixes[*].prefix
                    logging.info(
                        f'Ran into a complex evaluation which isn\'t supported yet, on {assignment_file}'
                    )
                    continue
                context_path, _ = self.extract_context_path(definition_path)
                if assignment_file in self.definitions_context.keys():
                    dpath.new(self.definitions_context[assignment_file],
                              f'evaluations/{var_name}/var_file', var_file)
                    dpath.new(self.definitions_context[assignment_file],
                              f'evaluations/{var_name}/value', var_value)
                    dpath.new(self.definitions_context[assignment_file],
                              f'evaluations/{var_name}/definitions',
                              assignments)
                if self._is_variable_only_expression(assignment_regex,
                                                     entry_expression):
                    # Preserve the original type of the variable if not part of a composite expression
                    evaluated_definition = var_value
                else:
                    evaluated_definition = re.sub(assignment_regex,
                                                  re.escape(var_value_string),
                                                  entry_expression)

                dpath.set(self.tf_definitions[assignment_file],
                          definition_path, evaluated_definition)
                self.logger.debug(
                    f'Evaluated definition {definition_name} in file {assignment_file}: default value of variable {var_file}: '
                    f'{var_name} to "{var_value_string}"')
示例#18
0
def build_openAPI_specification(api_data):
    tax_benefit_system = api_data['tax_benefit_system']
    file = open(OPEN_API_CONFIG_FILE, 'r')
    spec = yaml.safe_load(file)
    country_package_name = api_data['country_package_metadata']['name'].title()
    dpath.new(spec, 'info/title', spec['info']['title'].replace("{COUNTRY_PACKAGE_NAME}", country_package_name))
    dpath.new(spec, 'info/description', spec['info']['description'].replace("{COUNTRY_PACKAGE_NAME}", country_package_name))
    dpath.new(spec, 'info/version', api_data['country_package_metadata']['version'])

    for entity in tax_benefit_system.entities:
        name = entity.key.title()
        spec['definitions'][name] = get_entity_json_schema(entity, tax_benefit_system)

    situation_schema = get_situation_json_schema(tax_benefit_system)
    dpath.new(spec, 'definitions/SituationInput', situation_schema)
    dpath.new(spec, 'definitions/SituationOutput', situation_schema.copy())
    dpath.new(spec, 'definitions/Trace/properties/entitiesDescription/properties', {
        entity.plural: {'type': 'array', 'items': {"type": "string"}}
        for entity in tax_benefit_system.entities
        })

    # Get example from the served tax benefist system

    if tax_benefit_system.open_api_config.get('parameter_example'):
        parameter_id = tax_benefit_system.open_api_config['parameter_example']
        parameter_path = parameter_id.replace('.', '/')
        parameter_example = api_data['parameters'][parameter_path]
    else:
        parameter_example = next(iter(api_data['parameters'].values()))
    dpath.new(spec, 'definitions/Parameter/example', parameter_example)

    if tax_benefit_system.open_api_config.get('variable_example'):
        variable_example = api_data['variables'][tax_benefit_system.open_api_config['variable_example']]
    else:
        variable_example = next(iter(api_data['variables'].values()))
    dpath.new(spec, 'definitions/Variable/example', variable_example)

    if tax_benefit_system.open_api_config.get('simulation_example'):
        simulation_example = tax_benefit_system.open_api_config['simulation_example']
        dpath.new(spec, 'definitions/SituationInput/example', simulation_example)
        dpath.new(spec, 'definitions/SituationOutput/example', handlers.calculate(tax_benefit_system, deepcopy(simulation_example)))  # calculate has side-effects
        dpath.new(spec, 'definitions/Trace/example', handlers.trace(tax_benefit_system, simulation_example))
    else:
        message = "No simulation example has been defined for this tax and benefit system. If you are the maintainer of {}, you can define an example by following this documentation: https://openfisca.org/doc/openfisca-web-api/config-openapi.html".format(country_package_name)
        dpath.new(spec, 'definitions/SituationInput/example', message)
        dpath.new(spec, 'definitions/SituationOutput/example', message)
        dpath.new(spec, 'definitions/Trace/example', message)
    return spec
示例#19
0
def admin_request_body_field(context, field, value):
    dpath.new(context.obj, field, value)
示例#20
0
 def set(self, path, value):
     if (path == '/'):
         return False
     return dpath.new(self.info, path, value)
示例#21
0
def build_openAPI_specification(api_data):
    tax_benefit_system = api_data['tax_benefit_system']
    file = open(OPEN_API_CONFIG_FILE, 'r')
    spec = yaml.load(file)
    country_package_name = api_data['country_package_metadata']['name'].title()
    dpath.new(
        spec, 'info/title',
        spec['info']['title'].replace("{COUNTRY_PACKAGE_NAME}",
                                      country_package_name))
    dpath.new(
        spec, 'info/description',
        spec['info']['description'].replace("{COUNTRY_PACKAGE_NAME}",
                                            country_package_name))
    dpath.new(spec, 'info/version',
              api_data['country_package_metadata']['version'])

    for entity in tax_benefit_system.entities:
        name = entity.key.title()
        spec['definitions'][name] = get_entity_json_schema(
            entity, tax_benefit_system)

    situation_schema = get_situation_json_schema(tax_benefit_system)
    dpath.new(spec, 'definitions/SituationInput', situation_schema)
    dpath.new(spec, 'definitions/SituationOutput', situation_schema.copy())
    dpath.new(
        spec, 'definitions/Trace/properties/entitiesDescription/properties', {
            entity.plural: {
                'type': 'array',
                'items': {
                    "type": "string"
                }
            }
            for entity in tax_benefit_system.entities
        })

    # Get example from the served tax benefist system

    if tax_benefit_system.open_api_config.get('parameter_example'):
        parameter_id = tax_benefit_system.open_api_config['parameter_example']
        parameter_path = parameter_id.replace('.', '/')
        parameter_example = api_data['parameters'][parameter_path]
    else:
        parameter_example = next(iter(api_data['parameters'].values()))
    dpath.new(spec, 'definitions/Parameter/example', parameter_example)

    if tax_benefit_system.open_api_config.get('variable_example'):
        variable_example = api_data['variables'][
            tax_benefit_system.open_api_config['variable_example']]
    else:
        variable_example = next(iter(api_data['variables'].values()))
    dpath.new(spec, 'definitions/Variable/example', variable_example)

    if tax_benefit_system.open_api_config.get('simulation_example'):
        simulation_example = tax_benefit_system.open_api_config[
            'simulation_example']
        dpath.new(spec, 'definitions/SituationInput/example',
                  simulation_example)
        dpath.new(
            spec, 'definitions/SituationOutput/example',
            handlers.calculate(
                tax_benefit_system,
                deepcopy(simulation_example)))  # calculate has side-effects
        dpath.new(spec, 'definitions/Trace/example',
                  handlers.trace(tax_benefit_system, simulation_example))
    else:
        message = "No simulation example has been defined for this tax and benefit system. If you are the maintainer of {}, you can define an example by following this documentation: https://openfisca.org/doc/openfisca-web-api/config-openapi.html".format(
            country_package_name)
        dpath.new(spec, 'definitions/SituationInput/example', message)
        dpath.new(spec, 'definitions/SituationOutput/example', message)
        dpath.new(spec, 'definitions/Trace/example', message)
    return spec
示例#22
0
 def __init__(self, *args, **kwargs):
     self.requireComplete=kwargs.pop('requireComplete', True)
     kws_ = {}
     for k, v in kwargs.items():
         dpath.new( kws_, py_index_to_pdict(k), v, separator='.' )
     super().__init__(*args, **kws_)
示例#23
0
def execute_postponed_actions(context,
                              is_data: bool = True,
                              actions_switcher: dict = None):
    """
    Execute postponed actions
    :param actions_switcher: the automaton list of actions which can be postponed
    :param context: the current context
    :param is_data:  boolean, True means set only data, False means execute actions (use models)
    :return: None
    """
    log.debug("postponed_action")

    if is_data:
        #  Do settings
        log.debug("is data statement")
        key_list = set(ATTRIBUTE_LIST).intersection(
            context.pre_conditions["postponed"].keys())
        for key in key_list:
            log.debug("Key : {}".format(str(key)))
            while context.pre_conditions["postponed"][key]:
                log.debug("Context.pre_conditions[postponed][key]: {} ".format(
                    context.pre_conditions["postponed"][key]))
                elem = context.pre_conditions["postponed"][key].pop(0)
                log.debug("elem contains: {}".format(elem))
                try:
                    # Check the path exist
                    if dpath.search(context.pre_conditions[key], elem["path"]):
                        dpath.set(context.pre_conditions[key], elem["path"],
                                  elem["value"])
                    else:
                        # Create a new entry
                        dpath.new(context.pre_conditions[key], elem["path"],
                                  elem["value"])
                except AssertionError as assertion:
                    log.error("Update data failed.\n '{}'".format(
                        assertion.args[0]))
                    raise_exception(
                        AssertionError,
                        "Update data failed.\n '{}'".format(assertion.args[0]),
                        context.evidence_folder)
                log.debug("pre_conditions : {}".format(
                    str(context.pre_conditions[key])))
    else:
        #  Do execute steps
        log.debug("else statement")
        postponed_actions = deepcopy(
            context.pre_conditions["postponed"]["execution"])
        context.pre_conditions["postponed"]["execution"].clear()
        for index, action in enumerate(postponed_actions):
            log.debug("Index: {}, action: {}".format(index, action))
            if isinstance(action, str):
                context.execute_steps(action)
            elif isinstance(action, tuple) and len(action) == 2:
                log.debug("action switcher: {}".format(action))
                actions_switcher[action[0]](**action[1])
                sleep(0.5)
            else:
                raise Exception("Unknown action to process.\n"
                                "Get '{}'".format(repr(action)))

    log.debug("End of postponed_action ")