https://github.com/yusing/typing-ex
https://github.com/yusing/typing-ex
Last synced: 5 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/yusing/typing-ex
- Owner: yusing
- License: mit
- Created: 2024-02-16T12:21:49.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2024-02-20T22:38:38.000Z (almost 2 years ago)
- Last Synced: 2024-05-02T03:53:07.515Z (almost 2 years ago)
- Language: Python
- Size: 73.2 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# typing-ex
## A python package for extended `typing` (python 3.8+)
[](https://sonarcloud.io/summary/new_code?id=yusing_typing-ex)
[](https://sonarcloud.io/summary/new_code?id=yusing_typing-ex)
[](https://sonarcloud.io/summary/new_code?id=yusing_typing-ex)
[](https://sonarcloud.io/summary/new_code?id=yusing_typing-ex)
[](https://sonarcloud.io/summary/new_code?id=yusing_typing-ex)
[](https://sonarcloud.io/summary/new_code?id=yusing_typing-ex)
[](https://sonarcloud.io/summary/new_code?id=yusing_typing-ex)
[](https://sonarcloud.io/summary/new_code?id=yusing_typing-ex)
[](https://sonarcloud.io/summary/new_code?id=yusing_typing-ex)
## Notice
Even with all tests passed, unexpected bugs might occur on edge cases
## Project Overview
I made this for fun, and also as a dependency for my other project [docker-playbook](https://github.com/yusing/docker-playbook) (working in progress).
If you found any bug, or have any suggestions, please let me know.
## Target Audience
People who want more strict type checking and less runtime errors / bugs.
## Comparison
[typeguard](https://github.com/agronholm/typeguard) provides runtime type checking for functions and class methods with `@typeguard` decorator. This project aims to enforce type annotation instead.
[mypy](https://github.com/python/mypy) provides static type checking, a good companion for this project to provide both static and runtime type checking.
## Installation
`pip install typing-ex`
## Modules/Classes
All Docs in [docs](docs/) (AI generated with small modification, may be incomplete)
### TypedDefaultDict *[typed_defaultdict.py](typing_ex/typed_defaultdict.py)* [Documentation](docs/TypedDefaultDict.md)
`TypedDefaultDict` combines features of `TypedDict` and `defaultdict` with type checking in `__init__`, `__setitem__`, `__setattr__` and `update()`, similar to `pydantic.BaseModel`.
Attributes without type annotation or starting with underscore "_" will be treated as class variables
Good for writing schema as a class for `JSON`/`YAML`/`XML`/etc. data which provides both static and runtime type checking.
- `TypedDefaultDict.schema`: the schema dictionary: `MappingProxyType[str, NamedTuple[default: Any, type:TypeInfo]]`
- `TypedDefaultDict.on_get_unknown_property`: called on getting unknown property
- `TypedDefaultDict.on_set_unknown_property`: called on setting unknown property
- `TypedDefaultDict.set`: set a property to a value without property check and type check
- `@factorymethod(property_name: str)`: defines a factory method for property
```python
class OtherClass:
def __self__(self, s_list: List[str]):
...
class MyModel(TypedDefaultDict):
key1: str = "default value"
key2: Optional[int]
complex_key: SomeClass
@factorymethod("complex_key")
def complex_key_factory(value: List[str]) -> OtherClass:
return OtherClass(value)
my_dict = MyModel(key1="value1", complex_key=["1", "2", "3"])
# or dict way
my_dict = MyModel({
"key1": "value1",
"complex_key": ["1", "2", "3"]
})
print(my_dict["key1"]) # Output: value1
print(my_dict.complex_key) # Output: By definition of OtherClass
```
### TypeInfo *[type_info.py](typing_ex/type_info.py)* [Documentation](docs/TypeInfo.md)
`TypeInfo` provides type information and run-time type checking, no more `isinstance`, `issubclass`, `is`, `==` mess.
Useful when you want to check / assert variable type in runtime.
`TypeInfo` provides type information and run-time type checking
- `TypeInfo.get(t)`: alias of `TypeInfo[t]`
- `TypeInfo.of(value)`: return a `TypeInfo` object that represents the type of `value`
- `TypeInfo.check_union(t1, t2)`: check if union type t1 fulfill union type t2
- `TypeInfo[t].type`: type
- `TypeInfo[t].origin`: unsubscripted type
- `TypeInfo[t].args`: type arguments
- `TypeInfo[t].name`: name of type (including arguments)
- `TypeInfo[t].check_value(value)`: check if value matches the type in type info
- `TypeInfo[t].is_*`: check if type is _
### EnumEx *[enum_ex.py](typing_ex/enum_ex.py)* [Documentation](docs/EnumEx.md)
`EnumEx` is a `Enum` like class that support enum aliasing (keeping same value but different name). Useful if you want to output a different name but with same internal implementation.
- `EnumEx.__iter__`: a generator of all non-alias enum instances.
- `EnumEx.names`: a tuple of all enum names.
- `EnumEx.values`: a tuple of all enum values.
- `EnumEx.enums`: a tuple of all enum instances.
- `EnumEx.value_type`: returns `__value_type__` if defined, int otherwise.
- `EnumEx.X.value`: value of enum X
- `EnumEx.X.name`: name of enum X (i.e. X)
- `EnumEx.X_ALIAS.orig_name`: original name of enum X_ALIAS (i.e. X)
- `EnumEx.X_ALIAS.origin`: origin enum of X_ALIAS (i.e. EnumEx.X)
```python
class ActionEnum(EnumEx):
__value_type__ = int # Optional: Specify value type (defaults to `int`)
STOP = 0
CREATE = 1
START = CREATE # Alias for CREATE
UPDATE = 2
RESTART = UPDATE # Alias for RESTART
print(Action.CREATE) # Output: CREATE
print(Action.START) # Output: START
print(Action.START.orig_name) # Output: CREATE
print(MyEnum.START.value) # Output: 1
class Action:
action :ActionEnum
def start(self): ...
def stop(self): ...
def restart(self): ...
def execute(self):
with ProgressBar() as progress:
progress.text = f"{action.name.lower()}ing..."
getattr(self, action.orig_name.lower())()
progress.text = "Done"
```
### Frozen *[frozen.py](typing_ex/frozen.py)*
Useful when you want to lock data after processing, without static type checker complaining (i.e. when casting it to `tuple`)
- `FrozenList`: Immutable `list`
- `FrozenDict`: Immutable `dict`
- `frozen_copy`: Create frozen copy of supported types (`Sequence`, `Set`, `Mapping`)