0.9.0 add yesno() + make Waiter usable + document validators
This commit is contained in:
parent
f1f9a95189
commit
def2634f21
10 changed files with 83 additions and 16 deletions
|
|
@ -1,5 +1,12 @@
|
|||
# Changelog
|
||||
|
||||
## 0.9.0
|
||||
|
||||
+ Fix to make experimental `Waiter` usable
|
||||
+ Suspend `glue()` release indefinitely
|
||||
+ Add `yesno()`
|
||||
+ Document validators
|
||||
|
||||
## 0.8.2 and 0.7.9
|
||||
|
||||
+ `.color`: fix `chalk` not behaving as expected
|
||||
|
|
|
|||
|
|
@ -28,11 +28,11 @@ Please note that you probably already have those dependencies, if you just use t
|
|||
|
||||
## Features
|
||||
|
||||
...
|
||||
Read the [documentation](https://suou.readthedocs.io/).
|
||||
|
||||
## Support
|
||||
|
||||
Just a heads up: SUOU was made to support Sakuragasaki46 (me)'s own selfish, egoistic needs. Not to provide a service to the public.
|
||||
Just a heads up: SUOU was made to support Sakuragasaki46 (me)'s own selfish, egoistic needs. Not certainly to provide a service to the public.
|
||||
|
||||
As a consequence, 'add this add that' stuff is best-effort.
|
||||
|
||||
|
|
|
|||
|
|
@ -15,4 +15,5 @@ ease programmer's QoL and write shorter and cleaner code that works.
|
|||
|
||||
sqlalchemy
|
||||
iding
|
||||
validators
|
||||
api
|
||||
15
docs/validators.rst
Normal file
15
docs/validators.rst
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
validators
|
||||
==================
|
||||
|
||||
.. currentmodule:: suou.validators
|
||||
|
||||
Validators for use in frameworks such as Pydantic or Marshmallow.
|
||||
|
||||
.. autofunction:: matches
|
||||
|
||||
.. autofunction:: not_greater_than
|
||||
|
||||
.. autofunction:: not_less_than
|
||||
|
||||
.. autofunction:: yesno
|
||||
|
|
@ -32,12 +32,12 @@ from .signing import UserSigner
|
|||
from .snowflake import Snowflake, SnowflakeGen
|
||||
from .lex import symbol_table, lex, ilex
|
||||
from .strtools import PrefixIdentifier
|
||||
from .validators import matches
|
||||
from .validators import matches, not_less_than, not_greater_than, yesno
|
||||
from .redact import redact_url_password
|
||||
from .http import WantsContentType
|
||||
from .color import chalk, WebColor
|
||||
|
||||
__version__ = "0.8.2"
|
||||
__version__ = "0.9.0"
|
||||
|
||||
__all__ = (
|
||||
'ConfigOptions', 'ConfigParserConfigSource', 'ConfigSource', 'ConfigValue',
|
||||
|
|
@ -51,9 +51,10 @@ __all__ = (
|
|||
'cb32decode', 'chalk', 'count_ones', 'dei_args', 'deprecated',
|
||||
'future', 'ilex', 'join_bits',
|
||||
'jsonencode', 'kwargs_prefix', 'lex', 'ltuple', 'makelist', 'mask_shift',
|
||||
'matches', 'mod_ceil', 'mod_floor', 'none_pass', 'not_implemented',
|
||||
'matches', 'mod_ceil', 'mod_floor', 'must_be', 'none_pass', 'not_implemented',
|
||||
'not_less_than', 'not_greater_than',
|
||||
'redact_url_password', 'rtuple', 'split_bits', 'ssv_list', 'symbol_table',
|
||||
'timed_cache', 'twocolon_list', 'want_bytes', 'want_datetime', 'want_isodate',
|
||||
'want_str', 'want_timestamp', 'want_urlsafe', 'want_urlsafe_bytes',
|
||||
'want_str', 'want_timestamp', 'want_urlsafe', 'want_urlsafe_bytes', 'yesno',
|
||||
'z85encode', 'z85decode'
|
||||
)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||
|
||||
import datetime
|
||||
|
||||
from suou.functools import not_implemented
|
||||
from suou.luck import lucky
|
||||
from suou.validators import not_greater_than
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ from suou.classtools import MISSING
|
|||
from suou.functools import future
|
||||
|
||||
|
||||
@future(version="0.9.0")
|
||||
@future()
|
||||
class FakeModule(ModuleType):
|
||||
"""
|
||||
Fake module used in @glue() in case of import error
|
||||
|
|
@ -34,12 +34,12 @@ class FakeModule(ModuleType):
|
|||
raise AttributeError(f'Module {self.__name__} not found; this feature is not available ({self._exc})') from self._exc
|
||||
|
||||
|
||||
@future(version = "0.9.0")
|
||||
@future()
|
||||
def glue(*modules):
|
||||
"""
|
||||
Helper for "glue" code -- it imports the given modules and passes them as keyword arguments to the wrapped functions.
|
||||
|
||||
NEW 0.9.0
|
||||
EXPERIMENTAL
|
||||
"""
|
||||
module_dict = dict()
|
||||
imports_succeeded = True
|
||||
|
|
|
|||
|
|
@ -18,6 +18,10 @@ import re
|
|||
|
||||
from typing import Any, Iterable, TypeVar
|
||||
|
||||
from suou.classtools import MISSING
|
||||
|
||||
from .functools import future
|
||||
|
||||
_T = TypeVar('_T')
|
||||
|
||||
def matches(regex: str | int, /, length: int = 0, *, flags=0):
|
||||
|
|
@ -55,5 +59,13 @@ def not_less_than(y):
|
|||
"""
|
||||
return lambda x: x >= y
|
||||
|
||||
__all__ = ('matches', 'not_greater_than')
|
||||
def yesno(x: str) -> bool:
|
||||
"""
|
||||
Returns False if x.lower() is in '0', '', 'no', 'n', 'false' or 'off'.
|
||||
|
||||
*New in 0.9.0*
|
||||
"""
|
||||
return x not in (None, MISSING) and x.lower() not in ('', '0', 'off', 'n', 'no', 'false', 'f')
|
||||
|
||||
__all__ = ('matches', 'must_be', 'not_greater_than', 'not_less_than', 'yesno')
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||
"""
|
||||
|
||||
|
||||
from typing import Callable
|
||||
import warnings
|
||||
from starlette.applications import Starlette
|
||||
from starlette.responses import JSONResponse, PlainTextResponse, Response
|
||||
|
|
@ -27,15 +28,22 @@ from suou.functools import future
|
|||
|
||||
@future()
|
||||
class Waiter():
|
||||
_cached_app: Callable | None = None
|
||||
|
||||
def __init__(self):
|
||||
self.routes: list[Route] = []
|
||||
self.production = False
|
||||
|
||||
async def __call__(self, *args):
|
||||
return await self._build_app()(*args)
|
||||
|
||||
def _build_app(self) -> Starlette:
|
||||
return Starlette(
|
||||
if not self._cached_app:
|
||||
self._cached_app = Starlette(
|
||||
debug = not self.production,
|
||||
routes= self.routes
|
||||
)
|
||||
return self._cached_app
|
||||
|
||||
def get(self, endpoint: str, *a, **k):
|
||||
return self._route('GET', endpoint, *a, **k)
|
||||
|
|
|
|||
24
tests/test_validators.py
Normal file
24
tests/test_validators.py
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
|
||||
|
||||
import unittest
|
||||
from suou.validators import yesno
|
||||
|
||||
class TestValidators(unittest.TestCase):
|
||||
def setUp(self):
|
||||
...
|
||||
def tearDown(self):
|
||||
...
|
||||
def test_yesno(self):
|
||||
self.assertFalse(yesno('false'))
|
||||
self.assertFalse(yesno('FALSe'))
|
||||
self.assertTrue(yesno('fasle'))
|
||||
self.assertTrue(yesno('falso'))
|
||||
self.assertTrue(yesno('zero'))
|
||||
self.assertTrue(yesno('true'))
|
||||
self.assertFalse(yesno('0'))
|
||||
self.assertTrue(yesno('00'))
|
||||
self.assertTrue(yesno('.'))
|
||||
self.assertTrue(yesno('2'))
|
||||
self.assertTrue(yesno('o'))
|
||||
self.assertFalse(yesno('oFF'))
|
||||
self.assertFalse(yesno('no'))
|
||||
Loading…
Add table
Add a link
Reference in a new issue