Skip to content

Conversation

@exorevan
Copy link

Fix an error when links build with not internal model variable. Method resolve_param_values of AbstractHyperField deletes all rest parameters those are not got from HALHyperModel parameters. Now those parameters update original parameters dict.

fixes #104

Error example:

>>> from fastapi import FastAPI
>>> from fastapi_hypermodel import FrozenDict, HALFor, HALLinks, HALHyperModel
>>>
>>> app = FastAPI()
>>> @app.get(path="/rest/{process}/{operation}", response_model=int)
... def get_process(process: int, operation: str):
...     return process
... 
>>> class Process(HALHyperModel):
...     process: int
...     links: HALLinks = FrozenDict({"self": HALFor("get_process", {"process": "<process>", "operation": "wait"})})
... 
>>> Process(process=5)
Process(links=FrozenDict({'curies': []}), process=5)
>>> HALHyperModel.init_app(app)
>>> Process(process=5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/custom-statemachine-service/.venv/lib/python3.12/site-packages/pydantic/main.py", line 214, in __init__
    validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/custom-statemachine-service/.venv/lib/python3.12/site-packages/fastapi_hypermodel/hal/hal_hypermodel.py", line 202, in add_links
    valid_links = self._validate_factory(link_, vars(self))
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/custom-statemachine-service/.venv/lib/python3.12/site-packages/fastapi_hypermodel/base/hypermodel.py", line 130, in _validate_factory
    element = element_factory(self._app, properties)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/custom-statemachine-service/.venv/lib/python3.12/site-packages/fastapi_hypermodel/hal/hal_hypermodel.py", line 119, in __call__
    uri_path = self._get_uri_path(
               ^^^^^^^^^^^^^^^^^^^
  File "/usr/local/custom-statemachine-service/.venv/lib/python3.12/site-packages/fastapi_hypermodel/base/hypermodel.py", line 63, in _get_uri_path
    return UrlType(app.url_path_for(endpoint, **params))
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/custom-statemachine-service/.venv/lib/python3.12/site-packages/starlette/applications.py", line 106, in url_path_for
    return self.router.url_path_for(name, **path_params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/custom-statemachine-service/.venv/lib/python3.12/site-packages/starlette/routing.py", line 661, in url_path_for
    raise NoMatchFound(name, path_params)
starlette.routing.NoMatchFound: No route exists for name "get_process" and params "process".

@ELC
Copy link
Collaborator

ELC commented Mar 20, 2025

Please add a unit test to show he new expected behaviour

Another thing is that it is unexpected that Hypernodels are used as path params

@exorevan
Copy link
Author

Where should I put the test? Also what about #102

The example how it would work:

    from fastapi import FastAPI
    from fastapi_hypermodel import FrozenDict, HALFor, HALLinks, HALHyperModel
    
    app = FastAPI()

    @app.get(path="/rest/{process}/{operation}", response_model=int)
    def get_process(process: int, operation: str):
        return process

    class Process(HALHyperModel):
        process: int
        links: HALLinks = FrozenDict({
            "self": HALFor("get_process", {
                "process": "<process>",  # internal model parameter
                "operation": "wait"       # external hardcoded parameter
            })
        })
    
    HALHyperModel.init_app(app)

    process_instance = Process(process=5)

    assert "self" in process_instance.links
    assert process_instance.links["self"].href == "/rest/5/wait"

    process_instance_2 = Process(process=10)
    assert process_instance_2.links["self"].href == "/rest/10/wait"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fastapi_hypermodel can't create a link with non-model variable

2 participants