Phantom types for Python
Project description
phantom-types
Phantom types for Python will help you make illegal states unrepresentable and avoid shotgun parsing by enabling you to practice "Parse, don't validate".
Checkout the complete documentation on Read the Docs →
Installation
$ python3 -m pip install phantom-types
Extras
phantom-types[dateutil]
installs python-dateutil. Required to useTZAware
andTZNaive
for parsing strings.phantom-types[phonenumbers]
installs phonenumbers. Required to usephantom.ext.phonenumbers
.phantom-types[pydantic]
installs pydantic.phantom-types[all]
installs all of the above.
$ python3 -m pip install phantom-types[all]
Examples
By introducing a phantom type we can define a pre-condition for a function argument.
from phantom import Phantom
from phantom.predicates.collection import contained
class Name(str, Phantom, predicate=contained({"Jane", "Joe"})):
...
def greet(name: Name):
print(f"Hello {name}!")
Now this will be a valid call.
greet(Name.parse("Jane"))
... and so will this.
joe = "Joe"
assert isinstance(joe, Name)
greet(joe)
But this will yield a static type checking error.
greet("bird")
Runtime type checking
By combining phantom types with a runtime type-checker like beartype or typeguard, we can achieve the same level of security as you'd gain from using contracts.
import datetime
from beartype import beartype
from phantom.datetime import TZAware
@beartype
def soon(dt: TZAware) -> TZAware:
return dt + datetime.timedelta(seconds=10)
The soon
function will now validate that both its argument and return value is
timezone aware, e.g. pre- and post conditions.
Pydantic support
Phantom types are ready to use with pydantic and have integrated
support out-of-the-box. Subclasses of Phantom
work with both
pydantic's validation and its schema generation.
class Name(str, Phantom, predicate=contained({"Jane", "Joe"})):
@classmethod
def __schema__(cls) -> Schema:
return super().__schema__() | {
"description": "Either Jane or Joe",
"format": "custom-name",
}
class Person(BaseModel):
name: Name
created: TZAware
print(json.dumps(Person.schema(), indent=2))
The code above outputs the following JSONSchema.
{
"title": "Person",
"type": "object",
"properties": {
"name": {
"title": "Name",
"description": "Either Jane or Joe",
"format": "custom-name",
"type": "string"
},
"created": {
"title": "TZAware",
"description": "A date-time with timezone data.",
"type": "string",
"format": "date-time"
}
},
"required": ["name", "created"]
}
Development
Install development requirements, preferably in a virtualenv:
$ python3 -m pip install .[all,test]
Run tests:
$ pytest
# or
$ make test
Linting and static type checking is setup with pre-commit, after installing it you can setup hooks with the following command, so that checks run before you push changes.
# configure hooks to run when pushing
$ pre-commit install -t pre-push
# or when committing
$ pre-commit install -t pre-commit
# run all checks
$ pre-commit run --all-files
# or just a single hook
$ pre-commit run mypy --all-files
In addition to static type checking, the project is setup with pytest-mypy-plugins to test that exposed mypy types work as expected, these checks will run together with the rest of the test suite, but you can single them out with the following command.
$ make test-typing
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file phantom-types-1.0.0.tar.gz
.
File metadata
- Download URL: phantom-types-1.0.0.tar.gz
- Upload date:
- Size: 23.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.1 CPython/3.9.14
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | c08424050a63584d11f018291092a5aee5b6c4f43952b27eea6b82fc15b81f82 |
|
MD5 | e51115e58f78bf1e32f1aec04dc44e39 |
|
BLAKE2b-256 | 2a10968e9ebdd8240363d952672db0a8fe118957bd9ada534ec45cca32a1ecfb |
File details
Details for the file phantom_types-1.0.0-py3-none-any.whl
.
File metadata
- Download URL: phantom_types-1.0.0-py3-none-any.whl
- Upload date:
- Size: 28.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.1 CPython/3.9.14
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 080d7e5d9e01d799dd8b160ffad4d36549788b872e10ca3902c3cc518cab5c15 |
|
MD5 | 2fbc861a9d0afefb7578f2c573b1f347 |
|
BLAKE2b-256 | 7694c7d9d381f5b52fda3e0951997e9b8e9555de2c081f163ec3abf0f71f59da |