Skip to content

Commit 674dcff

Browse files
committed
Function modularized and validators added.
1 parent b6d0e83 commit 674dcff

File tree

3 files changed

+200
-225
lines changed

3 files changed

+200
-225
lines changed

README.md

Lines changed: 36 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -9,163 +9,54 @@
99

1010
# pyoload
1111

12-
Hy pythonista! I'm happy to present to you `pyoload`, as from my words:
12+
This adds some runtime type checking and warnings when enabled. It is disabled
13+
by default.
1314

14-
A python module for extended and recursive type checking and casting of
15-
function arguments and class attributes during runtime
15+
Pyoload permits you to add runtime checking to classes on instance attribute
16+
assignment and functions.
1617

17-
Here we use some of the beautiful and clean features offered by python, including
18-
decorators and descriptors to help you type check during runtime
18+
## usage
1919

20-
Here are some simple usage examples to fill this pypi page.
20+
pyoload provides two basic methods:
21+
- `pyoload.annotate`: decorator over functions or methods.
22+
- `pyoload.annotate_class`: decorator over classes.
23+
All wrapped by `pyoload()` which checks what to be called.
2124

22-
## annotate
25+
```py
26+
import pyoload
2327

24-
This decorator function uses the power of `inspect.signature` to check the arguments
25-
passed to the function using it's annotations with support for default values, generic aliase
26-
and annotations adding some more annotation types for convenience, lower some code.
28+
pyoload.debug()
2729

28-
```python
29-
from pyoload import *
30+
@pyoload
31+
def foo(a: int, b, c: str) -> tuple[str, int]:
32+
return ("ab", 23)
3033

31-
@annotate
32-
def foo(
33-
a: str, # this has an annotation
34-
b=3, # this uses a default value
35-
c: int = 0 # here both
36-
) -> tuple[str, int]: # The return type
37-
...
34+
@pyoload
35+
class myclass:
36+
pass
3837
```
3938

40-
```python
41-
from pyoload import *
39+
## pyolaod modes
4240

43-
@annotate
44-
def foo(
45-
b=dict[str | int, float], # here a GenericAlias
46-
c: Cast(list[int]) = '12345' # here a recursive cast
47-
): # No return type
48-
...
49-
```
50-
51-
## multimethod
52-
53-
This uses the same principles as annotate but allows multiple dispatching
54-
(a.k.a runtime overloading?) of functions.
55-
56-
```python
57-
from pyoload import *
58-
59-
@multimethod
60-
def foo(a, b):
61-
print("two arguments")
62-
63-
@multimethod
64-
def foo(a: Values((1, 2, 3))):
65-
print('either 1, 2 or 3')
66-
67-
@foo.overload
68-
def _(a: Any):
69-
raise ValueError()
70-
```
71-
72-
## annotations
73-
74-
These are what pyoload adds to the standard annotations:
75-
76-
> [!NOTE]
77-
> The added annotations are still not mergeable with the standard types.
78-
79-
### `pyoload.Values`
80-
81-
A simple `tuple` subclass, use them as annotation and it will validate only
82-
included values.
83-
```python
84-
@annotate
85-
def foo(bar: Values(range(5))):
86-
...
87-
```
88-
89-
### `pyoload.Cast`
90-
91-
This performs recursive casting of the passed arguments into the specified type
92-
It supports `dict` generic aliases as `dict[str, int | str] ` and tries cast in
93-
the specified order when the type is a Union.
94-
95-
```python
96-
@annotate
97-
def foo(bar: Cast(tuple[int | str])):
98-
print(bar)
99-
100-
foo((3, "3")) # (3, 3)
101-
foo((3j, " ")) # ('3j', ' ')
102-
```
103-
104-
### `pyoload.Checks`
41+
Pyoload includes three modes of enum type `pyoload.Mode` and where the current
42+
mode is in `pyoload.MODE`.
10543

106-
Permits You tou use custom checker methods, e.g
44+
* **DEBUG**: Shows warnings, comments, exceptions activate via `pyoload.debug()`
45+
* **DEV** : Does not call upon validatore
46+
* **PROD**(*DEFAULT*): `@pyoload` simply does nothing.
10747

108-
```python
109-
from pyoload import *
48+
## Adding validators
11049

111-
test = lambda val: True # put your check here
112-
113-
def foo(a: Checks(func=test):
114-
...
115-
```
116-
117-
If the check name is prepended with a `_`, it will be negated, and an exception
118-
is raised if it fails.
119-
You can register your own checks using `Check.register`, as
120-
121-
```python
122-
@Check.register('mycheck')
123-
def _(param, value):
124-
print(param, value)
125-
126-
Checks(mycheck='param')('val') # Will raise error on check failure
127-
128-
@annotate
129-
def foo(a: Checks(mycheck='param')):
130-
...
131-
```
132-
133-
Checks can be used as annotations;
134-
called using `pyoload.Checks` as `Checks(foo=bar)(val)`; or
135-
Invoked directly using `pyoload.Checks` as:
136-
`Check.check(name, param, arg)`
137-
138-
#### len
139-
140-
Receives as argument an integer value specified the expected length or
141-
a slice in which the length should be found
142-
143-
#### gt, lt, eq
144-
145-
Compares grater than, less than and aqual to from the parameter
146-
to the value.
147-
148-
#### func
149-
150-
Uses a function for validation, the function could return a boolean
151-
or raise an error.
152-
It could be passed directly as positional arguments to pyoload.Checks
153-
as: `Checks(func1, func2, foo=bar, foo2=bar2)`
154-
155-
### Checked and casted attributes
156-
157-
`CheckedAttr` and `CastedAttr`, are simple descriptors which will perform
158-
the casting or checks on assignment.
159-
160-
```python
161-
from pyoload import *
162-
163-
class address:
164-
number = CastedAttr(tuple[int])
165-
166-
```
50+
You may add validators to check values furthermore.
16751

168-
The values are checked or casted on assignment
52+
```py
53+
def validator(value) -> Optional[str]:
54+
if value.is_ok():
55+
return None
56+
else:
57+
return "Value is not Ok! pass a value which is Ok please."
16958

170-
> [!NOTE]
171-
> The attributes will return `None` if not yet initialized
59+
@pyoload(comments=dict(val=validator))
60+
def func(val):
61+
pass
62+
```

0 commit comments

Comments
 (0)