mirror of
https://github.com/kristoferssolo/School.git
synced 2025-10-21 20:10:38 +00:00
230 lines
5.6 KiB
Python
230 lines
5.6 KiB
Python
"""
|
|
Example:
|
|
>>> from aiogram.utils.helper import Helper, ListItem, HelperMode, Item
|
|
>>> class MyHelper(Helper):
|
|
... mode = HelperMode.lowerCamelCase
|
|
... FOO_ITEM = ListItem()
|
|
... BAR_ITEM = ListItem()
|
|
... BAZ_ITEM = ListItem()
|
|
... LOREM = Item()
|
|
...
|
|
>>> print(MyHelper.FOO_ITEM & MyHelper.BAR_ITEM)
|
|
<<< ['fooItem', 'barItem']
|
|
>>> print(MyHelper.all())
|
|
<<< ['barItem', 'bazItem', 'fooItem', 'lorem']
|
|
"""
|
|
from typing import List
|
|
|
|
PROPS_KEYS_ATTR_NAME = '_props_keys'
|
|
|
|
|
|
class Helper:
|
|
mode = ''
|
|
|
|
@classmethod
|
|
def all(cls):
|
|
"""
|
|
Get all consts
|
|
:return: list
|
|
"""
|
|
result = []
|
|
for name in dir(cls):
|
|
if not name.isupper():
|
|
continue
|
|
value = getattr(cls, name)
|
|
if isinstance(value, ItemsList):
|
|
result.append(value[0])
|
|
else:
|
|
result.append(value)
|
|
return result
|
|
|
|
|
|
class HelperMode(Helper):
|
|
mode = 'original'
|
|
|
|
SCREAMING_SNAKE_CASE = 'SCREAMING_SNAKE_CASE'
|
|
lowerCamelCase = 'lowerCamelCase'
|
|
CamelCase = 'CamelCase'
|
|
snake_case = 'snake_case'
|
|
lowercase = 'lowercase'
|
|
|
|
@classmethod
|
|
def all(cls):
|
|
return [
|
|
cls.SCREAMING_SNAKE_CASE,
|
|
cls.lowerCamelCase,
|
|
cls.CamelCase,
|
|
cls.snake_case,
|
|
cls.lowercase,
|
|
]
|
|
|
|
@classmethod
|
|
def _screaming_snake_case(cls, text):
|
|
"""
|
|
Transform text to SCREAMING_SNAKE_CASE
|
|
|
|
:param text:
|
|
:return:
|
|
"""
|
|
if text.isupper():
|
|
return text
|
|
result = ''
|
|
for pos, symbol in enumerate(text):
|
|
if symbol.isupper() and pos > 0:
|
|
result += '_' + symbol
|
|
else:
|
|
result += symbol.upper()
|
|
return result
|
|
|
|
@classmethod
|
|
def _snake_case(cls, text):
|
|
"""
|
|
Transform text to snake cale (Based on SCREAMING_SNAKE_CASE)
|
|
|
|
:param text:
|
|
:return:
|
|
"""
|
|
if text.islower():
|
|
return text
|
|
return cls._screaming_snake_case(text).lower()
|
|
|
|
@classmethod
|
|
def _camel_case(cls, text, first_upper=False):
|
|
"""
|
|
Transform text to camelCase or CamelCase
|
|
|
|
:param text:
|
|
:param first_upper: first symbol must be upper?
|
|
:return:
|
|
"""
|
|
result = ''
|
|
need_upper = False
|
|
for pos, symbol in enumerate(text):
|
|
if symbol == '_' and pos > 0:
|
|
need_upper = True
|
|
else:
|
|
if need_upper:
|
|
result += symbol.upper()
|
|
else:
|
|
result += symbol.lower()
|
|
need_upper = False
|
|
if first_upper:
|
|
result = result[0].upper() + result[1:]
|
|
return result
|
|
|
|
@classmethod
|
|
def apply(cls, text, mode):
|
|
"""
|
|
Apply mode for text
|
|
|
|
:param text:
|
|
:param mode:
|
|
:return:
|
|
"""
|
|
if mode == cls.SCREAMING_SNAKE_CASE:
|
|
return cls._screaming_snake_case(text)
|
|
if mode == cls.snake_case:
|
|
return cls._snake_case(text)
|
|
if mode == cls.lowercase:
|
|
return cls._snake_case(text).replace('_', '')
|
|
if mode == cls.lowerCamelCase:
|
|
return cls._camel_case(text)
|
|
if mode == cls.CamelCase:
|
|
return cls._camel_case(text, True)
|
|
if callable(mode):
|
|
return mode(text)
|
|
return text
|
|
|
|
|
|
class Item:
|
|
"""
|
|
Helper item
|
|
|
|
If a value is not provided,
|
|
it will be automatically generated based on a variable's name
|
|
"""
|
|
|
|
def __init__(self, value=None):
|
|
self._value = value
|
|
|
|
def __get__(self, instance, owner):
|
|
return self._value
|
|
|
|
def __set_name__(self, owner, name):
|
|
if not name.isupper():
|
|
raise NameError('Name for helper item must be in uppercase!')
|
|
if not self._value:
|
|
if hasattr(owner, 'mode'):
|
|
self._value = HelperMode.apply(name, getattr(owner, 'mode'))
|
|
|
|
|
|
class ListItem(Item):
|
|
"""
|
|
This item is always a list
|
|
|
|
You can use &, | and + operators for that.
|
|
"""
|
|
|
|
def add(self, other):
|
|
return self + other
|
|
|
|
def __get__(self, instance, owner):
|
|
return ItemsList(self._value)
|
|
|
|
def __getitem__(self, item):
|
|
# Only for IDE. This method is never be called.
|
|
return self._value
|
|
|
|
# Need only for IDE
|
|
__iadd__ = __add__ = __rand__ = __and__ = __ror__ = __or__ = add
|
|
|
|
|
|
class ItemsList(list):
|
|
"""
|
|
Patch for default list
|
|
|
|
This class provides +, &, |, +=, &=, |= operators for extending the list
|
|
"""
|
|
|
|
def __init__(self, *seq):
|
|
super(ItemsList, self).__init__(map(str, seq))
|
|
|
|
def add(self, other):
|
|
self.extend(other)
|
|
return self
|
|
|
|
__iadd__ = __add__ = __rand__ = __and__ = __ror__ = __or__ = add
|
|
|
|
|
|
class OrderedHelperMeta(type):
|
|
|
|
def __new__(mcs, name, bases, namespace, **kwargs):
|
|
cls = super().__new__(mcs, name, bases, namespace)
|
|
|
|
props_keys = []
|
|
|
|
for prop_name in (name for name, prop in namespace.items() if isinstance(prop, (Item, ListItem))):
|
|
props_keys.append(prop_name)
|
|
|
|
setattr(cls, PROPS_KEYS_ATTR_NAME, props_keys)
|
|
|
|
return cls
|
|
|
|
|
|
class OrderedHelper(metaclass=OrderedHelperMeta):
|
|
mode = ''
|
|
|
|
@classmethod
|
|
def all(cls) -> List[str]:
|
|
"""
|
|
Get all Items values
|
|
"""
|
|
result = []
|
|
for name in getattr(cls, PROPS_KEYS_ATTR_NAME, []):
|
|
value = getattr(cls, name)
|
|
if isinstance(value, ItemsList):
|
|
result.append(value[0])
|
|
else:
|
|
result.append(value)
|
|
return result
|