0.13.0a1 add .argparse, fix .sqlalchemy imports
This commit is contained in:
parent
d0701599fe
commit
11baf91dfd
6 changed files with 126 additions and 14 deletions
|
|
@ -1,5 +1,12 @@
|
|||
# Changelog
|
||||
|
||||
## 0.13.0
|
||||
|
||||
+ Added module `argparse` with class `LetterSubparsers()`
|
||||
+ module `sqlalchemy`:
|
||||
* removed deprecated alias `entity_base()`. use `declarative_base()` instead.
|
||||
* fix imports.
|
||||
|
||||
## 0.12.6
|
||||
|
||||
+ Added unittests to `dei_args()`
|
||||
|
|
|
|||
12
README.md
12
README.md
|
|
@ -1,6 +1,6 @@
|
|||
# SIS Unified Object Underarmor
|
||||
|
||||
Good morning, my brother! Welcome **SUOU** (**S**IS **U**nified **O**bject **U**nderarmor), the Python library which speeds up and makes it pleasing to develop API, database schemas and stuff in Python.
|
||||
Good morning, my brother! Welcome **SUOU** (**S**IS **U**nified **O**bject **U**nderarmor), the Python library which (maybe) speeds up and makes it pleasing to develop API, database schemas and stuff in Python.
|
||||
|
||||
It provides utilities such as:
|
||||
* SIQ ([specification](https://yusur.moe/protocols/siq.html) \[LINK BROKEN - WON'T FIX\] - [copy](https://suou.readthedocs.io/en/latest/iding.html))
|
||||
|
|
@ -15,13 +15,13 @@ It provides utilities such as:
|
|||
**Python 3.10**+ with Pip is required.
|
||||
|
||||
```bash
|
||||
$ pip install sakuragasaki46-suou
|
||||
$ pip install suou
|
||||
```
|
||||
|
||||
To install optional dependencies (i.e. `sqlalchemy`) for development use:
|
||||
|
||||
```bash
|
||||
$ pip install sakuragasaki46-suou[sqlalchemy]
|
||||
$ pip install suou[sqlalchemy]
|
||||
```
|
||||
|
||||
Please note that you probably already have those dependencies, if you just use the library.
|
||||
|
|
@ -34,7 +34,7 @@ Read the [documentation](https://suou.readthedocs.io/).
|
|||
|
||||
### Disclaimer
|
||||
|
||||
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.
|
||||
Just a heads up: SUOU was made to support yusurko (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.
|
||||
|
||||
|
|
@ -42,8 +42,6 @@ Expect breaking changes, disruptive renames in bugfix releases, sudden deprecati
|
|||
|
||||
Don't want to depend on my codebase for moral reasons (albeit unrelated)? It's fine. I did not ask you.
|
||||
|
||||
**DO NOT ASK TO MAKE SUOU SAFE FOR CHILDREN**. Enjoy having your fingers cut.
|
||||
|
||||
### "LTS"
|
||||
|
||||
The following versions are supported: the latest, the second-to-latest, 0.12.x and 0.7.x.
|
||||
|
|
@ -54,7 +52,7 @@ Licensed under the [Apache License, Version 2.0](LICENSE), a non-copyleft free a
|
|||
|
||||
This is a hobby project, made available “AS IS”, with __no warranty__ express or implied.
|
||||
|
||||
I (sakuragasaki46) may NOT be held accountable for Your use of my code.
|
||||
I (yusurko) may NOT be held accountable for Your use of my code.
|
||||
|
||||
> It's pointless to file a lawsuit because you feel damaged, and it's only going to turn against you. What a waste of money you could have spent on a vacation or charity, or invested in stocks.
|
||||
|
||||
|
|
|
|||
|
|
@ -37,13 +37,14 @@ from .redact import redact_url_password
|
|||
from .http import WantsContentType
|
||||
from .color import OKLabColor, chalk, WebColor, RGBColor, LinearRGBColor, XYZColor, OKLCHColor
|
||||
from .mat import Matrix
|
||||
from .argparse import LetterSubparsers
|
||||
|
||||
__version__ = "0.12.6"
|
||||
__version__ = "0.13.0a1"
|
||||
|
||||
__all__ = (
|
||||
'ConfigOptions', 'ConfigParserConfigSource', 'ConfigSource', 'ConfigValue',
|
||||
'DictConfigSource', 'EnvConfigSource', 'I18n', 'Incomplete', 'JsonI18n',
|
||||
'LinearRGBColor',
|
||||
'LetterSubparsers', 'LinearRGBColor',
|
||||
'Matrix', 'MissingConfigError', 'MissingConfigWarning', 'OKLabColor', 'OKLCHColor',
|
||||
'PrefixIdentifier', 'RGBColor',
|
||||
'Siq', 'SiqCache', 'SiqGen', 'SiqType', 'Snowflake', 'SnowflakeGen',
|
||||
|
|
@ -52,8 +53,8 @@ __all__ = (
|
|||
'addattr', 'additem', 'age_and_days', 'alru_cache', 'b2048decode', 'b2048encode',
|
||||
'b32ldecode', 'b32lencode', 'b64encode', 'b64decode', 'cb32encode',
|
||||
'cb32decode', 'chalk', 'count_ones', 'dei_args', 'deprecated',
|
||||
'future', 'ilex', 'join_bits',
|
||||
'jsonencode', 'kwargs_prefix', 'lex', 'ltuple', 'makelist', 'mask_shift',
|
||||
'future', 'ilex', 'join_bits', 'jsonencode', 'kwargs_prefix',
|
||||
'lex', 'ltuple', 'makelist', 'mask_shift',
|
||||
'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',
|
||||
|
|
|
|||
105
src/suou/argparse.py
Normal file
105
src/suou/argparse.py
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
"""
|
||||
Utilities for parsing arguments. Based on argparse.
|
||||
|
||||
---
|
||||
|
||||
Copyright (c) 2025 Sakuragasaki46.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
See LICENSE for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
This software is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
from typing import Callable, Mapping
|
||||
|
||||
class LetterSubparsers(object):
|
||||
"""
|
||||
Subparsers in pacman style, where action name can be shortened to a single letter, prefixed by a hyphen
|
||||
|
||||
(i.e. "-S" is expanded to "sync")
|
||||
|
||||
*New in 0.13.0*
|
||||
"""
|
||||
|
||||
_parser: argparse.ArgumentParser
|
||||
_letters: dict[str, str]
|
||||
_subparsers: argparse._SubParsersAction[argparse.ArgumentParser]
|
||||
|
||||
def __init__(self, parser : argparse.ArgumentParser, *, dest: str = 'action', **kwargs):
|
||||
self._parser = parser
|
||||
self._letters = {}
|
||||
self._subparsers = parser.add_subparsers(dest = dest, **kwargs)
|
||||
|
||||
def action(self, /, letter: str, name: str | None = None, **kwargs):
|
||||
"""
|
||||
Decorator which adds a subparser of an argument parser's subparsers, and specifies a letter to make a shorthand in pacman style.
|
||||
|
||||
For example, assuming name="sync" and letter="S", if the first argument is "-S", it will be turned to "sync", .
|
||||
|
||||
The first argument is always the object returned by ArgumentParser.add_subparsers().
|
||||
|
||||
Additional kwargs are passed to the add_parser constructor.
|
||||
"""
|
||||
|
||||
if len(letter) != 1:
|
||||
raise ValueError('letter must be one character')
|
||||
|
||||
o_name = name
|
||||
|
||||
def decorator(func: Callable[argparse.ArgumentParser, ...]):
|
||||
name = o_name or func.__name__
|
||||
parser = self._subparsers.add_parser(name, **kwargs)
|
||||
func(parser)
|
||||
|
||||
self._letters[letter] = name
|
||||
|
||||
return func
|
||||
return decorator
|
||||
|
||||
def parse_args(self, argv = None, system_exit: bool = True):
|
||||
"""
|
||||
Variation of ArgumentParser.parse_args() that takes shortcut letters into account.
|
||||
|
||||
Best used together with letter_action().
|
||||
"""
|
||||
|
||||
if argv is None:
|
||||
argv = sys.argv[1:]
|
||||
else:
|
||||
argv = list(argv)
|
||||
|
||||
if len(argv) > 0:
|
||||
first_arg = argv.pop(0)
|
||||
|
||||
if first_arg.startswith('-') and len(first_arg) >= 2:
|
||||
letter, rest = first_arg[1], first_arg[2:]
|
||||
if letter in self._letters:
|
||||
argv.insert(0, self._letters[letter])
|
||||
if rest:
|
||||
argv.insert(1, "-" + rest)
|
||||
else:
|
||||
# put it back
|
||||
argv.insert(0, first_arg)
|
||||
else:
|
||||
# put it back
|
||||
argv.insert(0, first_arg)
|
||||
|
||||
try:
|
||||
return self._parser.parse_args(argv)
|
||||
except SystemExit:
|
||||
# prevent SystemExit at parse fail
|
||||
if system_exit:
|
||||
raise
|
||||
|
||||
|
||||
__all__ = ('LetterSubparsers',)
|
||||
|
||||
|
|
@ -154,7 +154,7 @@ def require_auth_base(cls: type[DeclarativeBase], *, src: AuthSrc, column: str |
|
|||
return decorator
|
||||
|
||||
|
||||
from .asyncio import SQLAlchemy, async_query
|
||||
from .asyncio import SQLAlchemy, async_query, SessionWrapper, AsyncSelectPagination
|
||||
from .orm import (
|
||||
id_column, snowflake_column, match_column, match_constraint, bool_column, declarative_base, parent_children,
|
||||
author_pair, age_pair, bound_fk, unbound_fk, want_column, a_relationship, BitSelector, secret_column, username_column
|
||||
|
|
@ -168,7 +168,7 @@ except ImportError:
|
|||
|
||||
# Optional dependency: do not import into __init__.py
|
||||
__all__ = (
|
||||
'IdType', 'id_column', 'snowflake_column', 'entity_base', 'declarative_base', 'token_signer',
|
||||
'IdType', 'id_column', 'snowflake_column', 'declarative_base', 'token_signer',
|
||||
'match_column', 'match_constraint', 'bool_column', 'parent_children',
|
||||
'author_pair', 'age_pair', 'bound_fk', 'unbound_fk', 'want_column',
|
||||
'a_relationship', 'BitSelector', 'secret_column', 'username_column',
|
||||
|
|
|
|||
|
|
@ -146,6 +146,8 @@ def declarative_base(domain_name: str, master_secret: bytes, metadata: dict | No
|
|||
"""
|
||||
Drop-in replacement for sqlalchemy.orm.declarative_base()
|
||||
taking in account requirements for SIQ generation (i.e. domain name).
|
||||
|
||||
Also supports snowflake generation parameters such as epoch.
|
||||
"""
|
||||
if not isinstance(metadata, dict):
|
||||
metadata = dict()
|
||||
|
|
@ -160,7 +162,6 @@ def declarative_base(domain_name: str, master_secret: bytes, metadata: dict | No
|
|||
)
|
||||
Base = _declarative_base(metadata=MetaData(**metadata), **kwargs)
|
||||
return Base
|
||||
entity_base = warnings.deprecated('use declarative_base() instead')(declarative_base)
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue