Skip to content

Commit a09a2cf

Browse files
author
Sylvain MARIE
committed
Added API in api reference and updated documentation.
1 parent 84be9f3 commit a09a2cf

3 files changed

Lines changed: 76 additions & 2 deletions

File tree

docs/api_reference.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,14 @@ generating default value for <pyfields.core.Pocket object ...
132132
[]
133133
```
134134

135+
Several helper functions are available to create default factories:
136+
137+
- `copy_value(<value>)` returns a factory that creates a copy of the provided `val` everytime it is called. Handy if you wish to use mutable
138+
objects as default values for your fields ; for example lists.
139+
140+
- `copy_attr(<att_name>, deep=True)` returns a factory that creates a (deep or not) copy of the value in the given attribute everytime it is called.
141+
142+
- `copy_field(<field_or_name>, deep=True)` is similar to `copy_attr` but you can provide a `field` instead of a name.
135143

136144
### `@<field>.validator`
137145

@@ -343,3 +351,52 @@ Wall<height=1, color='white'>
343351
**Parameters:**
344352

345353
- `fields`: list of fields to initialize before entering the decorated `__init__` method. For each of these fields a corresponding argument will be added in the method's signature. If an empty list is provided, all fields from the class will be used including inherited fields following the mro.
354+
355+
356+
## API
357+
358+
### `has_fields`
359+
360+
```python
361+
def has_fields(cls,
362+
include_inherited=True # type: bool
363+
)
364+
```
365+
366+
Returns True if class `cls` defines at least one `pyfields` field.
367+
If `include_inherited` is `True` (default), the method will return `True` if at least a field is defined in the class or one of its ancestors. If `False`, the fields need to be defined on the class itself.
368+
369+
### `get_fields`
370+
371+
```python
372+
def get_fields(cls,
373+
include_inherited=True, # type: bool
374+
remove_duplicates=True, # type: bool
375+
ancestors_first=True, # type: bool
376+
container_type=tuple, # type: Type[T]
377+
)
378+
```
379+
380+
Utility method to collect all fields defined in a class, including all inherited or not.
381+
By default duplicates are removed and ancestor fields are included and appear first. If a field is overridden, it will appear at the position of the overridden field in the order.
382+
383+
### `yield_fields`
384+
385+
```python
386+
def yield_fields(cls,
387+
include_inherited=True, # type: bool
388+
remove_duplicates=True, # type: bool
389+
ancestors_first=True, # type: bool
390+
)
391+
```
392+
393+
Similar to `get_fields` but as a generator.
394+
395+
### `get_field`
396+
397+
```python
398+
def get_field(cls, name)
399+
```
400+
401+
Utility method to return the field member with name `name` in class `cls`.
402+
If the member is not a field, a `NotAFieldError` is raised.

docs/index.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
[![Documentation](https://img.shields.io/badge/doc-latest-blue.svg)](https://smarie.github.io/python-pyfields/) [![PyPI](https://img.shields.io/pypi/v/pyfields.svg)](https://pypi.python.org/pypi/pyfields/) [![Downloads](https://pepy.tech/badge/pyfields)](https://pepy.tech/project/pyfields) [![Downloads per week](https://pepy.tech/badge/pyfields/week)](https://pepy.tech/project/pyfields) [![GitHub stars](https://img.shields.io/github/stars/smarie/python-pyfields.svg)](https://github.com/smarie/python-pyfields/stargazers)
88

9+
!!! success "`pyfields` is now automatically supported by `autoclass` ! See [here](https://smarie.github.io/python-autoclass/#pyfields-combo) for details."
910

1011
`pyfields` provides a simple and elegant way to define fields in python classes. With `pyfields` you explicitly define all aspects of a field (default value, type, documentation...) in a single place, and can refer to it from other places.
1112

@@ -27,7 +28,9 @@ It provides **many optional features** that will make your object-oriented devel
2728

2829
- initializing fields in your *constructor* is very easy and highly customizable
2930

30-
If your first reaction is "what about `attrs` / `dataclasses` / `pydantic` / `characteristic` / `traits` / `traitlets` / `autoclass` / ...", please have a look [here](why.md).
31+
Finally, it offers an API that other libraries can leverage to get the list of fields. For example `autoclass` now leverages `pyfields` to automatically add hash/dict/eq/repr to your class.
32+
33+
If your first reaction is "what about `attrs` / `dataclasses` / `pydantic` / `characteristic` / `traits` / `traitlets` / ...", please have a look [here](why.md).
3134

3235

3336
## Installing
@@ -603,6 +606,14 @@ Note on the order of arguments in the resulting `__init__` signature: as you can
603606
604607
### 3. Misc.
605608
609+
#### API
610+
611+
`pyfields` offers an API so that other libraries can inspect the fields: `get_fields`, `yield_fields`, `has_fields`, `get_field`. See [API reference](https://smarie.github.io/python-pyfields/api_reference/#api) for details.
612+
613+
#### hash, dict, eq, repr
614+
615+
`autoclass` is now compliant with `pyfields`. So you can use `@autoclass`, or `@autorepr`, `@autohash`, `@autodict`... on the decorated class. That way, your fields definition is directly reused for most of the class behaviour. See [here](https://smarie.github.io/python-autoclass/#pyfields-combo) for details.
616+
606617
#### Slots
607618
608619
You can use `pyfields` if your class has `__slots__`. You will simply have to use an underscore in the slot name corresponding to a field: `_<field_name>`. For example:

pyfields/helpers.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ def yield_fields(cls,
5151
_auto_fix_fields=False # type: bool
5252
):
5353
"""
54+
Similar to `get_fields` but as a generator.
5455
5556
:param cls:
5657
:param include_inherited:
@@ -125,7 +126,9 @@ def has_fields(cls,
125126
include_inherited=True # type: bool
126127
):
127128
"""
128-
Returns True if class `cls` defines at least one `pyfields` field
129+
Returns True if class `cls` defines at least one `pyfields` field.
130+
If `include_inherited` is `True` (default), the method will return `True` if at least a field is defined in the
131+
class or one of its ancestors. If `False`, the fields need to be defined on the class itself.
129132
130133
:param cls:
131134
:param include_inherited:
@@ -145,6 +148,9 @@ def get_fields(cls,
145148
"""
146149
Utility method to collect all fields defined in a class, including all inherited or not.
147150
151+
By default duplicates are removed and ancestor fields are included and appear first. If a field is overridden,
152+
it will appear at the position of the overridden field in the order.
153+
148154
:param cls:
149155
:param include_inherited:
150156
:param remove_duplicates:

0 commit comments

Comments
 (0)