fastapi-hypermodel
fastapi-hypermodel copied to clipboard
Fix an error when variable in links can't be added to url
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".
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
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"