Skip to content

CustomField

Packages developers

This is the part of documentation will talks you about some features, that can be helpful to develop your own packages with FastDepends

Custom Arguments Field

If you wish to write your own FastAPI or another closely by architecture tool, you should define your own custom fields to specify application behavior. At FastAPI these fields are:

  • Body
  • Path
  • Query
  • Header
  • Cookie
  • Form
  • File
  • Security

Custom fields can be used to adding something specific to a function arguments (like a BackgroundTask) or parsing incoming objects special way. You able decide by own, why and how you will use these tools.

FastDepends grants you this opportunity a very intuitive and comfortable way.

Let's write Header

As an example, will try to implement FastAPI Header field

1
2
3
4
5
6
7
from fast_depends.library import CustomField

class Header(CustomField):
    def use(self, /, **kwargs):
        kwargs = super().use(**kwargs)
        kwargs[self.param_name] = kwargs["headers"][self.param_name]
        return kwargs

Just import fast_depends.library.CustomField and implements use (async or sync) method. That's all. We already have own Header field to parse kwargs the special way.

Header usage

Now we already can use the Header field

1
2
3
4
5
6
7
8
9
from fast_depends import inject

@inject
def my_func(header_field: int = Header()):
    return header_field

assert h(
    headers={"header_field": "1"}
) == 1

As we defined, Header parse incoming headers kwargs field, get a parameter by name and put it to original function as an argument.

More details

CustomField has some fields you should know about

class CustomField:
    param_name: str
    cast: bool
    required: bool
  • param_name - an original function argument name to replace by your field instance. It was header_field at the example above.
  • required - if CustomField is required, raises pydantic.error_wrappers.ValidationError if it is not present at final kwargs
  • cast - specify the typecasting behavior. Use False to disable pydantic typecasting for fields using with your CustomField
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class Header(CustomField):
    def __init__(self):
        super().__init__(cast=True)


class NotCastHeader(CustomField):
    def __init__(self):
        super().__init__(cast=False)


def func(
    h1: int = Header(),        # <-- casts to int
    h2: int = NotCastHeader()  # <-- just an annotation
): ...

Note

Pydantic understands only python-native annotation or Pydantic classes. If users will annotate your fields by other classes, you should set cast=False to avoid pydantic exceptions.

def use(self, **kwargs: AnyDict) -> AnyDict: ...

Your CustimField objects receive casted to kwargs an original function incoming arguments at use method. Returning from the use method dict replace an original one. Original function will be executed with a returned from your fields kwargs. Be accurate with.

And one more time:

1
2
3
4
5
6
7
8
9
original_kwargs = { "headers": { "field": 1 }}

new_kwargs = Header().set_param_name("field").use(**kwargs)
# new_kwargs = {
#   "headers": { "field": 1 },
#   "field": 1  <-- new field from Header
# }

original_function(**new_kwargs)

I hope it was clearly enough right now.

Also, custom fields using according their definition: from left to right. Next Custom Fields kwargs is a return of previous.

An example:

1
2
@inject
def func(field1 = Header(), field2 = Header()): ...

field2 incoming kwargs is an output of field1.use()