diff options
Diffstat (limited to 'python-cleand.spec')
-rw-r--r-- | python-cleand.spec | 396 |
1 files changed, 396 insertions, 0 deletions
diff --git a/python-cleand.spec b/python-cleand.spec new file mode 100644 index 0000000..68d0b0c --- /dev/null +++ b/python-cleand.spec @@ -0,0 +1,396 @@ +%global _empty_manifest_terminate_build 0 +Name: python-cleand +Version: 1.3.1 +Release: 1 +Summary: a declarative data validator +License: MIT License +URL: https://github.com/saryou/cleaned +Source0: https://mirrors.aliyun.com/pypi/web/packages/17/28/3b6a0d9b36297daf8b11b61d589216356b601fe4d53693a259a7940195e4/cleand-1.3.1.tar.gz +BuildArch: noarch + + +%description +# cleaned + +pypi: https://pypi.org/project/cleand/ + +(pypi's project name is not clean**e**d because it wasn't available then) + +## Overview + +`cleaned` is a declarative data validator. + +## Examples + +```python +import json +import cleaned as cl + + +class Request(cl.Cleaned): + username = cl.Str(pattern='^[a-zA-Z_]+$', blank=False, min_length=3) + password = cl.Str(blank=False, min_length=8) + age = cl.Int() + + +def register_user_api(request_json: str) -> ...: + dirty_data = json.loads(request_json) + cleaned_data = Request(**dirty_data) + + # username matches ^[a-zA-Z_]+$ and it has at least 3 characters + username = cleaned_data.username + + # password is at least 8 characters + password = cleaned_data.password + + # age is a int value + age = cleaned_data.age + + # do something with the data + print(username, password, age) + ... + + +register_user_api(json.dumps({ + 'username': 'user', + 'password': 'KJF83h9q3FAS', + 'age': '20', +})) + + +try: + Request(username='invalid format', password='short') +except cl.ValidationError as e: + print(e.nested['username']) + # ('The value must match: ^[a-zA-Z_]+$', 'pattern') + print(e.nested['password']) + # ('The length of the value must be longer than or equal to 8.', 'min_length') + print(e.nested['age']) + # ('This field is required', 'required') +``` + +## Static Typing + +mypy can handle almost all cleaned values in the library. + +```python +import cleaned as cl +import enum + + +class Examples(cl.Cleaned): + class NestedExample(cl.Cleaned): + a = cl.Int() + + class EnumExample(enum.Enum): + a = 1 + b = 2 + + a = cl.Either(cl.Int(), cl.Str(blank=False)) + b = cl.Int().opt() + c = cl.Dict(key=cl.Int(), value=cl.Float().opt()).opt() + d = cl.Nested(NestedExample) + e = cl.Enum(EnumExample) + f = cl.List(cl.Nested(NestedExample)) + g = cl.List(cl.Nested(lambda: Examples)) + + +ex = Examples() + +reveal_type(ex.a) +# Revealed type is 'Union[builtins.int*, builtins.str*]' + +reveal_type(ex.b) +# Revealed type is 'Union[builtins.int*, None]' + +reveal_type(ex.c) +# Revealed type is 'Union[builtins.dict*[builtins.int*, Union[builtins.float*, None]], None]' + +reveal_type(ex.d) +# Revealed type is 'Examples.NestedExample*' + +reveal_type(ex.e) +# Revealed type is 'Examples.EnumExample*' + +reveal_type(ex.f) +# Revealed type is 'builtins.list*[Examples.NestedExample*]' + +reveal_type(ex.g) +# Revealed type is 'builtins.list*[hoge.Examples*]' +``` + + +%package -n python3-cleand +Summary: a declarative data validator +Provides: python-cleand +BuildRequires: python3-devel +BuildRequires: python3-setuptools +BuildRequires: python3-pip +%description -n python3-cleand +# cleaned + +pypi: https://pypi.org/project/cleand/ + +(pypi's project name is not clean**e**d because it wasn't available then) + +## Overview + +`cleaned` is a declarative data validator. + +## Examples + +```python +import json +import cleaned as cl + + +class Request(cl.Cleaned): + username = cl.Str(pattern='^[a-zA-Z_]+$', blank=False, min_length=3) + password = cl.Str(blank=False, min_length=8) + age = cl.Int() + + +def register_user_api(request_json: str) -> ...: + dirty_data = json.loads(request_json) + cleaned_data = Request(**dirty_data) + + # username matches ^[a-zA-Z_]+$ and it has at least 3 characters + username = cleaned_data.username + + # password is at least 8 characters + password = cleaned_data.password + + # age is a int value + age = cleaned_data.age + + # do something with the data + print(username, password, age) + ... + + +register_user_api(json.dumps({ + 'username': 'user', + 'password': 'KJF83h9q3FAS', + 'age': '20', +})) + + +try: + Request(username='invalid format', password='short') +except cl.ValidationError as e: + print(e.nested['username']) + # ('The value must match: ^[a-zA-Z_]+$', 'pattern') + print(e.nested['password']) + # ('The length of the value must be longer than or equal to 8.', 'min_length') + print(e.nested['age']) + # ('This field is required', 'required') +``` + +## Static Typing + +mypy can handle almost all cleaned values in the library. + +```python +import cleaned as cl +import enum + + +class Examples(cl.Cleaned): + class NestedExample(cl.Cleaned): + a = cl.Int() + + class EnumExample(enum.Enum): + a = 1 + b = 2 + + a = cl.Either(cl.Int(), cl.Str(blank=False)) + b = cl.Int().opt() + c = cl.Dict(key=cl.Int(), value=cl.Float().opt()).opt() + d = cl.Nested(NestedExample) + e = cl.Enum(EnumExample) + f = cl.List(cl.Nested(NestedExample)) + g = cl.List(cl.Nested(lambda: Examples)) + + +ex = Examples() + +reveal_type(ex.a) +# Revealed type is 'Union[builtins.int*, builtins.str*]' + +reveal_type(ex.b) +# Revealed type is 'Union[builtins.int*, None]' + +reveal_type(ex.c) +# Revealed type is 'Union[builtins.dict*[builtins.int*, Union[builtins.float*, None]], None]' + +reveal_type(ex.d) +# Revealed type is 'Examples.NestedExample*' + +reveal_type(ex.e) +# Revealed type is 'Examples.EnumExample*' + +reveal_type(ex.f) +# Revealed type is 'builtins.list*[Examples.NestedExample*]' + +reveal_type(ex.g) +# Revealed type is 'builtins.list*[hoge.Examples*]' +``` + + +%package help +Summary: Development documents and examples for cleand +Provides: python3-cleand-doc +%description help +# cleaned + +pypi: https://pypi.org/project/cleand/ + +(pypi's project name is not clean**e**d because it wasn't available then) + +## Overview + +`cleaned` is a declarative data validator. + +## Examples + +```python +import json +import cleaned as cl + + +class Request(cl.Cleaned): + username = cl.Str(pattern='^[a-zA-Z_]+$', blank=False, min_length=3) + password = cl.Str(blank=False, min_length=8) + age = cl.Int() + + +def register_user_api(request_json: str) -> ...: + dirty_data = json.loads(request_json) + cleaned_data = Request(**dirty_data) + + # username matches ^[a-zA-Z_]+$ and it has at least 3 characters + username = cleaned_data.username + + # password is at least 8 characters + password = cleaned_data.password + + # age is a int value + age = cleaned_data.age + + # do something with the data + print(username, password, age) + ... + + +register_user_api(json.dumps({ + 'username': 'user', + 'password': 'KJF83h9q3FAS', + 'age': '20', +})) + + +try: + Request(username='invalid format', password='short') +except cl.ValidationError as e: + print(e.nested['username']) + # ('The value must match: ^[a-zA-Z_]+$', 'pattern') + print(e.nested['password']) + # ('The length of the value must be longer than or equal to 8.', 'min_length') + print(e.nested['age']) + # ('This field is required', 'required') +``` + +## Static Typing + +mypy can handle almost all cleaned values in the library. + +```python +import cleaned as cl +import enum + + +class Examples(cl.Cleaned): + class NestedExample(cl.Cleaned): + a = cl.Int() + + class EnumExample(enum.Enum): + a = 1 + b = 2 + + a = cl.Either(cl.Int(), cl.Str(blank=False)) + b = cl.Int().opt() + c = cl.Dict(key=cl.Int(), value=cl.Float().opt()).opt() + d = cl.Nested(NestedExample) + e = cl.Enum(EnumExample) + f = cl.List(cl.Nested(NestedExample)) + g = cl.List(cl.Nested(lambda: Examples)) + + +ex = Examples() + +reveal_type(ex.a) +# Revealed type is 'Union[builtins.int*, builtins.str*]' + +reveal_type(ex.b) +# Revealed type is 'Union[builtins.int*, None]' + +reveal_type(ex.c) +# Revealed type is 'Union[builtins.dict*[builtins.int*, Union[builtins.float*, None]], None]' + +reveal_type(ex.d) +# Revealed type is 'Examples.NestedExample*' + +reveal_type(ex.e) +# Revealed type is 'Examples.EnumExample*' + +reveal_type(ex.f) +# Revealed type is 'builtins.list*[Examples.NestedExample*]' + +reveal_type(ex.g) +# Revealed type is 'builtins.list*[hoge.Examples*]' +``` + + +%prep +%autosetup -n cleand-1.3.1 + +%build +%py3_build + +%install +%py3_install +install -d -m755 %{buildroot}/%{_pkgdocdir} +if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi +if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi +if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi +if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi +pushd %{buildroot} +if [ -d usr/lib ]; then + find usr/lib -type f -printf "\"/%h/%f\"\n" >> filelist.lst +fi +if [ -d usr/lib64 ]; then + find usr/lib64 -type f -printf "\"/%h/%f\"\n" >> filelist.lst +fi +if [ -d usr/bin ]; then + find usr/bin -type f -printf "\"/%h/%f\"\n" >> filelist.lst +fi +if [ -d usr/sbin ]; then + find usr/sbin -type f -printf "\"/%h/%f\"\n" >> filelist.lst +fi +touch doclist.lst +if [ -d usr/share/man ]; then + find usr/share/man -type f -printf "\"/%h/%f.gz\"\n" >> doclist.lst +fi +popd +mv %{buildroot}/filelist.lst . +mv %{buildroot}/doclist.lst . + +%files -n python3-cleand -f filelist.lst +%dir %{python3_sitelib}/* + +%files help -f doclist.lst +%{_docdir}/* + +%changelog +* Tue Jun 20 2023 Python_Bot <Python_Bot@openeuler.org> - 1.3.1-1 +- Package Spec generated |