Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: Support Pydantic V2 #35

Merged
merged 21 commits into from
Jun 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ trim_trailing_whitespace = True

[*.py]
charset = utf-8
max_line_length = 88

[*.{yml,yaml,md,toml}]
indent_size = 2
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
cache: pip
cache-dependency-path: setup.cfg
check-latest: true
- run: pip install -e '.[test]'
- run: pip install -e '.[test,pydantic]'
- run: coverage run -m pytest
- run: |
coverage report
Expand Down
3 changes: 2 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,10 @@ repos:
- types-setuptools==65.3.0
- phantom-types==0.17.1
- abcattrs==0.3.2
- typing-extensions==4.3.0
- typing-extensions==4.6.3
- hypothesis==6.54.4
- immutables==0.19.0
- pydantic==2.0b3
- repo: https://github.com/pre-commit/mirrors-prettier
rev: "v2.7.1"
hooks:
Expand Down
78 changes: 76 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
<a href=https://pypi.org/project/immoney/><img src=https://img.shields.io/pypi/pyversions/immoney.svg?color=informational&label=Python alt="Python versions"></a>
</p>

### Installation

```shell
$ pip install --require-venv immoney
```

### Design goals

There are a few core design aspects of this library that each eliminate entire classes
Expand Down Expand Up @@ -135,5 +141,73 @@ Traceback (most recent call last):
KeyError: 'foo'
```

For custom currency implementations, `immoney.registry.CurrencyCollector` can be used to
construct a custom registry.
#### Custom currency registries

The library ships with a sensible set of default currencies, however, you might want to
use a custom registry for two reasons:

- You want to use non-default currencies.
- You only want to allow a subset of the default currencies.

To achieve this, you can construct a custom set of types. It's recommended to use a
custom abstract base class for this, this way things will also play nice with the
Pydantic integration.

```python
import abc
from typing import Final
from immoney.registry import CurrencyCollector
from immoney.currencies import Currency

__currencies = CurrencyCollector()


class SpaceCurrency(Currency, abc.ABC):
...


class MoonCoinType(SpaceCurrency):
subunit = 100_000
code = "MCN"


MCN: Final = MoonCoinType()
__currencies.add(MCN)


class JupiterDollarType(SpaceCurrency):
subunit = 100
code = "JCN"


JCN: Final = JupiterDollarType()
__currencies.add(JCN)

custom_registry: Final = __currencies.finalize()
```

#### Pydantic V2 support

Install a compatible Pydantic version by supplying the `[pydantic]` extra.

```shell
$ pip install --require-venv immoney[pydantic]
```

The `Currency`, `Money`, `SubunitFraction` and `Overdraft` entities can all be used as
Pydantic model fields.

```pycon
>>> from pydantic import BaseModel
>>> from immoney import Money
>>> from immoney.currencies import USD
>>> class Model(BaseModel, frozen=True):
... money: Money
>>> print(instance.model_dump_json(indent=2))
{
"money": {
"subunits": 25000,
"currency": "USD"
}
}
```
8 changes: 6 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ package_dir =
packages = find:
python_requires = >=3.10
install_requires =
phantom-types>=0.16.0
typing-extensions>=4.2.0
phantom-types>=2.1.0
typing-extensions>=4.6.3
abcattrs>=0.3.2
immutables>=0.19.0

Expand All @@ -39,6 +39,9 @@ where = src
immoney = py.typed

[options.extras_require]
pydantic =
pydantic>=2.0b3

test =
pytest
coverage
Expand Down Expand Up @@ -101,3 +104,4 @@ exclude_lines =
pragma: no cover
# ignore non-implementations
^\s*\.\.\.
^\s*if TYPE_CHECKING:$
Loading