Esempio n. 1
0
    def lookup(
        self,
        module_name: str,
        rel: LinkRelation,
        parameter_values: Dict[str, str],
    ) -> EndpointEntry:
        """Look up an endpoint definition

        Args:
            module_name:
                The name of the module where the endpoint has been defined in.

            rel:
                The rel of the endpoint.

            parameter_values:
                A simple mapping of parameter-names to values.

        Returns:
            An endpoint-struct.

        """
        # Wen don't need to validate the matching of parameters after this as this expects all
        # parameters to be available to be supplied, else we never get the "endpoint_key".
        endpoint_key = (module_name, rel)
        parameter_key: ParameterKey = tuple(sorted(parameter_values.keys()))
        try:
            endpoint_entry = self._endpoints[endpoint_key]
        except KeyError:
            raise KeyError(f"Key {endpoint_key!r} not in {self._endpoints!r}")
        if parameter_key not in endpoint_entry:
            raise ValueError(
                f"Endpoint {endpoint_key} with parameters {parameter_key} not found. "
                f"The following parameter combinations are possible: "
                f"{list(endpoint_entry.keys())}")

        examples: Dict[str, OpenAPIParameter] = {
            key: {
                'example': value
            }
            for key, value in parameter_values.items()
        }

        # Needs to fill out path templates!
        entry = endpoint_entry[parameter_key]
        entry['href'] = fill_out_path_template(entry['href'], examples)
        return entry
Esempio n. 2
0
def fill_out_parameters(ctx: Dict[str, Any], val) -> str:
    """Fill out path parameters, either using the global parameter or the endpoint defined ones.

    This assumes the parameters to be defined as such:

        ctx['parameters']: Dict[str, Dict[str, str]]

    Args:
        ctx: A Jinja2 context
        val: The path template.

    Examples:

        This does a lot of Jinja2 setup. We may want to move this to a "proper" test-file.

        >>> parameters = {}
        >>> env = jinja2.Environment()
        >>> env.filters['fill_out_parameters'] = fill_out_parameters

        >>> host = {'name': 'host', 'in': 'path', 'example': 'example.com'}
        >>> service = {'name': 'service', 'in': 'path', 'example': 'CPU'}

        >>> tmpl_source = '{{ "/{host}/{service}" | fill_out_parameters }}'
        >>> tmpl = env.from_string(tmpl_source)

        >>> tmpl.render(path_params=[])
        Traceback (most recent call last):
        ...
        ValueError: Parameter 'host' needed, but not supplied in {}

        >>> tmpl.render(path_params=[host, service])
        '/example.com/CPU'

    Returns:
        A filled out string.
    """
    return fill_out_path_template(val, to_param_dict(ctx['path_params']))
Esempio n. 3
0
def _make_url(
    path: str,
    param_spec: Sequence[OpenAPIParameter],
    param_val: Dict[str, str],
) -> str:
    """Make a concrete URL according to parameter specs and value-mappings.

    Examples:

        For use in path

        >>> _make_url('/foo/{host}', [{'name': 'host', 'in': 'path'}], {'host': 'example.com'})
        '/foo/example.com'

        Or in query-string:

        >>> _make_url('/foo', [{'name': 'host', 'in': 'query'}], {'host': 'example.com'})
        '/foo?host=example.com'

        >>> _make_url('/foo', [{'name': 'host', 'in': 'query', 'required': False}],
        ...           {'host': 'example.com'})
        '/foo?host=example.com'

        >>> _make_url('/foo', [{'name': 'host', 'in': 'query', 'required': False}], {})
        '/foo'

        Some edge-cases which are caught.

        >>> _make_url('/foo', [{'name': 'host', 'in': 'path'}], {})
        Traceback (most recent call last):
        ...
        ValueError: No parameter mapping for required parameter 'host'.

        >>> _make_url('/foo', [{'name': 'host', 'in': 'path'}], {'host': 'example.com'})
        Traceback (most recent call last):
        ...
        ValueError: Parameter 'host' (required path-parameter), not found in path '/foo'

        >>> import pytest
        >>> # This exceptions gets thrown by another function, so we don't care about the wording.
        >>> with pytest.raises(ValueError):
        ...     _make_url('/foo/{host}', [], {'host': 'example.com'})

    Args:
        path:
            The path. May have "{variable_name}" template parts in the path-name or not.

        param_spec:
            A list of parameters.

        param_val:
            A mapping of parameter-names to their desired values. Used to fill out the templates.

    Returns:
        The formatted path, query-string appended if applicable.

    """
    path_params: Dict[str, OpenAPIParameter] = {}
    qs = []
    for p in param_spec:
        param_name = p['name']
        if param_name not in param_val:
            if p.get('required', True):
                raise ValueError(
                    f"No parameter mapping for required parameter {param_name!r}."
                )
            # We skip optional parameters, when we don't have values for them.
            continue

        param_value = param_val[param_name]
        if p['in'] == 'query':
            qs.append(f"{param_name}={param_value}")
        elif p['in'] == 'path':
            if param_name not in path_parameters(path):
                raise ValueError(
                    f"Parameter {param_name!r} (required path-parameter), "
                    f"not found in path {path!r}")
            path_params[param_name] = {'example': param_value}

    query_string = '&'.join(qs)
    rv = fill_out_path_template(path, path_params)
    if query_string:
        rv += f"?{query_string}"
    return rv