from threading import Lock
class ResourceContainer:
_instance = None
_lock = Lock()
def __new__(cls):
with cls._lock:
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self):
self._db_connection = None
self._message_broker_connection = None
self._config = {}
def get_db_connection(self):
return self._db_connection
def set_db_connection(self, connection):
self._db_connection = connection
def get_message_broker_connection(self):
return self._message_broker_connection
def set_message_broker_connection(self, connection):
self._message_broker_connection = connection
def get_config(self):
return self._config
def set_config(self, config):
self._config = config
def foo():
container = ResourceContainer()
db_conn = container.get_db_connection()
# use db_conn
def bar():
container = ResourceContainer()
config = container.get_config()
# use config
import time
import logging
from aiogram import Bot, Dispatcher, executor, types
TOKEN = ""
bot = Bot(token=TOKEN)
dp = Dispatcher(bot=bot)
text_for_user = "Напоминаю - 123, {})"
@dp.message_handler(commands = ["start"])
async def start_handler(message: types.message):
user_name = message.from_user.first_name
user_id = message.from_user.id
user_full_name - message.from_user.full_name
logging.info(f'{user_id=} {user_full_name=} {time.asctime()}')
await message.reply(f"123, {user_full_name}")
for i in range(10):
time.sleep(2)
await bot.send_message(user_id, text_for_user.format(user_name))
if __name__ == '__main__':
executor.start_polling(dp, skip_updates = True)
в качестве базы данных решено было использовать монгу.
async function sendTelegram(send_text) {
var chat_id = '-*****************'; // Номер группы Телеграм
// Токен, бот должен состоять в группе, куда шлем уведомления:
var bot_token = '*******************************************';
var url_obj = new URL('https://api.telegram.org/bot'+bot_token+'/sendMessage');
url_obj.searchParams.set('time', new Date().getTime());
var max_send_count = 3; var send_status = false;
do {
max_send_count--;
try {
var response = await (await fetch(url_obj.href, {
'method': 'POST',
'headers': {
'Content-Type': 'application/json; charset=UTF-8'
},
'body': JSON.stringify({
'chat_id': chat_id,
'text': send_text,
'parse_mode': 'HTML'
})
})).json();
if (response.ok) {
send_status = true;
console.log('Уведомление успешно отправлено в группу Телеграм:');
console.dir(response);
}
else {
console.log('Произошла ошибка при отправке уведомления в группу Телеграм:');
console.dir(response);
await new Promise(function(s) { setTimeout(s, 1000); });
}
}
catch (err) {
console.log('Произошла ошибка при отправке уведомления в группу Телеграм:');
console.error(err);
await new Promise(function(s) { setTimeout(s, 1000); });
}
} while (!send_status && max_send_count > 0);
if (!send_status) {
alert('Не удалось отправить уведомление в Телеграм, детали см. в консоли.');
}
return send_status;
}
def add_time(self, h: int = 0, m: int = 0, d: int = 0, dw: int = 0, mh: int = 0, y: int = 0):
if any(v < 0 for v in [h,m,d,dw,mh,y]):
raise ValueError()
args = {'h':h, 'm':m, 'd':d, 'dw':dw, 'mh':mh, 'y':y}
bad = list(filter(lambda k: args[k] < 0, args.keys()))
if bad:
raise ValueError('Invalid values for: ' + ','.join(bad))
import functools
import inspect
# пусть чек-функция имеет вид (value) -> bool, и возвращает True для "хороших" значений. Пример:
def not_whitespace(s: str) -> bool:
'String must not contain only whitespace' # док строка будет использоваться в сообщении об ошибке
return bool(s.strip()) # проверяем что строка не состоит из одних пробелов.
# чек-функции можно генерировать и на ходу:
def in_range(low, high):
def check(value):
return (low is None or low <= value) and (high is None or value <= high)
check.__doc__ = f'Value must be between {low} and {high}.'
return check
# теперь сделаем декоратор, который умеет принимать чек-функции и применять их перед вызовом цели
def check(**checks):
def wrapper(func):
sign = inspect.signature(func)
names = list(sign.parameters.keys()) # имена параметров по порядку
not_found = set(checks.keys()) - set(names) # все ли чеки ссылаются на известные параметры?
if not_found:
# у нас есть чек на неизвестный параметр!
raise NameError(', '.join(not_found))
# всё ок, делаем обёртку над функцией
@functools.wraps(func)
def wrapped(*args, **kwargs):
bad = []
for param_name, check_func in checks.items():
idx = names.index(param_name)
if idx < len(args):
# параметр был передан через args
value = args[idx]
if not check_func(value): # вызываем чек-функцию
err = getattr(check_func, '__doc__', '')
if err:
bad.append(f'{param_name} ({err})')
else:
bad.append(param_name)
else:
pass # могут быть хитрости с kwargs-only параметрами. Тут уж извини, мне влом писать.
if bad: # нашли ошибки?
raise ValueError('Bad value for parameters: '+', '.join(bad))
# тут ещё можно помудрить над скрытием последнего фрейма в traceback, но мне опять влом
else: # не нашли, вызываем функцию
return func(*args, **kwargs)
return wrapped
return wrapper
# пример использования
# строка должна быть не из одних пробелов
# число должно быть в пределах от 1 до 10 включительно
@check(s=not_whitespace, n=in_range(1, 10))
def repeat(s: str, n: int) -> str:
return s * n
print(repeat('test ', 3))
try:
print(repeat('test ', 20))
except ValueError as err:
print('yep! it failed!', err)
try:
print(repeat('test ', -1))
except ValueError as err:
print('yep! it failed!', err)
try:
print(repeat(' ', 5))
except ValueError as err:
print('yep! it failed!', err)
try:
print(repeat(' ', 15))
except ValueError as err:
print('yep! it failed!', err)
На фотографии представлен веб-браузер Qutebrowser с 7 открытыми вкладками, в режиме работы с QtWebkit. Как видно, даже с 7 вкладками (2 из которых — страницы Википедии с большим количеством картинок) браузер потребляет около 140 мегабайт, что позволяет комфортно сёрфить интернет на смешных 512 МБ RAM.
Из других браузеров, до сих пор поддерживающих QtWebkit, можно отметить Otter Browser и KDE’шный Konqueror, который дополнительно поддерживает еще и KHTML (3 движка в одном браузере), но в Debian собран только с WebEngine. Первый в репозиториях Debian не присутствует.
Браузер Seamonkey, актуальная версия которого построена на базе движка из Firefox 60, работает более-менее сносно, но не блестяще — рендерит дольше QtWebkit’а примерно в 2-3 раза, потребляет заметно больше памяти, зато работает со всеми современными сайтами. Можно использовать в качестве запасного варианта, когда QtWebkit не справляется.