server.voice.channels
- получить у объекта сервер свойство voice, а у объекта в этом свойстве - свойство channels.class Person:
def __init__(self, name: str):
self._name: str = ''
self.name = name
@property
def name(self) -> str:
return self._name
@name.setter
def name(self, value: str) -> None:
if not value:
raise ValueError('Must not be empty')
self._name = value
from typing import TypeVar, Type, Any, Annotated, Callable, Dict, get_args, get_origin
T = TypeVar('T')
ValidationRule = Callable[[Any], bool]
ValidationRules = Dict[str, ValidationRule]
class ValidatedProperty:
"""Экземпляры этого класса будут свойствами в валидируемых классах, и будут заниматься валидацией."""
def __init__(self, name: str, storagename: str, rules: ValidationRules):
self.name = name # как называется свойство
self.storagename = storagename # где его хранить
self.rules = rules # какие правила применять
def __get__(self, instance, owner=None):
return getattr(instance, self.storagename) # при чтении просто возвращаем свойство
def __set__(self, instance, value): # при записи валидируем
for message, rule in self.rules.items():
if not rule(value): # если правило нарушено, выкидываем исключение с сообщением
raise ValueError(f'{instance.__class__.__name__}.{self.name}: {message}')
setattr(instance, self.storagename, value)
def validated(klass: Type[T]) -> Type[T]:
"""Декоратор для валидируемых классов."""
for name, annot in klass.__annotations__.items(): # проверяем список аннотаций в классе
base = get_origin(annot) or annot
if base is not Annotated: # нас интересуют только те, которые помечены как Annotated
continue
args = get_args(annot)
rules = [arg for arg in args if isinstance(arg, dict)]
if not rules: # и только если один (любой) из аргументов Annotated - словарь
continue
# в этом случае мы считаем, что словарь содержит правила валидации, и создаём свойство класса
setattr(klass, name, ValidatedProperty(name, f'_{name}', rules[0]))
return klass # не забываем вернуть изменённый класс!
@validated
class Person:
name: Annotated[str, {'must not be empty': lambda v: bool(v)}]
age: Annotated[int, {'must be positive': lambda v: v > 0}]
def __init__(self, name: str, age: int):
self.name = name # валидация отработает уже здесь
self.age = age # валидация отработает уже здесь
def __repr__(self) -> str:
return f'Person(name={self.name!r}, age={self.age!r})'
try:
Person('John Doe', 23) # отработает успешно
except Exception as err:
print('Failed to create person 1')
print(f'{err.__class__.__name__}: {err!s}')
else:
print('Person 1 created')
try:
Person('', 23) # выкинет исключение
except Exception as err:
print('Failed to create person 2')
print(f'{err.__class__.__name__}: {err!s}')
else:
print('Person 2 created')
try:
Person('Jane Doe', -23) # выкинет исключение
except Exception as err:
print('Failed to create person 3')
print(f'{err.__class__.__name__}: {err!s}')
else:
print('Person 3 created')
p = Person('John Doe', 23)
try:
p.name = '' # выкинет исключение
except Exception as err:
print('Failed to modify person')
print(f'{err.__class__.__name__}: {err!s}')
try:
p.age = 0 # выкинет исключение
except Exception as err:
print('Failed to modify person')
print(f'{err.__class__.__name__}: {err!s}')
try:
p.age = 24 # отработает успешно
except Exception as err:
print('Failed to modify person')
print(f'{err.__class__.__name__}: {err!s}')
print(p)
print(vars(p))
import pytest
from unittest import mock
class B:
def __init__(self, db_connection):
self.__db_connection = db_connection
class A:
def __init__(self, b: B):
self.__b = b
def do_something(self) -> None:
pass
@pytest.fixture(scope="module")
def mock_b(mocker):
mocker.patch('path.to.B') # Здесь 'path.to.B' - это путь к классу B, который нужно замокать
return B(mock.MagicMock()) # Возвращаем экземпляр класса B с мок-объектом для db_connection
from multiprocessing import Process
class BotProcess:
def __init__(self):
self.process = None
def get(self) -> Process:
return self.process
def is_alive(self) -> bool:
if self.process is not None and self.process.is_alive():
return True
else:
return False
def stop(self) -> None:
self.process.terminate()
self.process = None
def start(self, process: Process) -> None:
self.process = process
self.process.start()
bot_process = BotProcess()
@app.route("/bot-start", methods=["GET"])
def bot_start():
if not bot_process.is_alive():
bot_process.start(Process(target=start_bot))
return "Bot started"
else:
return "Bot is already running"
@app.route("/bot-restart", methods=["GET"])
def bot_restart():
if bot_process.is_alive():
bot_process.stop()
bot_process.start(Process(target=start_bot))
return "Bot restarted"
else:
return "Bot is not running"
@app.route("/bot-stop", methods=["GET"])
def bot_stop():
if bot_process.is_alive():
bot_process.stop()
return "Bot stopped"
else:
return "Bot is not running"
>>> import inspect
>>> import requests
>>> print(inspect.getsource(requests.get))
def get(url, params=None, **kwargs):
r"""Sends a GET request.
:param url: URL for the new :class:`Request` object.
:param params: (optional) Dictionary, list of tuples or bytes to send
in the query string for the :class:`Request`.
:param \*\*kwargs: Optional arguments that ``request`` takes.
:return: :class:`Response <Response>` object
:rtype: requests.Response
"""
return request("get", url, params=params, **kwargs)
>>> import inspect
>>> print(inspect.getsource(sum))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.10/inspect.py", line 1139, in getsource
lines, lnum = getsourcelines(object)
File "/usr/lib/python3.10/inspect.py", line 1121, in getsourcelines
lines, lnum = findsource(object)
File "/usr/lib/python3.10/inspect.py", line 940, in findsource
file = getsourcefile(object)
File "/usr/lib/python3.10/inspect.py", line 817, in getsourcefile
filename = getfile(object)
File "/usr/lib/python3.10/inspect.py", line 797, in getfile
raise TypeError('module, class, method, function, traceback, frame, or '
TypeError: module, class, method, function, traceback, frame, or code object was expected, got builtin_function_or_method
In [1]: import requests
In [2]: %psource requests.get
def get(url, params=None, **kwargs):
r"""Sends a GET request.
:param url: URL for the new :class:`Request` object.
:param params: (optional) Dictionary, list of tuples or bytes to send
in the query string for the :class:`Request`.
:param \*\*kwargs: Optional arguments that ``request`` takes.
:return: :class:`Response <Response>` object
:rtype: requests.Response
"""
return request("get", url, params=params, **kwargs)