diff --git a/.gitignore b/.gitignore index 964ca9453..ac96cbc34 100644 --- a/.gitignore +++ b/.gitignore @@ -117,3 +117,4 @@ geckodriver.log *.sqlite* *.db log.txt +settings.* diff --git a/Base64_examples/decode_to_file.py b/Base64_examples/decode_to_file.py index 06d4ba375..a2ce75c7e 100644 --- a/Base64_examples/decode_to_file.py +++ b/Base64_examples/decode_to_file.py @@ -7,7 +7,7 @@ from base64 import b64decode -def decode_base64_to_file(file_name: str, text_base64: str): +def decode_base64_to_file(file_name: str, text_base64: str) -> None: with open(file_name, "wb") as f: data = b64decode(text_base64) f.write(data) diff --git a/Base64_examples/gui_base64.py b/Base64_examples/gui_base64.py index 70afbfd9e..ba49bbf97 100644 --- a/Base64_examples/gui_base64.py +++ b/Base64_examples/gui_base64.py @@ -24,7 +24,7 @@ from PySide.QtCore import * -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -136,7 +136,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle(path_split(__file__)[1]) @@ -205,7 +205,7 @@ def __init__(self): self.setLayout(layout) - def show_detail_error_massage(self): + def show_detail_error_massage(self) -> None: message = self.last_error_message + "\n\n" + self.last_detail_error_message mb = QErrorMessage() @@ -217,7 +217,7 @@ def show_detail_error_massage(self): mb.exec_() - def input_text_changed(self): + def input_text_changed(self) -> None: self.label_error.clear() self.button_detail_error.hide() @@ -256,7 +256,7 @@ def input_text_changed(self): self.label_error.setText("Error: " + self.last_error_message) - def change_convert_direct(self): + def change_convert_direct(self) -> None: self.direct_encode_text = not self.direct_encode_text self.button_direct.setText( "text -> base64" if self.direct_encode_text else "base64 -> text" diff --git a/CONTACT__examples/create_and_fill_database_from_dictionary.py b/CONTACT__examples/create_and_fill_database_from_dictionary.py index fc566ae27..4537d3050 100644 --- a/CONTACT__examples/create_and_fill_database_from_dictionary.py +++ b/CONTACT__examples/create_and_fill_database_from_dictionary.py @@ -120,7 +120,7 @@ def create_connect(): def create_table( table_name: str, sql_table: str, sql_table_data_rows: str, drop_table=False -): +) -> None: # Создание таблицы connect = create_connect() try: diff --git a/Callable modules/print_this.py b/Callable modules/print_this.py index 507c4999f..6f8f95e67 100644 --- a/Callable modules/print_this.py +++ b/Callable modules/print_this.py @@ -9,7 +9,7 @@ # SOURCE: https://stackoverflow.com/a/1060872/5909792 class mod_call(object): - def __call__(self, text): + def __call__(self, text) -> None: print(text) diff --git a/CreateNoteXmlNoteManagers/CreateNoteXmlNoteManagers.py b/CreateNoteXmlNoteManagers/CreateNoteXmlNoteManagers.py index 4d9c6ba97..cb60a4485 100644 --- a/CreateNoteXmlNoteManagers/CreateNoteXmlNoteManagers.py +++ b/CreateNoteXmlNoteManagers/CreateNoteXmlNoteManagers.py @@ -7,7 +7,7 @@ import os -def main(namespace): +def main(namespace) -> None: # @param namespace argparse.Namespace Содержит переданные в аргументах объекты. indent = " " * 8 @@ -22,7 +22,7 @@ def main(namespace): ) -def create_parser(): +def create_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser( prog="CreateNoteXml", description="Cкрипт генерирует xml-файл программы NotesManager.", @@ -35,10 +35,11 @@ def create_parser(): if __name__ == "__main__": parser = create_parser() - sys.argv = [ - sys.argv[0], - r"-dir=C:\Users\ipetrash\Desktop\NotesManager.v0.0.3.Windows\notes", - ] + # TODO: Remove + # sys.argv = [ + # sys.argv[0], + # r"-dir=C:\Users\ipetrash\Desktop\NotesManager.v0.0.3.Windows\notes", + # ] if len(sys.argv) == 1: parser.print_help() diff --git a/Crypto Git Repository/api.py b/Crypto Git Repository/api.py index f02684c0f..bbd03226b 100644 --- a/Crypto Git Repository/api.py +++ b/Crypto Git Repository/api.py @@ -33,7 +33,7 @@ def get_repo(): repo = get_repo() -def print_log(reverse=False): +def print_log(reverse=False) -> None: logs = repo.git.log("--pretty=format:%H%x09%an%x09%ad%x09%s").splitlines() print(f"Logs[{len(logs)}]:") @@ -44,27 +44,27 @@ def print_log(reverse=False): print(log) -def append(file_or_list): +def append(file_or_list) -> None: if type(file_or_list) == str: file_or_list = [file_or_list] repo.index.add(file_or_list) -def remove(file_or_list): +def remove(file_or_list) -> None: if type(file_or_list) == str: file_or_list = [file_or_list] repo.index.remove(file_or_list) -def commit(message): +def commit(message) -> None: repo.index.commit(message) -def pull(): +def pull() -> None: repo.remotes.origin.pull() -def push(): +def push() -> None: repo.remotes.origin.push() diff --git a/DNS price tracking/db.py b/DNS price tracking/db.py index 8bb6adc59..91a0635fe 100644 --- a/DNS price tracking/db.py +++ b/DNS price tracking/db.py @@ -16,7 +16,7 @@ DB_FILE_NAME = str(pathlib.Path(__file__).resolve().parent / "tracked_products.sqlite") -def db_create_backup(backup_dir="backup"): +def db_create_backup(backup_dir="backup") -> None: os.makedirs(backup_dir, exist_ok=True) file_name = str(dt.datetime.today().date()) + ".sqlite" @@ -67,12 +67,12 @@ def get_last_price_technopoint(self, actual_price=True): return last_price.value_technopoint - def append_price(self, value_dns, value_technopoint): + def append_price(self, value_dns, value_technopoint) -> None: Price.create( product=self, value_dns=value_dns, value_technopoint=value_technopoint ) - def __str__(self): + def __str__(self) -> str: # TODO: выводить последнюю цену и актуальную return ( f"Product(title={self.title!r}, " @@ -91,7 +91,7 @@ class Price(BaseModel): class Meta: indexes = ((("product_id", "date", "value_dns", "value_technopoint"), True),) - def __str__(self): + def __str__(self) -> str: return ( f"Price(value_dns={self.value_dns}, " f"value_technopoint={self.value_technopoint}, " diff --git "a/Damerau\342\200\223Levenshtein_distance__misprints__\320\276\320\277\320\265\321\207\320\260\321\202\320\272\320\270/use__pyxdameraulevenshtein/fix_command.py" "b/Damerau\342\200\223Levenshtein_distance__misprints__\320\276\320\277\320\265\321\207\320\260\321\202\320\272\320\270/use__pyxdameraulevenshtein/fix_command.py" index 1c3138000..3bb0a61ad 100644 --- "a/Damerau\342\200\223Levenshtein_distance__misprints__\320\276\320\277\320\265\321\207\320\260\321\202\320\272\320\270/use__pyxdameraulevenshtein/fix_command.py" +++ "b/Damerau\342\200\223Levenshtein_distance__misprints__\320\276\320\277\320\265\321\207\320\260\321\202\320\272\320\270/use__pyxdameraulevenshtein/fix_command.py" @@ -63,7 +63,7 @@ def fix_command(text): if __name__ == "__main__": # SHOW RESULT - def check(text): + def check(text) -> None: format_text = "{:<%s} -> {}" % (len(max(ALL_COMMANDS, key=len)) + 2) command = fix_command(text) @@ -95,8 +95,8 @@ def check(text): # # Run test - def run_tests(): - def test(text, expected): + def run_tests() -> None: + def test(text, expected) -> None: command = fix_command(text) assert expected == command, f'Expected: "{expected}", get: "{command}"' diff --git a/Decorators__examples/append_handlers.py b/Decorators__examples/append_handlers.py index d95bbe4ce..c44b19bfd 100644 --- a/Decorators__examples/append_handlers.py +++ b/Decorators__examples/append_handlers.py @@ -8,7 +8,7 @@ class Collector: - def __init__(self): + def __init__(self) -> None: self.handlers = [] self.handlers_by_name = defaultdict(list) @@ -26,7 +26,7 @@ def decorator(func): @collector.add(name="test") -def hello_world(end="!"): +def hello_world(end="!") -> None: print("hello world" + end) @@ -41,7 +41,7 @@ def hello_world(end="!"): @collector.add(name="this it say_hello!") -def say_hello(): +def say_hello() -> None: print("hello!") diff --git a/Decorators__examples/combine_decorators__with_args.py b/Decorators__examples/combine_decorators__with_args.py index 506c98594..6e71ff93a 100644 --- a/Decorators__examples/combine_decorators__with_args.py +++ b/Decorators__examples/combine_decorators__with_args.py @@ -18,7 +18,7 @@ def get_attrs_str(kwargs: dict) -> str: def makebold(**decorator_kwargs): def actual_decorator(func): @functools.wraps(func) - def wrapped(*args, **kwargs): + def wrapped(*args, **kwargs) -> str: attrs = get_attrs_str(decorator_kwargs) return f"{func(*args, **kwargs)}" @@ -30,7 +30,7 @@ def wrapped(*args, **kwargs): def makeitalic(**decorator_kwargs): def actual_decorator(func): @functools.wraps(func) - def wrapped(*args, **kwargs): + def wrapped(*args, **kwargs) -> str: attrs = get_attrs_str(decorator_kwargs) return f"{func(*args, **kwargs)}" @@ -53,7 +53,7 @@ def custom_tag( ): def actual_decorator(func): @functools.wraps(func) - def wrapped(*args, **kwargs): + def wrapped(*args, **kwargs) -> str: attrs = get_attrs_str(arguments) return f"<{name}{attrs}>{func(*args, **kwargs)}" diff --git a/Decorators__examples/decorator__args_as_funcs.py b/Decorators__examples/decorator__args_as_funcs.py index 1563f2dda..b6b27499f 100644 --- a/Decorators__examples/decorator__args_as_funcs.py +++ b/Decorators__examples/decorator__args_as_funcs.py @@ -5,7 +5,7 @@ class TextBuilder: - def __init__(self): + def __init__(self) -> None: self.result = [] # Функция, принимающая аргументы и возвращающая декоратор diff --git a/Decorators__examples/decorator_method_class__with_shelve.py b/Decorators__examples/decorator_method_class__with_shelve.py index 1a73a703a..5ff1f1429 100644 --- a/Decorators__examples/decorator_method_class__with_shelve.py +++ b/Decorators__examples/decorator_method_class__with_shelve.py @@ -22,7 +22,7 @@ class DB: db_name: str = str(DB_FILE_NAME) - def __init__(self): + def __init__(self) -> None: self.db: shelve.Shelf | None = None def session(*decorator_args, **decorator_kwargs): @@ -53,7 +53,7 @@ def get_value(self, name: str, default: Any = None) -> Any: return self.db.get(name) @session() - def set_value(self, name: str, value: Any): + def set_value(self, name: str, value: Any) -> None: self.db[name] = value def inc_value(self, name: str) -> int: diff --git a/Decorators__examples/example_1.py b/Decorators__examples/example_1.py index 82c0e38a6..e7d123809 100644 --- a/Decorators__examples/example_1.py +++ b/Decorators__examples/example_1.py @@ -1,7 +1,7 @@ __author__ = "ipetrash" -def getprint(str="hello world!"): +def getprint(str="hello world!") -> None: print(str) @@ -16,7 +16,7 @@ def wrapper(*args, **kwargs): return wrapper -def predecor(w="W"): +def predecor(w="W") -> None: print(w, end=": ") @@ -29,7 +29,7 @@ def predecor(w="W"): def rgb2hex(get_rgb_func): - def wrapper(*args, **kwargs): + def wrapper(*args, **kwargs) -> str: r, g, b = get_rgb_func(*args, **kwargs) return f"#{r:02x}{g:02x}{b:02x}" @@ -37,7 +37,7 @@ def wrapper(*args, **kwargs): class RGB: - def __init__(self): + def __init__(self) -> None: self._r = 0xFF self._g = 0xFF self._b = 0xFF @@ -45,7 +45,7 @@ def __init__(self): def getr(self): return self._r - def setr(self, r): + def setr(self, r) -> None: self._r = r r = property(getr, setr) @@ -53,7 +53,7 @@ def setr(self, r): def getg(self): return self._g - def setg(self, g): + def setg(self, g) -> None: self._g = g g = property(getg, setg) @@ -61,12 +61,12 @@ def setg(self, g): def getb(self): return self._b - def setb(self, b): + def setb(self, b) -> None: self._b = b b = property(getb, setb) - def setrgb(self, r, g, b): + def setrgb(self, r, g, b) -> None: self.r, self.g, self.b = r, g, b @rgb2hex @@ -82,7 +82,7 @@ def getrgb(self): @decor -def foo(a, b): +def foo(a, b) -> None: print(f"{a} ^ {b} = {(a ** b)}") diff --git a/Decorators__examples/memoize_class.py b/Decorators__examples/memoize_class.py index 2c68b48ae..3654b2225 100644 --- a/Decorators__examples/memoize_class.py +++ b/Decorators__examples/memoize_class.py @@ -6,7 +6,7 @@ # Using memoization as decorator (decorator-class) class MemoizeClass: - def __init__(self, func): + def __init__(self, func) -> None: self.func = func self.memo = dict() diff --git a/Decorators__examples/thread.py b/Decorators__examples/thread.py index bbb34bd2e..70426ff29 100644 --- a/Decorators__examples/thread.py +++ b/Decorators__examples/thread.py @@ -9,7 +9,7 @@ def thread(my_func): - def wrapper(*args, **kwargs): + def wrapper(*args, **kwargs) -> None: my_thread = Thread(target=my_func, args=args, kwargs=kwargs) my_thread.start() @@ -18,14 +18,14 @@ def wrapper(*args, **kwargs): if __name__ == "__main__": @thread - def _print_and_sleep(timeout=2): + def _print_and_sleep(timeout=2) -> None: print("start. print_and_sleep") time.sleep(timeout) print("finish. print_and_sleep") @thread - def _print_loop(name, max_num=10): + def _print_loop(name, max_num=10) -> None: print("start. _print_loop") i = 0 diff --git a/Decorators__examples/timer.py b/Decorators__examples/timer.py index aa8e5d92a..c441a32ad 100644 --- a/Decorators__examples/timer.py +++ b/Decorators__examples/timer.py @@ -19,7 +19,7 @@ def wrapper(*args, **kwargs): if __name__ == "__main__": @timer - def my_sleep(): + def my_sleep() -> None: print(123) time.sleep(0.3) print(456) diff --git a/EscapePyPromptLineString/main.py b/EscapePyPromptLineString/main.py index 57a403ee7..4555e837e 100644 --- a/EscapePyPromptLineString/main.py +++ b/EscapePyPromptLineString/main.py @@ -23,7 +23,7 @@ from PySide.QtCore import * -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -36,7 +36,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("EscapePyPromptLineString") @@ -77,7 +77,7 @@ def __init__(self): self.setLayout(layout) - def show_detail_error_massage(self): + def show_detail_error_massage(self) -> None: message = self.last_error_message + "\n\n" + self.last_detail_error_message mb = QErrorMessage() @@ -89,7 +89,7 @@ def show_detail_error_massage(self): mb.exec_() - def input_text_changed(self): + def input_text_changed(self) -> None: self.label_error.clear() self.button_detail_error.hide() diff --git a/EscapeString/main.py b/EscapeString/main.py index d90a6f4dc..c6b7903dd 100644 --- a/EscapeString/main.py +++ b/EscapeString/main.py @@ -23,7 +23,7 @@ from PySide.QtCore import * -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -47,7 +47,7 @@ class MainWindow(QWidget): ] TITLE = "EscapeString" - def __init__(self, parent=None): + def __init__(self, parent=None) -> None: super().__init__(parent) self.setWindowTitle(self.TITLE) @@ -129,7 +129,7 @@ def __init__(self, parent=None): self.setLayout(layout) - def show_detail_error_massage(self): + def show_detail_error_massage(self) -> None: if not self.last_error_message or not self.last_detail_error_message: return @@ -161,7 +161,7 @@ def _escape(self, in_text: str, ignored="") -> str: return "".join(out_text) - def input_text_changed(self): + def input_text_changed(self) -> None: self.label_error.clear() self.button_detail_error.hide() diff --git a/Fibonacci number/6 ways.py b/Fibonacci number/6 ways.py index 4cef3fe92..25cd58937 100644 --- a/Fibonacci number/6 ways.py +++ b/Fibonacci number/6 ways.py @@ -66,7 +66,7 @@ def memoize(fn, arg): # Example 5: Using memoization as decorator (decorator-class) class MemoizeClass: - def __init__(self, func): + def __init__(self, func) -> None: self.func = func self.memo = dict() diff --git a/Fibonacci number/FibonacciNumber.py b/Fibonacci number/FibonacciNumber.py index c9015d9c3..a164d783e 100644 --- a/Fibonacci number/FibonacciNumber.py +++ b/Fibonacci number/FibonacciNumber.py @@ -1,14 +1,14 @@ __author__ = "ipetrash" -def fibo_1(n): +def fibo_1(n) -> None: f = [0, 1] for i in range(2, n + 1): f.append(f[i - 1] + f[i - 2]) print(f) -def fibo_2(n): +def fibo_2(n) -> None: a, b = 0, 1 print(a, b, end=" ") for i in range(2, n + 1): diff --git a/HelloPython/HelloPython.py b/HelloPython/HelloPython.py index 45acc7ba5..388f750d8 100644 --- a/HelloPython/HelloPython.py +++ b/HelloPython/HelloPython.py @@ -5,7 +5,7 @@ from datetime import datetime, time -def main(namespace): +def main(namespace) -> None: args = namespace.parse_args() args.user = "Илья" if args.user: @@ -29,7 +29,7 @@ def main(namespace): print("Привет, Python!") -def create_parser(): +def create_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser(description="Hello World Example!") parser.add_argument("--user", type=str, help=" user name.") return parser diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 000000000..8e4fbe851 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Ilya Petrash (gil9red) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/No choice line edit.py b/No choice line edit.py index b28356739..c8db94aac 100644 --- a/No choice line edit.py +++ b/No choice line edit.py @@ -14,7 +14,7 @@ class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("No choice") @@ -33,7 +33,7 @@ def __init__(self): self.line_edit_no_choice.setFocus() - def on_text_edited_no_choice(self, text): + def on_text_edited_no_choice(self, text) -> None: text = self.line_edit_source.text()[: len(text)] self.line_edit_no_choice.setText(text) diff --git a/ObjectWithArrayAccess.py b/ObjectWithArrayAccess.py index 0cdd90e4e..1886745e0 100644 --- a/ObjectWithArrayAccess.py +++ b/ObjectWithArrayAccess.py @@ -5,16 +5,16 @@ class ObjectWithArrayAccess: - def __init__(self): + def __init__(self) -> None: self._fields = dict() def __getitem__(self, item): return self._fields.get(item) - def __setitem__(self, key, value): + def __setitem__(self, key, value) -> None: self._fields[key] = value - def __len__(self): + def __len__(self) -> int: return len(self._fields) diff --git a/OpenSSL_example/generate_selfsigned_cert.py b/OpenSSL_example/generate_selfsigned_cert.py index 8e9ee5663..c71bd75f5 100644 --- a/OpenSSL_example/generate_selfsigned_cert.py +++ b/OpenSSL_example/generate_selfsigned_cert.py @@ -22,7 +22,7 @@ def cert_gen( validity_end_in_seconds=10 * 365 * 24 * 60 * 60, key_file="key.pem", cert_file="cert.pem", -): +) -> None: # Create a key pair k = crypto.PKey() k.generate_key(crypto.TYPE_RSA, 4096) diff --git a/OpenSSL_example/p12_to_pem.py b/OpenSSL_example/p12_to_pem.py index d0d53a4ac..8c419fd66 100644 --- a/OpenSSL_example/p12_to_pem.py +++ b/OpenSSL_example/p12_to_pem.py @@ -8,7 +8,7 @@ from OpenSSL import crypto -def save_pem(p12_file_name, p12_password, pem_file_name=None): +def save_pem(p12_file_name, p12_password, pem_file_name=None) -> None: """Функция из p12 вытаскивает pem. Если pem_file_name не указан, сохраняется в той же папке, что и p12_file_name.""" diff --git a/Printing all instances of a class/use__garbage_collector__gc.py b/Printing all instances of a class/use__garbage_collector__gc.py index 63eb494c3..d407f84e8 100644 --- a/Printing all instances of a class/use__garbage_collector__gc.py +++ b/Printing all instances of a class/use__garbage_collector__gc.py @@ -15,7 +15,7 @@ def get_instances(class_: type) -> [type]: class X: - def __init__(self, name): + def __init__(self, name) -> None: self.name = name diff --git a/Printing all instances of a class/use__mixin_and_weakrefs.py b/Printing all instances of a class/use__mixin_and_weakrefs.py index c02bb2f7a..3cca80828 100644 --- a/Printing all instances of a class/use__mixin_and_weakrefs.py +++ b/Printing all instances of a class/use__mixin_and_weakrefs.py @@ -14,7 +14,7 @@ class KeepRefs: __refs__ = defaultdict(list) - def __init__(self): + def __init__(self) -> None: self.__refs__[self.__class__].append(weakref.ref(self)) @classmethod @@ -26,7 +26,7 @@ def get_instances(cls): class X(KeepRefs): - def __init__(self, name): + def __init__(self, name) -> None: super().__init__() self.name = name diff --git a/PyGithub_examples/gist_history_to_sqlite_db.py b/PyGithub_examples/gist_history_to_sqlite_db.py index 06b68f552..8cd7ca839 100644 --- a/PyGithub_examples/gist_history_to_sqlite_db.py +++ b/PyGithub_examples/gist_history_to_sqlite_db.py @@ -12,7 +12,7 @@ def create_connect(): return sqlite3.connect("gist_commits.sqlite") -def init_db(): +def init_db() -> None: # Создание базы и таблицы with create_connect() as connect: connect.execute( diff --git a/PyOpenGLExample/checkerboard.py b/PyOpenGLExample/checkerboard.py index 5d4ae28e6..c95783a60 100644 --- a/PyOpenGLExample/checkerboard.py +++ b/PyOpenGLExample/checkerboard.py @@ -10,7 +10,7 @@ """ -def initFun(): +def initFun() -> None: glClearColor(1.0, 1.0, 1.0, 0.0) glColor3f(0.0, 0.0, 0.0) glMatrixMode(GL_PROJECTION) @@ -18,7 +18,7 @@ def initFun(): gluOrtho2D(0.0, 640.0, 0.0, 480.0) -def displayFun(): +def displayFun() -> None: CELL_SIZE = 40 glClear(GL_COLOR_BUFFER_BIT) diff --git a/PyOpenGLExample/gingerbread.py b/PyOpenGLExample/gingerbread.py index da64a3b00..3a788504c 100644 --- a/PyOpenGLExample/gingerbread.py +++ b/PyOpenGLExample/gingerbread.py @@ -18,7 +18,7 @@ y = 121 -def initFun(): +def initFun() -> None: glClearColor(1.0, 1.0, 1.0, 0.0) glColor3f(0.0, 0.0, 0.0) glPointSize(4.0) @@ -27,7 +27,7 @@ def initFun(): gluOrtho2D(0.0, 640.0, 0.0, 480.0) -def mouseFun(button, state, xIn, yIn): +def mouseFun(button, state, xIn, yIn) -> None: global x global y if button == GLUT_LEFT_BUTTON and state == GLUT_DOWN: @@ -37,7 +37,7 @@ def mouseFun(button, state, xIn, yIn): glutPostRedisplay() -def displayFun(): +def displayFun() -> None: global x global y glClear(GL_COLOR_BUFFER_BIT) diff --git a/PyOpenGLExample/helloworld.py b/PyOpenGLExample/helloworld.py index 227086e07..eaaa108d3 100644 --- a/PyOpenGLExample/helloworld.py +++ b/PyOpenGLExample/helloworld.py @@ -14,7 +14,7 @@ """ -def initFun(): +def initFun() -> None: glClearColor(1.0, 1.0, 1.0, 0.0) glColor3f(0.0, 0.0, 0.0) glPointSize(4.0) @@ -23,7 +23,7 @@ def initFun(): gluOrtho2D(0.0, 640.0, 0.0, 480.0) -def displayFun(): +def displayFun() -> None: glClear(GL_COLOR_BUFFER_BIT) glBegin(GL_POINTS) glVertex2i(100, 50) diff --git a/PyOpenGLExample/maze.py b/PyOpenGLExample/maze.py index 039ffe3a0..0ed046b6c 100644 --- a/PyOpenGLExample/maze.py +++ b/PyOpenGLExample/maze.py @@ -38,7 +38,7 @@ class MazeCell: - def __init__(self, x, y): + def __init__(self, x, y) -> None: self.x = x self.y = y self.wall_north = True @@ -49,7 +49,7 @@ def __init__(self, x, y): class Maze: - def __init__(self, dimx, dimy): + def __init__(self, dimx, dimy) -> None: self.numx = dimx self.numy = dimy @@ -155,7 +155,7 @@ def __init__(self, dimx, dimy): # Push it back on the list since this is our next node cell_list.append(conn) - def draw(self): + def draw(self) -> None: """Draws the field""" glBegin(GL_LINES) for i in range(0, self.numx * self.numy): @@ -184,7 +184,7 @@ def draw(self): maze = Maze(MAZECOLS, MAZEROWS) -def init_fun(): +def init_fun() -> None: glClearColor(1.0, 1.0, 1.0, 0.0) glColor3f(0.0, 0.0, 0.0) glMatrixMode(GL_PROJECTION) @@ -193,7 +193,7 @@ def init_fun(): gluOrtho2D(-1.0, WIDTH, -1.0, HEIGHT) -def display_fun(): +def display_fun() -> None: glClear(GL_COLOR_BUFFER_BIT) maze.draw() glFlush() diff --git a/PyOpenGLExample/mouse.py b/PyOpenGLExample/mouse.py index 3903dce15..77a6f7bbb 100644 --- a/PyOpenGLExample/mouse.py +++ b/PyOpenGLExample/mouse.py @@ -18,7 +18,7 @@ class Point: - def __init__(self, x, y): + def __init__(self, x, y) -> None: self.x = x self.y = y @@ -26,7 +26,7 @@ def __init__(self, x, y): points = [] -def initFun(): +def initFun() -> None: glClearColor(1.0, 1.0, 1.0, 0.0) glColor3f(0.0, 0.0, 0.0) glMatrixMode(GL_PROJECTION) @@ -34,7 +34,7 @@ def initFun(): gluOrtho2D(0.0, 640.0, 0.0, 480.0) -def displayFun(): +def displayFun() -> None: global points glClear(GL_COLOR_BUFFER_BIT) glBegin(GL_LINE_STRIP) @@ -45,7 +45,7 @@ def displayFun(): glFlush() -def mouseFun(button, state, x, y): +def mouseFun(button, state, x, y) -> None: global points if button == GLUT_LEFT_BUTTON and state == GLUT_DOWN: p = Point(x, 480 - y) diff --git a/PyOpenGLExample/print_text.py b/PyOpenGLExample/print_text.py index 4d58f78c7..1a6c62e32 100644 --- a/PyOpenGLExample/print_text.py +++ b/PyOpenGLExample/print_text.py @@ -9,7 +9,7 @@ height = 0 -def glSetup(w, h): +def glSetup(w, h) -> None: global width, height width = w height = h @@ -31,7 +31,7 @@ def glSetup(w, h): glMatrixMode(GL_MODELVIEW) -def glResize(w, h): +def glResize(w, h) -> None: global width, height width = w height = h @@ -43,12 +43,12 @@ def glResize(w, h): glMatrixMode(GL_MODELVIEW) -def glSetupCam(): +def glSetupCam() -> None: gluPerspective(45.0, float(width) / float(height), 0.1, 100.0) gluLookAt(0, 0, 5, 0, 0, 0, 0, 1, 0) -def glDraw(): +def glDraw() -> None: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glLoadIdentity() @@ -62,7 +62,7 @@ def glDraw(): # glut_print adapted from http://stackoverflow.com/questions/12837747/print-text-with-glut-and-python -def glut_print(x, y, font, text, r, g, b, a): +def glut_print(x, y, font, text, r, g, b, a) -> None: glMatrixMode(GL_PROJECTION) glLoadIdentity() gluOrtho2D(0.0, width, height, 0.0) @@ -80,7 +80,7 @@ def glut_print(x, y, font, text, r, g, b, a): glDisable(GL_BLEND) -def keyPressed(*args): +def keyPressed(*args) -> None: ESCAPE = b"\x1b" if args[0] == ESCAPE: sys.exit() diff --git a/PyOpenGLExample/reshape.py b/PyOpenGLExample/reshape.py index 360c28728..d6db419d7 100644 --- a/PyOpenGLExample/reshape.py +++ b/PyOpenGLExample/reshape.py @@ -19,7 +19,7 @@ """ -def init_fun(): +def init_fun() -> None: glClearColor(1.0, 1.0, 1.0, 0.0) glColor3f(0.0, 0.0, 0.0) glMatrixMode(GL_PROJECTION) @@ -27,7 +27,7 @@ def init_fun(): gluOrtho2D(-100, 100, -100, 100) -def reshape_fun(w, h): +def reshape_fun(w, h) -> None: glViewport(0, 0, w, h) # if w > h: # glViewport((w - h) / 2, 0, h, h) @@ -35,7 +35,7 @@ def reshape_fun(w, h): # glViewport(0, (h - w) / 2, w, w) -def display_fun(): +def display_fun() -> None: glClear(GL_COLOR_BUFFER_BIT) glColor3f(0.0, 0.0, 1.0) glutWireTeapot(40) diff --git a/PyOpenGLExample/rosette.py b/PyOpenGLExample/rosette.py index 561e50f84..1668d4bc2 100644 --- a/PyOpenGLExample/rosette.py +++ b/PyOpenGLExample/rosette.py @@ -23,7 +23,7 @@ RADIUS = 95 -def init_fun(): +def init_fun() -> None: glClearColor(1.0, 1.0, 1.0, 0.0) glColor3f(0.0, 0.0, 0.0) glMatrixMode(GL_PROJECTION) @@ -31,7 +31,7 @@ def init_fun(): gluOrtho2D(-100, 100, -100, 100) -def reshape_fun(w, h): +def reshape_fun(w, h) -> None: glViewport(0, 0, w, h) # if w > h: @@ -40,7 +40,7 @@ def reshape_fun(w, h): # glViewport(0, (h - w) / 2, w, w) -def display_fun(): +def display_fun() -> None: glClear(GL_COLOR_BUFFER_BIT) glColor3f(0.0, 0.0, 1.0) xpts = [] diff --git a/PyOpenGLExample/scatter.py b/PyOpenGLExample/scatter.py index 82be48d3b..85ec9bbf4 100644 --- a/PyOpenGLExample/scatter.py +++ b/PyOpenGLExample/scatter.py @@ -19,7 +19,7 @@ """ -def initFun(): +def initFun() -> None: glClearColor(1.0, 1.0, 1.0, 0.0) glColor3f(0.0, 0.0, 0.0) glPointSize(1.0) @@ -39,7 +39,7 @@ def getRandom(mode): return random.gauss(200, 40) % 400 -def displayFun(): +def displayFun() -> None: glClear(GL_COLOR_BUFFER_BIT) glBegin(GL_POINTS) diff --git a/PyOpenGLExample/sierpinski.py b/PyOpenGLExample/sierpinski.py index f70bfb32d..3e10e1897 100644 --- a/PyOpenGLExample/sierpinski.py +++ b/PyOpenGLExample/sierpinski.py @@ -21,7 +21,7 @@ """ -def initFun(): +def initFun() -> None: glClearColor(1.0, 1.0, 1.0, 0.0) glColor3f(0.0, 0.0, 0.0) glPointSize(1.0) @@ -30,7 +30,7 @@ def initFun(): gluOrtho2D(0.0, 640.0, 0.0, 480.0) -def displayFun(): +def displayFun() -> None: glClear(GL_COLOR_BUFFER_BIT) glBegin(GL_POINTS) diff --git a/PyOpenGLExample/squares.py b/PyOpenGLExample/squares.py index 64dd72e86..b75d7d0a2 100644 --- a/PyOpenGLExample/squares.py +++ b/PyOpenGLExample/squares.py @@ -16,7 +16,7 @@ """ -def initFun(): +def initFun() -> None: glClearColor(1.0, 1.0, 1.0, 0.0) glColor3f(0.0, 0.0, 0.0) glMatrixMode(GL_PROJECTION) @@ -24,7 +24,7 @@ def initFun(): gluOrtho2D(0.0, 640.0, 0.0, 480.0) -def displayFun(): +def displayFun() -> None: glClear(GL_COLOR_BUFFER_BIT) for i in range(0, 25): gray = random.randint(0, 25) / 25.0 diff --git a/PyOpenGLExample/turtle.py b/PyOpenGLExample/turtle.py index a1deb6187..4b8e94969 100644 --- a/PyOpenGLExample/turtle.py +++ b/PyOpenGLExample/turtle.py @@ -23,7 +23,7 @@ angle = 0.0 -def reset(): +def reset() -> None: """Reset the position to the origin""" global curX global curY @@ -34,19 +34,19 @@ def reset(): angle = 0.0 -def turnTo(deg): +def turnTo(deg) -> None: """Turn to a certain angle""" global angle angle = deg -def turn(deg): +def turn(deg) -> None: """Turn a certain number of degrees""" global angle angle += deg -def forw(len, visible): +def forw(len, visible) -> None: """Move forward over a certain distance""" global curX global curY @@ -61,7 +61,7 @@ def forw(len, visible): glEnd() -def initFun(): +def initFun() -> None: glClearColor(1.0, 1.0, 1.0, 0.0) glColor3f(0.0, 0.0, 0.0) glMatrixMode(GL_PROJECTION) @@ -69,7 +69,7 @@ def initFun(): gluOrtho2D(-100, 100, -100, 100) -def reshapeFun(w, h): +def reshapeFun(w, h) -> None: glViewport(0, 0, w, h) # if w > h: # glViewport((w-h)/2,0,h,h) @@ -77,7 +77,7 @@ def reshapeFun(w, h): # glViewport(0,(h-w)/2,w,w) -def turtle_1(): +def turtle_1() -> None: glClear(GL_COLOR_BUFFER_BIT) reset() glColor3f(0.0, 0.0, 1.0) @@ -93,7 +93,7 @@ def turtle_1(): glFlush() -def turtle_2(): +def turtle_2() -> None: glClear(GL_COLOR_BUFFER_BIT) glColor3f(0.0, 0.0, 1.0) reset() @@ -106,7 +106,7 @@ def turtle_2(): glFlush() -def turtle_3(): +def turtle_3() -> None: glClear(GL_COLOR_BUFFER_BIT) glColor3f(0.0, 0.0, 1.0) reset() @@ -119,7 +119,7 @@ def turtle_3(): glFlush() -def turtle_4(): +def turtle_4() -> None: glClear(GL_COLOR_BUFFER_BIT) glColor3f(0.0, 0.0, 1.0) reset() @@ -132,7 +132,7 @@ def turtle_4(): glFlush() -def turtle_5(): +def turtle_5() -> None: glClear(GL_COLOR_BUFFER_BIT) glColor3f(0.0, 0.0, 1.0) reset() @@ -145,7 +145,7 @@ def turtle_5(): glFlush() -def turtle_6(): +def turtle_6() -> None: glClear(GL_COLOR_BUFFER_BIT) glColor3f(0.0, 0.0, 1.0) reset() @@ -159,7 +159,7 @@ def turtle_6(): glFlush() -def turtle_7(): +def turtle_7() -> None: glClear(GL_COLOR_BUFFER_BIT) glColor3f(0.0, 0.0, 1.0) reset() @@ -172,7 +172,7 @@ def turtle_7(): glFlush() -def turtle_8(): +def turtle_8() -> None: glClear(GL_COLOR_BUFFER_BIT) glColor3f(0.0, 0.0, 1.0) reset() @@ -192,7 +192,7 @@ def turtle_8(): glFlush() -def turtle_9(): +def turtle_9() -> None: glClear(GL_COLOR_BUFFER_BIT) glColor3f(0.0, 0.0, 1.0) reset() @@ -208,7 +208,7 @@ def turtle_9(): glFlush() -def turtle_10(): +def turtle_10() -> None: glClear(GL_COLOR_BUFFER_BIT) glColor3f(0.0, 0.0, 1.0) reset() diff --git a/PyOpenGLExample/wireframe.py b/PyOpenGLExample/wireframe.py index 47523d88b..1d16c92d7 100644 --- a/PyOpenGLExample/wireframe.py +++ b/PyOpenGLExample/wireframe.py @@ -12,7 +12,7 @@ """ -def axis(length): +def axis(length) -> None: """Draws an axis (basicly a line with a cone on top)""" glPushMatrix() glBegin(GL_LINES) @@ -24,7 +24,7 @@ def axis(length): glPopMatrix() -def three_axis(length): +def three_axis(length) -> None: """Draws an X, Y and Z-axis""" glPushMatrix() @@ -42,7 +42,7 @@ def three_axis(length): glPopMatrix() -def display_fun(): +def display_fun() -> None: glMatrixMode(GL_PROJECTION) glLoadIdentity() glOrtho(-2.0 * 64 / 48.0, 2.0 * 64 / 48.0, -1.5, 1.5, 0.1, 100) diff --git a/Serialize with pickle/SerializeWithPickle.py b/Serialize with pickle/SerializeWithPickle.py index e799b9918..2ad97101d 100644 --- a/Serialize with pickle/SerializeWithPickle.py +++ b/Serialize with pickle/SerializeWithPickle.py @@ -48,20 +48,20 @@ class Monster: """Monster class!""" - def __init__(self, health, power, name, level): + def __init__(self, health, power, name, level) -> None: self.health = health self.power = power self.name = name self.level = level self.abilities = ["Eater"] - def __str__(self): + def __str__(self) -> str: return ( f"Name: '{self.name}' lv {self.level}, health: {self.health}, " f"power: {self.power}, abilities: {self.abilities}: {hex(id(self))}" ) - def say(self): + def say(self) -> None: print("I'm %s" % self.name) zombi = Monster(name="Zombi", health=100, power=10, level=2) diff --git a/Sorting algorithm list/comparison_of_sorting.py b/Sorting algorithm list/comparison_of_sorting.py index 72edff600..afb189f32 100644 --- a/Sorting algorithm list/comparison_of_sorting.py +++ b/Sorting algorithm list/comparison_of_sorting.py @@ -15,17 +15,17 @@ class Kill(Exception): class KThread(Thread): - def __init__(self, *args, **keywords): + def __init__(self, *args, **keywords) -> None: Thread.__init__(self, *args, **keywords) self.killed = False - def start(self): + def start(self) -> None: """Start the thread.""" self.__run_backup = self.run self.run = self.__run # Force the Thread to install our trace. Thread.start(self) - def __run(self): + def __run(self) -> None: """Hacked run function, which installs the trace.""" sys.settrace(self.globaltrace) @@ -48,7 +48,7 @@ def localtrace(self, frame, why, arg): raise Kill() return self.localtrace - def kill(self): + def kill(self) -> None: self.killed = True @@ -88,7 +88,7 @@ def the_wrapper_around_the_original_function(*args, **kwargs): print(name) @timeout(seconds=10, raise_timeout=True) - def run(): + def run() -> None: new_items = list(items) algo(new_items) diff --git a/Sorting algorithm list/sorts/bogosort.py b/Sorting algorithm list/sorts/bogosort.py index 6d302b43f..84b3c9d9a 100644 --- a/Sorting algorithm list/sorts/bogosort.py +++ b/Sorting algorithm list/sorts/bogosort.py @@ -26,7 +26,7 @@ def bogosort(collection): [-45, -5, -2] """ - def isSorted(collection): + def isSorted(collection) -> bool: if len(collection) < 2: return True for i in range(len(collection) - 1): diff --git a/Sorting algorithm list/sorts/heap_sort.py b/Sorting algorithm list/sorts/heap_sort.py index d1eeb2356..869ed18fb 100644 --- a/Sorting algorithm list/sorts/heap_sort.py +++ b/Sorting algorithm list/sorts/heap_sort.py @@ -13,7 +13,7 @@ from __future__ import print_function -def heapify(unsorted, index, heap_size): +def heapify(unsorted, index, heap_size) -> None: largest = index left_index = 2 * index + 1 right_index = 2 * index + 2 diff --git a/Sorting/sorting.py b/Sorting/sorting.py index 330c7038c..e441a5323 100644 --- a/Sorting/sorting.py +++ b/Sorting/sorting.py @@ -24,11 +24,11 @@ class Student: - def __init__(self, name, age): + def __init__(self, name, age) -> None: self.name = name self.age = age - def __repr__(self): + def __repr__(self) -> str: return "%s (%d)" % (self.name, self.age) diff --git a/Timer/pyside_qtimer.py b/Timer/pyside_qtimer.py index 1d02eeb79..4d6640a2f 100644 --- a/Timer/pyside_qtimer.py +++ b/Timer/pyside_qtimer.py @@ -8,7 +8,7 @@ from PySide.QtCore import * -def say(): +def say() -> None: print("say!") diff --git a/WrapperMap__work_with_dict_through_atts.py b/WrapperMap__work_with_dict_through_atts.py index 8cc9b7cfe..316813bf1 100644 --- a/WrapperMap__work_with_dict_through_atts.py +++ b/WrapperMap__work_with_dict_through_atts.py @@ -5,7 +5,7 @@ class WrapperMap: - def __init__(self, d: dict): + def __init__(self, d: dict) -> None: self.d = d def get_value(self): @@ -18,7 +18,7 @@ def __getattr__(self, item: str): return value - def __repr__(self): + def __repr__(self) -> str: return repr(self.d) diff --git a/XML/XML_to_dict__xmltodict__examples/simple_python_object_to_xml__unparse.py b/XML/XML_to_dict__xmltodict__examples/simple_python_object_to_xml__unparse.py index 9c53aa684..1297bfeb7 100644 --- a/XML/XML_to_dict__xmltodict__examples/simple_python_object_to_xml__unparse.py +++ b/XML/XML_to_dict__xmltodict__examples/simple_python_object_to_xml__unparse.py @@ -12,13 +12,13 @@ class Dog: - def __init__(self, name): + def __init__(self, name) -> None: self.name = name self.type = "Animal" self.paws = 4 self.has_tail = True - def __repr__(self): + def __repr__(self) -> str: return f'' diff --git a/XML/XML_to_dict__xmltodict__examples/streaming_mode.py b/XML/XML_to_dict__xmltodict__examples/streaming_mode.py index c7c8086e4..ead6df188 100644 --- a/XML/XML_to_dict__xmltodict__examples/streaming_mode.py +++ b/XML/XML_to_dict__xmltodict__examples/streaming_mode.py @@ -11,7 +11,7 @@ import xmltodict -def handle(path, item): +def handle(path, item) -> bool: print(f"path: {path} item: {item!r}") return True diff --git a/XML/XML_to_dict__xmltodict__examples/streaming_mode__from_url_gzip.py b/XML/XML_to_dict__xmltodict__examples/streaming_mode__from_url_gzip.py index d9be22934..49daf60e6 100644 --- a/XML/XML_to_dict__xmltodict__examples/streaming_mode__from_url_gzip.py +++ b/XML/XML_to_dict__xmltodict__examples/streaming_mode__from_url_gzip.py @@ -18,7 +18,7 @@ url = "http://discogs-data.s3-us-west-2.amazonaws.com/data/2018/discogs_20180201_artists.xml.gz" -def handle_artist(_, artist): +def handle_artist(_, artist) -> bool: print(artist["name"]) return True diff --git a/XML/sax_FIAS_with_progress__HOUSEGUID.py b/XML/sax_FIAS_with_progress__HOUSEGUID.py index ddcb1ba70..39f211183 100644 --- a/XML/sax_FIAS_with_progress__HOUSEGUID.py +++ b/XML/sax_FIAS_with_progress__HOUSEGUID.py @@ -13,10 +13,10 @@ class AttrHandler(xml.sax.handler.ContentHandler): - def startDocument(self): + def startDocument(self) -> None: self.it = iter(tqdm(iter(lambda: 0, 1))) - def startElement(self, name, attrs): + def startElement(self, name, attrs) -> None: if "HOUSEGUID" in attrs: all_house_guid.add(attrs["HOUSEGUID"]) diff --git a/XML/sax_FIAS_with_progress__HOUSEGUID__no_collect.py b/XML/sax_FIAS_with_progress__HOUSEGUID__no_collect.py index b4f98434c..71e03517a 100644 --- a/XML/sax_FIAS_with_progress__HOUSEGUID__no_collect.py +++ b/XML/sax_FIAS_with_progress__HOUSEGUID__no_collect.py @@ -13,11 +13,11 @@ class AttrHandler(xml.sax.handler.ContentHandler): - def startDocument(self): + def startDocument(self) -> None: self.it = iter(tqdm(iter(lambda: 0, 1))) self.number = 0 - def startElement(self, name, attrs): + def startElement(self, name, attrs) -> None: if "HOUSEGUID" in attrs: guid = attrs["HOUSEGUID"] if self.number > 0: diff --git a/XML/sax_FIAS_with_progress__HOUSEGUID__no_collect__with_write_handler.py b/XML/sax_FIAS_with_progress__HOUSEGUID__no_collect__with_write_handler.py index 48891d48b..644ab2882 100644 --- a/XML/sax_FIAS_with_progress__HOUSEGUID__no_collect__with_write_handler.py +++ b/XML/sax_FIAS_with_progress__HOUSEGUID__no_collect__with_write_handler.py @@ -9,19 +9,19 @@ class WriteHouseGuidHandler(xml.sax.handler.ContentHandler): - def __init__(self, file_name: str): + def __init__(self, file_name: str) -> None: super().__init__() self.f = open(file_name, "w") self.it = None self.number = 0 - def startDocument(self): + def startDocument(self) -> None: self.it = iter(tqdm(iter(lambda: 0, 1))) self.number = 0 self.f.write("[") - def startElement(self, name, attrs): + def startElement(self, name, attrs) -> None: if "HOUSEGUID" in attrs: guid = attrs["HOUSEGUID"] @@ -33,7 +33,7 @@ def startElement(self, name, attrs): next(self.it) - def endDocument(self): + def endDocument(self) -> None: self.f.write("]") self.f.close() diff --git a/XML/xml.etree.ElementTree__examples/pretty_print.py b/XML/xml.etree.ElementTree__examples/pretty_print.py index ff36c786a..93836b547 100644 --- a/XML/xml.etree.ElementTree__examples/pretty_print.py +++ b/XML/xml.etree.ElementTree__examples/pretty_print.py @@ -10,7 +10,7 @@ # SOURCE: http://effbot.org/zone/element-lib.htm#prettyprint -def indent(elem, level=0): +def indent(elem, level=0) -> None: i = "\n" + level * " " if len(elem): if not elem.text or not elem.text.strip(): diff --git a/XML/xml.parsers.expat__examples__like_sax/hello_world.py b/XML/xml.parsers.expat__examples__like_sax/hello_world.py index f9f24ae66..0fa8d4d0d 100644 --- a/XML/xml.parsers.expat__examples__like_sax/hello_world.py +++ b/XML/xml.parsers.expat__examples__like_sax/hello_world.py @@ -11,15 +11,15 @@ # 3 handler functions -def on_start_element(name, attrs): +def on_start_element(name, attrs) -> None: print("Start element:", name, attrs) -def on_end_element(name): +def on_end_element(name) -> None: print("End element:", name) -def on_char_data(data): +def on_char_data(data) -> None: print("Character data:", repr(data)) diff --git a/XML/xml_replace_comments/xml_replace_comments.py b/XML/xml_replace_comments/xml_replace_comments.py index a08375ee6..868ee74e4 100644 --- a/XML/xml_replace_comments/xml_replace_comments.py +++ b/XML/xml_replace_comments/xml_replace_comments.py @@ -9,7 +9,7 @@ from lxml import etree -def replace(file_name, save_file_name): +def replace(file_name, save_file_name) -> None: with open(file_name, encoding="utf8") as f: text = f.read() diff --git a/_FOO_TEST_TEST/FOO_TEST_TEST.py b/_FOO_TEST_TEST/FOO_TEST_TEST.py index db91dee5e..86c64dacc 100644 --- a/_FOO_TEST_TEST/FOO_TEST_TEST.py +++ b/_FOO_TEST_TEST/FOO_TEST_TEST.py @@ -4,6 +4,86 @@ __author__ = "ipetrash" +# # pip install ollama==0.6.1 +# import ollama +# from ollama import chat +# from ollama import ChatResponse +# +# +# response = ollama.generate( +# model='qwen2.5:7b', +# prompt="Выдели из фразы: 'Напомни купить молоко завтра в 9 утра' событие и время.", +# format='json', # КЛЮЧЕВОЙ МОМЕНТ +# system="Отвечай строго в формате JSON с полями 'task' и 'time'.", +# ) +# print(response['response']) +# # +# # rs = requests.get("http://localhost:11434") +# # print(rs.text) + + +from ollama import chat +from pydantic import BaseModel + +# 1. Описываем структуру данных +class CityInfo(BaseModel): + city: str + population: int + is_capital: bool + about: str + region: str + country: str + +class PersonInfo(BaseModel): + full_name: str + url_github: str + city: str + about: str + country: str + +# # 2. Делаем запрос +# response = chat( +# # model='qwen2.5', +# model='qwen3:4b', +# messages=[ +# {'role': 'system', 'content': 'Отвечай на вопросы на русском языке'}, +# {'role': 'user', 'content': 'Расскажи про gil9red'}, +# ], +# format=PersonInfo.model_json_schema(), # Передаем схему JSON +# options={'temperature': 0}, +# ) +# +# # 3. Валидируем и превращаем в объект Python +# print(response) +# print(response.message.content) +# person_data = PersonInfo.model_validate_json(response.message.content) +# print(person_data) + +from datetime import datetime +dt = datetime.now() + +# 2. Делаем запрос +response = chat( + # model='qwen2.5', + model='qwen3:4b', + messages=[ + {'role': 'system', 'content': 'Отвечай на вопросы на русском языке'}, + {'role': 'user', 'content': 'Расскажи про Магнитогорск'}, + ], + format=CityInfo.model_json_schema(), # Передаем схему JSON + options={'temperature': 0}, +) + +# 3. Валидируем и превращаем в объект Python +print(response) +print(response.message.content) +city_data = CityInfo.model_validate_json(response.message.content) +print(city_data) +print(city_data.city, city_data.population) +print(datetime.now() - dt) + +quit() + import sys import traceback from random import randint @@ -22,7 +102,7 @@ from PyQt6.QtCore import QRectF, QLineF, Qt, QTimer -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}\n" text += "".join(traceback.format_tb(tb)) print(text) @@ -149,7 +229,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class Ball: - def __init__(self, ball_item: QGraphicsEllipseItem, v_x, v_y): + def __init__(self, ball_item: QGraphicsEllipseItem, v_x, v_y) -> None: # def __init__(self, x, y, r, v_x, v_y, color): # TODO: self.x = ball_item.x() @@ -163,7 +243,7 @@ def __init__(self, ball_item: QGraphicsEllipseItem, v_x, v_y): self.is_collision: bool = False # self.color = color - def update(self): + def update(self) -> None: self.x += self.v_x self.y += self.v_y @@ -290,7 +370,7 @@ def update(self): class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("TODO") @@ -331,7 +411,7 @@ def get_random_vector() -> tuple[int, int]: self.setCentralWidget(self.view) # TODO: - def tick(self): + def tick(self) -> None: # TODO: Использовать # Считаем сколько времени прошло с прошлого обсчета dt = default_timer() - self.t @@ -358,7 +438,7 @@ def tick(self): # # self.update() - def on_scene_changed(self, region: list[QRectF]): + def on_scene_changed(self, region: list[QRectF]) -> None: print("on_scene_changed", region) # if self.ball.is_collision: @@ -478,7 +558,7 @@ def on_scene_changed(self, region: list[QRectF]): quit() -from datetime import date, timedelta +from datetime import date, timedelta, datetime start = date(year=1992, month=8, day=18) year = 1 @@ -536,7 +616,7 @@ def chunks(l: Sized, n: int) -> Generator[Any, None, None]: from PyQt5.QtWidgets import QApplication, QTextEdit, QMessageBox -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -642,7 +722,7 @@ class Release: testing_finish_date: date = field(init=False) support_end_date: date = field(init=False) - def __post_init__(self): + def __post_init__(self) -> None: self.free_commit_date = add_to_month(self.date, number=1) - timedelta(days=1) self.testing_finish_date = add_to_month(self.date, number=2) self.support_end_date = add_to_month( @@ -787,7 +867,7 @@ def to_ms(d: date) -> int: return int(utc_timestamp * 1000) -d = datetime.utcnow().date() +d = datetime.now(timezone.utc).date() print(d) # 2025-01-10 diff --git a/_FOO_TEST_TEST/db.py b/_FOO_TEST_TEST/db.py index a0c07c85d..129c2fef2 100644 --- a/_FOO_TEST_TEST/db.py +++ b/_FOO_TEST_TEST/db.py @@ -82,7 +82,7 @@ class Logged(BaseModel): total_seconds_human: str @classmethod - def create_table(cls): + def create_table(cls) -> None: QSqlQuery( f""" CREATE TABLE IF NOT EXISTS {cls.get_table_name()}( @@ -117,7 +117,7 @@ def update( id: int, total_seconds: int, total_seconds_human: str, - ): + ) -> None: query = QSqlQuery() query.prepare( f""" @@ -145,7 +145,7 @@ class LoggedItem(BaseModel): jira_title: str @classmethod - def create_table(cls): + def create_table(cls) -> None: QSqlQuery( f""" CREATE TABLE IF NOT EXISTS {cls.get_table_name()}( diff --git a/about clipboard changed/with_notification/notifications.py b/about clipboard changed/with_notification/notifications.py index 983993f5c..09aa68cfa 100644 --- a/about clipboard changed/with_notification/notifications.py +++ b/about clipboard changed/with_notification/notifications.py @@ -19,7 +19,7 @@ class WindowsBalloonTip: @staticmethod - def balloon_tip(title, msg, duration=5, icon_path_name=None): + def balloon_tip(title, msg, duration=5, icon_path_name=None) -> None: message_map = { win32con.WM_DESTROY: WindowsBalloonTip.on_destroy, } @@ -62,7 +62,7 @@ def balloon_tip(title, msg, duration=5, icon_path_name=None): UnregisterClass(wc.lpszClassName, None) @staticmethod - def on_destroy(hwnd, msg, wparam, lparam): + def on_destroy(hwnd, msg, wparam, lparam) -> None: nid = (hwnd, 0) Shell_NotifyIcon(NIM_DELETE, nid) PostQuitMessage(0) # Terminate the app. diff --git a/ago.py b/ago.py index ec9fb86d1..42bdca4b3 100644 --- a/ago.py +++ b/ago.py @@ -18,7 +18,7 @@ class UnitSeconds(IntEnum): YEAR = 12 * MONTH -class L10N: +class L10n: def get_template(self) -> str: return "{value} {unit} ago" @@ -33,7 +33,7 @@ def get_value(self, value: int, unit: UnitSeconds) -> str: return self.get_template().format(value=value, unit=unit) -class L10N_RU(L10N): +class L10nRu(L10n): def get_template(self) -> str: return "{value} {unit} назад" @@ -50,6 +50,7 @@ def declension(n: int, form_0: str, form_1: str, form_2: str) -> str: return form_1 if units in [2, 3, 4]: return form_2 + return "" def get_unit(self, value: int, unit: UnitSeconds) -> str: match unit: @@ -78,7 +79,7 @@ def get_unit(self, value: int, unit: UnitSeconds) -> str: raise NotImplemented() -def ago(seconds: timedelta, l10n: L10N = L10N()) -> str: +def ago(seconds: timedelta, l10n: L10n = L10n()) -> str: seconds = int(seconds.total_seconds()) if seconds < 0: seconds = -seconds @@ -157,9 +158,9 @@ def ago(seconds: timedelta, l10n: L10N = L10N()) -> str: (timedelta(weeks=5 * 12 * 4), "5 лет назад"), ] for value, expected in items: - actual = ago(dt - (dt - value), l10n=L10N_RU()) + actual = ago(dt - (dt - value), l10n=L10nRu()) print(f"{value!r} -> {actual!r}") assert expected == actual, f"{expected!r} != {actual!r}" dt2 = datetime(year=2024, month=12, day=10) - assert ago(dt2 - dt, l10n=L10N_RU()) == "2 дня назад" + assert ago(dt2 - dt, l10n=L10nRu()) == "2 дня назад" diff --git a/aiohttp__asyncio__examples/aiohttp_check_user_agent.py b/aiohttp__asyncio__examples/aiohttp_check_user_agent.py index 8f074b831..b905dc183 100644 --- a/aiohttp__asyncio__examples/aiohttp_check_user_agent.py +++ b/aiohttp__asyncio__examples/aiohttp_check_user_agent.py @@ -10,7 +10,7 @@ import aiohttp -async def main(): +async def main() -> None: async with aiohttp.ClientSession() as session: async with session.get("https://httpbin.org/get") as rs: print("Status:", rs.status) diff --git a/aiohttp__asyncio__examples/aiohttp_client.py b/aiohttp__asyncio__examples/aiohttp_client.py index 07dd57d52..44ba6d470 100644 --- a/aiohttp__asyncio__examples/aiohttp_client.py +++ b/aiohttp__asyncio__examples/aiohttp_client.py @@ -10,7 +10,7 @@ import aiohttp -async def main(): +async def main() -> None: url = "https://python.org" async with aiohttp.ClientSession() as session: diff --git a/aiohttp__asyncio__examples/asyncio__hello_world.py b/aiohttp__asyncio__examples/asyncio__hello_world.py index 1c4032bd3..432a7777e 100644 --- a/aiohttp__asyncio__examples/asyncio__hello_world.py +++ b/aiohttp__asyncio__examples/asyncio__hello_world.py @@ -7,7 +7,7 @@ import asyncio -async def main(): +async def main() -> None: print("Hello ", end="") await asyncio.sleep(1) print("World!") diff --git a/aiohttp__asyncio__examples/concurrent_requests.py b/aiohttp__asyncio__examples/concurrent_requests.py index cfc4fe6ea..647a97859 100644 --- a/aiohttp__asyncio__examples/concurrent_requests.py +++ b/aiohttp__asyncio__examples/concurrent_requests.py @@ -12,7 +12,7 @@ from ignore_aiohttp_ssl_error import ignore_aiohttp_ssl_error -async def fetch_page(url: str, idx: int): +async def fetch_page(url: str, idx: int) -> None: async with aiohttp.request("GET", url) as rs: if rs.status == 200: print(f"[{idx}] Data fetched successfully") @@ -21,7 +21,7 @@ async def fetch_page(url: str, idx: int): print(rs.content) -async def main(): +async def main() -> None: url = "https://python.org" urls = [url] * 100 diff --git a/aiohttp__asyncio__examples/hello_world.py b/aiohttp__asyncio__examples/hello_world.py index 40e951117..0a395a322 100644 --- a/aiohttp__asyncio__examples/hello_world.py +++ b/aiohttp__asyncio__examples/hello_world.py @@ -17,7 +17,7 @@ async def fetch(session, url): return await response.text() -async def main(): +async def main() -> None: async with aiohttp.ClientSession() as session: html = await fetch(session, "http://python.org") print(html) diff --git a/aiohttp__asyncio__examples/hello_world__parse__lxml_etree.py b/aiohttp__asyncio__examples/hello_world__parse__lxml_etree.py index a432ebd34..508eefbc5 100644 --- a/aiohttp__asyncio__examples/hello_world__parse__lxml_etree.py +++ b/aiohttp__asyncio__examples/hello_world__parse__lxml_etree.py @@ -20,7 +20,7 @@ async def fetch(session, url): return await response.content.read() -async def main(): +async def main() -> None: async with aiohttp.ClientSession() as session: xml_str = await fetch(session, "https://sdvk-oboi.ru/sitemap.xml") root = etree.fromstring(xml_str) diff --git a/aiohttp__asyncio__examples/ignore_aiohttp_ssl_error.py b/aiohttp__asyncio__examples/ignore_aiohttp_ssl_error.py index f30eb2205..f6beffd36 100644 --- a/aiohttp__asyncio__examples/ignore_aiohttp_ssl_error.py +++ b/aiohttp__asyncio__examples/ignore_aiohttp_ssl_error.py @@ -19,7 +19,7 @@ SSL_PROTOCOLS = (*SSL_PROTOCOLS, uvloop.loop.SSLProtocol) -def ignore_aiohttp_ssl_error(loop): +def ignore_aiohttp_ssl_error(loop) -> None: """Ignore aiohttp #3535 / cpython #13548 issue with SSL data after close There is an issue in Python 3.7 up to 3.7.3 that over-reports a @@ -41,7 +41,7 @@ def ignore_aiohttp_ssl_error(loop): orig_handler = loop.get_exception_handler() - def ignore_ssl_error(loop, context): + def ignore_ssl_error(loop, context) -> None: if context.get("message") in { "SSL error in data received", "Fatal error on transport", diff --git a/alpha2_to_country/main.py b/alpha2_to_country/main.py index 8cba527aa..c8ca59b42 100644 --- a/alpha2_to_country/main.py +++ b/alpha2_to_country/main.py @@ -18,7 +18,7 @@ ALPHA2_TO_COUNTRY = None -def init(): +def init() -> None: global ALPHA2_TO_COUNTRY if FILE_NAME_COUNTRY.exists(): diff --git a/api_clans.py b/api_clans.py index 66108962c..54ee5fbb6 100644 --- a/api_clans.py +++ b/api_clans.py @@ -14,7 +14,7 @@ class Api: # TODO: this API_URL = "/api_clans/1/index.php?request=" - def __init__(self, login: str, password: str): + def __init__(self, login: str, password: str) -> None: self.login = login self.password = password diff --git a/ascii_table__simple_pretty__format.py b/ascii_table__simple_pretty__format.py index 5bf24e712..afe0340f7 100644 --- a/ascii_table__simple_pretty__format.py +++ b/ascii_table__simple_pretty__format.py @@ -32,7 +32,7 @@ def pretty_table(data, cell_sep=" | ", header_separator=True, align=">") -> str: return "\n".join(lines) -def print_pretty_table(data, cell_sep=" | ", header_separator=True, align=">"): +def print_pretty_table(data, cell_sep=" | ", header_separator=True, align=">") -> None: print(pretty_table(data, cell_sep, header_separator, align)) diff --git a/ascii_table__simple_pretty__ljust.py b/ascii_table__simple_pretty__ljust.py index dda60264d..b762934b4 100644 --- a/ascii_table__simple_pretty__ljust.py +++ b/ascii_table__simple_pretty__ljust.py @@ -31,7 +31,7 @@ def pretty_table(data, cell_sep=" | ", header_separator=True) -> str: return "\n".join(lines) -def print_pretty_table(data, cell_sep=" | ", header_separator=True): +def print_pretty_table(data, cell_sep=" | ", header_separator=True) -> None: print(pretty_table(data, cell_sep, header_separator)) diff --git a/ascii_table__simple_pretty__rjust.py b/ascii_table__simple_pretty__rjust.py index 2b3ce49a0..8abdf420d 100644 --- a/ascii_table__simple_pretty__rjust.py +++ b/ascii_table__simple_pretty__rjust.py @@ -31,7 +31,7 @@ def pretty_table(data, cell_sep=" | ", header_separator=True) -> str: return "\n".join(lines) -def print_pretty_table(data, cell_sep=" | ", header_separator=True): +def print_pretty_table(data, cell_sep=" | ", header_separator=True) -> None: print(pretty_table(data, cell_sep, header_separator)) diff --git a/autoclick_RDP_task_icon/main.py b/autoclick_RDP_task_icon/main.py index 02cee0956..d8caa22fe 100644 --- a/autoclick_RDP_task_icon/main.py +++ b/autoclick_RDP_task_icon/main.py @@ -42,7 +42,7 @@ def get_pos_rdp_task_icon() -> tuple[int, int] | None: pass -def run(): +def run() -> None: logging.info("") logging.info("Run") diff --git a/bin2str/gui.py b/bin2str/gui.py index f96c4e1a1..808c22891 100644 --- a/bin2str/gui.py +++ b/bin2str/gui.py @@ -24,7 +24,7 @@ from bin2str import bin2str, str2bin -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -37,7 +37,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("bin2str") @@ -65,13 +65,13 @@ def __init__(self): self.setLayout(layout) - def _bin2str(self): + def _bin2str(self) -> None: text = self.plain_text_bin.toPlainText() text = bin2str(text) self.plain_text_str.setPlainText(text) - def _str2bin(self): + def _str2bin(self) -> None: text = self.plain_text_str.toPlainText() text = str2bin(text) diff --git a/build_exe/pyinstaller_example/compress_exe/main.py b/build_exe/pyinstaller_example/compress_exe/main.py index 88ac109f1..f1e929469 100644 --- a/build_exe/pyinstaller_example/compress_exe/main.py +++ b/build_exe/pyinstaller_example/compress_exe/main.py @@ -17,7 +17,7 @@ button = QPushButton("Add") text_edit = QTextEdit() - def add_to_text(): + def add_to_text() -> None: text = line_edit.text() text_edit.append(text) diff --git a/build_exe/pyinstaller_example/gui/qt_pyqt5/main.py b/build_exe/pyinstaller_example/gui/qt_pyqt5/main.py index 97c3ea417..f504fb661 100644 --- a/build_exe/pyinstaller_example/gui/qt_pyqt5/main.py +++ b/build_exe/pyinstaller_example/gui/qt_pyqt5/main.py @@ -22,7 +22,7 @@ text_edit = QTextEdit() -def add_to_text(): +def add_to_text() -> None: text = line_edit.text() text_edit.append(text) diff --git a/build_exe/pyinstaller_example/gui/qt_pyside/main.py b/build_exe/pyinstaller_example/gui/qt_pyside/main.py index 88ac109f1..f1e929469 100644 --- a/build_exe/pyinstaller_example/gui/qt_pyside/main.py +++ b/build_exe/pyinstaller_example/gui/qt_pyside/main.py @@ -17,7 +17,7 @@ button = QPushButton("Add") text_edit = QTextEdit() - def add_to_text(): + def add_to_text() -> None: text = line_edit.text() text_edit.append(text) diff --git a/build_fake_image__build_exe/generator.py b/build_fake_image__build_exe/generator.py index f16052dc1..8b0eabda3 100644 --- a/build_fake_image__build_exe/generator.py +++ b/build_fake_image__build_exe/generator.py @@ -9,7 +9,7 @@ # SOURCE: https://github.com/gil9red/SimplePyScripts/blob/7cebedb16a5ac81333ebf62af410fdb53a690d29/convert_image_to_ico/main.py -def convert_image_to_ico(file_name, file_name_ico, icon_sizes=None): +def convert_image_to_ico(file_name, file_name_ico, icon_sizes=None) -> None: img = Image.open(file_name) if icon_sizes: @@ -22,7 +22,7 @@ def convert_image_to_ico(file_name, file_name_ico, icon_sizes=None): # SOURCE: https://github.com/gil9red/SimplePyScripts/blob/aec64c1749d4f6f3176e3222c7e7c554f40c693f/generator_py_with_inner_image_with_open/main.py -def generate(file_name, inject_code: str): +def generate(file_name, inject_code: str) -> None: with open(file_name, "rb") as f: img_bytes = f.read() diff --git a/codewars/parse_molecule__Molecule to atoms.py b/codewars/parse_molecule__Molecule to atoms.py index 18f928ef8..3484bc9eb 100644 --- a/codewars/parse_molecule__Molecule to atoms.py +++ b/codewars/parse_molecule__Molecule to atoms.py @@ -97,7 +97,7 @@ def parse_molecule(formula): if __name__ == "__main__": - def equals_atomically(obj1, obj2): + def equals_atomically(obj1, obj2) -> bool: if len(obj1) != len(obj2): return False for k in obj1: diff --git a/codingame/medium/Bender - Episode 1.py b/codingame/medium/Bender - Episode 1.py index 9b293e7e7..bd97edcc7 100644 --- a/codingame/medium/Bender - Episode 1.py +++ b/codingame/medium/Bender - Episode 1.py @@ -45,12 +45,12 @@ DEBUG = False -def log(*args, **kwargs): +def log(*args, **kwargs) -> None: DEBUG and print(*args, **kwargs) class Bender: - def __init__(self, city_map): + def __init__(self, city_map) -> None: self.objects_map = dict() # Соберем все объекты на карте в словарь, исключаются пустые места и стенки @@ -81,7 +81,7 @@ def __init__(self, city_map): self.steps = list() # self.steps_log_list = list() - def _set_pos_i(self, value): + def _set_pos_i(self, value) -> None: # Устанавливаем i, и старое j self.pos = value, self.pos[1] @@ -90,7 +90,7 @@ def _get_pos_i(self): pos_i = property(_get_pos_i, _set_pos_i) - def _set_pos_j(self, value): + def _set_pos_j(self, value) -> None: # Устанавливаем старое i и j self.pos = self.pos[0], value @@ -99,7 +99,7 @@ def _get_pos_j(self): pos_j = property(_get_pos_j, _set_pos_j) - def _set_pos(self, value): + def _set_pos(self, value) -> None: self.objects_map["@"] = value def _get_pos(self): @@ -120,13 +120,13 @@ def city_map(self): return map - def print_city_map(self): + def print_city_map(self) -> None: log() for row in self.city_map(): log(*row, sep="") log() - def _set_direction_name(self, name): + def _set_direction_name(self, name) -> None: self._direction_name = name def _get_direction_name(self): diff --git a/collector_bash_im/collector_bash_im.py b/collector_bash_im/collector_bash_im.py index 1998bca75..eddb6ae3c 100644 --- a/collector_bash_im/collector_bash_im.py +++ b/collector_bash_im/collector_bash_im.py @@ -43,13 +43,13 @@ def get_logger(name, file="log.txt", encoding="utf8"): class Quote: - def __init__(self, id, date, rating, text): + def __init__(self, id, date, rating, text) -> None: self.id = id self.date = date self.rating = rating self.text = text - def __repr__(self): + def __repr__(self) -> str: return ( "".format(len(self.text), **self.__dict__) diff --git a/concurrency_in_python__threading_processing/about_1__single_thread.py b/concurrency_in_python__threading_processing/about_1__single_thread.py index d0c526330..b03abd482 100644 --- a/concurrency_in_python__threading_processing/about_1__single_thread.py +++ b/concurrency_in_python__threading_processing/about_1__single_thread.py @@ -16,14 +16,14 @@ # A CPU heavy calculation, just as an example. This can be anything you like -def heavy(n, myid): +def heavy(n, myid) -> None: for x in range(1, n): for y in range(1, n): x**y print(myid, "is done") -def sequential(n): +def sequential(n) -> None: for i in range(n): heavy(N, i) diff --git a/concurrency_in_python__threading_processing/about_2__multithreading.py b/concurrency_in_python__threading_processing/about_2__multithreading.py index b2bdc2974..4e68c7285 100644 --- a/concurrency_in_python__threading_processing/about_2__multithreading.py +++ b/concurrency_in_python__threading_processing/about_2__multithreading.py @@ -14,7 +14,7 @@ from about_1__single_thread import heavy, WORKERS, N -def threaded(n): +def threaded(n) -> None: threads = [] for i in range(n): diff --git a/concurrency_in_python__threading_processing/about_3__multiprocessing.py b/concurrency_in_python__threading_processing/about_3__multiprocessing.py index d2121c1b0..6e71b2722 100644 --- a/concurrency_in_python__threading_processing/about_3__multiprocessing.py +++ b/concurrency_in_python__threading_processing/about_3__multiprocessing.py @@ -14,7 +14,7 @@ from about_1__single_thread import heavy, WORKERS, N -def multiproc(n): +def multiproc(n) -> None: processes = [] for i in range(n): diff --git a/concurrency_in_python__threading_processing/about_4__multiprocessing_with_Pool.py b/concurrency_in_python__threading_processing/about_4__multiprocessing_with_Pool.py index 1b7dbfd35..473e2ffdf 100644 --- a/concurrency_in_python__threading_processing/about_4__multiprocessing_with_Pool.py +++ b/concurrency_in_python__threading_processing/about_4__multiprocessing_with_Pool.py @@ -14,11 +14,11 @@ from about_1__single_thread import heavy, WORKERS, N -def doit(n): +def doit(n) -> None: heavy(N, n) -def pooled(n): +def pooled(n) -> None: # By default, our pool will have processes slots with multiprocessing.Pool() as pool: pool.map(doit, range(n)) diff --git a/concurrency_in_python__threading_processing/multiprocessing__examples/Manager__example.py b/concurrency_in_python__threading_processing/multiprocessing__examples/Manager__example.py index 6f440e73d..7695daacc 100644 --- a/concurrency_in_python__threading_processing/multiprocessing__examples/Manager__example.py +++ b/concurrency_in_python__threading_processing/multiprocessing__examples/Manager__example.py @@ -7,7 +7,7 @@ from multiprocessing import Process, Manager -def f(users_data): +def f(users_data) -> None: users_data["users"][0]["coins"] += 1 diff --git a/concurrency_in_python__threading_processing/multiprocessing__examples/code_execution_with_time_limit.py b/concurrency_in_python__threading_processing/multiprocessing__examples/code_execution_with_time_limit.py index bdc947530..e7b3623b8 100644 --- a/concurrency_in_python__threading_processing/multiprocessing__examples/code_execution_with_time_limit.py +++ b/concurrency_in_python__threading_processing/multiprocessing__examples/code_execution_with_time_limit.py @@ -7,7 +7,7 @@ import multiprocessing -def run(): +def run() -> None: import time i = 1 diff --git a/concurrency_in_python__threading_processing/multiprocessing__examples/create_process_get_result__communication__Pipe.py b/concurrency_in_python__threading_processing/multiprocessing__examples/create_process_get_result__communication__Pipe.py index 376ccd528..734daa4dc 100644 --- a/concurrency_in_python__threading_processing/multiprocessing__examples/create_process_get_result__communication__Pipe.py +++ b/concurrency_in_python__threading_processing/multiprocessing__examples/create_process_get_result__communication__Pipe.py @@ -7,7 +7,7 @@ from multiprocessing import Process, Pipe -def f(con, name): +def f(con, name) -> None: con.send("Hello, " + name) con.close() diff --git a/concurrency_in_python__threading_processing/multiprocessing__examples/create_process_get_result__communication__Queue.py b/concurrency_in_python__threading_processing/multiprocessing__examples/create_process_get_result__communication__Queue.py index ba4474230..b0f74df34 100644 --- a/concurrency_in_python__threading_processing/multiprocessing__examples/create_process_get_result__communication__Queue.py +++ b/concurrency_in_python__threading_processing/multiprocessing__examples/create_process_get_result__communication__Queue.py @@ -7,7 +7,7 @@ from multiprocessing import Process, Queue -def f(q, name): +def f(q, name) -> None: q.put("Hello, " + name) diff --git a/concurrency_in_python__threading_processing/multiprocessing__examples/hello_world__Process.py b/concurrency_in_python__threading_processing/multiprocessing__examples/hello_world__Process.py index 56b47918a..c4504997e 100644 --- a/concurrency_in_python__threading_processing/multiprocessing__examples/hello_world__Process.py +++ b/concurrency_in_python__threading_processing/multiprocessing__examples/hello_world__Process.py @@ -7,7 +7,7 @@ from multiprocessing import Process -def f(name): +def f(name) -> None: print("Hello,", name) diff --git a/concurrency_in_python__threading_processing/multiprocessing__examples/hello_world__with_daemon.py b/concurrency_in_python__threading_processing/multiprocessing__examples/hello_world__with_daemon.py index 61d1c752e..2cb0f3016 100644 --- a/concurrency_in_python__threading_processing/multiprocessing__examples/hello_world__with_daemon.py +++ b/concurrency_in_python__threading_processing/multiprocessing__examples/hello_world__with_daemon.py @@ -8,7 +8,7 @@ import time -def run(): +def run() -> None: print(current_process()) for i in "Hello World!": diff --git a/concurrency_in_python__threading_processing/multiprocessing__examples/hello_world__without_daemon.py b/concurrency_in_python__threading_processing/multiprocessing__examples/hello_world__without_daemon.py index 68d040a7d..3317578cb 100644 --- a/concurrency_in_python__threading_processing/multiprocessing__examples/hello_world__without_daemon.py +++ b/concurrency_in_python__threading_processing/multiprocessing__examples/hello_world__without_daemon.py @@ -8,7 +8,7 @@ import time -def run(): +def run() -> None: print(current_process()) for i in "Hello World!": diff --git a/concurrency_in_python__threading_processing/multiprocessing__examples/multiprocessing__QApplication__create_child_process__with__Tkinter_and_Qt.py b/concurrency_in_python__threading_processing/multiprocessing__examples/multiprocessing__QApplication__create_child_process__with__Tkinter_and_Qt.py index 1da85f550..08fc65fc4 100644 --- a/concurrency_in_python__threading_processing/multiprocessing__examples/multiprocessing__QApplication__create_child_process__with__Tkinter_and_Qt.py +++ b/concurrency_in_python__threading_processing/multiprocessing__examples/multiprocessing__QApplication__create_child_process__with__Tkinter_and_Qt.py @@ -9,12 +9,12 @@ from multiprocessing__Tkinter__in_other_process import go as go_tk -def create_qt(): +def create_qt() -> None: p = Process(target=go_qt, args=("Qt",)) p.start() -def create_tk(): +def create_tk() -> None: p = Process(target=go_tk, args=("Tk",)) p.start() diff --git a/concurrency_in_python__threading_processing/multiprocessing__examples/multiprocessing__QApplication__in_other_process.py b/concurrency_in_python__threading_processing/multiprocessing__examples/multiprocessing__QApplication__in_other_process.py index a8b24f1b8..fb2789a80 100644 --- a/concurrency_in_python__threading_processing/multiprocessing__examples/multiprocessing__QApplication__in_other_process.py +++ b/concurrency_in_python__threading_processing/multiprocessing__examples/multiprocessing__QApplication__in_other_process.py @@ -7,7 +7,7 @@ from PyQt5.Qt import QApplication, Qt, QLabel -def go(name): +def go(name) -> None: app = QApplication([]) mw = QLabel() diff --git a/concurrency_in_python__threading_processing/multiprocessing__examples/multiprocessing__Tkinter__in_other_process.py b/concurrency_in_python__threading_processing/multiprocessing__examples/multiprocessing__Tkinter__in_other_process.py index cb49bec54..4b2b670fd 100644 --- a/concurrency_in_python__threading_processing/multiprocessing__examples/multiprocessing__Tkinter__in_other_process.py +++ b/concurrency_in_python__threading_processing/multiprocessing__examples/multiprocessing__Tkinter__in_other_process.py @@ -7,7 +7,7 @@ import tkinter as tk -def go(name): +def go(name) -> None: app = tk.Tk() app.minsize(150, 50) diff --git a/concurrency_in_python__threading_processing/multiprocessing__examples/multiprocessing_with_webservers__flask.py b/concurrency_in_python__threading_processing/multiprocessing__examples/multiprocessing_with_webservers__flask.py index 081faf97b..486e8fe87 100644 --- a/concurrency_in_python__threading_processing/multiprocessing__examples/multiprocessing_with_webservers__flask.py +++ b/concurrency_in_python__threading_processing/multiprocessing__examples/multiprocessing_with_webservers__flask.py @@ -12,19 +12,19 @@ from flask import Flask -def go(port: int): +def go(port: int) -> None: app = Flask(__name__) logging.basicConfig(level=logging.DEBUG) @app.route("/") - def index(): + def index() -> str: return f"Hello World! (port={port})" app.run(port=port) -def go_parser(urls): +def go_parser(urls) -> None: while True: for url in urls: try: diff --git a/concurrency_in_python__threading_processing/multiprocessing__examples/print_process_info.py b/concurrency_in_python__threading_processing/multiprocessing__examples/print_process_info.py index 82077c0b0..260a1ecce 100644 --- a/concurrency_in_python__threading_processing/multiprocessing__examples/print_process_info.py +++ b/concurrency_in_python__threading_processing/multiprocessing__examples/print_process_info.py @@ -8,14 +8,14 @@ import os -def info(title): +def info(title) -> None: print(title) print("module name:", __name__) print("parent process:", os.getppid()) print("process id:", os.getpid()) -def f(name): +def f(name) -> None: info("function f") print("Hello,", name) diff --git a/concurrency_in_python__threading_processing/multiprocessing__examples/synchronization_between_processes.py b/concurrency_in_python__threading_processing/multiprocessing__examples/synchronization_between_processes.py index 2354f06da..e55c96cbf 100644 --- a/concurrency_in_python__threading_processing/multiprocessing__examples/synchronization_between_processes.py +++ b/concurrency_in_python__threading_processing/multiprocessing__examples/synchronization_between_processes.py @@ -11,7 +11,7 @@ import time -def f(lock, i): +def f(lock, i) -> None: with lock: print("hello world", i) diff --git a/concurrency_in_python__threading_processing/multithreading__threading__examples/ProcessPoolExecutor__examples/hello_world.py b/concurrency_in_python__threading_processing/multithreading__threading__examples/ProcessPoolExecutor__examples/hello_world.py index 48ddc315b..9b6a9b408 100644 --- a/concurrency_in_python__threading_processing/multithreading__threading__examples/ProcessPoolExecutor__examples/hello_world.py +++ b/concurrency_in_python__threading_processing/multithreading__threading__examples/ProcessPoolExecutor__examples/hello_world.py @@ -21,7 +21,7 @@ ] -def is_prime(n): +def is_prime(n) -> bool: if n < 2: return False if n == 2: @@ -36,7 +36,7 @@ def is_prime(n): return True -def main(): +def main() -> None: # NOTE: max_workers must be defined # with concurrent.futures.ProcessPoolExecutor(max_workers=MAX_WORKERS) as executor: diff --git a/concurrency_in_python__threading_processing/multithreading__threading__examples/ThreadPoolExecutor__examples/time_sleep.py b/concurrency_in_python__threading_processing/multithreading__threading__examples/ThreadPoolExecutor__examples/time_sleep.py index 272919efa..277878b81 100644 --- a/concurrency_in_python__threading_processing/multithreading__threading__examples/ThreadPoolExecutor__examples/time_sleep.py +++ b/concurrency_in_python__threading_processing/multithreading__threading__examples/ThreadPoolExecutor__examples/time_sleep.py @@ -15,7 +15,7 @@ MAX_WORKERS = 5 -def run(name): +def run(name) -> None: print(f"name: {name}") time.sleep(randint(1, 4)) diff --git a/concurrency_in_python__threading_processing/multithreading__threading__examples/ThreadPoolExecutor__examples/time_sleep__as_completed.py b/concurrency_in_python__threading_processing/multithreading__threading__examples/ThreadPoolExecutor__examples/time_sleep__as_completed.py index f8473ff8f..28ccadb7e 100644 --- a/concurrency_in_python__threading_processing/multithreading__threading__examples/ThreadPoolExecutor__examples/time_sleep__as_completed.py +++ b/concurrency_in_python__threading_processing/multithreading__threading__examples/ThreadPoolExecutor__examples/time_sleep__as_completed.py @@ -15,7 +15,7 @@ MAX_WORKERS = 5 -def run(name): +def run(name) -> str: time.sleep(randint(1, 4)) return f"name: {name}" diff --git a/concurrency_in_python__threading_processing/multithreading__threading__examples/atomic_counter.py b/concurrency_in_python__threading_processing/multithreading__threading__examples/atomic_counter.py index 1ce431733..c0f4b1dc8 100644 --- a/concurrency_in_python__threading_processing/multithreading__threading__examples/atomic_counter.py +++ b/concurrency_in_python__threading_processing/multithreading__threading__examples/atomic_counter.py @@ -41,7 +41,7 @@ class AtomicCounter: 400000 """ - def __init__(self, initial=0): + def __init__(self, initial=0) -> None: """Initialize a new atomic counter to given initial value (default 0).""" self.value = initial self._lock = threading.Lock() @@ -66,7 +66,7 @@ def increment(self, num=1): counter = AtomicCounter() - def incrementor(): + def incrementor() -> None: for i in range(NUM): counter.increment() diff --git a/concurrency_in_python__threading_processing/multithreading__threading__examples/code_execution_with_time_limit.py b/concurrency_in_python__threading_processing/multithreading__threading__examples/code_execution_with_time_limit.py index b8e1c9419..d882d8e3b 100644 --- a/concurrency_in_python__threading_processing/multithreading__threading__examples/code_execution_with_time_limit.py +++ b/concurrency_in_python__threading_processing/multithreading__threading__examples/code_execution_with_time_limit.py @@ -8,7 +8,7 @@ import time -def run(): +def run() -> None: i = 1 # Бесконечный цикл diff --git a/concurrency_in_python__threading_processing/multithreading__threading__examples/example multiprocessing.dummy/urls.py b/concurrency_in_python__threading_processing/multithreading__threading__examples/example multiprocessing.dummy/urls.py index d9df962b1..2cf9018ae 100644 --- a/concurrency_in_python__threading_processing/multithreading__threading__examples/example multiprocessing.dummy/urls.py +++ b/concurrency_in_python__threading_processing/multithreading__threading__examples/example multiprocessing.dummy/urls.py @@ -37,7 +37,7 @@ # ------- VERSUS ------- # -def go(count=1): +def go(count=1) -> None: t = time.clock() pool = ThreadPool(count) results = pool.map(urlopen, urls) diff --git a/concurrency_in_python__threading_processing/multithreading__threading__examples/flask__threaded/threaded__with.py b/concurrency_in_python__threading_processing/multithreading__threading__examples/flask__threaded/threaded__with.py index 488e0fa0c..31c26c6a2 100644 --- a/concurrency_in_python__threading_processing/multithreading__threading__examples/flask__threaded/threaded__with.py +++ b/concurrency_in_python__threading_processing/multithreading__threading__examples/flask__threaded/threaded__with.py @@ -12,7 +12,7 @@ @app.route("/") -def index(): +def index() -> str: return f"Current thread: {threading.current_thread()}" diff --git a/concurrency_in_python__threading_processing/multithreading__threading__examples/flask__threaded/threaded__without.py b/concurrency_in_python__threading_processing/multithreading__threading__examples/flask__threaded/threaded__without.py index b8ca68bfb..0e80e4203 100644 --- a/concurrency_in_python__threading_processing/multithreading__threading__examples/flask__threaded/threaded__without.py +++ b/concurrency_in_python__threading_processing/multithreading__threading__examples/flask__threaded/threaded__without.py @@ -12,7 +12,7 @@ @app.route("/") -def index(): +def index() -> str: return f"Current thread: {threading.current_thread()}" diff --git a/concurrency_in_python__threading_processing/multithreading__threading__examples/hello_world__with_daemon.py b/concurrency_in_python__threading_processing/multithreading__threading__examples/hello_world__with_daemon.py index 43eb3f4fd..1b93b6521 100644 --- a/concurrency_in_python__threading_processing/multithreading__threading__examples/hello_world__with_daemon.py +++ b/concurrency_in_python__threading_processing/multithreading__threading__examples/hello_world__with_daemon.py @@ -8,7 +8,7 @@ import time -def run(): +def run() -> None: print(threading.current_thread()) for i in "Hello World!": print(i) diff --git a/concurrency_in_python__threading_processing/multithreading__threading__examples/hello_world__without_daemon.py b/concurrency_in_python__threading_processing/multithreading__threading__examples/hello_world__without_daemon.py index 1d58ddeec..94303fb54 100644 --- a/concurrency_in_python__threading_processing/multithreading__threading__examples/hello_world__without_daemon.py +++ b/concurrency_in_python__threading_processing/multithreading__threading__examples/hello_world__without_daemon.py @@ -8,7 +8,7 @@ import time -def run(): +def run() -> None: print(threading.current_thread()) for i in "Hello World!": print(i) diff --git a/concurrency_in_python__threading_processing/multithreading__threading__examples/mini_example__with_threading.py b/concurrency_in_python__threading_processing/multithreading__threading__examples/mini_example__with_threading.py index b76d3b282..579a59232 100644 --- a/concurrency_in_python__threading_processing/multithreading__threading__examples/mini_example__with_threading.py +++ b/concurrency_in_python__threading_processing/multithreading__threading__examples/mini_example__with_threading.py @@ -8,7 +8,7 @@ import time -def run(name="main", sleep_seconds=None): +def run(name="main", sleep_seconds=None) -> None: if sleep_seconds: time.sleep(sleep_seconds) diff --git a/concurrency_in_python__threading_processing/multithreading__threading__examples/race_condition.py b/concurrency_in_python__threading_processing/multithreading__threading__examples/race_condition.py index 52a71aac2..0a09c9fc3 100644 --- a/concurrency_in_python__threading_processing/multithreading__threading__examples/race_condition.py +++ b/concurrency_in_python__threading_processing/multithreading__threading__examples/race_condition.py @@ -13,14 +13,14 @@ lock = threading.Lock() -def inc(*args): +def inc(*args) -> None: global number DATA["number"] += 1 number += 1 -def inc_lock(*args): +def inc_lock(*args) -> None: global number with lock: diff --git a/concurrency_in_python__threading_processing/multithreading__threading__examples/thread__with__callback.py b/concurrency_in_python__threading_processing/multithreading__threading__examples/thread__with__callback.py index 86014f261..15a3a15b3 100644 --- a/concurrency_in_python__threading_processing/multithreading__threading__examples/thread__with__callback.py +++ b/concurrency_in_python__threading_processing/multithreading__threading__examples/thread__with__callback.py @@ -8,13 +8,13 @@ from threading import Thread -def go(callback_func): +def go(callback_func) -> None: while True: time.sleep(2) callback_func(":)") -def it_callback(s): +def it_callback(s) -> None: global status status = s diff --git a/concurrency_in_python__threading_processing/multithreading__threading__examples/threading_with_webservers__flask.py b/concurrency_in_python__threading_processing/multithreading__threading__examples/threading_with_webservers__flask.py index 0eae78b3b..e6fdcdda9 100644 --- a/concurrency_in_python__threading_processing/multithreading__threading__examples/threading_with_webservers__flask.py +++ b/concurrency_in_python__threading_processing/multithreading__threading__examples/threading_with_webservers__flask.py @@ -10,7 +10,7 @@ from flask import Flask -def run(port: int = 80): +def run(port: int = 80) -> None: app = Flask(__name__) logging.basicConfig(level=logging.DEBUG) diff --git a/concurrency_in_python__threading_processing/multithreading__threading__examples/timeout_run_function.py b/concurrency_in_python__threading_processing/multithreading__threading__examples/timeout_run_function.py index f1ec750a9..f64ab1a3a 100644 --- a/concurrency_in_python__threading_processing/multithreading__threading__examples/timeout_run_function.py +++ b/concurrency_in_python__threading_processing/multithreading__threading__examples/timeout_run_function.py @@ -9,10 +9,10 @@ class User: - def __init__(self, name): + def __init__(self, name) -> None: self.name = name - def post_msg(self): + def post_msg(self) -> None: time.sleep(3) # Написать пользователю @@ -26,7 +26,7 @@ def post_msg(self): Thread(target=user_2.post_msg).start() -def foo(name): +def foo(name) -> None: time.sleep(5) # Написать пользователю diff --git a/console_change_data_in_line.py b/console_change_data_in_line.py index 8b6ff06cb..2e79600ef 100644 --- a/console_change_data_in_line.py +++ b/console_change_data_in_line.py @@ -8,7 +8,7 @@ import time -def f1(n): +def f1(n) -> None: last_num_chars = 0 write, flush = sys.stdout.write, sys.stdout.flush @@ -23,7 +23,7 @@ def f1(n): print() -def f2(n): +def f2(n) -> None: last_num_chars = 0 write, flush = sys.stdout.write, sys.stdout.flush diff --git a/contextlib__redirect__stdout_stderr/redirect__to_file_like_object.py b/contextlib__redirect__stdout_stderr/redirect__to_file_like_object.py index afdc6c4d4..db0959749 100644 --- a/contextlib__redirect__stdout_stderr/redirect__to_file_like_object.py +++ b/contextlib__redirect__stdout_stderr/redirect__to_file_like_object.py @@ -11,7 +11,7 @@ with StringIO() as f, redirect_stdout(f): print("Hello ", end="") - def foo(): + def foo() -> None: print("World") foo() diff --git a/convert_image_to_ico/main.py b/convert_image_to_ico/main.py index 1f4f6442c..6fc355776 100644 --- a/convert_image_to_ico/main.py +++ b/convert_image_to_ico/main.py @@ -7,7 +7,7 @@ from PIL import Image -def convert_image_to_ico(file_name, file_name_ico, icon_sizes=None): +def convert_image_to_ico(file_name, file_name_ico, icon_sizes=None) -> None: img = Image.open(file_name) if icon_sizes: diff --git a/copy2clipboard.py b/copy2clipboard.py index 707e468c3..95f5988f2 100644 --- a/copy2clipboard.py +++ b/copy2clipboard.py @@ -15,7 +15,7 @@ from PySide.QtGui import QApplication -def to(text: str): +def to(text: str) -> None: app = QApplication([]) app.clipboard().setText(text) app = None diff --git a/copy2clipboard__via_pyperclip.py b/copy2clipboard__via_pyperclip.py index 389413c51..7db33e437 100644 --- a/copy2clipboard__via_pyperclip.py +++ b/copy2clipboard__via_pyperclip.py @@ -7,7 +7,7 @@ import pyperclip -def to(text: str): +def to(text: str) -> None: pyperclip.copy(text) pyperclip.paste() diff --git a/copy_example.py b/copy_example.py index 60d83b6e3..b511a48da 100644 --- a/copy_example.py +++ b/copy_example.py @@ -28,7 +28,7 @@ ] -def _print_complex_data(data): +def _print_complex_data(data) -> None: print(data, id(data)) print(data[2], id(data[2])) print(data[2][2], id(data[2][2])) diff --git a/crash_on_windows.py b/crash_on_windows.py index 7612dabdc..a22874ffe 100644 --- a/crash_on_windows.py +++ b/crash_on_windows.py @@ -7,7 +7,7 @@ from ctypes import wintypes, windll, c_void_p, c_size_t, POINTER, c_ubyte, cast -def main(): +def main() -> None: # Define constants FILE_MAP_ALL_ACCESS = 983071 PAGE_READWRITE = 4 diff --git a/create_vars__use_globals.py b/create_vars__use_globals.py index d994c9077..78c52f113 100644 --- a/create_vars__use_globals.py +++ b/create_vars__use_globals.py @@ -18,7 +18,7 @@ number = 0 -def counter(): +def counter() -> None: # If not exists global # if 'number' not in globals(): # globals()['number'] = 0 diff --git a/cron_converter__examples/test_from_jenkins.py b/cron_converter__examples/test_from_jenkins.py index 077ab2b8b..52ce933fb 100644 --- a/cron_converter__examples/test_from_jenkins.py +++ b/cron_converter__examples/test_from_jenkins.py @@ -13,7 +13,7 @@ class Test(TestCase): - def test_do_convert_every_15_minutes(self): + def test_do_convert_every_15_minutes(self) -> None: # Every fifteen minutes cron = "H/15 * * * *" @@ -33,7 +33,7 @@ def test_do_convert_every_15_minutes(self): self.assertEqual(actual, expected) - def test_do_convert_every_1_hours(self): + def test_do_convert_every_1_hours(self) -> None: cron = "H * * * *" cron = do_convert(cron) @@ -52,7 +52,7 @@ def test_do_convert_every_1_hours(self): self.assertEqual(actual, expected) - def test_do_convert_every_8_hours(self): + def test_do_convert_every_8_hours(self) -> None: cron = "H */8 * * *" cron = do_convert(cron) @@ -79,7 +79,7 @@ def test_do_convert_every_8_hours(self): self.assertEqual(actual, expected) - def test_do_convert_every_24_hours(self): + def test_do_convert_every_24_hours(self) -> None: cron = "H 0 * * *" cron = do_convert(cron) @@ -98,7 +98,7 @@ def test_do_convert_every_24_hours(self): self.assertEqual(actual, expected) - def test_do_convert_hourly(self): + def test_do_convert_hourly(self) -> None: cron = "@hourly" cron = do_convert(cron) @@ -117,7 +117,7 @@ def test_do_convert_hourly(self): self.assertEqual(actual, expected) - def test_do_convert_daily(self): + def test_do_convert_daily(self) -> None: cron = "@daily" cron = do_convert(cron) @@ -136,7 +136,7 @@ def test_do_convert_daily(self): self.assertEqual(actual, expected) - def test_do_convert_midnight(self): + def test_do_convert_midnight(self) -> None: cron = "@midnight" cron = do_convert(cron) @@ -165,7 +165,7 @@ def test_do_convert_midnight(self): self.assertEqual(actual, expected) - def test_do_convert_weekly(self): + def test_do_convert_weekly(self) -> None: cron = "@weekly" cron = do_convert(cron) @@ -194,7 +194,7 @@ def test_do_convert_weekly(self): self.assertEqual(actual, expected) - def test_do_convert_monthly(self): + def test_do_convert_monthly(self) -> None: cron = "@monthly" cron = do_convert(cron) @@ -223,7 +223,7 @@ def test_do_convert_monthly(self): self.assertEqual(actual, expected) - def test_do_convert_yearly(self): + def test_do_convert_yearly(self) -> None: cron = "@yearly" cron = do_convert(cron) @@ -242,7 +242,7 @@ def test_do_convert_yearly(self): self.assertEqual(actual, expected) - def test_do_convert_annually(self): + def test_do_convert_annually(self) -> None: cron = "@annually" cron = do_convert(cron) @@ -261,7 +261,7 @@ def test_do_convert_annually(self): self.assertEqual(actual, expected) - def test_do_convert_complex_1(self): + def test_do_convert_complex_1(self) -> None: # Every ten minutes in the first half of every hour cron = "H(0-29)/10 * * * *" @@ -297,7 +297,7 @@ def test_do_convert_complex_1(self): self.assertEqual(actual, expected) - def test_do_convert_complex_2(self): + def test_do_convert_complex_2(self) -> None: # Once every two hours at 45 minutes past the hour starting at 9:45 AM and finishing at 3:45 PM every weekday cron = "45 9-16/2 * * 1-5" @@ -331,7 +331,7 @@ def test_do_convert_complex_2(self): self.assertEqual(actual, expected) - def test_do_convert_complex_3(self): + def test_do_convert_complex_3(self) -> None: # Once in every two hour slot between 8 AM and 4 PM every weekday cron = "H H(8-15)/2 * * 1-5" @@ -365,7 +365,7 @@ def test_do_convert_complex_3(self): self.assertEqual(actual, expected) - def test_do_convert_complex_4(self): + def test_do_convert_complex_4(self) -> None: # Once a day on the 1st and 15th of every month except December cron = "H H 1,15 1-11 *" diff --git a/css_to_xpath__gui/main.py b/css_to_xpath__gui/main.py index ab875202e..7a78a57ce 100644 --- a/css_to_xpath__gui/main.py +++ b/css_to_xpath__gui/main.py @@ -16,7 +16,7 @@ css_to_xpath = HTMLTranslator(xhtml=True).css_to_xpath -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -29,7 +29,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class MainWindow(Qt.QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("css_to_xpath__gui") @@ -71,7 +71,7 @@ def __init__(self): self.setLayout(layout) - def on_process(self): + def on_process(self) -> None: self.text_edit_output.clear() self.label_error.clear() self.button_detail_error.hide() @@ -100,7 +100,7 @@ def on_process(self): self.label_error.setText("Error: " + self.last_error_message) - def show_detail_error_message(self): + def show_detail_error_message(self) -> None: message = self.last_error_message + "\n\n" + self.last_detail_error_message mb = Qt.QErrorMessage() diff --git a/curtain for sleeping.py b/curtain for sleeping.py index 110281b9e..e9744f935 100644 --- a/curtain for sleeping.py +++ b/curtain for sleeping.py @@ -33,7 +33,7 @@ class CurtainWidget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Curtain for sleeping") @@ -60,10 +60,10 @@ def __init__(self): self.setMouseTracking(True) - def _activate(self, _): + def _activate(self, _) -> None: self.showFullScreen() - def showNormal(self): + def showNormal(self) -> None: self._activate_button.show() self.unsetCursor() @@ -73,7 +73,7 @@ def showNormal(self): self.setWindowFlags(self._flags) self.show() - def showFullScreen(self): + def showFullScreen(self) -> None: self._activate_button.hide() self.setCursor(Qt.BlankCursor) self._timer_block_normal.start() @@ -83,13 +83,13 @@ def showFullScreen(self): super().showFullScreen() - def mouseMoveEvent(self, event): + def mouseMoveEvent(self, event) -> None: if not self._timer_block_normal.isActive() and self.isFullScreen(): self.showNormal() super().mouseMoveEvent(event) - def paintEvent(self, event): + def paintEvent(self, event) -> None: painter = QPainter(self) painter.setBrush(Qt.black) painter.setPen(Qt.black) diff --git a/custom_with__context_manager/sqlite_execute.py b/custom_with__context_manager/sqlite_execute.py index f07f5a261..c27bb8f52 100644 --- a/custom_with__context_manager/sqlite_execute.py +++ b/custom_with__context_manager/sqlite_execute.py @@ -6,8 +6,11 @@ import sqlite3 +from types import TracebackType +from typing import Optional, Type -def old_old_variant(): + +def old_old_variant() -> None: connect = sqlite3.connect(":memory:") try: @@ -33,7 +36,7 @@ def old_old_variant(): connect.close() -def old_variant(): +def old_variant() -> None: with sqlite3.connect(":memory:") as connect: print(connect.execute("SELECT sqlite_version();").fetchone()) @@ -55,17 +58,17 @@ def old_variant(): class SQLite3Connect(object): - def __init__(self, database): + def __init__(self, database) -> None: self._connect = sqlite3.connect(database) def __enter__(self): return self._connect - def __exit__(self, exc_type, exc_value, exc_traceback): + def __exit__(self, exc_type: Optional[Type[BaseException]], exc_value: Optional[BaseException], exc_traceback: Optional[TracebackType]) -> None: self._connect.close() -def new_variant(): +def new_variant() -> None: with SQLite3Connect(":memory:") as connect: print(connect.execute("SELECT sqlite_version();").fetchone()) diff --git a/custom_with__context_manager/time_this_using_with__class.py b/custom_with__context_manager/time_this_using_with__class.py index 8eb256f73..c907ff1df 100644 --- a/custom_with__context_manager/time_this_using_with__class.py +++ b/custom_with__context_manager/time_this_using_with__class.py @@ -5,10 +5,12 @@ from timeit import default_timer +from types import TracebackType +from typing import Optional, Type class TimeThis: - def __init__(self, title: str = "TimeThis"): + def __init__(self, title: str = "TimeThis") -> None: self.title: str = title self.start_time: float = 0.0 @@ -16,7 +18,7 @@ def __enter__(self) -> "TimeThis": self.start_time = default_timer() return self - def __exit__(self, exc_type, exc_value, exc_traceback): + def __exit__(self, exc_type: Optional[Type[BaseException]], exc_value: Optional[BaseException], exc_traceback: Optional[TracebackType]) -> None: print(f"[{self.title}] total time: {default_timer() - self.start_time:.3f} sec") diff --git a/cydoomgeneric__examples/pyqt5.py b/cydoomgeneric__examples/pyqt5.py index b3e0f1c40..153a54342 100644 --- a/cydoomgeneric__examples/pyqt5.py +++ b/cydoomgeneric__examples/pyqt5.py @@ -15,7 +15,7 @@ from PyQt5.QtWidgets import QApplication, QWidget, QMessageBox -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}\n" text += "".join(traceback.format_tb(tb)) print(text) @@ -95,7 +95,7 @@ def __init__( path_wad: str, width: int, height: int, - ): + ) -> None: super().__init__() self.path_wad = path_wad @@ -109,7 +109,7 @@ def get_key(self) -> tuple[int, int] | None: key, is_pressed = KEY_PRESSED.popitem() return int(is_pressed), key - def run(self): + def run(self) -> None: cdg.init( self.width, self.height, @@ -121,7 +121,7 @@ def run(self): class WidgetDoom(QWidget): - def __init__(self, path_wad: str): + def __init__(self, path_wad: str) -> None: super().__init__() self._resx = 640 @@ -142,21 +142,21 @@ def __init__(self, path_wad: str): self.setFixedSize(self._resx, self._resy) - def draw_frame(self, pixels: np.ndarray): + def draw_frame(self, pixels: np.ndarray) -> None: self.img = numpy_array_to_QImage(pixels) self.update() - def keyPressEvent(self, event: QKeyEvent): + def keyPressEvent(self, event: QKeyEvent) -> None: key = get_key(event) if key is not None: KEY_PRESSED[key] = True - def keyReleaseEvent(self, event: QKeyEvent): + def keyReleaseEvent(self, event: QKeyEvent) -> None: key = get_key(event) if key is not None: KEY_PRESSED[key] = False - def paintEvent(self, event: QPaintEvent): + def paintEvent(self, event: QPaintEvent) -> None: if not self.img: return diff --git a/datetime_example/get_human_delta.py b/datetime_example/get_human_delta.py index 329c41b4f..d7c13c4d3 100644 --- a/datetime_example/get_human_delta.py +++ b/datetime_example/get_human_delta.py @@ -4,7 +4,7 @@ __author__ = "ipetrash" -from datetime import timedelta, datetime +from datetime import timedelta def get_human_delta(delta: timedelta) -> str: diff --git a/datetime_strptime__and__setlocale.py b/datetime_strptime__and__setlocale.py index f34d68f7f..1e69345ba 100644 --- a/datetime_strptime__and__setlocale.py +++ b/datetime_strptime__and__setlocale.py @@ -8,7 +8,7 @@ from datetime import datetime -def check(): +def check() -> None: try: print( datetime.strptime( diff --git a/delete_sublist.py b/delete_sublist.py index c2d3a32af..a8bdc3e50 100644 --- a/delete_sublist.py +++ b/delete_sublist.py @@ -25,7 +25,7 @@ def find_sublist(l, m): pass -def delete_sublist(l, m): +def delete_sublist(l, m) -> None: for i, j in find_sublist(l, m): del l[i:j] diff --git a/design_patterns__examples/Abstract Factory/example.py b/design_patterns__examples/Abstract Factory/example.py index 23ab0a200..5566162ff 100644 --- a/design_patterns__examples/Abstract Factory/example.py +++ b/design_patterns__examples/Abstract Factory/example.py @@ -40,22 +40,22 @@ def create_button(self) -> IButton: class WinLabel(ILabel): - def paint(self): + def paint(self) -> None: print("WinLabel") class OSXLabel(ILabel): - def paint(self): + def paint(self) -> None: print("OSXLabel") class WinButton(IButton): - def paint(self): + def paint(self) -> None: print("WinButton") class OSXButton(IButton): - def paint(self): + def paint(self) -> None: print("OSXButton") diff --git a/design_patterns__examples/Adapter/example__using_composition.py b/design_patterns__examples/Adapter/example__using_composition.py index d876d7176..008874430 100644 --- a/design_patterns__examples/Adapter/example__using_composition.py +++ b/design_patterns__examples/Adapter/example__using_composition.py @@ -18,17 +18,17 @@ def get_picture(self): class GameConsole: - def create_game_picture(self): + def create_game_picture(self) -> str: return "picture from console" class Antenna: - def create_wave_picture(self): + def create_wave_picture(self) -> str: return "picture from wave" class SourceGameConsoleAdapter(SourceAdapter): - def __init__(self, game_console: GameConsole): + def __init__(self, game_console: GameConsole) -> None: self.game_console = game_console def get_picture(self): @@ -36,7 +36,7 @@ def get_picture(self): class SourceAntennaAdapter(SourceAdapter): - def __init__(self, antenna: Antenna): + def __init__(self, antenna: Antenna) -> None: self.antenna = antenna def get_picture(self): @@ -44,7 +44,7 @@ def get_picture(self): class TV: - def __init__(self, source: SourceAdapter): + def __init__(self, source: SourceAdapter) -> None: self.source = source def show_picture(self): diff --git a/design_patterns__examples/Adapter/example__using_inheritance.py b/design_patterns__examples/Adapter/example__using_inheritance.py index 6caaa7d33..6fff68655 100644 --- a/design_patterns__examples/Adapter/example__using_inheritance.py +++ b/design_patterns__examples/Adapter/example__using_inheritance.py @@ -18,12 +18,12 @@ def get_picture(self): class GameConsole: - def create_game_picture(self): + def create_game_picture(self) -> str: return "picture from console" class Antenna: - def create_wave_picture(self): + def create_wave_picture(self) -> str: return "picture from wave" @@ -38,7 +38,7 @@ def get_picture(self): class TV: - def __init__(self, source: SourceAdapter): + def __init__(self, source: SourceAdapter) -> None: self.source = source def show_picture(self): diff --git a/design_patterns__examples/Bridge/example_1/devices/radio.py b/design_patterns__examples/Bridge/example_1/devices/radio.py index 0dfa9888a..d639c3eba 100644 --- a/design_patterns__examples/Bridge/example_1/devices/radio.py +++ b/design_patterns__examples/Bridge/example_1/devices/radio.py @@ -8,7 +8,7 @@ class Radio(Device): - def __init__(self): + def __init__(self) -> None: self._on = False self._volume = 30 self._channel = 1 @@ -16,16 +16,16 @@ def __init__(self): def is_enabled(self) -> bool: return self._on - def enable(self): + def enable(self) -> None: self._on = True - def disable(self): + def disable(self) -> None: self._on = False def get_volume(self) -> int: return self._volume - def set_volume(self, volume: int): + def set_volume(self, volume: int) -> None: if volume > 100: self._volume = 100 elif volume < 0: @@ -36,10 +36,10 @@ def set_volume(self, volume: int): def get_channel(self) -> int: return self._channel - def set_channel(self, channel: int): + def set_channel(self, channel: int) -> None: self._channel = channel - def print_status(self): + def print_status(self) -> None: print("------------------------------------") print("| I'm radio.") print("| I'm " + ("enabled" if self._on else "disabled")) diff --git a/design_patterns__examples/Bridge/example_1/devices/tv.py b/design_patterns__examples/Bridge/example_1/devices/tv.py index fc884e464..5adfc0437 100644 --- a/design_patterns__examples/Bridge/example_1/devices/tv.py +++ b/design_patterns__examples/Bridge/example_1/devices/tv.py @@ -8,7 +8,7 @@ class Tv(Device): - def __init__(self): + def __init__(self) -> None: self._on = False self._volume = 30 self._channel = 1 @@ -16,16 +16,16 @@ def __init__(self): def is_enabled(self) -> bool: return self._on - def enable(self): + def enable(self) -> None: self._on = True - def disable(self): + def disable(self) -> None: self._on = False def get_volume(self) -> int: return self._volume - def set_volume(self, volume: int): + def set_volume(self, volume: int) -> None: if volume > 100: self._volume = 100 elif volume < 0: @@ -36,10 +36,10 @@ def set_volume(self, volume: int): def get_channel(self) -> int: return self._channel - def set_channel(self, channel: int): + def set_channel(self, channel: int) -> None: self._channel = channel - def print_status(self): + def print_status(self) -> None: print("------------------------------------") print("| I'm TV set.") print("| I'm " + ("enabled" if self._on else "disabled")) diff --git a/design_patterns__examples/Bridge/example_1/main.py b/design_patterns__examples/Bridge/example_1/main.py index 53354a257..745a2a1f5 100644 --- a/design_patterns__examples/Bridge/example_1/main.py +++ b/design_patterns__examples/Bridge/example_1/main.py @@ -17,7 +17,7 @@ from remotes.advanced_remote import AdvancedRemote -def test_device(device): +def test_device(device) -> None: print("Tests with basic remote.") basic_remote = BasicRemote(device) basic_remote.power() diff --git a/design_patterns__examples/Bridge/example_1/remotes/advanced_remote.py b/design_patterns__examples/Bridge/example_1/remotes/advanced_remote.py index ef84acb61..c0367b280 100644 --- a/design_patterns__examples/Bridge/example_1/remotes/advanced_remote.py +++ b/design_patterns__examples/Bridge/example_1/remotes/advanced_remote.py @@ -10,6 +10,6 @@ class AdvancedRemote(BasicRemote): """Улучшенный пульт""" - def mute(self): + def mute(self) -> None: print("Remote: mute") self._device.set_volume(0) diff --git a/design_patterns__examples/Bridge/example_1/remotes/basic_remote.py b/design_patterns__examples/Bridge/example_1/remotes/basic_remote.py index 8c6bf5385..80b681269 100644 --- a/design_patterns__examples/Bridge/example_1/remotes/basic_remote.py +++ b/design_patterns__examples/Bridge/example_1/remotes/basic_remote.py @@ -11,28 +11,28 @@ class BasicRemote(Remote): """Стандартный пульт""" - def __init__(self, device: Device): + def __init__(self, device: Device) -> None: self._device = device - def power(self): + def power(self) -> None: print("Remote: power toggle") if self._device.is_enabled(): self._device.disable() else: self._device.enable() - def volume_down(self): + def volume_down(self) -> None: print("Remote: volume down") self._device.set_volume(self._device.get_volume() - 10) - def volume_up(self): + def volume_up(self) -> None: print("Remote: volume up") self._device.set_volume(self._device.get_volume() + 10) - def channel_down(self): + def channel_down(self) -> None: print("Remote: channel down") self._device.set_channel(self._device.get_channel() - 1) - def channel_up(self): + def channel_up(self) -> None: print("Remote: channel up") self._device.set_channel(self._device.get_channel() + 1) diff --git a/design_patterns__examples/Bridge/example_2.py b/design_patterns__examples/Bridge/example_2.py index 223c133e9..3e2248dd7 100644 --- a/design_patterns__examples/Bridge/example_2.py +++ b/design_patterns__examples/Bridge/example_2.py @@ -20,7 +20,7 @@ def draw_circle(self, x: int, y: int, radius: int): class SmallCircleDrawer(Drawer): RADIUS_MULTIPLIER = 0.25 - def draw_circle(self, x: int, y: int, radius: int): + def draw_circle(self, x: int, y: int, radius: int) -> None: print( f"Small circle center = {x},{y} radius = {radius * self.RADIUS_MULTIPLIER}" ) @@ -29,37 +29,37 @@ def draw_circle(self, x: int, y: int, radius: int): class LargeCircleDrawer(Drawer): RADIUS_MULTIPLIER = 10 - def draw_circle(self, x: int, y: int, radius: int): + def draw_circle(self, x: int, y: int, radius: int) -> None: print( f"Large circle center = {x},{y} radius = {radius * self.RADIUS_MULTIPLIER}" ) class Shape(ABC): - def __init__(self, drawer: Drawer): + def __init__(self, drawer: Drawer) -> None: self._drawer = drawer @abstractmethod - def draw(self): + def draw(self) -> None: pass @abstractmethod - def enlarge_radius(self, multiplier: int): + def enlarge_radius(self, multiplier: int) -> None: pass class Circle(Shape): - def __init__(self, x: int, y: int, radius: int, drawer: Drawer): + def __init__(self, x: int, y: int, radius: int, drawer: Drawer) -> None: super().__init__(drawer) self._x = x self._y = y self._radius = radius - def draw(self): + def draw(self) -> None: self._drawer.draw_circle(self._x, self._y, self._radius) - def enlarge_radius(self, multiplier: int): + def enlarge_radius(self, multiplier: int) -> None: self._radius *= multiplier def get_x(self) -> int: @@ -71,13 +71,13 @@ def get_y(self) -> int: def get_radius(self) -> int: return self._radius - def set_x(self, x: int): + def set_x(self, x: int) -> None: self._x = x - def set_y(self, y: int): + def set_y(self, y: int) -> None: self._y = y - def set_radius(self, radius: int): + def set_radius(self, radius: int) -> None: self._radius = radius diff --git a/design_patterns__examples/Builder/example.py b/design_patterns__examples/Builder/example.py index 549cd2c36..ea97765c8 100644 --- a/design_patterns__examples/Builder/example.py +++ b/design_patterns__examples/Builder/example.py @@ -13,84 +13,84 @@ # "Product" class Pizza: - def __init__(self): + def __init__(self) -> None: self._dough = "" self._sauce = "" self._topping = "" - def set_dough(self, dough: str): + def set_dough(self, dough: str) -> None: self._dough = dough - def set_sauce(self, sauce: str): + def set_sauce(self, sauce: str) -> None: self._sauce = sauce - def set_topping(self, topping: str): + def set_topping(self, topping: str) -> None: self._topping = topping - def __str__(self): + def __str__(self) -> str: return f'Pizza(dough="{self._dough}, sauce="{self._sauce}, topping="{self._topping}")' # "Abstract Builder" class PizzaBuilder(ABC): - def __init__(self): + def __init__(self) -> None: self._pizza = None def get_pizza(self) -> Pizza: return self._pizza - def create_new_pizza_product(self): + def create_new_pizza_product(self) -> None: self._pizza = Pizza() @abstractmethod - def build_dough(self): + def build_dough(self) -> None: pass @abstractmethod - def build_sauce(self): + def build_sauce(self) -> None: pass @abstractmethod - def build_topping(self): + def build_topping(self) -> None: pass # "ConcreteBuilder" class HawaiianPizzaBuilder(PizzaBuilder): - def build_dough(self): + def build_dough(self) -> None: self._pizza.set_dough("cross") - def build_sauce(self): + def build_sauce(self) -> None: self._pizza.set_sauce("mild") - def build_topping(self): + def build_topping(self) -> None: self._pizza.set_topping("ham+pineapple") # "ConcreteBuilder" class SpicyPizzaBuilder(PizzaBuilder): - def build_dough(self): + def build_dough(self) -> None: self._pizza.set_dough("pan baked") - def build_sauce(self): + def build_sauce(self) -> None: self._pizza.set_sauce("hot") - def build_topping(self): + def build_topping(self) -> None: self._pizza.set_topping("pepperoni+salami") # "Director" class Waiter: - def __init__(self): + def __init__(self) -> None: self.pizza_builder = None - def set_pizza_builder(self, pb: PizzaBuilder): + def set_pizza_builder(self, pb: PizzaBuilder) -> None: self.pizza_builder = pb def get_pizza(self) -> Pizza: return self.pizza_builder.get_pizza() - def construct_pizza(self): + def construct_pizza(self) -> None: self.pizza_builder.create_new_pizza_product() self.pizza_builder.build_dough() self.pizza_builder.build_sauce() diff --git a/design_patterns__examples/Builder/example2.py b/design_patterns__examples/Builder/example2.py index f7b067050..9acb0c03d 100644 --- a/design_patterns__examples/Builder/example2.py +++ b/design_patterns__examples/Builder/example2.py @@ -4,27 +4,30 @@ __author__ = "ipetrash" +from typing import Any, Self + + class Foo: - def __init__(self): + def __init__(self) -> None: self.items = [] self.key_by_value = dict() - def add_item(self, value): + def add_item(self, value) -> Self: self.items.append(value) return self - def add_items(self, values): + def add_items(self, values) -> Self: self.items += values return self - def set_value(self, key, value): + def set_value(self, key, value) -> Self: self.key_by_value[key] = value return self - def get_value(self, key): + def get_value(self, key) -> Any: return self.key_by_value[key] - def __repr__(self): + def __repr__(self) -> str: return f"Foo" diff --git a/design_patterns__examples/Builder/example_wok.py b/design_patterns__examples/Builder/example_wok.py index 4dae818e4..45e91d4f3 100644 --- a/design_patterns__examples/Builder/example_wok.py +++ b/design_patterns__examples/Builder/example_wok.py @@ -149,7 +149,7 @@ class Wok: sauce_additional: WokSauce = None topping: List[WokTopping] = None - def __init__(self): + def __init__(self) -> None: self.topping = [] def get_order_text(self) -> str: @@ -187,7 +187,7 @@ def get_order_weight(self) -> int: return sum(x.weight for x in self.get_order_items()) class Builder: - def __init__(self): + def __init__(self) -> None: self.wok = Wok() def set_base(self, base: WokBase) -> "Builder": diff --git a/design_patterns__examples/Chain of responsibility/example_1.py b/design_patterns__examples/Chain of responsibility/example_1.py index 45cfa0b43..388756434 100644 --- a/design_patterns__examples/Chain of responsibility/example_1.py +++ b/design_patterns__examples/Chain of responsibility/example_1.py @@ -25,10 +25,10 @@ def set_next(self, handler: "Handler") -> "Handler": return self._next_handler @abstractmethod - def handle(self, obj): + def handle(self, obj) -> None: pass - def next_handle(self, obj): + def next_handle(self, obj) -> None: # Вызываем следующий обработки if self._next_handler: self._next_handler.handle(obj) @@ -43,7 +43,7 @@ def handle(self, obj): class IsNotStringHandler(Handler): - def handle(self, obj): + def handle(self, obj) -> None: if type(obj) != str: raise Exception(f"Object {repr(obj)} is not string!") @@ -51,10 +51,10 @@ def handle(self, obj): class IsNotMatchReHandler(Handler): - def __init__(self, re_pattern: str): + def __init__(self, re_pattern: str) -> None: self._re_pattern = re_pattern - def handle(self, obj): + def handle(self, obj) -> None: if not re.search(self._re_pattern, obj): raise Exception( f'String {repr(obj)} is not matching by regexp: "{self._re_pattern}"!' @@ -64,7 +64,7 @@ def handle(self, obj): if __name__ == "__main__": - def client_code(handler: Handler): + def client_code(handler: Handler) -> None: for obj in [None, "123", "456", "111", 456]: print(f"Object {repr(obj)} is ", end="") diff --git a/design_patterns__examples/Chain of responsibility/example_2.py b/design_patterns__examples/Chain of responsibility/example_2.py index 63e6002bc..b1b310fe3 100644 --- a/design_patterns__examples/Chain of responsibility/example_2.py +++ b/design_patterns__examples/Chain of responsibility/example_2.py @@ -10,39 +10,39 @@ class Car: - def __init__(self): + def __init__(self) -> None: self.name = None self.km = 11100 self.fuel = 5 self.oil = 5 -def handle_fuel(car): +def handle_fuel(car) -> None: if car.fuel < 10: print("Added fuel") car.fuel = 100 -def handle_km(car): +def handle_km(car) -> None: if car.km > 10000: print("Made a car test.") car.km = 0 -def handle_oil(car): +def handle_oil(car) -> None: if car.oil < 10: print("Added oil") car.oil = 100 class Garage: - def __init__(self): + def __init__(self) -> None: self.handlers = [] - def add_handler(self, handler): + def add_handler(self, handler) -> None: self.handlers.append(handler) - def handle_car(self, car): + def handle_car(self, car) -> None: for handler in self.handlers: handler(car) diff --git a/design_patterns__examples/Chain of responsibility/example_3.py b/design_patterns__examples/Chain of responsibility/example_3.py index 1ef248c00..7b6461f84 100644 --- a/design_patterns__examples/Chain of responsibility/example_3.py +++ b/design_patterns__examples/Chain of responsibility/example_3.py @@ -38,7 +38,7 @@ class Logger(ABC): Abstract handler in chain of responsibility pattern. """ - def __init__(self, levels: List[LogLevel]): + def __init__(self, levels: List[LogLevel]) -> None: """ Initialize new logger @@ -62,7 +62,7 @@ def set_next(self, next_logger: "Logger") -> "Logger": self._next = next_logger return self._next - def message(self, msg: str, severity: LogLevel): + def message(self, msg: str, severity: LogLevel) -> None: """ Message writer handler. @@ -91,7 +91,7 @@ def write_message(self, msg: str): class ConsoleLogger(Logger): - def write_message(self, msg: str): + def write_message(self, msg: str) -> None: """ Overrides parent's abstract method to write to console. @@ -109,7 +109,7 @@ class EmailLogger(Logger): msg (str): Message string. """ - def write_message(self, msg: str): + def write_message(self, msg: str) -> None: print("Sending via email:", msg) @@ -121,11 +121,11 @@ class FileLogger(Logger): msg (str): Message string. """ - def write_message(self, msg: str): + def write_message(self, msg: str) -> None: print("Writing to log file:", msg) -def main(): +def main() -> None: """ Building the chain of responsibility. """ diff --git a/design_patterns__examples/Chain of responsibility/example_4.py b/design_patterns__examples/Chain of responsibility/example_4.py index c02b511ea..4e1f86e83 100644 --- a/design_patterns__examples/Chain of responsibility/example_4.py +++ b/design_patterns__examples/Chain of responsibility/example_4.py @@ -14,7 +14,7 @@ # Вспомогательный класс, описывающий некоторое преступление class CriminalAction: - def __init__(self, complexity: int, description: str): + def __init__(self, complexity: int, description: str) -> None: # Сложность дела self.complexity = complexity @@ -24,7 +24,7 @@ def __init__(self, complexity: int, description: str): # Абстрактный полицейский, который может заниматься расследованием преступлений class Policeman(ABC): - def __init__(self, deduction: int): + def __init__(self, deduction: int) -> None: # Дедукция (умение распутывать сложные дела) у данного полицейского self.deduction = deduction @@ -43,7 +43,7 @@ def set_next(self, policeman: "Policeman") -> "Policeman": return self.next # Полицейский начинает расследование или, если дело слишком сложное, передает ее более опытному коллеге - def investigate(self, criminal_action: CriminalAction): + def investigate(self, criminal_action: CriminalAction) -> None: if self.deduction < criminal_action.complexity: if self.next: self.next.investigate(criminal_action) @@ -55,19 +55,19 @@ def investigate(self, criminal_action: CriminalAction): class MartinRiggs(Policeman): - def _investigate_сoncrete(self, description: str): + def _investigate_сoncrete(self, description: str) -> None: print('Расследование по делу "' + description + '" ведет сержант Мартин Риггс') class JohnMcClane(Policeman): - def _investigate_сoncrete(self, description: str): + def _investigate_сoncrete(self, description: str) -> None: print( 'Расследование по делу "' + description + '" ведет детектив Джон Макклейн' ) class VincentHanna(Policeman): - def _investigate_сoncrete(self, description: str): + def _investigate_сoncrete(self, description: str) -> None: print( 'Расследование по делу "' + description + '" ведет лейтенант Винсент Ханна' ) diff --git a/design_patterns__examples/Chain of responsibility/example_6.py b/design_patterns__examples/Chain of responsibility/example_6.py index a1544e3d4..0b5be3e07 100644 --- a/design_patterns__examples/Chain of responsibility/example_6.py +++ b/design_patterns__examples/Chain of responsibility/example_6.py @@ -20,7 +20,7 @@ def get_timestamp() -> int: # Базовый класс цепочки. class Middleware(ABC): - def __init__(self): + def __init__(self) -> None: self._next: "Middleware" = None # Помогает строить цепь из объектов-проверок. @@ -44,7 +44,7 @@ def _check_next(self, email: str, password: str) -> bool: # Конкретный элемент цепи обрабатывает запрос по-своему. class ThrottlingMiddleware(Middleware): - def __init__(self, request_per_minute: int): + def __init__(self, request_per_minute: int) -> None: super().__init__() self._request: int = 0 @@ -72,7 +72,7 @@ def check(self, email: str, password: str) -> bool: # Конкретный элемент цепи обрабатывает запрос по-своему. class UserExistsMiddleware(Middleware): - def __init__(self, server: "Server"): + def __init__(self, server: "Server") -> None: super().__init__() self._server: Server = server @@ -102,13 +102,13 @@ def check(self, email: str, password: str) -> bool: # Класс сервера. class Server: - def __init__(self): + def __init__(self) -> None: self._users: Dict[str, str] = dict() self._middleware: Middleware = None # Клиент подаёт готовую цепочку в сервер. Это увеличивает гибкость и # упрощает тестирование класса сервера. - def set_middleware(self, middleware: Middleware): + def set_middleware(self, middleware: Middleware) -> None: self._middleware = middleware # Сервер получает email и пароль от клиента и запускает проверку @@ -123,7 +123,7 @@ def log_in(self, email: str, password: str) -> bool: return False - def register(self, email: str, password: str): + def register(self, email: str, password: str) -> None: self._users[email] = password def has_email(self, email: str) -> bool: diff --git a/design_patterns__examples/Command/example.py b/design_patterns__examples/Command/example.py index 866378b56..e21d52dd6 100644 --- a/design_patterns__examples/Command/example.py +++ b/design_patterns__examples/Command/example.py @@ -19,34 +19,34 @@ def execute(self): class Car: - def start_engine(self): + def start_engine(self) -> None: print("Запустить двигатель") - def stop_engine(self): + def stop_engine(self) -> None: print("Остановить двигатель") class StartCar(Command): - def __init__(self, car: Car): + def __init__(self, car: Car) -> None: self.car: Car = car - def execute(self): + def execute(self) -> None: self.car.start_engine() class StopCar(Command): - def __init__(self, car: Car): + def __init__(self, car: Car) -> None: self.car: Car = car - def execute(self): + def execute(self) -> None: self.car.stop_engine() class CarInvoker: - def __init__(self, command: Command): + def __init__(self, command: Command) -> None: self.command: Command = command - def execute(self): + def execute(self) -> None: self.command.execute() diff --git a/design_patterns__examples/Composite/example.py b/design_patterns__examples/Composite/example.py index 53e69a2e5..0c3b6fc2c 100644 --- a/design_patterns__examples/Composite/example.py +++ b/design_patterns__examples/Composite/example.py @@ -19,65 +19,65 @@ def draw(self, *args, **kwargs): class CompositeGraphic(Graphic): - def __init__(self): + def __init__(self) -> None: self._child_graphics: List[Graphic] = [] - def draw(self, *args, **kwargs): + def draw(self, *args, **kwargs) -> None: for graphic in self._child_graphics: graphic.draw(*args, **kwargs) # Adds the graphic to the composition - def add(self, graphic: Graphic): + def add(self, graphic: Graphic) -> None: if graphic in self._child_graphics: return self._child_graphics.append(graphic) # Removes the graphic from the composition - def remove(self, graphic: Graphic): + def remove(self, graphic: Graphic) -> None: self._child_graphics.remove(graphic) class Ellipse(Graphic): - def __init__(self, x, y, rx, ry): + def __init__(self, x, y, rx, ry) -> None: self.x = x self.y = y self.rx = rx self.ry = ry - def draw(self, *args, **kwargs): + def draw(self, *args, **kwargs) -> None: print(f"Ellipse: x={self.x}, y={self.y}, rx={self.rx}, ry={self.ry}") class Point(Graphic): - def __init__(self, x, y): + def __init__(self, x, y) -> None: self.x = x self.y = y - def draw(self, *args, **kwargs): + def draw(self, *args, **kwargs) -> None: print(f"Point: x={self.x}, y={self.y}") class Rect(Graphic): - def __init__(self, x, y, w, h): + def __init__(self, x, y, w, h) -> None: self.x = x self.y = y self.w = w self.h = h - def draw(self, *args, **kwargs): + def draw(self, *args, **kwargs) -> None: print(f"Rect: x={self.x}, y={self.y}, w={self.w}, h={self.h}") class Line(Graphic): - def __init__(self, x1, y1, x2, y2): + def __init__(self, x1, y1, x2, y2) -> None: self.x1 = x1 self.y1 = y1 self.x2 = x2 self.y2 = y2 - def draw(self, *args, **kwargs): + def draw(self, *args, **kwargs) -> None: print(f"Line: x1={self.x1}, y1={self.y1}, x2={self.x2}, y2={self.y2}") diff --git a/design_patterns__examples/Composite/example__pyqt_draw.py b/design_patterns__examples/Composite/example__pyqt_draw.py index 35022ecef..a9e97de75 100644 --- a/design_patterns__examples/Composite/example__pyqt_draw.py +++ b/design_patterns__examples/Composite/example__pyqt_draw.py @@ -17,7 +17,7 @@ from PyQt5.Qt import * -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -31,82 +31,82 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class Graphic(ABC): @abstractmethod - def draw(self, painter: QPainter): + def draw(self, painter: QPainter) -> None: pass class CompositeGraphic(Graphic): - def __init__(self): + def __init__(self) -> None: self._child_graphics: List[Graphic] = [] - def draw(self, painter: QPainter): + def draw(self, painter: QPainter) -> None: for graphic in self._child_graphics: graphic.draw(painter) # Adds the graphic to the composition - def add(self, graphic: Graphic): + def add(self, graphic: Graphic) -> None: if graphic in self._child_graphics: return self._child_graphics.append(graphic) # Removes the graphic from the composition - def remove(self, graphic: Graphic): + def remove(self, graphic: Graphic) -> None: self._child_graphics.remove(graphic) class Ellipse(Graphic): - def __init__(self, x, y, rx, ry): + def __init__(self, x, y, rx, ry) -> None: self.x = x self.y = y self.rx = rx self.ry = ry - def draw(self, painter: QPainter): + def draw(self, painter: QPainter) -> None: painter.drawEllipse(self.x, self.y, self.rx, self.ry) class Point(Graphic): - def __init__(self, x, y): + def __init__(self, x, y) -> None: self.x = x self.y = y - def draw(self, painter: QPainter): + def draw(self, painter: QPainter) -> None: painter.drawPoint(self.x, self.y) class Rect(Graphic): - def __init__(self, x, y, w, h): + def __init__(self, x, y, w, h) -> None: self.x = x self.y = y self.w = w self.h = h - def draw(self, painter: QPainter): + def draw(self, painter: QPainter) -> None: painter.drawRect(self.x, self.y, self.w, self.h) class Line(Graphic): - def __init__(self, x1, y1, x2, y2): + def __init__(self, x1, y1, x2, y2) -> None: self.x1 = x1 self.y1 = y1 self.x2 = x2 self.y2 = y2 - def draw(self, painter: QPainter): + def draw(self, painter: QPainter) -> None: painter.drawLine(self.x1, self.y1, self.x2, self.y2) class CanvasWidget(QWidget): - def __init__(self, graphic: Graphic): + def __init__(self, graphic: Graphic) -> None: super().__init__() self.setWindowTitle("Canvas") self.graphic = graphic - def paintEvent(self, event): + def paintEvent(self, event) -> None: painter = QPainter(self) painter.setBrush(Qt.green) diff --git a/design_patterns__examples/Decorator/example_1.py b/design_patterns__examples/Decorator/example_1.py index 8fd09366a..12edf7a6f 100644 --- a/design_patterns__examples/Decorator/example_1.py +++ b/design_patterns__examples/Decorator/example_1.py @@ -23,7 +23,7 @@ def run(self, text: str) -> str: class BaseDecorator(IOperation): - def __init__(self, operation: IOperation): + def __init__(self, operation: IOperation) -> None: self._wrapped = operation diff --git a/design_patterns__examples/Decorator/example_2.py b/design_patterns__examples/Decorator/example_2.py index ff6c8f878..87a965c17 100644 --- a/design_patterns__examples/Decorator/example_2.py +++ b/design_patterns__examples/Decorator/example_2.py @@ -10,44 +10,44 @@ class Notifier: - def send(self, message: str): + def send(self, message: str) -> None: print(f'[Email] Send "{message}".') class BaseDecorator(Notifier): - def __init__(self, notifier: Notifier): + def __init__(self, notifier: Notifier) -> None: self._wrapped = notifier class SMSDecorator(BaseDecorator): - def send(self, message: str): + def send(self, message: str) -> None: self._wrapped.send(message) print(f'[SMS] send "{message}".') class FacebookDecorator(BaseDecorator): - def send(self, message: str): + def send(self, message: str) -> None: self._wrapped.send(message) print(f'[Facebook] send "{message}".') class SlackDecorator(BaseDecorator): - def send(self, message: str): + def send(self, message: str) -> None: self._wrapped.send(message) print(f'[Slack] send "{message}".') class Application: - def __init__(self): + def __init__(self) -> None: self._notifier: Notifier = None - def set_notifier(self, notifier: Notifier): + def set_notifier(self, notifier: Notifier) -> None: self._notifier = notifier - def about_alert(self): + def about_alert(self) -> None: if self._notifier: self._notifier.send("Alert!") diff --git a/design_patterns__examples/Facade/example_1.py b/design_patterns__examples/Facade/example_1.py index 4a120dc39..9142444d4 100644 --- a/design_patterns__examples/Facade/example_1.py +++ b/design_patterns__examples/Facade/example_1.py @@ -15,13 +15,13 @@ # Class CPU, отвечает за работу процессора class CPU: - def freeze(self): + def freeze(self) -> None: pass - def jump(self, position: int): + def jump(self, position: int) -> None: pass - def execute(self): + def execute(self) -> None: pass @@ -29,7 +29,7 @@ def execute(self): class Memory: BOOT_ADDRESS = 0x0005 - def load(self, position: int, data: bytes): + def load(self, position: int, data: bytes) -> None: pass @@ -46,13 +46,13 @@ def read(self, lba: int, size: int) -> bytes: # В качестве унифицированного объекта выступает Компьютер. # За этим объектом будут скрыты, все детали работы его внутренних частей. class Computer: - def __init__(self): + def __init__(self) -> None: self._cpu = CPU() self._memory = Memory() self._hard_drive = HardDrive() # Упрощённая обработка поведения "запуск компьютера" - def start_computer(self): + def start_computer(self) -> None: self._cpu.freeze() self._memory.load( self._memory.BOOT_ADDRESS, diff --git a/design_patterns__examples/Facade/example_3.py b/design_patterns__examples/Facade/example_3.py index a4826d882..468c49830 100644 --- a/design_patterns__examples/Facade/example_3.py +++ b/design_patterns__examples/Facade/example_3.py @@ -14,67 +14,67 @@ # Абстрактный музыкант - не является обязательной составляющей паттерна, введен для упрощения кода class Musician(ABC): - def __init__(self, name: str): + def __init__(self, name: str) -> None: self.name = name - def output(self, text: str): + def output(self, text: str) -> None: print(self.name + " " + text + ".") # Конкретные музыканты class Vocalist(Musician): - def sing_couplet(self, couplet_number: int): + def sing_couplet(self, couplet_number: int) -> None: self.output("спел куплет №" + str(couplet_number)) - def sing_chorus(self): + def sing_chorus(self) -> None: self.output("спел припев") class Guitarist(Musician): - def play_cool_opening(self): + def play_cool_opening(self) -> None: self.output("начинает с крутого вступления") - def play_cool_riffs(self): + def play_cool_riffs(self) -> None: self.output("играет крутые риффы") - def play_another_cool_riffs(self): + def play_another_cool_riffs(self) -> None: self.output("играет другие крутые риффы") - def play_incredibly_cool_solo(self): + def play_incredibly_cool_solo(self) -> None: self.output("выдает невероятно крутое соло") - def play_final_accord(self): + def play_final_accord(self) -> None: self.output("заканчивает песню мощным аккордом") class Bassist(Musician): - def follow_the_drums(self): + def follow_the_drums(self) -> None: self.output("следует за барабанами") - def change_rhythm(self, type_rhythm: str): + def change_rhythm(self, type_rhythm: str) -> None: self.output("перешел на ритм " + type_rhythm + "a") - def stop_playing(self): + def stop_playing(self) -> None: self.output("заканчивает играть") class Drummer(Musician): - def start_playing(self): + def start_playing(self) -> None: self.output("начинает играть") - def stop_playing(self): + def stop_playing(self) -> None: self.output("заканчивает играть") # Фасад, в данном случае - знаменитая рок-группа class BlackSabbath: - def __init__(self): + def __init__(self) -> None: self.vocalist = Vocalist("Оззи Осборн") self.guitarist = Guitarist("Тони Айомми") self.bassist = Bassist("Гизер Батлер") self.drummer = Drummer("Билл Уорд") - def play_cool_song(self): + def play_cool_song(self) -> None: self.guitarist.play_cool_opening() self.drummer.start_playing() self.bassist.follow_the_drums() diff --git a/design_patterns__examples/Factory/example_2.py b/design_patterns__examples/Factory/example_2.py index b6551353a..ae56828b1 100644 --- a/design_patterns__examples/Factory/example_2.py +++ b/design_patterns__examples/Factory/example_2.py @@ -21,17 +21,17 @@ def initial(animal: str) -> "Animal": raise Exception(f'Unsupported animal "{animal}"') @abstractmethod - def voice(self): + def voice(self) -> None: pass class Lion(Animal): - def voice(self): + def voice(self) -> None: print("Rrrrrrrr i'm the lion") class Cat(Animal): - def voice(self): + def voice(self) -> None: print("Meow, meow i'm the kitty") diff --git a/design_patterns__examples/Flyweight/example_1.py b/design_patterns__examples/Flyweight/example_1.py index 6384760aa..5f91166f1 100644 --- a/design_patterns__examples/Flyweight/example_1.py +++ b/design_patterns__examples/Flyweight/example_1.py @@ -12,16 +12,16 @@ class Flyweight: - def __init__(self, row: int): + def __init__(self, row: int) -> None: self.row = row print("ctor:", self.row) - def report(self, col: int): + def report(self, col: int) -> None: print(f" {self.row}{col}", end="") class Factory: - def __init__(self, max_rows: int): + def __init__(self, max_rows: int) -> None: self._pool: list[Flyweight | None] = [None] * max_rows def get_flyweight(self, row: int) -> Flyweight: diff --git a/design_patterns__examples/Flyweight/example_2.py b/design_patterns__examples/Flyweight/example_2.py index 809e30af4..f945f6de2 100644 --- a/design_patterns__examples/Flyweight/example_2.py +++ b/design_patterns__examples/Flyweight/example_2.py @@ -20,14 +20,14 @@ class Character(ABC): descent: int point_size: int - def display(self, point_size: int): + def display(self, point_size: int) -> None: self.point_size = point_size print(f"{self.symbol} (point_size {self.point_size})") # "FlyweightFactory" class CharacterFactory: - def __init__(self): + def __init__(self) -> None: self._characters: dict[str, Character] = dict() def get_character(self, key: str) -> Character: @@ -52,7 +52,7 @@ def get_character(self, key: str) -> Character: # "ConcreteFlyweight" class CharacterA(Character): - def __init__(self): + def __init__(self) -> None: self.symbol = "A" self.height = 100 self.width = 120 @@ -62,7 +62,7 @@ def __init__(self): # "ConcreteFlyweight" class CharacterB(Character): - def __init__(self): + def __init__(self) -> None: self.symbol = "B" self.height = 100 self.width = 140 @@ -75,7 +75,7 @@ def __init__(self): # "ConcreteFlyweight" class CharacterZ(Character): - def __init__(self): + def __init__(self) -> None: self.symbol = "Z" self.height = 100 self.width = 100 diff --git a/design_patterns__examples/Mediator/example_1.py b/design_patterns__examples/Mediator/example_1.py index 5ad6c2649..2309230b6 100644 --- a/design_patterns__examples/Mediator/example_1.py +++ b/design_patterns__examples/Mediator/example_1.py @@ -28,13 +28,13 @@ def notify(self, sender: object, event: str): # Конкретные Посредники реализуют совместное поведение, координируя отдельные компоненты. class ConcreteMediator(IMediator): - def __init__(self, component1, component2): + def __init__(self, component1, component2) -> None: self._component1 = component1 self._component1.set_mediator(self) self._component2 = component2 self._component2.set_mediator(self) - def notify(self, sender: object, event: str): + def notify(self, sender: object, event: str) -> None: print(f'[+] Mediator notify(sender={sender}, event="{event}")') if event == "A": @@ -57,31 +57,31 @@ class BaseComponent(ABC): посредника внутри объектов компонентов. """ - def __init__(self, mediator: IMediator = None): + def __init__(self, mediator: IMediator = None) -> None: self._mediator = mediator - def set_mediator(self, mediator: IMediator): + def set_mediator(self, mediator: IMediator) -> None: self._mediator = mediator # Конкретные Компоненты реализуют различную функциональность. Они не зависят от других # компонентов. Они также не зависят от каких-либо конкретных классов посредников. class Component1(BaseComponent): - def do_a(self): + def do_a(self) -> None: print("Component 1 does A.") self._mediator.notify(self, "A") - def do_b(self): + def do_b(self) -> None: print("Component 1 does B.") self._mediator.notify(self, "B") class Component2(BaseComponent): - def do_c(self): + def do_c(self) -> None: print("Component 2 does C.") self._mediator.notify(self, "C") - def do_d(self): + def do_d(self) -> None: print("Component 2 does D.") self._mediator.notify(self, "D") diff --git a/design_patterns__examples/Mediator/example_2.py b/design_patterns__examples/Mediator/example_2.py index 81ec8852c..f0ccd146b 100644 --- a/design_patterns__examples/Mediator/example_2.py +++ b/design_patterns__examples/Mediator/example_2.py @@ -11,15 +11,15 @@ class Mediator: @staticmethod - def send_message(user: "User", msg: str): + def send_message(user: "User", msg: str) -> None: print(f"{user.name}: {msg}") class User: - def __init__(self, name: str): + def __init__(self, name: str) -> None: self.name = name - def send_message(self, msg: str): + def send_message(self, msg: str) -> None: Mediator.send_message(self, msg) diff --git a/design_patterns__examples/Mediator/example_notes__pyqt.py b/design_patterns__examples/Mediator/example_notes__pyqt.py index 364fcec13..e0facea05 100644 --- a/design_patterns__examples/Mediator/example_notes__pyqt.py +++ b/design_patterns__examples/Mediator/example_notes__pyqt.py @@ -30,7 +30,7 @@ from PySide.QtCore import * -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -44,14 +44,14 @@ def log_uncaught_exceptions(ex_cls, ex, tb): # Класс заметок class Note: - def __init__(self): + def __init__(self) -> None: self._name = "note" self._text = "" - def setName(self, name: str): + def setName(self, name: str) -> None: self._name = name - def setText(self, text: str): + def setText(self, text: str) -> None: self._text = text def getName(self) -> str: @@ -62,12 +62,12 @@ def getText(self) -> str: class DefaultListModel(QAbstractListModel): - def __init__(self): + def __init__(self) -> None: super().__init__() self.items: list[Note] = [] - def rowCount(self, parent: QModelIndex = None): + def rowCount(self, parent: QModelIndex = None) -> int: return len(self.items) def data(self, index: QModelIndex, role: int = Qt.DisplayRole) -> Any: @@ -84,7 +84,7 @@ def data(self, index: QModelIndex, role: int = Qt.DisplayRole) -> Any: def get_element(self, index: int) -> Note: return self.items[index] - def addElement(self, element: Note): + def addElement(self, element: Note) -> None: length = self.rowCount() self.beginInsertRows(QModelIndex(), length, length) @@ -94,7 +94,7 @@ def addElement(self, element: Note): # Говорим view, что данные изменились self.dataChanged.emit(self.createIndex(length, 0), self.createIndex(length, 0)) - def removeElement(self, index: int): + def removeElement(self, index: int) -> None: self.beginRemoveRows(QModelIndex(), index, index) self.items.pop(index) self.endRemoveRows() @@ -109,57 +109,57 @@ def get_items(self) -> list[Note]: # Общий интерфейс посредников. class Mediator: @abstractmethod - def addNewNote(self, note: Note): + def addNewNote(self, note: Note) -> None: pass @abstractmethod - def deleteNote(self): + def deleteNote(self) -> None: pass @abstractmethod - def getInfoFromList(self, note: Note): + def getInfoFromList(self, note: Note) -> None: pass @abstractmethod - def saveChanges(self): + def saveChanges(self) -> None: pass @abstractmethod - def markNote(self): + def markNote(self) -> None: pass @abstractmethod - def clear(self): + def clear(self) -> None: pass @abstractmethod - def sendToFilter(self, listModel: DefaultListModel): + def sendToFilter(self, listModel: DefaultListModel) -> None: pass @abstractmethod - def setElementsList(self, listModel: DefaultListModel): + def setElementsList(self, listModel: DefaultListModel) -> None: pass @abstractmethod - def registerComponent(self, component: "Component"): + def registerComponent(self, component: "Component") -> None: pass @abstractmethod - def hideElements(self, flag: bool): + def hideElements(self, flag: bool) -> None: pass @abstractmethod - def createGUI(self): + def createGUI(self) -> None: pass class Component: """Общий класс компонентов.""" - def __init__(self): + def __init__(self) -> None: self._mediator: Mediator = None - def setMediator(self, mediator: Mediator): + def setMediator(self, mediator: Mediator) -> None: self._mediator = mediator @abstractmethod @@ -170,7 +170,7 @@ def getName(self) -> str: # Конкретные компоненты никак не связаны между собой. У них есть только один # канал общения – через отправку уведомлений посреднику. class AddButton(QPushButton, Component): - def __init__(self): + def __init__(self) -> None: super().__init__("Add") # При клике на кнопку вызываем метод посредника @@ -183,7 +183,7 @@ def getName(self) -> str: # Конкретные компоненты никак не связаны между собой. У них есть только один # канал общения – через отправку уведомлений посреднику. class DeleteButton(QPushButton, Component): - def __init__(self): + def __init__(self) -> None: super().__init__("Del") # При клике на кнопку вызываем метод посредника @@ -196,21 +196,21 @@ def getName(self) -> str: # Конкретные компоненты никак не связаны между собой. У них есть только один # канал общения – через отправку уведомлений посреднику. class Filter(QLineEdit, Component): - def __init__(self): + def __init__(self) -> None: super().__init__() self._listModel: DefaultListModel = None - def setList(self, listModel: DefaultListModel): + def setList(self, listModel: DefaultListModel) -> None: self._listModel = listModel - def keyPressEvent(self, event: "QKeyEvent"): + def keyPressEvent(self, event: "QKeyEvent") -> None: super().keyPressEvent(event) start = self.text() self._searchElements(start) - def _searchElements(self, text: str): + def _searchElements(self, text: str) -> None: if self._listModel is None: return @@ -235,13 +235,13 @@ def getName(self) -> str: # Конкретные компоненты никак не связаны между собой. У них есть только один # канал общения – через отправку уведомлений посреднику. class ListNote(QListView, Component): - def __init__(self, listModel: DefaultListModel): + def __init__(self, listModel: DefaultListModel) -> None: super().__init__() self._listModel = listModel self.setModel(self._listModel) - def addElement(self, note: Note): + def addElement(self, note: Note) -> None: self._listModel.addElement(note) index = self._listModel.rowCount() - 1 index = self._listModel.index(index, 0) @@ -250,7 +250,7 @@ def addElement(self, note: Note): self._mediator.sendToFilter(self._listModel) - def deleteElement(self): + def deleteElement(self) -> None: if not self.currentIndex().isValid(): return @@ -273,7 +273,7 @@ def getName(self) -> str: # Конкретные компоненты никак не связаны между собой. У них есть только один # канал общения – через отправку уведомлений посреднику. class SaveButton(QPushButton, Component): - def __init__(self): + def __init__(self) -> None: super().__init__("Save") # При клике на кнопку вызываем метод посредника @@ -286,7 +286,7 @@ def getName(self) -> str: # Конкретные компоненты никак не связаны между собой. У них есть только один # канал общения – через отправку уведомлений посреднику. class TextBox(QTextEdit, Component): - def keyPressEvent(self, event: "QKeyEvent"): + def keyPressEvent(self, event: "QKeyEvent") -> None: super().keyPressEvent(event) self._mediator.markNote() @@ -298,7 +298,7 @@ def getName(self) -> str: # Конкретные компоненты никак не связаны между собой. У них есть только один # канал общения – через отправку уведомлений посреднику. class Title(QLineEdit, Component): - def keyPressEvent(self, event: "QKeyEvent"): + def keyPressEvent(self, event: "QKeyEvent") -> None: super().keyPressEvent(event) self._mediator.markNote() @@ -311,7 +311,7 @@ def getName(self) -> str: # код посредника. Он получает извещения от своих компонентов и знает как на них # реагировать. class Editor(Mediator): - def __init__(self): + def __init__(self) -> None: self._title: Title = None self._textBox: TextBox = None self._add: AddButton = None @@ -327,7 +327,7 @@ def __init__(self): self._mainWindow = None # Здесь происходит регистрация компонентов посредником. - def registerComponent(self, component: Component): + def registerComponent(self, component: Component) -> None: component.setMediator(self) if component.getName() == "AddButton": @@ -342,7 +342,7 @@ def registerComponent(self, component: Component): elif component.getName() == "List": self._list: ListNote = component - def foo(*args): + def foo(*args) -> None: empty = len(self._list.selectedIndexes()) == 0 self.hideElements(empty) @@ -366,7 +366,7 @@ def foo(*args): # Разнообразные методы общения с компонентами. # - def addNewNote(self, note: Note): + def addNewNote(self, note: Note) -> None: # Инкрементальные названия text = note.getName() + str(self._list.model().rowCount() + 1) note.setName(text) @@ -375,14 +375,14 @@ def addNewNote(self, note: Note): self._textBox.setText("") self._list.addElement(note) - def deleteNote(self): + def deleteNote(self) -> None: self._list.deleteElement() - def getInfoFromList(self, note: Note): + def getInfoFromList(self, note: Note) -> None: self._title.setText(note.getName().replace("*", " ")) self._textBox.setText(note.getText()) - def saveChanges(self): + def saveChanges(self) -> None: try: note = self._list.getCurrentElement() note.setName(self._title.text()) @@ -393,7 +393,7 @@ def saveChanges(self): except Exception: traceback.print_exc() - def markNote(self): + def markNote(self) -> None: try: note = self._list.getCurrentElement() name = note.getName() @@ -408,18 +408,18 @@ def markNote(self): except Exception: traceback.print_exc() - def clear(self): + def clear(self) -> None: self._title.setText("") self._textBox.setText("") - def sendToFilter(self, listModel: DefaultListModel): + def sendToFilter(self, listModel: DefaultListModel) -> None: self._filter.setList(listModel) - def setElementsList(self, listModel: DefaultListModel): + def setElementsList(self, listModel: DefaultListModel) -> None: self._list.setModel(listModel) self._list.update() - def hideElements(self, flag: bool): + def hideElements(self, flag: bool) -> None: self._titleLabel.setVisible(not flag) self._textLabel.setVisible(not flag) self._title.setVisible(not flag) @@ -427,7 +427,7 @@ def hideElements(self, flag: bool): self._save.setVisible(not flag) self._label.setVisible(flag) - def createGUI(self): + def createGUI(self) -> None: # notes_side notes_side_filter_layout = QHBoxLayout() notes_side_filter_layout.addWidget(QLabel("Filter:")) diff --git a/design_patterns__examples/Observer/example_1.py b/design_patterns__examples/Observer/example_1.py index 678e01cf0..2585c4c06 100644 --- a/design_patterns__examples/Observer/example_1.py +++ b/design_patterns__examples/Observer/example_1.py @@ -42,23 +42,23 @@ def notify_observers(self): class WeatherData(Observable): - def __init__(self): + def __init__(self) -> None: self.observers = [] self.temperature: float = None self.humidity: float = None self.pressure: int = None - def register_observer(self, o: Observer): + def register_observer(self, o: Observer) -> None: self.observers.append(o) - def remove_observer(self, o: Observer): + def remove_observer(self, o: Observer) -> None: self.observers.remove(o) - def notify_observers(self): + def notify_observers(self) -> None: for observer in self.observers: observer.update(self.temperature, self.humidity, self.pressure) - def set_measurements(self, temperature: float, humidity: float, pressure: int): + def set_measurements(self, temperature: float, humidity: float, pressure: int) -> None: self.temperature = temperature self.humidity = humidity self.pressure = pressure @@ -66,7 +66,7 @@ def set_measurements(self, temperature: float, humidity: float, pressure: int): class CurrentConditionsDisplay(Observer): - def __init__(self, weather_data: WeatherData): + def __init__(self, weather_data: WeatherData) -> None: self.weather_data = weather_data self.weather_data.register_observer(self) @@ -74,14 +74,14 @@ def __init__(self, weather_data: WeatherData): self.humidity: float = None self.pressure: int = None - def update(self, temperature: float, humidity: float, pressure: int): + def update(self, temperature: float, humidity: float, pressure: int) -> None: self.temperature = temperature self.humidity = humidity self.pressure = pressure self.display() - def display(self): + def display(self) -> None: print( f"Сейчас значения: {self.temperature:.1f} градусов цельсия и {self.humidity:.1f}% влажности. " f"Давление {self.pressure} мм рт. ст." diff --git a/design_patterns__examples/Observer/example_4.py b/design_patterns__examples/Observer/example_4.py index 95453aed2..c797b1f59 100644 --- a/design_patterns__examples/Observer/example_4.py +++ b/design_patterns__examples/Observer/example_4.py @@ -31,33 +31,33 @@ def update(self, event_type: str, file: IO): class EventManager: - def __init__(self, *operations): + def __init__(self, *operations) -> None: self.listeners: dict[str, list[EventListener]] = dict() for operation in operations: self.listeners[operation] = [] - def subscribe(self, event_type: str, listener: EventListener): + def subscribe(self, event_type: str, listener: EventListener) -> None: items = self.listeners[event_type] items.append(listener) - def unsubscribe(self, event_type: str, listener: EventListener): + def unsubscribe(self, event_type: str, listener: EventListener) -> None: items = self.listeners[event_type] if listener in items: items.remove(listener) - def notify(self, event_type: str, file: IO): + def notify(self, event_type: str, file: IO) -> None: items = self.listeners[event_type] for listener in items: listener.update(event_type, file) class Editor: - def __init__(self): + def __init__(self) -> None: self.file: IO = None self.events = EventManager("open", "save") - def open_file(self, file_path: str): + def open_file(self, file_path: str) -> None: self.file = open(file_path, "w", encoding="utf-8") self.events.notify("open", self.file) @@ -69,10 +69,10 @@ def save_file(self): class EmailNotificationListener(EventListener): - def __init__(self, email: str): + def __init__(self, email: str) -> None: self.email = email - def update(self, event_type: str, file: IO): + def update(self, event_type: str, file: IO) -> None: print( f"Email to {self.email}: Someone has performed {event_type} " f"operation with the following file: {file.name}" @@ -80,11 +80,11 @@ def update(self, event_type: str, file: IO): class LogOpenListener(EventListener): - def __init__(self, file_name: str): + def __init__(self, file_name: str) -> None: # self.log: IO = open(file_name, encoding='utf-8') self.file_name = file_name - def update(self, event_type: str, file: IO): + def update(self, event_type: str, file: IO) -> None: # print(f"Save to log {self.log}: Someone has performed {event_type} " # f"operation with the following file: {file.name}") print( diff --git a/design_patterns__examples/Prototype/example.py b/design_patterns__examples/Prototype/example.py index 86aded0b7..d9793cacf 100644 --- a/design_patterns__examples/Prototype/example.py +++ b/design_patterns__examples/Prototype/example.py @@ -9,21 +9,22 @@ import copy +from typing import Any class Prototype: - def __init__(self): + def __init__(self) -> None: self._objects = dict() - def register_object(self, name, obj): + def register_object(self, name, obj) -> None: """Register an object""" self._objects[name] = obj - def unregister_object(self, name): + def unregister_object(self, name) -> None: """Unregister an object""" self._objects.pop(name) - def clone(self, name, **attr): + def clone(self, name, **attr) -> Any: """Clone a registered object and update inner attributes dictionary""" obj = copy.deepcopy(self._objects.get(name)) obj.__dict__.update(attr) @@ -33,13 +34,13 @@ def clone(self, name, **attr): if __name__ == "__main__": class A: - def __init__(self): + def __init__(self) -> None: self.x = 3 self.y = 8 self.z = 15 self.garbage = [38, 11, 19] - def __str__(self): + def __str__(self) -> str: return f"A({self.x}, {self.y}, {self.z}, {self.garbage})" a = A() diff --git a/design_patterns__examples/Proxy/example.py b/design_patterns__examples/Proxy/example.py index d67ba0e66..2c520c2b7 100644 --- a/design_patterns__examples/Proxy/example.py +++ b/design_patterns__examples/Proxy/example.py @@ -43,7 +43,7 @@ def div(self, x, y): class MathProxy(IMath): """Прокси""" - def __init__(self): + def __init__(self) -> None: self.math = None # Быстрые операции - не требуют реального субъекта diff --git a/design_patterns__examples/Proxy/example__cached.py b/design_patterns__examples/Proxy/example__cached.py index f0e37f308..e3c7ee6d7 100644 --- a/design_patterns__examples/Proxy/example__cached.py +++ b/design_patterns__examples/Proxy/example__cached.py @@ -5,6 +5,9 @@ from abc import ABC, abstractmethod +from types import TracebackType +from typing import Optional, Type + import requests @@ -33,7 +36,7 @@ def get_status_code(self, url: str) -> int: class GoUrlCachedProxy(IGoUrl): """Прокси""" - def __init__(self): + def __init__(self) -> None: self._url = GoUrl() self._cache = dict() self._cache_status_code = dict() @@ -58,15 +61,20 @@ def get_status_code(self, url: str) -> int: if __name__ == "__main__": - import time + from timeit import default_timer class TimeThis: def __enter__(self): - self.start_time = time.clock() + self.start_time = default_timer() return self - def __exit__(self, exc_type, exc_value, exc_traceback): - print(f"Elapsed time: {time.clock() - self.start_time:.6f} sec") + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_value: Optional[BaseException], + exc_traceback: Optional[TracebackType], + ) -> None: + print(f"Elapsed time: {default_timer() - self.start_time:.6f} sec") url = "https://github.com/gil9red" diff --git a/design_patterns__examples/Proxy/example__logged.py b/design_patterns__examples/Proxy/example__logged.py index ab1e7d987..10e59266e 100644 --- a/design_patterns__examples/Proxy/example__logged.py +++ b/design_patterns__examples/Proxy/example__logged.py @@ -8,6 +8,8 @@ import sys from logging.handlers import RotatingFileHandler +from types import TracebackType +from typing import Optional, Type from example__cached import IGoUrl, GoUrl, GoUrlCachedProxy, requests @@ -23,7 +25,9 @@ def get_logger(name, file="log.txt", encoding="utf-8"): # Simple file handler # fh = logging.FileHandler(file, encoding=encoding) # or: - fh = RotatingFileHandler(file, maxBytes=10_000_000, backupCount=5, encoding=encoding) + fh = RotatingFileHandler( + file, maxBytes=10_000_000, backupCount=5, encoding=encoding + ) fh.setFormatter(formatter) log.addHandler(fh) @@ -39,7 +43,7 @@ class GoUrlLoggedProxy(IGoUrl): _LOGGER = get_logger("GoUrlLoggedProxy") - def __init__(self, go_url: IGoUrl = None): + def __init__(self, go_url: IGoUrl = None) -> None: if go_url is None: go_url = GoUrl() @@ -61,20 +65,25 @@ def get_status_code(self, url: str) -> int: return code - def _log(self, text: str): + def _log(self, text: str) -> None: GoUrlLoggedProxy._LOGGER.debug(text) if __name__ == "__main__": - import time + from timeit import default_timer class TimeThis: def __enter__(self): - self.start_time = time.clock() + self.start_time = default_timer() return self - def __exit__(self, exc_type, exc_value, exc_traceback): - print(f"Elapsed time: {time.clock() - self.start_time:.6f} sec") + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_value: Optional[BaseException], + exc_traceback: Optional[TracebackType], + ) -> None: + print(f"Elapsed time: {default_timer() - self.start_time:.6f} sec") url = "https://github.com/gil9red" diff --git a/design_patterns__examples/Proxy/example__with_abc.py b/design_patterns__examples/Proxy/example__with_abc.py index 82c9c4f68..30ff7f6b4 100644 --- a/design_patterns__examples/Proxy/example__with_abc.py +++ b/design_patterns__examples/Proxy/example__with_abc.py @@ -49,7 +49,7 @@ def div(self, x, y): class MathProxy(IMath): """Прокси""" - def __init__(self): + def __init__(self) -> None: self.math = None # Быстрые операции - не требуют реального субъекта diff --git a/design_patterns__examples/Strategy/example.py b/design_patterns__examples/Strategy/example.py index 70aa3e7d2..dddbba159 100644 --- a/design_patterns__examples/Strategy/example.py +++ b/design_patterns__examples/Strategy/example.py @@ -19,23 +19,23 @@ def download(self, file: str): class DownloadWindowsStrategy(Strategy): - def download(self, file: str): + def download(self, file: str) -> None: print("Windows download: " + file) class DownloadLinuxStrategy(Strategy): - def download(self, file: str): + def download(self, file: str) -> None: print("Linux download: " + file) class Context: - def __init__(self, strategy: Strategy): + def __init__(self, strategy: Strategy) -> None: self._strategy = strategy - def set_strategy(self, strategy: Strategy): + def set_strategy(self, strategy: Strategy) -> None: self._strategy = strategy - def download(self, file: str): + def download(self, file: str) -> None: self._strategy.download(file) diff --git a/design_patterns__examples/Strategy/example_1.py b/design_patterns__examples/Strategy/example_1.py index 11ed51b47..5519920bb 100644 --- a/design_patterns__examples/Strategy/example_1.py +++ b/design_patterns__examples/Strategy/example_1.py @@ -28,10 +28,10 @@ def action(self, a, b): class Context: - def __init__(self, strategy: Strategy): + def __init__(self, strategy: Strategy) -> None: self._strategy = strategy - def set_strategy(self, strategy: Strategy): + def set_strategy(self, strategy: Strategy) -> None: self._strategy = strategy def action(self, a, b): diff --git a/design_patterns__examples/Template method/example_2.py b/design_patterns__examples/Template method/example_2.py index 3a47b5056..6c6b81956 100644 --- a/design_patterns__examples/Template method/example_2.py +++ b/design_patterns__examples/Template method/example_2.py @@ -18,19 +18,19 @@ def end_of_game(self) -> bool: pass @abstractmethod - def initialize_game(self): + def initialize_game(self) -> None: pass @abstractmethod - def make_play(self, player: int): + def make_play(self, player: int) -> None: pass @abstractmethod - def print_winner(self): + def print_winner(self) -> None: pass # A template method : - def play_one_game(self, players_count: int): + def play_one_game(self, players_count: int) -> None: self.players_count = players_count self.initialize_game() @@ -46,18 +46,18 @@ def play_one_game(self, players_count: int): # Now we can extend this class in order to implement actual games: class Monopoly(GameObject): # Implementation of necessary concrete methods - def initialize_game(self): + def initialize_game(self) -> None: # Initialize money ... - def make_play(self, player: int): + def make_play(self, player: int) -> None: # Process one turn of player ... def end_of_game(self) -> bool: return True - def print_winner(self): + def print_winner(self) -> None: # Display who won ... @@ -67,11 +67,11 @@ def print_winner(self): class Chess(GameObject): # Implementation of necessary concrete methods - def initialize_game(self): + def initialize_game(self) -> None: # Put the pieces on the board ... - def make_play(self, player: int): + def make_play(self, player: int) -> None: # Process a turn for the player ... @@ -79,7 +79,7 @@ def end_of_game(self) -> bool: # Return true if in Checkmate or Stalemate has been reached return True - def print_winner(self): + def print_winner(self) -> None: # Display the winning player ... diff --git a/design_patterns__examples/Template method/example_3.py b/design_patterns__examples/Template method/example_3.py index 234fd0b7b..6ea680ff2 100644 --- a/design_patterns__examples/Template method/example_3.py +++ b/design_patterns__examples/Template method/example_3.py @@ -41,13 +41,13 @@ def send_data(self, data: bytes) -> bool: pass @abstractmethod - def log_out(self): + def log_out(self) -> None: pass # Класс социальной сети. class Facebook(Network): - def __init__(self, user_name: str, password: str): + def __init__(self, user_name: str, password: str) -> None: self.user_name = user_name self.password = password @@ -68,10 +68,10 @@ def send_data(self, data: bytes) -> bool: return False - def log_out(self): + def log_out(self) -> None: print("User: '" + self.user_name + "' was logged out from Facebook") - def _simulate_network_latency(self): + def _simulate_network_latency(self) -> None: print() try: @@ -87,7 +87,7 @@ def _simulate_network_latency(self): # Класс социальной сети. class Twitter(Network): - def __init__(self, user_name: str, password: str): + def __init__(self, user_name: str, password: str) -> None: self.user_name = user_name self.password = password @@ -108,10 +108,10 @@ def send_data(self, data: bytes) -> bool: return False - def log_out(self): + def log_out(self) -> None: print("User: '" + self.user_name + "' was logged out from Twitter") - def _simulate_network_latency(self): + def _simulate_network_latency(self) -> None: print() try: diff --git a/design_patterns__examples/Template method/example_4.py b/design_patterns__examples/Template method/example_4.py index 076c6c080..31c765e05 100644 --- a/design_patterns__examples/Template method/example_4.py +++ b/design_patterns__examples/Template method/example_4.py @@ -19,7 +19,7 @@ def center(self) -> ...: class GameAI(ABC): - def __init__(self): + def __init__(self) -> None: self.scouts = [] self.warriors = [] self.map = Map() @@ -27,14 +27,14 @@ def __init__(self): # Шаблонный метод должен быть задан в базовом классе. Он # состоит из вызовов методов в определённом порядке. Чаще # всего эти методы являются шагами некоего алгоритма. - def turn(self): + def turn(self) -> None: self.collect_resources() self.build_structures() self.build_units() self.attack() # Некоторые из этих методов могут быть реализованы прямо в базовом классе. - def collect_resources(self): + def collect_resources(self) -> None: for s in self.build_structures(): s.collect() @@ -44,11 +44,11 @@ def build_structures(self) -> list["Structure"]: pass @abstractmethod - def build_units(self): + def build_units(self) -> None: pass # Кстати, шаблонных методов в классе может быть несколько. - def attack(self): + def attack(self) -> None: enemy = self.closest_enemy() if enemy is None: @@ -60,11 +60,11 @@ def closest_enemy(self) -> Optional["Enemy"]: ... @abstractmethod - def send_scouts(self, position): + def send_scouts(self, position) -> None: pass @abstractmethod - def send_warriors(self, position): + def send_warriors(self, position) -> None: pass @@ -82,7 +82,7 @@ def build_structures(self) -> list["Structure"]: return structures - def build_units(self): + def build_units(self) -> None: there_are_plenty_of_resources: bool = ... there_are_no_scouts: bool = ... @@ -96,12 +96,12 @@ def build_units(self): # ... - def send_scouts(self, position): + def send_scouts(self, position) -> None: if self.scouts: # Отправить разведчиков на позицию. ... - def send_warriors(self, position): + def send_warriors(self, position) -> None: if len(self.warriors) > 5: # Отправить воинов на позицию. ... @@ -110,24 +110,24 @@ def send_warriors(self, position): # Подклассы могут не только реализовывать абстрактные шаги, но # и переопределять шаги, уже реализованные в базовом классе. class MonstersAI(GameAI): - def collect_resources(self): + def collect_resources(self) -> None: # Ничего не делать. pass - def build_structures(self): + def build_structures(self) -> None: # Ничего не делать. pass - def build_units(self): + def build_units(self) -> None: # Ничего не делать. pass - def send_scouts(self, position): + def send_scouts(self, position) -> None: if self.scouts: # Отправить разведчиков на позицию. ... - def send_warriors(self, position): + def send_warriors(self, position) -> None: if len(self.warriors) > 5: # Отправить воинов на позицию. ... diff --git a/detection_of_site_changes_Unistream/gui.py b/detection_of_site_changes_Unistream/gui.py index 703ba6118..afaf178f9 100644 --- a/detection_of_site_changes_Unistream/gui.py +++ b/detection_of_site_changes_Unistream/gui.py @@ -22,7 +22,7 @@ class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("detection_of_site_changes_Unistream") @@ -53,7 +53,7 @@ def __init__(self): self.setCentralWidget(self.revision_list_widget) - def _show_last_diff(self, item): + def _show_last_diff(self, item) -> None: row = self.revision_list_widget.row(item) file_name_a = "file_a" diff --git a/detection_of_site_changes_Unistream/main.py b/detection_of_site_changes_Unistream/main.py index 2267877cd..bfb3676bb 100644 --- a/detection_of_site_changes_Unistream/main.py +++ b/detection_of_site_changes_Unistream/main.py @@ -57,7 +57,7 @@ def get_site_text(url="https://test.api.unistream.com/help/index.html"): ) class WebPage(QWebPage): - def userAgentForUrl(self, url): + def userAgentForUrl(self, url) -> str: return "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0" if QApplication.instance() is None: @@ -149,7 +149,7 @@ class TextRevision(Base): # Содержимым является только разница diff = Column(String) - def __init__(self, new_text, old_text=""): + def __init__(self, new_text, old_text="") -> None: """ Конструктор принимает контент и сравниваемый контент, запоминает хеш содержимого, текущую дату и время и результат сравнения @@ -166,7 +166,7 @@ def __init__(self, new_text, old_text=""): self.diff_full = get_diff(old_text, new_text) self.diff = get_diff(old_text, new_text, full=False) - def __repr__(self): + def __repr__(self) -> str: return f"" diff --git a/dict_to_url_params.py b/dict_to_url_params.py index 45e869033..c30173bf5 100644 --- a/dict_to_url_params.py +++ b/dict_to_url_params.py @@ -5,7 +5,7 @@ def dict_to_url_params(json_data, root): - def deep(node, root, items): + def deep(node, root, items) -> None: if isinstance(node, list): for i, value in enumerate(node): node_root = root + f"[{i}]" diff --git a/dis__bytecode__is_empty_function.py b/dis__bytecode__is_empty_function.py index 2d7e1768e..7f54f9bea 100644 --- a/dis__bytecode__is_empty_function.py +++ b/dis__bytecode__is_empty_function.py @@ -20,10 +20,10 @@ def check_is_empty_function(function): if __name__ == "__main__": - def foo(): + def foo() -> None: pass - def foo2(): + def foo2() -> int: return 1 print("Empty:", check_is_empty_function(foo)) diff --git a/download_file/download_file.py b/download_file/download_file.py index 81641a7fa..bb3e5e297 100644 --- a/download_file/download_file.py +++ b/download_file/download_file.py @@ -28,26 +28,26 @@ def wrapper(*args, **kwargs): @timer -def way1(url: str, file_name: str): +def way1(url: str, file_name: str) -> None: resource = urlopen(url) with open(file_name, "wb") as f: f.write(resource.read()) @timer -def way2(url: str, file_name: str): +def way2(url: str, file_name: str) -> None: urlretrieve(url, file_name) @timer -def way3(url: str, file_name: str): +def way3(url: str, file_name: str) -> None: p = requests.get(url) with open(file_name, "wb") as f: f.write(p.content) @timer -def way4(url: str, file_name: str): +def way4(url: str, file_name: str) -> None: h = httplib2.Http(".cache") response, content = h.request(url) with open(file_name, "wb") as f: @@ -55,7 +55,7 @@ def way4(url: str, file_name: str): @timer -def way5(url: str, file_name: str): +def way5(url: str, file_name: str) -> None: g = Grab() g.go(url) g.response.save(file_name) diff --git a/download_file/with_progress.py b/download_file/with_progress.py index 14288e6e2..4eccbcc5a 100644 --- a/download_file/with_progress.py +++ b/download_file/with_progress.py @@ -9,7 +9,7 @@ from threading import Thread -def reporthook(blocknum, blocksize, totalsize): +def reporthook(blocknum, blocksize, totalsize) -> None: readsofar = blocknum * blocksize if totalsize > 0: percent = readsofar * 100.0 / totalsize @@ -56,7 +56,7 @@ def run(url, file_name, reporthook, callback_func): print(download(URL, "SimplePyScripts.zip", as_thread=True)) - def callback_func(file_name: str): + def callback_func(file_name: str) -> None: print("File name:", file_name) print( diff --git a/download_volume_readmanga.py b/download_volume_readmanga.py index 8f9143f81..b29ce0054 100644 --- a/download_volume_readmanga.py +++ b/download_volume_readmanga.py @@ -39,7 +39,7 @@ def get_url_images(url): return [i[0] + i[2] for i in urls] -def save_urls_to_zip(zip_file_name, urls): +def save_urls_to_zip(zip_file_name, urls) -> None: if not urls: print("Cписок изображений пустой.") return diff --git a/draw fractal/Apollon_Set/Apollon_Set__PIL.py b/draw fractal/Apollon_Set/Apollon_Set__PIL.py index 6e54f6655..0359ebadc 100644 --- a/draw fractal/Apollon_Set/Apollon_Set__PIL.py +++ b/draw fractal/Apollon_Set/Apollon_Set__PIL.py @@ -69,7 +69,7 @@ from PIL import Image, ImageDraw -def draw_apollon_set(draw_by_image, step): +def draw_apollon_set(draw_by_image, step) -> None: x = 0.2 y = 0.3 diff --git a/draw fractal/Cantor_dust/Cantor_dust__PIL.py b/draw fractal/Cantor_dust/Cantor_dust__PIL.py index 4b6e59555..3dd63d6aa 100644 --- a/draw fractal/Cantor_dust/Cantor_dust__PIL.py +++ b/draw fractal/Cantor_dust/Cantor_dust__PIL.py @@ -40,8 +40,8 @@ from PIL import Image, ImageDraw -def draw_cantor_dust(draw_by_image): - def draw(x, y, size): +def draw_cantor_dust(draw_by_image) -> None: + def draw(x, y, size) -> None: if size > 1: s = size / 3 draw(x, y + 20, s) diff --git a/draw fractal/Circular_fractal/Circular_fractal__PIL.py b/draw fractal/Circular_fractal/Circular_fractal__PIL.py index f74d1c0b9..28735840b 100644 --- a/draw fractal/Circular_fractal/Circular_fractal__PIL.py +++ b/draw fractal/Circular_fractal/Circular_fractal__PIL.py @@ -39,7 +39,7 @@ from PIL import Image, ImageDraw -def draw_circular_fractal(draw_by_image, x, y, size): +def draw_circular_fractal(draw_by_image, x, y, size) -> None: m = 6 n = 3 diff --git a/draw fractal/Dragon_curve_1/Dragon_curve_1__PIL.py b/draw fractal/Dragon_curve_1/Dragon_curve_1__PIL.py index 9cd17d4fd..dad5d9eb2 100644 --- a/draw fractal/Dragon_curve_1/Dragon_curve_1__PIL.py +++ b/draw fractal/Dragon_curve_1/Dragon_curve_1__PIL.py @@ -40,7 +40,7 @@ from PIL import Image, ImageDraw -def draw_dragon_curve_1(draw_by_image, x1, y1, x2, y2, k): +def draw_dragon_curve_1(draw_by_image, x1, y1, x2, y2, k) -> None: if k > 0: xn = (x1 + x2) // 2 + (y2 - y1) // 2 yn = (y1 + y2) // 2 - (x2 - x1) // 2 diff --git a/draw fractal/Fern/Fern__PIL.py b/draw fractal/Fern/Fern__PIL.py index e19823408..5353cc35b 100644 --- a/draw fractal/Fern/Fern__PIL.py +++ b/draw fractal/Fern/Fern__PIL.py @@ -49,7 +49,7 @@ from PIL import Image, ImageDraw -def draw_fern(draw_by_image, width, height): +def draw_fern(draw_by_image, width, height) -> None: n = 255 cx = 0.251 diff --git a/draw fractal/Fern_2/Fern_2__PIL.py b/draw fractal/Fern_2/Fern_2__PIL.py index 0f850aabb..9662a6311 100644 --- a/draw fractal/Fern_2/Fern_2__PIL.py +++ b/draw fractal/Fern_2/Fern_2__PIL.py @@ -46,11 +46,11 @@ from PIL import Image, ImageDraw -def draw_fern_2(draw_by_image): - def line_to(x, y, l, u): +def draw_fern_2(draw_by_image) -> None: + def line_to(x, y, l, u) -> None: draw_by_image.line((x, y, x + l * cos(u), y - l * sin(u)), "black") - def draw(x, y, l, u): + def draw(x, y, l, u) -> None: if l > 1: line_to(x, y, l, u) diff --git a/draw fractal/Fingerprint/Fingerprint__PIL.py b/draw fractal/Fingerprint/Fingerprint__PIL.py index 676cdbff6..ad6415f4f 100644 --- a/draw fractal/Fingerprint/Fingerprint__PIL.py +++ b/draw fractal/Fingerprint/Fingerprint__PIL.py @@ -48,7 +48,7 @@ from PIL import Image, ImageDraw -def draw_fingerprint(draw_by_image, width, height): +def draw_fingerprint(draw_by_image, width, height) -> None: n = 255 max = 10 diff --git a/draw fractal/Fractal_tree/Fractal_tree__PIL.py b/draw fractal/Fractal_tree/Fractal_tree__PIL.py index baa0f658d..97316863e 100644 --- a/draw fractal/Fractal_tree/Fractal_tree__PIL.py +++ b/draw fractal/Fractal_tree/Fractal_tree__PIL.py @@ -64,7 +64,7 @@ from PIL import Image, ImageDraw -def draw_fractal_tree(draw_by_image, x, y, a, l): +def draw_fractal_tree(draw_by_image, x, y, a, l) -> None: if l < 8: return diff --git a/draw fractal/Fractal_tree/Fractal_tree__Qt_gui.py b/draw fractal/Fractal_tree/Fractal_tree__Qt_gui.py index 0389a994c..7495fbfde 100644 --- a/draw fractal/Fractal_tree/Fractal_tree__Qt_gui.py +++ b/draw fractal/Fractal_tree/Fractal_tree__Qt_gui.py @@ -59,7 +59,7 @@ class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Fractal tree") @@ -76,7 +76,7 @@ def __init__(self): self.setLayout(main_layout) - def generate_tree(self): + def generate_tree(self) -> None: img = Image.new("RGB", (700, 600), "white") draw_fractal_tree(ImageDraw.Draw(img), 350, 580, 3 * math.pi / 2, 200) diff --git a/draw fractal/Gosper_curve/Gosper_curve__PIL.py b/draw fractal/Gosper_curve/Gosper_curve__PIL.py index 7add7cecf..dd23d5b81 100644 --- a/draw fractal/Gosper_curve/Gosper_curve__PIL.py +++ b/draw fractal/Gosper_curve/Gosper_curve__PIL.py @@ -61,8 +61,8 @@ from PIL import Image, ImageDraw -def draw_gosper_curve(draw_by_image, step): - def draw(x, y, l, u, t, q): +def draw_gosper_curve(draw_by_image, step) -> None: + def draw(x, y, l, u, t, q) -> None: if t > 0: if q == 1: x += l * math.cos(u) diff --git a/draw fractal/Ice_fractal_1/Circular_fractal_1__PIL.py b/draw fractal/Ice_fractal_1/Circular_fractal_1__PIL.py index 9ecb1c28d..a4628ee1c 100644 --- a/draw fractal/Ice_fractal_1/Circular_fractal_1__PIL.py +++ b/draw fractal/Ice_fractal_1/Circular_fractal_1__PIL.py @@ -49,12 +49,12 @@ from PIL import Image, ImageDraw -def draw_ice_fractal_1(draw_by_image, step): +def draw_ice_fractal_1(draw_by_image, step) -> None: def draw2(x, y, l, u, t): draw(x, y, l, u, t) return x + l * cos(u), y - l * sin(u) - def draw(x, y, l, u, t): + def draw(x, y, l, u, t) -> None: if t > 0: l *= 0.5 x, y = draw2(x, y, l, u, t - 1) diff --git a/draw fractal/Ice_fractal_2/Circular_fractal_2__PIL.py b/draw fractal/Ice_fractal_2/Circular_fractal_2__PIL.py index a447e22b1..38e5d0d56 100644 --- a/draw fractal/Ice_fractal_2/Circular_fractal_2__PIL.py +++ b/draw fractal/Ice_fractal_2/Circular_fractal_2__PIL.py @@ -51,12 +51,12 @@ from PIL import Image, ImageDraw -def draw_ice_fractal_2(draw_by_image, step): +def draw_ice_fractal_2(draw_by_image, step) -> None: def draw2(x, y, l, u, t): draw(x, y, l, u, t) return x + l * cos(u), y - l * sin(u) - def draw(x, y, l, u, t): + def draw(x, y, l, u, t) -> None: if t > 0: l *= 0.5 x, y = draw2(x, y, l, u, t - 1) diff --git a/draw fractal/Koch_curve/Koch_curve__PIL.py b/draw fractal/Koch_curve/Koch_curve__PIL.py index 17b9e2dd7..db728139f 100644 --- a/draw fractal/Koch_curve/Koch_curve__PIL.py +++ b/draw fractal/Koch_curve/Koch_curve__PIL.py @@ -60,7 +60,7 @@ from PIL import Image, ImageDraw -def draw_koch(draw, xa, ya, xe, ye, n): +def draw_koch(draw, xa, ya, xe, ye, n) -> None: """ Draws koch curve between two points. diff --git a/draw fractal/Koch_curve/Koch_curve__Qt.py b/draw fractal/Koch_curve/Koch_curve__Qt.py index 67a5346cb..90aa52c09 100644 --- a/draw fractal/Koch_curve/Koch_curve__Qt.py +++ b/draw fractal/Koch_curve/Koch_curve__Qt.py @@ -57,7 +57,7 @@ # ?> -def draw_koch(painter, xa, ya, xe, ye, n): +def draw_koch(painter, xa, ya, xe, ye, n) -> None: """ Draws koch curve between two points. diff --git a/draw fractal/Koch_curve/Koch_curve__Qt_gui.py b/draw fractal/Koch_curve/Koch_curve__Qt_gui.py index 1dad3cf96..0996c3e50 100644 --- a/draw fractal/Koch_curve/Koch_curve__Qt_gui.py +++ b/draw fractal/Koch_curve/Koch_curve__Qt_gui.py @@ -57,7 +57,7 @@ # ?> -def draw_koch(painter, xa, ya, xe, ye, n): +def draw_koch(painter, xa, ya, xe, ye, n) -> None: """ Draws koch curve between two points. @@ -130,7 +130,7 @@ def draw_koch(painter, xa, ya, xe, ye, n): class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Koch_curve snowflake") @@ -155,7 +155,7 @@ def __init__(self): self.draw_by_step(self.step_spinbox.value()) - def draw_by_step(self, step): + def draw_by_step(self, step) -> None: img = QImage(600, 200, QImage.Format_RGB16) img.fill(Qt.white) diff --git a/draw fractal/Koch_snowflake/Koch_snowflake__PIL.py b/draw fractal/Koch_snowflake/Koch_snowflake__PIL.py index 3d3fb0f43..8a97d9a14 100644 --- a/draw fractal/Koch_snowflake/Koch_snowflake__PIL.py +++ b/draw fractal/Koch_snowflake/Koch_snowflake__PIL.py @@ -50,13 +50,13 @@ from PIL import Image, ImageDraw -def draw_snowflake_koch(draw_by_image, step): +def draw_snowflake_koch(draw_by_image, step) -> None: """ Draws koch snowflake. """ - def draw(x, y, l, u, t): + def draw(x, y, l, u, t) -> None: if t == 0: draw_by_image.line( (x, y, x + math.cos(u) * l, y - math.sin(u) * l), fill="black" diff --git a/draw fractal/Levy_curve/Levy_curve__PIL.py b/draw fractal/Levy_curve/Levy_curve__PIL.py index 369776b57..50cb3752d 100644 --- a/draw fractal/Levy_curve/Levy_curve__PIL.py +++ b/draw fractal/Levy_curve/Levy_curve__PIL.py @@ -56,7 +56,7 @@ from PIL import Image, ImageDraw -def draw_levy(draw): +def draw_levy(draw) -> None: iter = 50000 mx = 200 diff --git a/draw fractal/Mandelbrot_Set_1/Mandelbrot_Set_1__PIL.py b/draw fractal/Mandelbrot_Set_1/Mandelbrot_Set_1__PIL.py index 0048dc005..5c6a3ed5b 100644 --- a/draw fractal/Mandelbrot_Set_1/Mandelbrot_Set_1__PIL.py +++ b/draw fractal/Mandelbrot_Set_1/Mandelbrot_Set_1__PIL.py @@ -48,7 +48,7 @@ from PIL import Image, ImageDraw -def draw_mandelbrot_set_1(draw_by_image, width, height): +def draw_mandelbrot_set_1(draw_by_image, width, height) -> None: n = 255 max = 10 diff --git a/draw fractal/Mandelbrot_Set_2/Mandelbrot_Set_2__PIL.py b/draw fractal/Mandelbrot_Set_2/Mandelbrot_Set_2__PIL.py index 9467f811e..d03467eb2 100644 --- a/draw fractal/Mandelbrot_Set_2/Mandelbrot_Set_2__PIL.py +++ b/draw fractal/Mandelbrot_Set_2/Mandelbrot_Set_2__PIL.py @@ -48,7 +48,7 @@ from PIL import Image, ImageDraw -def draw_mandelbrot_set_2(draw_by_image, width, height): +def draw_mandelbrot_set_2(draw_by_image, width, height) -> None: n = 255 max = 10 diff --git a/draw fractal/Minkowski_curve/Minkowski_curve__PIL.py b/draw fractal/Minkowski_curve/Minkowski_curve__PIL.py index e282614e6..f8f631a4e 100644 --- a/draw fractal/Minkowski_curve/Minkowski_curve__PIL.py +++ b/draw fractal/Minkowski_curve/Minkowski_curve__PIL.py @@ -79,7 +79,7 @@ from PIL import Image, ImageDraw -def draw_minkowski(draw, xa, ya, xi, yi, n): +def draw_minkowski(draw, xa, ya, xi, yi, n) -> None: """ Draws minkowski curve between two points. diff --git a/draw fractal/Monkey_tree/Monkey_tree__PIL.py b/draw fractal/Monkey_tree/Monkey_tree__PIL.py index 74cd0ff9a..e1d71f847 100644 --- a/draw fractal/Monkey_tree/Monkey_tree__PIL.py +++ b/draw fractal/Monkey_tree/Monkey_tree__PIL.py @@ -77,12 +77,12 @@ from PIL import Image, ImageDraw -def draw_monkey_tree(draw_by_image): +def draw_monkey_tree(draw_by_image) -> None: def draw2(x, y, l, u, t, q, s): draw(x, y, l, u, t, q, s) return x + l * cos(u), y - l * sin(u) - def draw(x, y, l, u, t, q, s): + def draw(x, y, l, u, t, q, s) -> None: if t > 0: if q == 1: x += l * cos(u) diff --git a/draw fractal/Pythagoras_tree_2/Pythagoras_tree_2__PIL.py b/draw fractal/Pythagoras_tree_2/Pythagoras_tree_2__PIL.py index fd56eb7fa..05c44e2a6 100644 --- a/draw fractal/Pythagoras_tree_2/Pythagoras_tree_2__PIL.py +++ b/draw fractal/Pythagoras_tree_2/Pythagoras_tree_2__PIL.py @@ -45,11 +45,11 @@ from PIL import Image, ImageDraw -def draw_pythagoras_tree_2(draw_by_image): - def line_to(x, y, l, u): +def draw_pythagoras_tree_2(draw_by_image) -> None: + def line_to(x, y, l, u) -> None: draw_by_image.line((x, y, x + l * cos(u), y - l * sin(u)), "black") - def draw(x, y, l, u): + def draw(x, y, l, u) -> None: if l > 3: l *= 0.7 line_to(x, y, l, u) diff --git a/draw fractal/Sierpinski_carpet/Sierpinski_carpet__PIL.py b/draw fractal/Sierpinski_carpet/Sierpinski_carpet__PIL.py index 4b249abbe..4ecafccf6 100644 --- a/draw fractal/Sierpinski_carpet/Sierpinski_carpet__PIL.py +++ b/draw fractal/Sierpinski_carpet/Sierpinski_carpet__PIL.py @@ -50,8 +50,8 @@ from PIL import Image, ImageDraw -def draw_sierpinski_carpet(draw_by_image, Z): - def serp(x1, y1, x2, y2, n): +def draw_sierpinski_carpet(draw_by_image, Z) -> None: + def serp(x1, y1, x2, y2, n) -> None: if n > 0: x1n = 2 * x1 / 3 + x2 / 3 x2n = x1 / 3 + 2 * x2 / 3 diff --git a/draw fractal/Sierpinski_triangle/Sierpinski_triangle__PIL.py b/draw fractal/Sierpinski_triangle/Sierpinski_triangle__PIL.py index 6add5bead..7037a8d6e 100644 --- a/draw fractal/Sierpinski_triangle/Sierpinski_triangle__PIL.py +++ b/draw fractal/Sierpinski_triangle/Sierpinski_triangle__PIL.py @@ -52,15 +52,15 @@ from PIL import Image, ImageDraw -def draw_sierpinski_triangle(draw_by_image, Z): +def draw_sierpinski_triangle(draw_by_image, Z) -> None: color = "black" - def tr(x1, y1, x2, y2, x3, y3): + def tr(x1, y1, x2, y2, x3, y3) -> None: draw_by_image.line((x1, y1, x2, y2), color) draw_by_image.line((x2, y2, x3, y3), color) draw_by_image.line((x3, y3, x1, y1), color) - def draw(x1, y1, x2, y2, x3, y3, n): + def draw(x1, y1, x2, y2, x3, y3, n) -> None: if n > 0: x1n = (x1 + x2) / 2 y1n = (y1 + y2) / 2 diff --git a/draw fractal/Snowflake/Snowflake__PIL.py b/draw fractal/Snowflake/Snowflake__PIL.py index ce9dba293..28ca5b02c 100644 --- a/draw fractal/Snowflake/Snowflake__PIL.py +++ b/draw fractal/Snowflake/Snowflake__PIL.py @@ -39,8 +39,8 @@ from PIL import Image, ImageDraw -def draw_snowflake(draw_by_image, width, height, count): - def draw(x0, y0, r, n): +def draw_snowflake(draw_by_image, width, height, count) -> None: + def draw(x0, y0, r, n) -> None: t = 2 * pi / count for i in range(count): diff --git a/draw_wave.py b/draw_wave.py index b9beb005a..a84976c18 100644 --- a/draw_wave.py +++ b/draw_wave.py @@ -44,7 +44,7 @@ def format_db(x, pos=None): return int(db) -def draw(file_name): +def draw(file_name) -> None: wav = wave.open(file_name, mode="r") global nframes, k, peak, duration (nchannels, sampwidth, framerate, nframes, comptype, compname) = wav.getparams() diff --git a/dynamic_methods_link_call.py b/dynamic_methods_link_call.py index 93793c5a6..7755ae318 100644 --- a/dynamic_methods_link_call.py +++ b/dynamic_methods_link_call.py @@ -5,7 +5,7 @@ class CallBuilder: - def __init__(self, part=None, sep=""): + def __init__(self, part=None, sep="") -> None: self._part = part self._sep = sep diff --git a/effect_of_vanishing_photos/effect_of_vanishing_photos.py b/effect_of_vanishing_photos/effect_of_vanishing_photos.py index 7153581b3..37ec67af4 100644 --- a/effect_of_vanishing_photos/effect_of_vanishing_photos.py +++ b/effect_of_vanishing_photos/effect_of_vanishing_photos.py @@ -31,7 +31,7 @@ from PySide.QtCore import * -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -45,14 +45,14 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class Timer(QTimer): class Circle: - def __init__(self, pos_center): + def __init__(self, pos_center) -> None: self.pos_center = pos_center self.radii = 1 - def next(self): + def next(self) -> None: self.radii += 1 - def __init__(self, widget, image): + def __init__(self, widget, image) -> None: super().__init__() self.circle_list = list() @@ -68,10 +68,10 @@ def __init__(self, widget, image): self.painter.setPen(Qt.NoPen) self.painter.setBrush(Qt.transparent) - def add(self, pos_center): + def add(self, pos_center) -> None: self.circle_list.append(Timer.Circle(pos_center)) - def tick(self): + def tick(self) -> None: for circle in self.circle_list: self.painter.drawEllipse(circle.pos_center, circle.radii, circle.radii) circle.next() @@ -80,7 +80,7 @@ def tick(self): class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("effect_of_vanishing_photos.py") @@ -91,12 +91,12 @@ def __init__(self): self.timer = Timer(self, self.im) self.timer.start() - def mouseReleaseEvent(self, event): + def mouseReleaseEvent(self, event) -> None: super().mouseReleaseEvent(event) self.timer.add(event.pos()) - def paintEvent(self, event): + def paintEvent(self, event) -> None: super().paintEvent(event) p = QPainter(self) diff --git a/enum__examples.py b/enum__examples.py index 3b7bc718e..2c9cbae63 100644 --- a/enum__examples.py +++ b/enum__examples.py @@ -60,7 +60,7 @@ class Planet(Enum): URANUS = (8.686e25, 2.5559e7) NEPTUNE = (1.024e26, 2.4746e7) - def __init__(self, mass, radius): + def __init__(self, mass, radius) -> None: self.mass = mass # in kilograms self.radius = radius # in meters diff --git a/exit_handler.py b/exit_handler.py index dbd843a3d..b4a31d9a0 100644 --- a/exit_handler.py +++ b/exit_handler.py @@ -11,7 +11,7 @@ start_time = timer() -def exit_handler(): +def exit_handler() -> None: print(f"Execution time: {timer() - start_time:.3f} secs.") @@ -20,7 +20,7 @@ def exit_handler(): # OR with decorator: @atexit.register -def exit_handler(): +def exit_handler() -> None: print(f"Execution time: {timer() - start_time:.3f} secs.") diff --git a/explore__windows.py b/explore__windows.py index 6dc61ba18..818614c91 100644 --- a/explore__windows.py +++ b/explore__windows.py @@ -9,7 +9,7 @@ from pathlib import Path -def explore(path: str | Path, select=True): +def explore(path: str | Path, select=True) -> None: path = Path(path).resolve() if path.is_dir() or path.is_file(): diff --git a/f-strings__formatted string literals__PEP 498/example_from__python_docs.py b/f-strings__formatted string literals__PEP 498/example_from__python_docs.py index ef665738e..e320daade 100644 --- a/f-strings__formatted string literals__PEP 498/example_from__python_docs.py +++ b/f-strings__formatted string literals__PEP 498/example_from__python_docs.py @@ -53,7 +53,7 @@ # Formatted string literals cannot be used as docstrings, even if they do not include expressions. -def foo(): +def foo() -> None: f"Not a docstring" diff --git a/f-strings__formatted string literals__PEP 498/my_example.py b/f-strings__formatted string literals__PEP 498/my_example.py index 05a16f2cd..b8e6168e4 100644 --- a/f-strings__formatted string literals__PEP 498/my_example.py +++ b/f-strings__formatted string literals__PEP 498/my_example.py @@ -41,17 +41,17 @@ def strange_1(text): # Use class class Foo: - def __init__(self, text=""): + def __init__(self, text="") -> None: self.text = text def strange_2(self, text): return re.sub(r"[aeo]", " ", text) @staticmethod - def strange_3(text): + def strange_3(text) -> str: return f'"{text}"' - def __format__(self, format_spec): + def __format__(self, format_spec) -> str: format_spec = format_spec.strip() if not format_spec: @@ -65,10 +65,10 @@ def __format__(self, format_spec): return self.__str__() - def __str__(self): + def __str__(self) -> str: return f'' - def __repr__(self): + def __repr__(self) -> str: return f'' diff --git a/fastapi__examples/blog_from_stepic/src/blog/repositories.py b/fastapi__examples/blog_from_stepic/src/blog/repositories.py index ee45a6676..c2926d033 100644 --- a/fastapi__examples/blog_from_stepic/src/blog/repositories.py +++ b/fastapi__examples/blog_from_stepic/src/blog/repositories.py @@ -27,7 +27,7 @@ class MemoryUsersRepository(UsersRepository): Реализация пользовательского хранилища в оперативной памяти. Пользователи инициализируются во время инициализации репозитория """ - def __init__(self): + def __init__(self) -> None: self.users = [ Admin( id="29ae7ebf-4445-42f2-9548-a3a54f095220", # это uuid4 – уникальный идентификатор пользователя @@ -70,13 +70,13 @@ def create_article(self, article: Article): class ShelveArticlesRepository(ArticlesRepository): - def __init__(self): + def __init__(self) -> None: self.db_name = "articles" def get_articles(self) -> list[Article]: with shelve.open(self.db_name) as db: return list(db.values()) - def create_article(self, article: Article): + def create_article(self, article: Article) -> None: with shelve.open(self.db_name) as db: db[article.id] = article diff --git a/fastapi__examples/blog_from_stepic/src/blog/resources.py b/fastapi__examples/blog_from_stepic/src/blog/resources.py index 6d5e3a82c..d46096528 100644 --- a/fastapi__examples/blog_from_stepic/src/blog/resources.py +++ b/fastapi__examples/blog_from_stepic/src/blog/resources.py @@ -23,7 +23,7 @@ @router.get("/", response_class=HTMLResponse) -def index(): +def index() -> str: return """
diff --git a/fastapi__examples/market_from_stepic/requirements.txt b/fastapi__examples/market_from_stepic/requirements.txt index 1cebfb6b5..72cc557f6 100644 --- a/fastapi__examples/market_from_stepic/requirements.txt +++ b/fastapi__examples/market_from_stepic/requirements.txt @@ -1,5 +1,5 @@ fastapi==0.111.0 uvicorn[standard]==0.30.1 -PyJWT==2.8.0 +PyJWT==2.13.0 passlib==1.7.4 bcrypt==4.0.1 \ No newline at end of file diff --git a/fastapi__examples/market_from_stepic/src/market/db.py b/fastapi__examples/market_from_stepic/src/market/db.py index caf8b76b1..8a164a2ef 100644 --- a/fastapi__examples/market_from_stepic/src/market/db.py +++ b/fastapi__examples/market_from_stepic/src/market/db.py @@ -31,7 +31,7 @@ class InvalidException(DbException): class InvalidOrderStatusException(InvalidException): - def __init__(self, prev_status: models.StatusOrderEnum, new_status: models.StatusOrderEnum): + def __init__(self, prev_status: models.StatusOrderEnum, new_status: models.StatusOrderEnum) -> None: super().__init__(f"Unable to change order status {prev_status.value!r} to {new_status.value!r}") @@ -80,10 +80,10 @@ def get_value(self, name: str, default: Any = None) -> Any: return self.db.get(name) @session() - def set_value(self, name: str, value: Any): + def set_value(self, name: str, value: Any) -> None: self.db[name] = value - def __init__(self, file_name: Path | str = DB_FILE_NAME): + def __init__(self, file_name: Path | str = DB_FILE_NAME) -> None: self.file_name: str = str(file_name) self.db: shelve.Shelf | None = None @@ -93,7 +93,7 @@ def _generate_id(self) -> str: return str(uuid4()) @lock() - def rebuild_indexes(self, clear: bool = True): + def rebuild_indexes(self, clear: bool = True) -> None: indexes: dict[str, dict[str, str]] = self.get_value(self.KEY_INDEXES, default=dict()) if self.KEY_USERS not in indexes: @@ -111,14 +111,14 @@ def rebuild_indexes(self, clear: bool = True): self.set_value(self.KEY_INDEXES, indexes) @lock() - def add_index(self, table: str, key: str, id: str): + def add_index(self, table: str, key: str, id: str) -> None: indexes: dict[str, dict[str, str]] = self.get_value(self.KEY_INDEXES) indexes[table][key] = id self.set_value(self.KEY_INDEXES, indexes) @lock() - def remove_index(self, table: str, key: str): + def remove_index(self, table: str, key: str) -> None: indexes: dict[str, dict[str, str]] = self.get_value(self.KEY_INDEXES) indexes[table].pop(key) @@ -130,7 +130,7 @@ def get_id_from_index(self, table: str, key: str) -> str | None: return indexes[table].get(key) @lock() - def _do_init_db_objects(self): + def _do_init_db_objects(self) -> None: self.rebuild_indexes(clear=False) if self.KEY_USERS not in self.get_value(""): @@ -271,7 +271,7 @@ def update_product( name: str | None = None, price_minor: int | None = None, description: str | None = None, - ): + ) -> None: product = self.get_product(id, check_exists=True) if name is not None: @@ -311,7 +311,7 @@ def create_shopping_cart(self, product_ids: list[str]) -> models.ShoppingCart: return obj @lock() - def delete_shopping_cart(self, shopping_cart_id: str): + def delete_shopping_cart(self, shopping_cart_id: str) -> None: # Проверка наличия self.get_shopping_cart(shopping_cart_id, check_exists=True) @@ -325,7 +325,7 @@ def update_shopping_cart( self, shopping_cart_id: str, product_ids: list[str], - ): + ) -> None: shopping_cart: models.ShoppingCart = self.get_shopping_cart( shopping_cart_id, check_exists=True ) @@ -356,7 +356,7 @@ def add_product_in_shopping_cart( self, shopping_cart_id: str, product_id: str, - ): + ) -> None: shopping_cart: models.ShoppingCart = self.get_shopping_cart( shopping_cart_id, check_exists=True ) @@ -372,7 +372,7 @@ def remove_product_from_shopping_cart( self, shopping_cart_id: str, product_id: str, - ): + ) -> None: shopping_cart: models.ShoppingCart = self.get_shopping_cart( shopping_cart_id, check_exists=True ) diff --git a/fastapi__examples/market_from_stepic/src/market/main.py b/fastapi__examples/market_from_stepic/src/market/main.py index 321ed6139..2e1ecb5a4 100644 --- a/fastapi__examples/market_from_stepic/src/market/main.py +++ b/fastapi__examples/market_from_stepic/src/market/main.py @@ -28,7 +28,7 @@ async def unicorn_exception_handler(_: Request, exc: DbException): @app.get("/", response_class=HTMLResponse) -def index(): +def index() -> str: return """\ diff --git a/fastapi__examples/market_from_stepic/src/market/resources.py b/fastapi__examples/market_from_stepic/src/market/resources.py index 0a02406f5..cb3467622 100644 --- a/fastapi__examples/market_from_stepic/src/market/resources.py +++ b/fastapi__examples/market_from_stepic/src/market/resources.py @@ -178,7 +178,7 @@ def create_shopping_cart( @router.delete("/shopping-cart/{id}", status_code=status.HTTP_204_NO_CONTENT) -def delete_shopping_cart(id: str): +def delete_shopping_cart(id: str) -> None: services.delete_shopping_cart(id) diff --git a/fastapi__examples/market_from_stepic/src/market/services.py b/fastapi__examples/market_from_stepic/src/market/services.py index 7f0c12b06..e0f838b71 100644 --- a/fastapi__examples/market_from_stepic/src/market/services.py +++ b/fastapi__examples/market_from_stepic/src/market/services.py @@ -66,7 +66,7 @@ def update_product( name: str | None = None, price_minor: int | None = None, # Копейки description: str | None = None, -): +) -> None: db.update_product( id=id, name=name, @@ -85,15 +85,15 @@ def create_shopping_cart(product_ids: list[str] = None) -> models.IdBasedObj: return models.IdBasedObj(id=shopping_cart.id) -def delete_shopping_cart(shopping_cart_id: str): +def delete_shopping_cart(shopping_cart_id: str) -> None: db.delete_shopping_cart(shopping_cart_id) def add_product_in_shopping_cart( shopping_cart_id: str, product_id: str, -): - return db.add_product_in_shopping_cart( +) -> None: + db.add_product_in_shopping_cart( shopping_cart_id=shopping_cart_id, product_id=product_id, ) @@ -102,8 +102,8 @@ def add_product_in_shopping_cart( def remove_product_from_shopping_cart( shopping_cart_id: str, product_id: str, -): - return db.remove_product_from_shopping_cart( +) -> None: + db.remove_product_from_shopping_cart( shopping_cart_id=shopping_cart_id, product_id=product_id, ) @@ -143,7 +143,7 @@ def update_order( status: models.StatusOrderEnum | None = None, cancel_reason: str | None = None, context_user: models.User | None = None, -): +) -> None: # Клиент не может сам запускать выполнение заказа или завершать его if context_user is None and status in (models.StatusOrderEnum.IN_PROCESSED, models.StatusOrderEnum.FINISHED): raise fastapi.HTTPException( @@ -177,7 +177,7 @@ def submit_order( id: str, status: models.StatusOrderEnum, context_user: models.User | None = None, -): +) -> None: update_order( id=id, status=status, diff --git a/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_bs4.py b/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_bs4.py index 19a1ea629..c64aaff27 100644 --- a/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_bs4.py +++ b/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_bs4.py @@ -23,7 +23,7 @@ from common import get_file_name_from_binary -def do(file_name, output_dir="output", debug=True): +def do(file_name, output_dir="output", debug=True) -> None: dir_fb2 = os.path.basename(file_name) dir_im = os.path.join(output_dir, dir_fb2) os.makedirs(dir_im, exist_ok=True) diff --git a/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_lxml.py b/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_lxml.py index 58541edfa..80f3eb0a4 100644 --- a/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_lxml.py +++ b/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_lxml.py @@ -23,7 +23,7 @@ from common import get_file_name_from_binary -def do(file_name, output_dir="output", debug=True): +def do(file_name, output_dir="output", debug=True) -> None: dir_fb2 = os.path.basename(file_name) dir_im = os.path.join(output_dir, dir_fb2) os.makedirs(dir_im, exist_ok=True) diff --git a/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_lxml_iterwalk.py b/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_lxml_iterwalk.py index 97edda09a..c896e749b 100644 --- a/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_lxml_iterwalk.py +++ b/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_lxml_iterwalk.py @@ -23,7 +23,7 @@ from common import get_file_name_from_binary -def do(file_name, output_dir="output", debug=True): +def do(file_name, output_dir="output", debug=True) -> None: dir_fb2 = os.path.basename(file_name) dir_im = os.path.join(output_dir, dir_fb2) os.makedirs(dir_im, exist_ok=True) diff --git a/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_re.py b/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_re.py index 0afbe7af7..480e171d1 100644 --- a/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_re.py +++ b/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_re.py @@ -25,7 +25,7 @@ from common import get_file_name_from_binary -def do(file_name, output_dir="output", debug=True): +def do(file_name, output_dir="output", debug=True) -> None: dir_fb2 = os.path.basename(file_name) dir_im = os.path.join(output_dir, dir_fb2) os.makedirs(dir_im, exist_ok=True) diff --git a/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_str_find.py b/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_str_find.py index dc5110be0..cbe234673 100644 --- a/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_str_find.py +++ b/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_str_find.py @@ -54,7 +54,7 @@ def iter_blocks(text: str, start_str: str, end_str: str) -> Iterator[str]: yield block -def do(file_name, output_dir="output", debug=True): +def do(file_name, output_dir="output", debug=True) -> None: dir_fb2 = os.path.basename(file_name) dir_im = os.path.join(output_dir, dir_fb2) os.makedirs(dir_im, exist_ok=True) diff --git a/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_xml_etree.py b/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_xml_etree.py index 0809d8bfc..867a8b221 100644 --- a/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_xml_etree.py +++ b/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_xml_etree.py @@ -23,7 +23,7 @@ from common import get_file_name_from_binary -def do(file_name, output_dir="output", debug=True): +def do(file_name, output_dir="output", debug=True) -> None: dir_fb2 = os.path.basename(file_name) dir_im = os.path.join(output_dir, dir_fb2) os.makedirs(dir_im, exist_ok=True) diff --git a/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_xml_etree_xpath.py b/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_xml_etree_xpath.py index fbcde20a3..ae0c4e5a1 100644 --- a/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_xml_etree_xpath.py +++ b/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_xml_etree_xpath.py @@ -23,7 +23,7 @@ from common import get_file_name_from_binary -def do(file_name, output_dir="output", debug=True): +def do(file_name, output_dir="output", debug=True) -> None: dir_fb2 = os.path.basename(file_name) dir_im = os.path.join(output_dir, dir_fb2) os.makedirs(dir_im, exist_ok=True) diff --git a/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_xml_expat.py b/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_xml_expat.py index 6be8b363c..11740ce17 100644 --- a/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_xml_expat.py +++ b/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_xml_expat.py @@ -22,7 +22,7 @@ from common import get_file_name_from_binary -def do(file_name, output_dir="output", debug=True): +def do(file_name, output_dir="output", debug=True) -> None: dir_fb2 = os.path.basename(file_name) dir_im = os.path.join(output_dir, dir_fb2) os.makedirs(dir_im, exist_ok=True) @@ -36,18 +36,18 @@ def do(file_name, output_dir="output", debug=True): "number": 1, } - def on_start_element(name, attrs): + def on_start_element(name, attrs) -> None: PARSE_DATA["last_start_tag"] = name PARSE_DATA["last_tag_attrs"] = attrs PARSE_DATA["last_tag_data"] = "" - def on_char_data(data): + def on_char_data(data) -> None: if PARSE_DATA["last_start_tag"] != "binary": return PARSE_DATA["last_tag_data"] += data - def on_end_element(name): + def on_end_element(name) -> None: if name != "binary": return diff --git a/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_xml_sax.py b/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_xml_sax.py index d96312892..9877c212b 100644 --- a/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_xml_sax.py +++ b/fb2__parsing/extract_pictures_from_fb2/fb2_pictures__using_xml_sax.py @@ -22,7 +22,7 @@ from common import get_file_name_from_binary -def do(file_name, output_dir="output", debug=True): +def do(file_name, output_dir="output", debug=True) -> None: dir_fb2 = os.path.basename(file_name) dir_im = os.path.join(output_dir, dir_fb2) os.makedirs(dir_im, exist_ok=True) @@ -39,18 +39,18 @@ def do(file_name, output_dir="output", debug=True): } class BinaryHandler(xml.sax.ContentHandler): - def startElement(self, name, attrs): + def startElement(self, name, attrs) -> None: PARSE_DATA["last_start_tag"] = name PARSE_DATA["last_tag_attrs"] = attrs PARSE_DATA["last_tag_data"] = "" - def characters(self, content): + def characters(self, content) -> None: if PARSE_DATA["last_start_tag"] != "binary": return PARSE_DATA["last_tag_data"] += content - def endElement(self, name): + def endElement(self, name) -> None: if name != "binary": return diff --git a/fb2__parsing/get_sections.py b/fb2__parsing/get_sections.py index ec6be26b7..fdf63a009 100644 --- a/fb2__parsing/get_sections.py +++ b/fb2__parsing/get_sections.py @@ -9,7 +9,7 @@ def get_sections_as_dict(root) -> dict[str, dict]: # Рекурсивная функция поиска
- def _find_sections(root, root_dict: dict): + def _find_sections(root, root_dict: dict) -> None: for section in root.find_all("section", recursive=False): title = section.title.text.strip() children = dict() @@ -29,7 +29,7 @@ def _find_sections(root, root_dict: dict): def get_sections_as_list(root) -> list[tuple[str, list]]: # Рекурсивная функция поиска
- def _find_sections(root, children_list: list): + def _find_sections(root, children_list: list) -> None: for section in root.find_all("section", recursive=False): title = section.title.text.strip() children = [] @@ -51,7 +51,7 @@ def _find_sections(root, children_list: list): import glob import json - def _print_sections(root: dict, level=1): + def _print_sections(root: dict, level=1) -> None: for title, children in root.items(): text = "{}{}".format(" " * (level - 1), title.replace("\n", ". ")) if children: diff --git a/fb2__parsing/print_section_by_text_number_length.py b/fb2__parsing/print_section_by_text_number_length.py index 1851f3446..54a691d8e 100644 --- a/fb2__parsing/print_section_by_text_number_length.py +++ b/fb2__parsing/print_section_by_text_number_length.py @@ -9,7 +9,7 @@ def get_sections_as_dict(root) -> tuple[dict[str, dict], dict[str, Tag]]: # Рекурсивная функция поиска
- def _find_sections(root, root_dict: dict, title_by_section: dict): + def _find_sections(root, root_dict: dict, title_by_section: dict) -> None: for section in root.find_all("section", recursive=False): title = section.title.text.strip() children = dict() @@ -33,7 +33,7 @@ def get_section_by_text( section_by_children: dict[str, dict], title_by_section: dict[str, Tag], ) -> dict[str, str]: - def _find_sections(section_by_text, section_by_children): + def _find_sections(section_by_text, section_by_children) -> None: for title, children in section_by_children.items(): if children: _find_sections(section_by_text, children) @@ -64,8 +64,8 @@ def _print_sections( section_by_text: dict, number_length_book_text, level=1 - ): - def _find_section_lines(root, level, lines: list): + ) -> None: + def _find_section_lines(root, level, lines: list) -> None: for title, children in root.items(): text = "{}{}".format(" " * (level - 1), title.replace("\n", ". ")) diff --git a/file_tree_maker.py b/file_tree_maker.py index eb6561044..67fbab1cd 100644 --- a/file_tree_maker.py +++ b/file_tree_maker.py @@ -13,7 +13,7 @@ class FileTreeMaker: - def _recurse(self, parent_path, file_list, prefix, output_buf, level): + def _recurse(self, parent_path, file_list, prefix, output_buf, level) -> None: if len(file_list) == 0 or (self.max_level != -1 and self.max_level <= level): return else: diff --git a/firefox/api.py b/firefox/api.py index 2cd9f4deb..5e509a032 100644 --- a/firefox/api.py +++ b/firefox/api.py @@ -38,7 +38,7 @@ def close_tabs( file_name_session: Path, urls: list[str], log: logging.Logger, -): +) -> None: modified = False json_data = get_sessionstore(file_name_session) @@ -61,7 +61,7 @@ def close_tabs( def close_duplicate_tabs( file_name_session: Path, log: logging.Logger, -): +) -> None: json_data = get_sessionstore(file_name_session) urls = get_tab_urls_from_sessionstore(json_data) @@ -99,7 +99,7 @@ def close_bookmarks( file_name_places: Path, urls: list[str], log: logging.Logger, -): +) -> None: with sqlite3.connect(file_name_places) as connect: for url in urls: sql = "SELECT id FROM moz_bookmarks WHERE fk = (SELECT id FROM moz_places WHERE url = ?)" diff --git a/firefox/jsonlz4_mozLz4/mozlz4a.py b/firefox/jsonlz4_mozLz4/mozlz4a.py index 128014ee3..bbee46ea8 100644 --- a/firefox/jsonlz4_mozLz4/mozlz4a.py +++ b/firefox/jsonlz4_mozLz4/mozlz4a.py @@ -79,7 +79,7 @@ def loads_json(file_obj: BinaryIO) -> dict: return json.loads(data) -def dumps_json(file_obj: BinaryIO, json_data: dict): +def dumps_json(file_obj: BinaryIO, json_data: dict) -> None: data = json.dumps(json_data).encode("utf-8") compressed = compress_data(data) diff --git a/firefox/jsonlz4_mozLz4/test/test.py b/firefox/jsonlz4_mozLz4/test/test.py index a65eed66f..2179a9864 100644 --- a/firefox/jsonlz4_mozLz4/test/test.py +++ b/firefox/jsonlz4_mozLz4/test/test.py @@ -22,11 +22,11 @@ class TestAll(unittest.TestCase): - def test_1_exists_file(self): + def test_1_exists_file(self) -> None: self.assertTrue(FILE_TEST.exists()) self.assertTrue(FILE_TEST.read_bytes()) - def test_decompress_compress(self): + def test_decompress_compress(self) -> None: with open(FILE_TEST, "rb") as f: expected_data = mozlz4a.decompress(f) @@ -38,7 +38,7 @@ def test_decompress_compress(self): self.assertEqual(expected_data, data) - def test_compress_decompress_data(self): + def test_compress_decompress_data(self) -> None: expected_data = str(uuid.uuid4()).encode("utf-8") compressed_data = mozlz4a.compress_data(expected_data) @@ -46,7 +46,7 @@ def test_compress_decompress_data(self): self.assertEqual(expected_data, data) - def test_json(self): + def test_json(self) -> None: with open(FILE_TEST, "rb") as f: expected_json_data = mozlz4a.loads_json(f) diff --git a/flask-paginate__example/app.py b/flask-paginate__example/app.py index 73d99425f..57ed5fd7c 100644 --- a/flask-paginate__example/app.py +++ b/flask-paginate__example/app.py @@ -17,14 +17,14 @@ @app.before_request -def before_request(): +def before_request() -> None: g.conn = sqlite3.connect("test.db") g.conn.row_factory = sqlite3.Row g.cur = g.conn.cursor() @app.teardown_request -def teardown(error): +def teardown(error) -> None: if hasattr(g, "conn"): g.conn.close() @@ -135,7 +135,7 @@ def get_pagination(**kwargs): @click.command() @click.option("--port", "-p", default=5000, help="listening port") -def run(port): +def run(port) -> None: app.run(debug=True, port=port) diff --git a/flask-paginate__example/sql.py b/flask-paginate__example/sql.py index 6364baef1..21fc60f4b 100644 --- a/flask-paginate__example/sql.py +++ b/flask-paginate__example/sql.py @@ -16,12 +16,12 @@ @click.group() -def cli(): +def cli() -> None: pass @cli.command(short_help="initialize database and tables") -def init_db(): +def init_db() -> None: conn = sqlite3.connect("test.db") cur = conn.cursor() cur.execute(sql) @@ -31,7 +31,7 @@ def init_db(): @cli.command(short_help="fill records to database") @click.option("--total", "-t", default=300, help="fill data for example") -def fill_data(total): +def fill_data(total) -> None: conn = sqlite3.connect("test.db") cur = conn.cursor() for i in range(total): diff --git a/flask__webservers/cors__hello_world.py b/flask__webservers/cors__hello_world.py index 533425d6f..f771cddde 100644 --- a/flask__webservers/cors__hello_world.py +++ b/flask__webservers/cors__hello_world.py @@ -16,7 +16,7 @@ @app.route("/") -def index(): +def index() -> str: return "Hello World!" diff --git a/flask__webservers/custom_error_page/main.py b/flask__webservers/custom_error_page/main.py index 70626a955..64c67879b 100644 --- a/flask__webservers/custom_error_page/main.py +++ b/flask__webservers/custom_error_page/main.py @@ -39,7 +39,7 @@ def index(): @app.route("/500") -def do_500(): +def do_500() -> None: 1/0 diff --git a/flask__webservers/flask_debugtoolbar__examples/app.py b/flask__webservers/flask_debugtoolbar__examples/app.py index 567468709..85a51fbea 100644 --- a/flask__webservers/flask_debugtoolbar__examples/app.py +++ b/flask__webservers/flask_debugtoolbar__examples/app.py @@ -28,7 +28,7 @@ class ExampleModel(db.Model): @app.before_first_request -def setup(): +def setup() -> None: db.create_all() diff --git a/flask__webservers/flask_debugtoolbar__examples/hello_world.py b/flask__webservers/flask_debugtoolbar__examples/hello_world.py index 58fbad365..d6846fb15 100644 --- a/flask__webservers/flask_debugtoolbar__examples/hello_world.py +++ b/flask__webservers/flask_debugtoolbar__examples/hello_world.py @@ -17,7 +17,7 @@ @app.route("/") -def index(): +def index() -> str: # NOTE: Need tab body: "Could not insert debug toolbar. tag not found in response." return "Hello World!" diff --git a/flask__webservers/get_URL__parameter_argument_query.py b/flask__webservers/get_URL__parameter_argument_query.py index 2038e8ad8..1145a004d 100644 --- a/flask__webservers/get_URL__parameter_argument_query.py +++ b/flask__webservers/get_URL__parameter_argument_query.py @@ -13,7 +13,7 @@ @app.route("/") -def index(): +def index() -> str: return """
diff --git a/flask__webservers/get_upload_and_image_process/main.py b/flask__webservers/get_upload_and_image_process/main.py index a62f2f7bc..6c7b48f64 100644 --- a/flask__webservers/get_upload_and_image_process/main.py +++ b/flask__webservers/get_upload_and_image_process/main.py @@ -35,7 +35,7 @@ # SOURCE: https://github.com/gil9red/SimplePyScripts/blob/master/img_to_base64_html/main.py -def img_to_base64_html(file_name__or__bytes__or__file_object): +def img_to_base64_html(file_name__or__bytes__or__file_object) -> str: arg = file_name__or__bytes__or__file_object if type(arg) == str: @@ -72,12 +72,12 @@ def img_to_base64_html(file_name__or__bytes__or__file_object): LAST_IMAGE = "last_image.jpg" -def save_last_image(file_data): +def save_last_image(file_data) -> None: with open(LAST_IMAGE, "wb") as f: f.write(file_data) -def load_last_image(): +def load_last_image() -> bytes: with open(LAST_IMAGE, "rb") as f: return f.read() diff --git a/flask__webservers/get_upload_image_info/main.py b/flask__webservers/get_upload_image_info/main.py index 20f5cc492..b1a2edacb 100644 --- a/flask__webservers/get_upload_image_info/main.py +++ b/flask__webservers/get_upload_image_info/main.py @@ -85,7 +85,7 @@ def get_exif_tags(file_object_or_file_name, as_category=True): # SOURCE: https://github.com/gil9red/SimplePyScripts/blob/master/img_to_base64_html/main.py -def img_to_base64_html(file_name__or__bytes__or__file_object): +def img_to_base64_html(file_name__or__bytes__or__file_object) -> str: arg = file_name__or__bytes__or__file_object if type(arg) == str: diff --git a/flask__webservers/hello_world.py b/flask__webservers/hello_world.py index 0c8f7ba98..90f9c84e3 100644 --- a/flask__webservers/hello_world.py +++ b/flask__webservers/hello_world.py @@ -14,7 +14,7 @@ @app.route("/") -def index(): +def index() -> str: return "Hello World!" diff --git a/flask__webservers/logging__examples/main_new.py b/flask__webservers/logging__examples/main_new.py index 0d6d4809a..8000e0e63 100644 --- a/flask__webservers/logging__examples/main_new.py +++ b/flask__webservers/logging__examples/main_new.py @@ -41,7 +41,7 @@ @app.route("/") -def index(): +def index() -> str: log.debug("call index") return "Hello World!" diff --git a/flask__webservers/logging__examples/main_old.py b/flask__webservers/logging__examples/main_old.py index fa9b5c5f8..e5bdab429 100644 --- a/flask__webservers/logging__examples/main_old.py +++ b/flask__webservers/logging__examples/main_old.py @@ -43,7 +43,7 @@ @app.route("/") -def index(): +def index() -> str: log.debug("call index") return "Hello World!" diff --git a/flask__webservers/logging__remove_date_from_werkzeug_logs/main_new.py b/flask__webservers/logging__remove_date_from_werkzeug_logs/main_new.py index 4602df5a8..6c2e83aec 100644 --- a/flask__webservers/logging__remove_date_from_werkzeug_logs/main_new.py +++ b/flask__webservers/logging__remove_date_from_werkzeug_logs/main_new.py @@ -41,7 +41,7 @@ @app.route("/") -def index(): +def index() -> str: log.debug("call index") return "Hello World!" diff --git a/flask__webservers/logging__remove_date_from_werkzeug_logs/main_old.py b/flask__webservers/logging__remove_date_from_werkzeug_logs/main_old.py index 46cd6c1a3..7b7c003bb 100644 --- a/flask__webservers/logging__remove_date_from_werkzeug_logs/main_old.py +++ b/flask__webservers/logging__remove_date_from_werkzeug_logs/main_old.py @@ -47,7 +47,7 @@ @app.route("/") -def index(): +def index() -> str: log.debug("call index") return "Hello World!" diff --git a/flask__webservers/post_data.py b/flask__webservers/post_data.py index d220702f3..6d22577a5 100644 --- a/flask__webservers/post_data.py +++ b/flask__webservers/post_data.py @@ -13,7 +13,7 @@ @app.route("/") -def index(): +def index() -> str: return """
diff --git a/flask__webservers/post_data__as_form.py b/flask__webservers/post_data__as_form.py index 8cb12bb16..ab732dd71 100644 --- a/flask__webservers/post_data__as_form.py +++ b/flask__webservers/post_data__as_form.py @@ -13,7 +13,7 @@ @app.route("/") -def index(): +def index() -> str: return """

diff --git a/flask__webservers/post_data__as_json.py b/flask__webservers/post_data__as_json.py index 5a312d5e3..3c44aa550 100644 --- a/flask__webservers/post_data__as_json.py +++ b/flask__webservers/post_data__as_json.py @@ -13,7 +13,7 @@ @app.route("/") -def index(): +def index() -> str: return """
diff --git a/flask__webservers/print_hex_post_data/main.py b/flask__webservers/print_hex_post_data/main.py index f3c94f9b7..e8b699b97 100644 --- a/flask__webservers/print_hex_post_data/main.py +++ b/flask__webservers/print_hex_post_data/main.py @@ -16,7 +16,7 @@ @app.route("/", methods=["POST"]) -def index(): +def index() -> str: data = request.data print(binascii.hexlify(data), data) diff --git a/flask__webservers/run_with_random_port/main.py b/flask__webservers/run_with_random_port/main.py index 56f3411aa..f9a8d2d53 100644 --- a/flask__webservers/run_with_random_port/main.py +++ b/flask__webservers/run_with_random_port/main.py @@ -13,7 +13,7 @@ @app.route("/") -def hello(): +def hello() -> str: return "Hello, world! running on %s" % request.host diff --git a/flask__webservers/server__handle_stdin__input.py b/flask__webservers/server__handle_stdin__input.py index 3abaef6fa..288ff43e8 100644 --- a/flask__webservers/server__handle_stdin__input.py +++ b/flask__webservers/server__handle_stdin__input.py @@ -20,7 +20,7 @@ text = "Hello World!" -def go(): +def go() -> None: time.sleep(2) print("\n") diff --git a/flask__webservers/server_with_additional_command_thread/main.py b/flask__webservers/server_with_additional_command_thread/main.py index 9b02595ba..fcb917e94 100644 --- a/flask__webservers/server_with_additional_command_thread/main.py +++ b/flask__webservers/server_with_additional_command_thread/main.py @@ -40,7 +40,7 @@ def img_search(): return "text: " + text -def loop_command_function(): +def loop_command_function() -> None: while True: global EXECUTE_COMMAND, COMMAND_TEXT diff --git a/flask__webservers/server_with_window_notification/main.py b/flask__webservers/server_with_window_notification/main.py index 57feff913..c7a16d49f 100644 --- a/flask__webservers/server_with_window_notification/main.py +++ b/flask__webservers/server_with_window_notification/main.py @@ -23,7 +23,7 @@ logging.basicConfig(level=logging.DEBUG) -def show(text): +def show(text) -> None: title = str(threading.current_thread()) run_in_thread(title, text, duration=20) @@ -34,7 +34,7 @@ def index(): @app.route("/show_notification") -def show_notification(): +def show_notification() -> str: text = request.args.get("text") print("text:", text) diff --git a/flask__webservers/show_lunch_menu_from_email/main.py b/flask__webservers/show_lunch_menu_from_email/main.py index a8635c7aa..6ebcd5323 100644 --- a/flask__webservers/show_lunch_menu_from_email/main.py +++ b/flask__webservers/show_lunch_menu_from_email/main.py @@ -67,7 +67,7 @@ def save_attachment(msg): return file_name -def add_lunch_email_info(msg, file_name): +def add_lunch_email_info(msg, file_name) -> None: """ Функция для добавления в поле comments docx информации о письме. diff --git a/flask__webservers/show_my_ip/main.py b/flask__webservers/show_my_ip/main.py index 88f4f3558..8ff891a59 100644 --- a/flask__webservers/show_my_ip/main.py +++ b/flask__webservers/show_my_ip/main.py @@ -13,7 +13,7 @@ @app.route("/") -def index(): +def index() -> str: return f"""Your IPv4 Address Is: {request.remote_addr}""" diff --git a/flask__webservers/simple_upload_server/main.py b/flask__webservers/simple_upload_server/main.py index 0eeb582f9..2f5faf9aa 100644 --- a/flask__webservers/simple_upload_server/main.py +++ b/flask__webservers/simple_upload_server/main.py @@ -11,7 +11,7 @@ @app.route("/", methods=["POST"]) -def index(): +def index() -> str: file = request.files["file"] # file.save(file.filename) # OR: diff --git a/flask__webservers/upload_and_download_files/test_download_from_script.py b/flask__webservers/upload_and_download_files/test_download_from_script.py index 473254f09..c52b6b141 100644 --- a/flask__webservers/upload_and_download_files/test_download_from_script.py +++ b/flask__webservers/upload_and_download_files/test_download_from_script.py @@ -10,7 +10,7 @@ from humanize import naturalsize as sizeof_fmt -def progress(count, block_size, total_size): +def progress(count, block_size, total_size) -> None: percent = count * block_size * 100.0 / total_size print( f"Download: {sizeof_fmt(count * block_size)}/{sizeof_fmt(total_size)}({percent:.1f}%)" @@ -19,7 +19,7 @@ def progress(count, block_size, total_size): ) -def create_test_file(): +def create_test_file() -> None: file_name = "uploads/bigfile" if os.path.exists(file_name): return diff --git a/flask__webservers/url_shortener/db.py b/flask__webservers/url_shortener/db.py index 37cfb91a8..2b8c3dc08 100644 --- a/flask__webservers/url_shortener/db.py +++ b/flask__webservers/url_shortener/db.py @@ -23,7 +23,7 @@ def generate_link_id(length: int = LENGTH_URL_ID) -> str: class NotDefinedParameterException(Exception): - def __init__(self, parameter_name: str): + def __init__(self, parameter_name: str) -> None: self.parameter_name = parameter_name text = f'Parameter "{self.parameter_name}" must be defined!' @@ -73,7 +73,7 @@ def get_inherited_models(cls) -> list[Type["BaseModel"]]: return sorted(cls.__subclasses__(), key=lambda x: x.__name__) @classmethod - def print_count_of_tables(cls): + def print_count_of_tables(cls) -> None: items = [] for sub_cls in cls.get_inherited_models(): name = sub_cls.__name__ @@ -89,7 +89,7 @@ def count(cls, filters: Iterable = None) -> int: query = query.filter(*filters) return query.count() - def __str__(self): + def __str__(self) -> str: fields = [] for k, field in self._meta.fields.items(): v = getattr(self, k) diff --git a/flask__webservers/users/main_with_db.py b/flask__webservers/users/main_with_db.py index 1a8a7a961..7f8fb28af 100644 --- a/flask__webservers/users/main_with_db.py +++ b/flask__webservers/users/main_with_db.py @@ -207,7 +207,7 @@ def logout(): @app.route("/protected") @flask_login.login_required -def protected(): +def protected() -> str: return f"Logged in as: {flask_login.current_user.username}" diff --git a/flask__webservers/users/main_without_db.py b/flask__webservers/users/main_without_db.py index a98b7223d..927caa1fd 100644 --- a/flask__webservers/users/main_without_db.py +++ b/flask__webservers/users/main_without_db.py @@ -119,7 +119,7 @@ def login(): @app.route("/protected") @flask_login.login_required -def protected(): +def protected() -> str: return f"Logged in as: {flask_login.current_user.id}" diff --git a/flask__websocket/ajax_vs_websocket/websocket/main.py b/flask__websocket/ajax_vs_websocket/websocket/main.py index 34a2f922d..f39e0d5b1 100644 --- a/flask__websocket/ajax_vs_websocket/websocket/main.py +++ b/flask__websocket/ajax_vs_websocket/websocket/main.py @@ -40,7 +40,7 @@ def index(): @socketio.on("post_method", namespace="/test") -def post_method(message): +def post_method(message) -> None: # print(message) with lock: diff --git a/flask__websocket/commands__websocket__flask-socketio/main.py b/flask__websocket/commands__websocket__flask-socketio/main.py index 0eeecb564..4324325e4 100644 --- a/flask__websocket/commands__websocket__flask-socketio/main.py +++ b/flask__websocket/commands__websocket__flask-socketio/main.py @@ -27,7 +27,7 @@ def index(): @socketio.on("my_event", namespace="/test") -def test_message(message): +def test_message(message) -> None: session["receive_count"] = session.get("receive_count", 0) + 1 print(message) @@ -54,17 +54,17 @@ def test_message(message): @socketio.on("my_ping", namespace="/test") -def ping_pong(): +def ping_pong() -> None: emit("my_pong") @socketio.on("connect", namespace="/test") -def test_connect(): +def test_connect() -> None: emit("my_response", {"data": "Connected"}) @socketio.on("disconnect", namespace="/test") -def test_disconnect(): +def test_disconnect() -> None: print("Client disconnected", request.sid) diff --git a/flask__websocket/sending_all_from_while_in_thread/main.py b/flask__websocket/sending_all_from_while_in_thread/main.py index 814dd0a34..fce7334c0 100644 --- a/flask__websocket/sending_all_from_while_in_thread/main.py +++ b/flask__websocket/sending_all_from_while_in_thread/main.py @@ -25,7 +25,7 @@ socketio = SocketIO(app, async_mode=async_mode) -def send_all_cycled(): +def send_all_cycled() -> None: with app.app_context(): i = 0 while True: @@ -50,7 +50,7 @@ def index(): @socketio.on("my_event") -def test_message(message): +def test_message(message) -> None: session["receive_count"] = session.get("receive_count", 0) + 1 print(message) @@ -63,18 +63,18 @@ def test_message(message): @socketio.on("my_ping") -def ping_pong(): +def ping_pong() -> None: emit("my_pong") @socketio.on("connect") -def test_connect(): +def test_connect() -> None: print("Client connected", request.sid) emit("my_response", {"data": f"Connected!", "count": 0, "sid": request.sid}) @socketio.on("disconnect") -def test_disconnect(): +def test_disconnect() -> None: print("Client disconnected", request.sid) diff --git a/flask__websocket/simple_chat/main.py b/flask__websocket/simple_chat/main.py index 3b39ff133..55928b994 100644 --- a/flask__websocket/simple_chat/main.py +++ b/flask__websocket/simple_chat/main.py @@ -26,7 +26,7 @@ def index(): @socketio.on("my_event", namespace="/test") -def test_message(message): +def test_message(message) -> None: session["receive_count"] = session.get("receive_count", 0) + 1 print(message) @@ -39,17 +39,17 @@ def test_message(message): @socketio.on("my_ping", namespace="/test") -def ping_pong(): +def ping_pong() -> None: emit("my_pong") @socketio.on("connect", namespace="/test") -def test_connect(): +def test_connect() -> None: emit("my_response", {"data": f"Connected!", "count": 0, "sid": request.sid}) @socketio.on("disconnect", namespace="/test") -def test_disconnect(): +def test_disconnect() -> None: print("Client disconnected", request.sid) diff --git a/flask__websocket/websocket__flask-socketio_example/app.py b/flask__websocket/websocket__flask-socketio_example/app.py index d66496e44..526556795 100644 --- a/flask__websocket/websocket__flask-socketio_example/app.py +++ b/flask__websocket/websocket__flask-socketio_example/app.py @@ -27,7 +27,7 @@ thread_lock = Lock() -def background_thread(): +def background_thread() -> None: """Example of how to send server generated events to clients.""" count = 0 while True: @@ -46,7 +46,7 @@ def index(): @socketio.on("my_event", namespace="/test") -def test_message(message): +def test_message(message) -> None: session["receive_count"] = session.get("receive_count", 0) + 1 emit( "my_response", @@ -55,7 +55,7 @@ def test_message(message): @socketio.on("my_broadcast_event", namespace="/test") -def test_broadcast_message(message): +def test_broadcast_message(message) -> None: session["receive_count"] = session.get("receive_count", 0) + 1 emit( "my_response", @@ -65,7 +65,7 @@ def test_broadcast_message(message): @socketio.on("join", namespace="/test") -def join(message): +def join(message) -> None: join_room(message["room"]) session["receive_count"] = session.get("receive_count", 0) + 1 emit( @@ -75,7 +75,7 @@ def join(message): @socketio.on("leave", namespace="/test") -def leave(message): +def leave(message) -> None: leave_room(message["room"]) session["receive_count"] = session.get("receive_count", 0) + 1 emit( @@ -85,7 +85,7 @@ def leave(message): @socketio.on("close_room", namespace="/test") -def close(message): +def close(message) -> None: session["receive_count"] = session.get("receive_count", 0) + 1 emit( "my_response", @@ -99,7 +99,7 @@ def close(message): @socketio.on("my_room_event", namespace="/test") -def send_room_message(message): +def send_room_message(message) -> None: session["receive_count"] = session.get("receive_count", 0) + 1 emit( "my_response", @@ -109,9 +109,9 @@ def send_room_message(message): @socketio.on("disconnect_request", namespace="/test") -def disconnect_request(): +def disconnect_request() -> None: @copy_current_request_context - def can_disconnect(): + def can_disconnect() -> None: disconnect() session["receive_count"] = session.get("receive_count", 0) + 1 @@ -126,12 +126,12 @@ def can_disconnect(): @socketio.on("my_ping", namespace="/test") -def ping_pong(): +def ping_pong() -> None: emit("my_pong") @socketio.on("connect", namespace="/test") -def test_connect(): +def test_connect() -> None: global thread with thread_lock: if thread is None: @@ -140,7 +140,7 @@ def test_connect(): @socketio.on("disconnect", namespace="/test") -def test_disconnect(): +def test_disconnect() -> None: print("Client disconnected", request.sid) diff --git a/flask__websocket/websocket__flask-socketio_example/app_namespace.py b/flask__websocket/websocket__flask-socketio_example/app_namespace.py index f7afbc120..8b8b9bf6d 100644 --- a/flask__websocket/websocket__flask-socketio_example/app_namespace.py +++ b/flask__websocket/websocket__flask-socketio_example/app_namespace.py @@ -27,7 +27,7 @@ thread_lock = Lock() -def background_thread(): +def background_thread() -> None: """Example of how to send server generated events to clients.""" count = 0 while True: @@ -46,14 +46,14 @@ def index(): class MyNamespace(Namespace): - def on_my_event(self, message): + def on_my_event(self, message) -> None: session["receive_count"] = session.get("receive_count", 0) + 1 emit( "my_response", {"data": message["data"], "count": session["receive_count"]}, ) - def on_my_broadcast_event(self, message): + def on_my_broadcast_event(self, message) -> None: session["receive_count"] = session.get("receive_count", 0) + 1 emit( "my_response", @@ -61,7 +61,7 @@ def on_my_broadcast_event(self, message): broadcast=True, ) - def on_join(self, message): + def on_join(self, message) -> None: join_room(message["room"]) session["receive_count"] = session.get("receive_count", 0) + 1 emit( @@ -72,7 +72,7 @@ def on_join(self, message): }, ) - def on_leave(self, message): + def on_leave(self, message) -> None: leave_room(message["room"]) session["receive_count"] = session.get("receive_count", 0) + 1 emit( @@ -83,7 +83,7 @@ def on_leave(self, message): }, ) - def on_close_room(self, message): + def on_close_room(self, message) -> None: session["receive_count"] = session.get("receive_count", 0) + 1 emit( "my_response", @@ -95,7 +95,7 @@ def on_close_room(self, message): ) close_room(message["room"]) - def on_my_room_event(self, message): + def on_my_room_event(self, message) -> None: session["receive_count"] = session.get("receive_count", 0) + 1 emit( "my_response", @@ -103,7 +103,7 @@ def on_my_room_event(self, message): room=message["room"], ) - def on_disconnect_request(self): + def on_disconnect_request(self) -> None: session["receive_count"] = session.get("receive_count", 0) + 1 emit( "my_response", @@ -111,17 +111,17 @@ def on_disconnect_request(self): ) disconnect() - def on_my_ping(self): + def on_my_ping(self) -> None: emit("my_pong") - def on_connect(self): + def on_connect(self) -> None: global thread with thread_lock: if thread is None: thread = socketio.start_background_task(background_thread) emit("my_response", {"data": "Connected", "count": 0}) - def on_disconnect(self): + def on_disconnect(self) -> None: print("Client disconnected", request.sid) diff --git a/flask__websocket/websocket__flask-socketio_example/requirements.txt b/flask__websocket/websocket__flask-socketio_example/requirements.txt index fd8b27c6b..736c5fac4 100644 --- a/flask__websocket/websocket__flask-socketio_example/requirements.txt +++ b/flask__websocket/websocket__flask-socketio_example/requirements.txt @@ -8,4 +8,4 @@ MarkupSafe==1.1.0 python-engineio python-socketio six==1.11.0 -Werkzeug==3.1.5 +Werkzeug==3.1.6 diff --git a/flask__websocket/websocket__flask-socketio_example/sessions.py b/flask__websocket/websocket__flask-socketio_example/sessions.py index 9920d6b83..882e6749c 100644 --- a/flask__websocket/websocket__flask-socketio_example/sessions.py +++ b/flask__websocket/websocket__flask-socketio_example/sessions.py @@ -13,7 +13,7 @@ class User(UserMixin, object): - def __init__(self, id=None): + def __init__(self, id=None) -> None: self.id = id @@ -46,7 +46,7 @@ def session_access(): @socketio.on("get-session") -def get_session(): +def get_session() -> None: emit( "refresh-session", { @@ -57,7 +57,7 @@ def get_session(): @socketio.on("set-session") -def set_session(data): +def set_session(data) -> None: if "session" in data: session["value"] = data["session"] elif "user" in data: diff --git a/flask_http_auth/http_digest_auth.py b/flask_http_auth/http_digest_auth.py index db5c92ce8..c3eb060c9 100644 --- a/flask_http_auth/http_digest_auth.py +++ b/flask_http_auth/http_digest_auth.py @@ -34,7 +34,7 @@ def get_password(username: str) -> str | None: @app.route("/") @auth.login_required -def index(): +def index() -> str: return f"Hello, {auth.username()}!" diff --git a/flask_restful__examples/todo/main.py b/flask_restful__examples/todo/main.py index b1b3a647b..5ef9fa067 100644 --- a/flask_restful__examples/todo/main.py +++ b/flask_restful__examples/todo/main.py @@ -22,7 +22,7 @@ } -def abort_if_todo_doesnt_exist(todo_id): +def abort_if_todo_doesnt_exist(todo_id) -> None: if todo_id not in TODOS: abort(404, message=f"Todo {todo_id} doesn't exist") diff --git "a/for_games/Bloodborne/bloodborne_fandom_com__ru__wiki__\320\221\320\276\321\201\321\201\321\213/main.py" "b/for_games/Bloodborne/bloodborne_fandom_com__ru__wiki__\320\221\320\276\321\201\321\201\321\213/main.py" index 6f9976f18..a84dade8d 100644 --- "a/for_games/Bloodborne/bloodborne_fandom_com__ru__wiki__\320\221\320\276\321\201\321\201\321\213/main.py" +++ "b/for_games/Bloodborne/bloodborne_fandom_com__ru__wiki__\320\221\320\276\321\201\321\201\321\213/main.py" @@ -54,7 +54,7 @@ def get_bosses() -> dict[str, list[Boss]]: return bosses_by_category -def print_bosses(bosses: dict[str, list[Boss]]): +def print_bosses(bosses: dict[str, list[Boss]]) -> None: total = sum(len(i) for i in bosses.values()) print(f"Боссы ({total}):") @@ -75,7 +75,7 @@ def convert_bosses_to_only_name(bosses: dict[str, list[Boss]]) -> dict[str, list return bosses_only_name -def export_to_json(file_name: Path, bosses: dict[str, list[Boss | str]]): +def export_to_json(file_name: Path, bosses: dict[str, list[Boss | str]]) -> None: file_name.parent.mkdir(parents=True, exist_ok=True) json.dump( @@ -87,7 +87,7 @@ def export_to_json(file_name: Path, bosses: dict[str, list[Boss | str]]): ) -def export_to_simple_text(file_name, bosses: dict[str, list[Boss]]): +def export_to_simple_text(file_name, bosses: dict[str, list[Boss]]) -> None: file_name.parent.mkdir(parents=True, exist_ok=True) with open(file_name, "w", encoding="utf-8") as f: diff --git "a/for_games/Bloodborne/bloodborne_fandom_com__ru__wiki__\320\232\320\260\321\202\320\265\320\263\320\276\321\200\320\270\321\217_\320\233\320\276\320\272\320\260\321\206\320\270\320\270/dumps/locations.json" "b/for_games/Bloodborne/bloodborne_fandom_com__ru__wiki__\320\232\320\260\321\202\320\265\320\263\320\276\321\200\320\270\321\217_\320\233\320\276\320\272\320\260\321\206\320\270\320\270/dumps/locations.json" new file mode 100644 index 000000000..2f871ea0d --- /dev/null +++ "b/for_games/Bloodborne/bloodborne_fandom_com__ru__wiki__\320\232\320\260\321\202\320\265\320\263\320\276\321\200\320\270\321\217_\320\233\320\276\320\272\320\260\321\206\320\270\320\270/dumps/locations.json" @@ -0,0 +1,46 @@ +{ + "Алтарь отчаяния": "https://bloodborne.fandom.com/ru/wiki/%D0%90%D0%BB%D1%82%D0%B0%D1%80%D1%8C_%D0%BE%D1%82%D1%87%D0%B0%D1%8F%D0%BD%D0%B8%D1%8F", + "Астральная часовая башня": "https://bloodborne.fandom.com/ru/wiki/%D0%90%D1%81%D1%82%D1%80%D0%B0%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D1%87%D0%B0%D1%81%D0%BE%D0%B2%D0%B0%D1%8F_%D0%B1%D0%B0%D1%88%D0%BD%D1%8F", + "Большой мост": "https://bloodborne.fandom.com/ru/wiki/%D0%91%D0%BE%D0%BB%D1%8C%D1%88%D0%BE%D0%B9_%D0%BC%D0%BE%D1%81%D1%82", + "Бюргенверт": "https://bloodborne.fandom.com/ru/wiki/%D0%91%D1%8E%D1%80%D0%B3%D0%B5%D0%BD%D0%B2%D0%B5%D1%80%D1%82", + "Верхний Соборный округ": "https://bloodborne.fandom.com/ru/wiki/%D0%92%D0%B5%D1%80%D1%85%D0%BD%D0%B8%D0%B9_%D0%A1%D0%BE%D0%B1%D0%BE%D1%80%D0%BD%D1%8B%D0%B9_%D0%BE%D0%BA%D1%80%D1%83%D0%B3", + "Главный собор": "https://bloodborne.fandom.com/ru/wiki/%D0%93%D0%BB%D0%B0%D0%B2%D0%BD%D1%8B%D0%B9_%D1%81%D0%BE%D0%B1%D0%BE%D1%80", + "Главный собор кошмара": "https://bloodborne.fandom.com/ru/wiki/%D0%93%D0%BB%D0%B0%D0%B2%D0%BD%D1%8B%D0%B9_%D1%81%D0%BE%D0%B1%D0%BE%D1%80_%D0%BA%D0%BE%D1%88%D0%BC%D0%B0%D1%80%D0%B0", + "Граница кошмара": "https://bloodborne.fandom.com/ru/wiki/%D0%93%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0_%D0%BA%D0%BE%D1%88%D0%BC%D0%B0%D1%80%D0%B0", + "Гробница Идон": "https://bloodborne.fandom.com/ru/wiki/%D0%93%D1%80%D0%BE%D0%B1%D0%BD%D0%B8%D1%86%D0%B0_%D0%98%D0%B4%D0%BE%D0%BD", + "Зал Амигдалы": "https://bloodborne.fandom.com/ru/wiki/%D0%97%D0%B0%D0%BB_%D0%90%D0%BC%D0%B8%D0%B3%D0%B4%D0%B0%D0%BB%D1%8B", + "Зал исследований": "https://bloodborne.fandom.com/ru/wiki/%D0%97%D0%B0%D0%BB_%D0%B8%D1%81%D1%81%D0%BB%D0%B5%D0%B4%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B9", + "Зал королевы Нечистокровных": "https://bloodborne.fandom.com/ru/wiki/%D0%97%D0%B0%D0%BB_%D0%BA%D0%BE%D1%80%D0%BE%D0%BB%D0%B5%D0%B2%D1%8B_%D0%9D%D0%B5%D1%87%D0%B8%D1%81%D1%82%D0%BE%D0%BA%D1%80%D0%BE%D0%B2%D0%BD%D1%8B%D1%85", + "Запретная могила": "https://bloodborne.fandom.com/ru/wiki/%D0%97%D0%B0%D0%BF%D1%80%D0%B5%D1%82%D0%BD%D0%B0%D1%8F_%D0%BC%D0%BE%D0%B3%D0%B8%D0%BB%D0%B0", + "Запретный лес": "https://bloodborne.fandom.com/ru/wiki/%D0%97%D0%B0%D0%BF%D1%80%D0%B5%D1%82%D0%BD%D1%8B%D0%B9_%D0%BB%D0%B5%D1%81", + "Кладбище Черного чудовища": "https://bloodborne.fandom.com/ru/wiki/%D0%9A%D0%BB%D0%B0%D0%B4%D0%B1%D0%B8%D1%89%D0%B5_%D0%A7%D0%B5%D1%80%D0%BD%D0%BE%D0%B3%D0%BE_%D1%87%D1%83%D0%B4%D0%BE%D0%B2%D0%B8%D1%89%D0%B0", + "Кошмар Менсиса": "https://bloodborne.fandom.com/ru/wiki/%D0%9A%D0%BE%D1%88%D0%BC%D0%B0%D1%80_%D0%9C%D0%B5%D0%BD%D1%81%D0%B8%D1%81%D0%B0", + "Кошмар охотника": "https://bloodborne.fandom.com/ru/wiki/%D0%9A%D0%BE%D1%88%D0%BC%D0%B0%D1%80_%D0%BE%D1%85%D0%BE%D1%82%D0%BD%D0%B8%D0%BA%D0%B0", + "Лекционный корпус": "https://bloodborne.fandom.com/ru/wiki/%D0%9B%D0%B5%D0%BA%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BA%D0%BE%D1%80%D0%BF%D1%83%D1%81", + "Лечебница Йозефки": "https://bloodborne.fandom.com/ru/wiki/%D0%9B%D0%B5%D1%87%D0%B5%D0%B1%D0%BD%D0%B8%D1%86%D0%B0_%D0%99%D0%BE%D0%B7%D0%B5%D1%84%D0%BA%D0%B8", + "Лунарий Кормилицы Мерго": "https://bloodborne.fandom.com/ru/wiki/%D0%9B%D1%83%D0%BD%D0%B0%D1%80%D0%B8%D0%B9_%D0%9A%D0%BE%D1%80%D0%BC%D0%B8%D0%BB%D0%B8%D1%86%D1%8B_%D0%9C%D0%B5%D1%80%D0%B3%D0%BE", + "Мастерская Церкви исцеления": "https://bloodborne.fandom.com/ru/wiki/%D0%9C%D0%B0%D1%81%D1%82%D0%B5%D1%80%D1%81%D0%BA%D0%B0%D1%8F_%D0%A6%D0%B5%D1%80%D0%BA%D0%B2%D0%B8_%D0%B8%D1%81%D1%86%D0%B5%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F", + "Место Логариуса": "https://bloodborne.fandom.com/ru/wiki/%D0%9C%D0%B5%D1%81%D1%82%D0%BE_%D0%9B%D0%BE%D0%B3%D0%B0%D1%80%D0%B8%D1%83%D1%81%D0%B0", + "Молельный переулок Хемвик": "https://bloodborne.fandom.com/ru/wiki/%D0%9C%D0%BE%D0%BB%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9_%D0%BF%D0%B5%D1%80%D0%B5%D1%83%D0%BB%D0%BE%D0%BA_%D0%A5%D0%B5%D0%BC%D0%B2%D0%B8%D0%BA", + "Обитель ведьмы": "https://bloodborne.fandom.com/ru/wiki/%D0%9E%D0%B1%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_%D0%B2%D0%B5%D0%B4%D1%8C%D0%BC%D1%8B", + "Озеро лунного отражения": "https://bloodborne.fandom.com/ru/wiki/%D0%9E%D0%B7%D0%B5%D1%80%D0%BE_%D0%BB%D1%83%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BE%D1%82%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F", + "Площадь Пришествия": "https://bloodborne.fandom.com/ru/wiki/%D0%9F%D0%BB%D0%BE%D1%89%D0%B0%D0%B4%D1%8C_%D0%9F%D1%80%D0%B8%D1%88%D0%B5%D1%81%D1%82%D0%B2%D0%B8%D1%8F", + "Побережье": "https://bloodborne.fandom.com/ru/wiki/%D0%9F%D0%BE%D0%B1%D0%B5%D1%80%D0%B5%D0%B6%D1%8C%D0%B5", + "Подземелье чаши": "https://bloodborne.fandom.com/ru/wiki/%D0%9F%D0%BE%D0%B4%D0%B7%D0%B5%D0%BC%D0%B5%D0%BB%D1%8C%D0%B5_%D1%87%D0%B0%D1%88%D0%B8", + "Подземная куча трупов": "https://bloodborne.fandom.com/ru/wiki/%D0%9F%D0%BE%D0%B4%D0%B7%D0%B5%D0%BC%D0%BD%D0%B0%D1%8F_%D0%BA%D1%83%D1%87%D0%B0_%D1%82%D1%80%D1%83%D0%BF%D0%BE%D0%B2", + "Подземная тюрьма": "https://bloodborne.fandom.com/ru/wiki/%D0%9F%D0%BE%D0%B4%D0%B7%D0%B5%D0%BC%D0%BD%D0%B0%D1%8F_%D1%82%D1%8E%D1%80%D1%8C%D0%BC%D0%B0", + "Покинутый замок Кейнхёрст": "https://bloodborne.fandom.com/ru/wiki/%D0%9F%D0%BE%D0%BA%D0%B8%D0%BD%D1%83%D1%82%D1%8B%D0%B9_%D0%B7%D0%B0%D0%BC%D0%BE%D0%BA_%D0%9A%D0%B5%D0%B9%D0%BD%D1%85%D1%91%D1%80%D1%81%D1%82", + "Рыбацкая деревня": "https://bloodborne.fandom.com/ru/wiki/%D0%A0%D1%8B%D0%B1%D0%B0%D1%86%D0%BA%D0%B0%D1%8F_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BD%D1%8F", + "Сад светящегося дерева": "https://bloodborne.fandom.com/ru/wiki/%D0%A1%D0%B0%D0%B4_%D1%81%D0%B2%D0%B5%D1%82%D1%8F%D1%89%D0%B5%D0%B3%D0%BE%D1%81%D1%8F_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B0", + "Сады светящихся цветов": "https://bloodborne.fandom.com/ru/wiki/%D0%A1%D0%B0%D0%B4%D1%8B_%D1%81%D0%B2%D0%B5%D1%82%D1%8F%D1%89%D0%B8%D1%85%D1%81%D1%8F_%D1%86%D0%B2%D0%B5%D1%82%D0%BE%D0%B2", + "Соборный округ": "https://bloodborne.fandom.com/ru/wiki/%D0%A1%D0%BE%D0%B1%D0%BE%D1%80%D0%BD%D1%8B%D0%B9_%D0%BE%D0%BA%D1%80%D1%83%D0%B3", + "Сон охотника": "https://bloodborne.fandom.com/ru/wiki/%D0%A1%D0%BE%D0%BD_%D0%BE%D1%85%D0%BE%D1%82%D0%BD%D0%B8%D0%BA%D0%B0", + "Старая заброшенная мастерская": "https://bloodborne.fandom.com/ru/wiki/%D0%A1%D1%82%D0%B0%D1%80%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B1%D1%80%D0%BE%D1%88%D0%B5%D0%BD%D0%BD%D0%B0%D1%8F_%D0%BC%D0%B0%D1%81%D1%82%D0%B5%D1%80%D1%81%D0%BA%D0%B0%D1%8F", + "Старый Ярнам": "https://bloodborne.fandom.com/ru/wiki/%D0%A1%D1%82%D0%B0%D1%80%D1%8B%D0%B9_%D0%AF%D1%80%D0%BD%D0%B0%D0%BC", + "Хижина рядом с маяком": "https://bloodborne.fandom.com/ru/wiki/%D0%A5%D0%B8%D0%B6%D0%B8%D0%BD%D0%B0_%D1%80%D1%8F%D0%B4%D0%BE%D0%BC_%D1%81_%D0%BC%D0%B0%D1%8F%D0%BA%D0%BE%D0%BC", + "Центральный Ярнам": "https://bloodborne.fandom.com/ru/wiki/%D0%A6%D0%B5%D0%BD%D1%82%D1%80%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9_%D0%AF%D1%80%D0%BD%D0%B0%D0%BC", + "Церковь Доброй чаши": "https://bloodborne.fandom.com/ru/wiki/%D0%A6%D0%B5%D1%80%D0%BA%D0%BE%D0%B2%D1%8C_%D0%94%D0%BE%D0%B1%D1%80%D0%BE%D0%B9_%D1%87%D0%B0%D1%88%D0%B8", + "Церковь кошмара": "https://bloodborne.fandom.com/ru/wiki/%D0%A6%D0%B5%D1%80%D0%BA%D0%BE%D0%B2%D1%8C_%D0%BA%D0%BE%D1%88%D0%BC%D0%B0%D1%80%D0%B0", + "Часовня Идон": "https://bloodborne.fandom.com/ru/wiki/%D0%A7%D0%B0%D1%81%D0%BE%D0%B2%D0%BD%D1%8F_%D0%98%D0%B4%D0%BE%D0%BD", + "Яаар'гул, духовная деревня": "https://bloodborne.fandom.com/ru/wiki/%D0%AF%D0%B0%D0%B0%D1%80%27%D0%B3%D1%83%D0%BB,_%D0%B4%D1%83%D1%85%D0%BE%D0%B2%D0%BD%D0%B0%D1%8F_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BD%D1%8F" +} \ No newline at end of file diff --git "a/for_games/Bloodborne/bloodborne_fandom_com__ru__wiki__\320\232\320\260\321\202\320\265\320\263\320\276\321\200\320\270\321\217_\320\233\320\276\320\272\320\260\321\206\320\270\320\270/dumps/locations_graph.html" "b/for_games/Bloodborne/bloodborne_fandom_com__ru__wiki__\320\232\320\260\321\202\320\265\320\263\320\276\321\200\320\270\321\217_\320\233\320\276\320\272\320\260\321\206\320\270\320\270/dumps/locations_graph.html" new file mode 100644 index 000000000..7a99fbe73 --- /dev/null +++ "b/for_games/Bloodborne/bloodborne_fandom_com__ru__wiki__\320\232\320\260\321\202\320\265\320\263\320\276\321\200\320\270\321\217_\320\233\320\276\320\272\320\260\321\206\320\270\320\270/dumps/locations_graph.html" @@ -0,0 +1,145 @@ + + + + +Locations Bloodborne + + + + + + + + + \ No newline at end of file diff --git "a/for_games/Bloodborne/bloodborne_fandom_com__ru__wiki__\320\232\320\260\321\202\320\265\320\263\320\276\321\200\320\270\321\217_\320\233\320\276\320\272\320\260\321\206\320\270\320\270/dumps/locations_transitions.json" "b/for_games/Bloodborne/bloodborne_fandom_com__ru__wiki__\320\232\320\260\321\202\320\265\320\263\320\276\321\200\320\270\321\217_\320\233\320\276\320\272\320\260\321\206\320\270\320\270/dumps/locations_transitions.json" new file mode 100644 index 000000000..95592ee00 --- /dev/null +++ "b/for_games/Bloodborne/bloodborne_fandom_com__ru__wiki__\320\232\320\260\321\202\320\265\320\263\320\276\321\200\320\270\321\217_\320\233\320\276\320\272\320\260\321\206\320\270\320\270/dumps/locations_transitions.json" @@ -0,0 +1,374 @@ +[ + [ + "Алтарь отчаяния", + "Сады светящихся цветов" + ], + [ + "Астральная часовая башня", + "Зал исследований" + ], + [ + "Астральная часовая башня", + "Рыбацкая деревня" + ], + [ + "Астральная часовая башня", + "Сад светящегося дерева" + ], + [ + "Большой мост", + "Центральный Ярнам" + ], + [ + "Бюргенверт", + "Запретный лес" + ], + [ + "Бюргенверт", + "Озеро лунного отражения" + ], + [ + "Верхний Соборный округ", + "Мастерская Церкви исцеления" + ], + [ + "Верхний Соборный округ", + "Соборный округ" + ], + [ + "Главный собор", + "Соборный округ" + ], + [ + "Главный собор кошмара", + "Кошмар охотника" + ], + [ + "Граница кошмара", + "Лекционный корпус" + ], + [ + "Гробница Идон", + "Центральный Ярнам" + ], + [ + "Гробница Идон", + "Часовня Идон" + ], + [ + "Зал Амигдалы", + "Граница кошмара" + ], + [ + "Зал исследований", + "Подземная куча трупов" + ], + [ + "Зал исследований", + "Сад светящегося дерева" + ], + [ + "Зал королевы Нечистокровных", + "Место Логариуса" + ], + [ + "Зал королевы Нечистокровных", + "Покинутый замок Кейнхёрст" + ], + [ + "Запретная могила", + "Бюргенверт" + ], + [ + "Запретная могила", + "Запретный лес" + ], + [ + "Запретный лес", + "Бюргенверт" + ], + [ + "Запретный лес", + "Лечебница Йозефки" + ], + [ + "Запретный лес", + "Соборный округ" + ], + [ + "Кладбище Черного чудовища", + "Подземная тюрьма" + ], + [ + "Кладбище Черного чудовища", + "Старый Ярнам" + ], + [ + "Кладбище Черного чудовища", + "Яаар'гул, духовная деревня" + ], + [ + "Кошмар Менсиса", + "Лекционный корпус" + ], + [ + "Кошмар Менсиса", + "Лунарий Кормилицы Мерго" + ], + [ + "Кошмар охотника", + "Подземная куча трупов" + ], + [ + "Кошмар охотника", + "Церковь кошмара" + ], + [ + "Лекционный корпус", + "Граница кошмара" + ], + [ + "Лекционный корпус", + "Кошмар Менсиса" + ], + [ + "Лекционный корпус", + "Площадь Пришествия" + ], + [ + "Лекционный корпус", + "Соборный округ" + ], + [ + "Лекционный корпус", + "Яаар'гул, духовная деревня" + ], + [ + "Лечебница Йозефки", + "Запретный лес" + ], + [ + "Лечебница Йозефки", + "Центральный Ярнам" + ], + [ + "Лунарий Кормилицы Мерго", + "Кошмар Менсиса" + ], + [ + "Мастерская Церкви исцеления", + "Верхний Соборный округ" + ], + [ + "Мастерская Церкви исцеления", + "Главный собор" + ], + [ + "Мастерская Церкви исцеления", + "Соборный округ" + ], + [ + "Мастерская Церкви исцеления", + "Старая заброшенная мастерская" + ], + [ + "Мастерская Церкви исцеления", + "Часовня Идон" + ], + [ + "Место Логариуса", + "Зал королевы Нечистокровных" + ], + [ + "Место Логариуса", + "Покинутый замок Кейнхёрст" + ], + [ + "Молельный переулок Хемвик", + "Обитель ведьмы" + ], + [ + "Молельный переулок Хемвик", + "Покинутый замок Кейнхёрст" + ], + [ + "Молельный переулок Хемвик", + "Соборный округ" + ], + [ + "Обитель ведьмы", + "Молельный переулок Хемвик" + ], + [ + "Озеро лунного отражения", + "Бюргенверт" + ], + [ + "Озеро лунного отражения", + "Яаар'гул, духовная деревня" + ], + [ + "Площадь Пришествия", + "Лекционный корпус" + ], + [ + "Площадь Пришествия", + "Яаар'гул, духовная деревня" + ], + [ + "Побережье", + "Рыбацкая деревня" + ], + [ + "Подземелье чаши", + "Сон охотника" + ], + [ + "Подземная куча трупов", + "Зал исследований" + ], + [ + "Подземная куча трупов", + "Кошмар охотника" + ], + [ + "Подземная куча трупов", + "Церковь кошмара" + ], + [ + "Подземная тюрьма", + "Старый Ярнам" + ], + [ + "Покинутый замок Кейнхёрст", + "Место Логариуса" + ], + [ + "Покинутый замок Кейнхёрст", + "Молельный переулок Хемвик" + ], + [ + "Рыбацкая деревня", + "Астральная часовая башня" + ], + [ + "Рыбацкая деревня", + "Побережье" + ], + [ + "Рыбацкая деревня", + "Хижина рядом с маяком" + ], + [ + "Сад светящегося дерева", + "Астральная часовая башня" + ], + [ + "Сад светящегося дерева", + "Зал исследований" + ], + [ + "Сады светящихся цветов", + "Алтарь отчаяния" + ], + [ + "Сады светящихся цветов", + "Верхний Соборный округ" + ], + [ + "Соборный округ", + "Запретный лес" + ], + [ + "Соборный округ", + "Кошмар охотника" + ], + [ + "Соборный округ", + "Лекционный корпус" + ], + [ + "Соборный округ", + "Мастерская Церкви исцеления" + ], + [ + "Соборный округ", + "Молельный переулок Хемвик" + ], + [ + "Соборный округ", + "Старый Ярнам" + ], + [ + "Соборный округ", + "Яаар'гул, духовная деревня" + ], + [ + "Старая заброшенная мастерская", + "Мастерская Церкви исцеления" + ], + [ + "Старый Ярнам", + "Соборный округ" + ], + [ + "Старый Ярнам", + "Яаар'гул, духовная деревня" + ], + [ + "Хижина рядом с маяком", + "Побережье" + ], + [ + "Хижина рядом с маяком", + "Рыбацкая деревня" + ], + [ + "Центральный Ярнам", + "Большой мост" + ], + [ + "Центральный Ярнам", + "Гробница Идон" + ], + [ + "Центральный Ярнам", + "Лечебница Йозефки" + ], + [ + "Церковь Доброй чаши", + "Старый Ярнам" + ], + [ + "Церковь кошмара", + "Кошмар охотника" + ], + [ + "Церковь кошмара", + "Подземная куча трупов" + ], + [ + "Часовня Идон", + "Мастерская Церкви исцеления" + ], + [ + "Часовня Идон", + "Соборный округ" + ], + [ + "Часовня Идон", + "Центральный Ярнам" + ], + [ + "Яаар'гул, духовная деревня", + "Лекционный корпус" + ], + [ + "Яаар'гул, духовная деревня", + "Озеро лунного отражения" + ], + [ + "Яаар'гул, духовная деревня", + "Площадь Пришествия" + ] +] \ No newline at end of file diff --git "a/for_games/Bloodborne/bloodborne_fandom_com__ru__wiki__\320\232\320\260\321\202\320\265\320\263\320\276\321\200\320\270\321\217_\320\233\320\276\320\272\320\260\321\206\320\270\320\270/main.py" "b/for_games/Bloodborne/bloodborne_fandom_com__ru__wiki__\320\232\320\260\321\202\320\265\320\263\320\276\321\200\320\270\321\217_\320\233\320\276\320\272\320\260\321\206\320\270\320\270/main.py" new file mode 100644 index 000000000..0bc856a10 --- /dev/null +++ "b/for_games/Bloodborne/bloodborne_fandom_com__ru__wiki__\320\232\320\260\321\202\320\265\320\263\320\276\321\200\320\270\321\217_\320\233\320\276\320\272\320\260\321\206\320\270\320\270/main.py" @@ -0,0 +1,118 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +import json +import time +import sys + +from dataclasses import dataclass +from urllib.parse import urljoin +from pathlib import Path + +import requests +from bs4 import BeautifulSoup, Tag + + +DIR: Path = Path(__file__).resolve().parent + +sys.path.append( + str(DIR.parent.parent / "Dark Souls" / "generate_HTML_location_graph__with_d3js") +) +from generate_graph_html import generate as generate_graph_html + + +DIR_DUMPS: Path = DIR / "dumps" +DIR_DUMPS.mkdir(parents=True, exist_ok=True) + +URL: str = "https://bloodborne.fandom.com/ru/wiki/Категория:Локации" + + +@dataclass +class Location: + title: str + url: str + + @classmethod + def from_tag(cls, tag: Tag) -> "Location": + return cls( + title=tag["title"], + url=urljoin(URL, tag["href"]), + ) + + +links: set[tuple[str, str]] = set() +location_by_url: dict[str, str] = dict() + +rs = requests.get(URL) +rs.raise_for_status() + +soup = BeautifulSoup(rs.content, "html.parser") +locations: list[Location] = [ + Location.from_tag(a) + for a in soup.select("a.category-page__member-link[href][title]") +] + +for location in locations: + time.sleep(1) + for _ in range(3): + try: + # TODO: Оптимизации не хватает + rs = requests.get(location.url) + rs.raise_for_status() + except Exception as e: + print(f"Error: {e}, url: {location.url}") + time.sleep(1) + + soup = BeautifulSoup(rs.content, "html.parser") + + to_locations: list[tuple[str, str]] = [ + (a["title"], urljoin(rs.url, a["href"])) + for a in soup.select('[data-source="Переходы"] a[href][title]') + ] + # У любой локации есть связанная с ней локация. Если нет - значит это страница не про локацию + if not to_locations: + continue + + location_by_url[location.title] = location.url + + print(location.title, location.url) + print(" Переходы:") + + # Найдем связанные локации + for to_title, to_url in to_locations: + # Проверяем что ссылка ведет на локацию + if not any(True for l in locations if l.url == to_url): # TODO: Рефакторинг? + continue + + print(f" {to_title}: {to_url}") + location_by_url[to_title] = to_url + + links.add((location.title, to_title)) + +print() + +# Экспорт в json +location_by_url: dict[str, str] = dict(sorted(location_by_url.items())) +json.dump( + location_by_url, + open(DIR_DUMPS / "locations.json", "w", encoding="utf-8"), + ensure_ascii=False, + indent=4, +) + +links: list[tuple[str, str]] = sorted(links) +json.dump( + links, + open(DIR_DUMPS / "locations_transitions.json", "w", encoding="utf-8"), + ensure_ascii=False, + indent=4, +) + +generate_graph_html( + file_name_to=DIR_DUMPS / "locations_graph.html", + links=links, + title="Locations Bloodborne", +) diff --git a/for_games/Bot Buff Knight Advanced/__foo_test.py b/for_games/Bot Buff Knight Advanced/__foo_test.py index 05cfafd8d..f4ed97917 100644 --- a/for_games/Bot Buff Knight Advanced/__foo_test.py +++ b/for_games/Bot Buff Knight Advanced/__foo_test.py @@ -20,7 +20,7 @@ from common import get_current_datetime_str -def draw_rects(img, contours_rects, color=(0, 255, 0)): +def draw_rects(img, contours_rects, color=(0, 255, 0)) -> None: for x, y, w, h in contours_rects: cv2.rectangle(img, (x, y), (x + w, y + h), color, thickness=5) # cv2.rectangle(img, (x, y), (x + w, y + h), color, thickness=-1) diff --git a/for_games/Bot Buff Knight Advanced/main.py b/for_games/Bot Buff Knight Advanced/main.py index 78770abe8..26105e37c 100644 --- a/for_games/Bot Buff Knight Advanced/main.py +++ b/for_games/Bot Buff Knight Advanced/main.py @@ -61,7 +61,7 @@ def filter_fairy_and_button(rect_fairy, rect_button): os.mkdir(DIR) -def save_screenshot(prefix, img_hsv): +def save_screenshot(prefix, img_hsv) -> None: file_name = f"{DIR}/{prefix}__{get_current_datetime_str()}.png" log.debug(file_name) cv2.imwrite(file_name, cv2.cvtColor(np.array(img_hsv), cv2.COLOR_HSV2BGR)) @@ -90,12 +90,12 @@ def save_screenshot(prefix, img_hsv): } -def change_start(): +def change_start() -> None: BOT_DATA["START"] = not BOT_DATA["START"] log.debug("START: %s", BOT_DATA["START"]) -def change_auto_attack(): +def change_auto_attack() -> None: BOT_DATA["AUTO_ATTACK"] = not BOT_DATA["AUTO_ATTACK"] log.debug("AUTO_ATTACK: %s", BOT_DATA["AUTO_ATTACK"]) @@ -105,7 +105,7 @@ def change_auto_attack(): log.debug('Press "%s" for AUTO_ATTACK', AUTO_ATTACK_COMBINATION) -def process_auto_attack(): +def process_auto_attack() -> None: while True: if not BOT_DATA["START"]: time.sleep(0.01) @@ -118,7 +118,7 @@ def process_auto_attack(): time.sleep(0.01) -def process_find_fairy(img_hsv): +def process_find_fairy(img_hsv) -> None: rects_blue = find_rect_contours(img_hsv, BLUE_HSV_MIN, BLUE_HSV_MAX) rects_orange = find_rect_contours(img_hsv, ORANGE_HSV_MIN, ORANGE_HSV_MAX) rects_fairy = find_rect_contours(img_hsv, FAIRY_HSV_MIN, FAIRY_HSV_MAX) diff --git a/for_games/Dark Souls/backup__save_files/by_autosave/common.py b/for_games/Dark Souls/backup__save_files/by_autosave/common.py index 7cab5c366..d9a398a5a 100644 --- a/for_games/Dark Souls/backup__save_files/by_autosave/common.py +++ b/for_games/Dark Souls/backup__save_files/by_autosave/common.py @@ -21,7 +21,7 @@ log = get_logger(__file__) -def backup_saves(path_ds_save: str, forced: bool = False, modified_minutes: int = 5): +def backup_saves(path_ds_save: str, forced: bool = False, modified_minutes: int = 5) -> None: try: for path_file_name in glob(path_ds_save): log.debug(f"Check: {path_file_name}") @@ -50,7 +50,7 @@ def backup_saves(path_ds_save: str, forced: bool = False, modified_minutes: int time.sleep(5 * 60) -def run(path_ds_save: str, timeout_minutes: int = 5): +def run(path_ds_save: str, timeout_minutes: int = 5) -> None: # Example: r'~\Documents\NBGI\DarkSouls\*\DRAKS0005.sl2' path_ds_save: str = os.path.expanduser(path_ds_save) diff --git a/for_games/Dark Souls/backup__save_files/by_hotkey/common.py b/for_games/Dark Souls/backup__save_files/by_hotkey/common.py index 2baac18c6..345c3c0c4 100644 --- a/for_games/Dark Souls/backup__save_files/by_hotkey/common.py +++ b/for_games/Dark Souls/backup__save_files/by_hotkey/common.py @@ -21,7 +21,7 @@ import keyboard -def beep(): +def beep() -> None: try: winsound.Beep(1000, duration=50) except: @@ -35,7 +35,7 @@ def beep(): HOTKEY = "CTRL + F1" -def backup_saves(path_ds_save: str): +def backup_saves(path_ds_save: str) -> None: try: for path_file_name in glob(path_ds_save): file_name_backup = backup(path_file_name) @@ -48,7 +48,7 @@ def backup_saves(path_ds_save: str): time.sleep(5 * 60) -def run(path_ds_save: str, hotkey: str = HOTKEY): +def run(path_ds_save: str, hotkey: str = HOTKEY) -> None: # Example: r'~\Documents\NBGI\DarkSouls\*\DRAKS0005.sl2' path_ds_save = os.path.expanduser(path_ds_save) diff --git a/for_games/Dark Souls/common.py b/for_games/Dark Souls/common.py index 5ecfb72cf..ae3d620bf 100644 --- a/for_games/Dark Souls/common.py +++ b/for_games/Dark Souls/common.py @@ -17,7 +17,7 @@ class Parser: - def __init__(self, url_locations: str, log=True): + def __init__(self, url_locations: str, log=True) -> None: self._url_locations = url_locations self._is_log = log @@ -43,7 +43,7 @@ def DS2(log=True) -> "Parser": def DS3(log=True) -> "Parser": return Parser(URL_DS3, log) - def _log(self, *args, **kwargs): + def _log(self, *args, **kwargs) -> None: self._is_log and print(*args, **kwargs) @staticmethod diff --git a/for_games/Dark Souls/generate_HTML_location_graph__with_d3js/generate_graph_html.py b/for_games/Dark Souls/generate_HTML_location_graph__with_d3js/generate_graph_html.py index ce3f9bbd7..edeadb617 100644 --- a/for_games/Dark Souls/generate_HTML_location_graph__with_d3js/generate_graph_html.py +++ b/for_games/Dark Souls/generate_HTML_location_graph__with_d3js/generate_graph_html.py @@ -4,6 +4,12 @@ __author__ = "ipetrash" +from pathlib import Path + + +DIR: Path = Path(__file__).resolve().parent + + def get_dataset_text(links: list[tuple[str, str]]) -> str: # Список всех узлов графа nodes = set() @@ -54,16 +60,17 @@ def get_dataset_text(links: list[tuple[str, str]]) -> str: def generate( - file_name_to: str, + file_name_to: str | Path, links: list[tuple[str, str]], title: str = "Graph", -): + file_name_template: str | Path = DIR / "template_graph.html", +) -> None: template_title = "{{title}}" template_dataset = "{{dataset}}" dataset_text = get_dataset_text(links) - with open("template_graph.html", "r", encoding="utf-8") as f: + with open(file_name_template, "r", encoding="utf-8") as f: text = f.read() text = text.replace(template_title, title) text = text.replace(template_dataset, dataset_text) diff --git a/for_games/Dark Souls/ru_darksouls_wikia_com__fandom__bosses/print_stats_by_health_and_souls/_utils.py b/for_games/Dark Souls/ru_darksouls_wikia_com__fandom__bosses/print_stats_by_health_and_souls/_utils.py index a6ed481dd..f5bd70785 100644 --- a/for_games/Dark Souls/ru_darksouls_wikia_com__fandom__bosses/print_stats_by_health_and_souls/_utils.py +++ b/for_games/Dark Souls/ru_darksouls_wikia_com__fandom__bosses/print_stats_by_health_and_souls/_utils.py @@ -228,7 +228,7 @@ def print_stats( rows: List[Tuple[str, int, int]], headers=("NAME", "HEALTH", "SOULS"), sort_column=1, -): +) -> None: rows.sort(key=lambda x: x[sort_column], reverse=True) rows.insert(0, headers) diff --git a/for_games/Dark Souls/ru_darksouls_wikia_com__fandom__bosses/utils.py b/for_games/Dark Souls/ru_darksouls_wikia_com__fandom__bosses/utils.py index 4b897e8e2..c0d5129c4 100644 --- a/for_games/Dark Souls/ru_darksouls_wikia_com__fandom__bosses/utils.py +++ b/for_games/Dark Souls/ru_darksouls_wikia_com__fandom__bosses/utils.py @@ -85,7 +85,7 @@ def get_bosses(url: str) -> Dict[str, List[Boss]]: return bosses_by_category -def print_bosses(url: str, bosses: Dict[str, List[Boss]]): +def print_bosses(url: str, bosses: Dict[str, List[Boss]]) -> None: total = sum(len(i) for i in bosses.values()) print(f"{url} ({total}):") @@ -108,7 +108,7 @@ def convert_bosses_to_only_name(bosses: Dict[str, List[Boss]]) -> Dict[str, List return bosses_only_name -def export_to_json(file_name, bosses): +def export_to_json(file_name, bosses) -> None: dir_name = os.path.dirname(file_name) os.makedirs(dir_name, exist_ok=True) @@ -120,7 +120,7 @@ def export_to_json(file_name, bosses): ) -def export_to_sqlite(file_name: str, bosses_ds123: Dict[str, Dict[str, List[Boss]]]): +def export_to_sqlite(file_name: str, bosses_ds123: Dict[str, Dict[str, List[Boss]]]) -> None: dir_name = os.path.dirname(file_name) os.makedirs(dir_name, exist_ok=True) diff --git "a/for_games/Demons Souls/demonssouls_fandom_com__ru__wiki__\320\221\320\276\321\201\321\201\321\213/main.py" "b/for_games/Demons Souls/demonssouls_fandom_com__ru__wiki__\320\221\320\276\321\201\321\201\321\213/main.py" index aba252d9f..aecf16556 100644 --- "a/for_games/Demons Souls/demonssouls_fandom_com__ru__wiki__\320\221\320\276\321\201\321\201\321\213/main.py" +++ "b/for_games/Demons Souls/demonssouls_fandom_com__ru__wiki__\320\221\320\276\321\201\321\201\321\213/main.py" @@ -55,7 +55,7 @@ def get_bosses(url: str) -> dict[str, list[Boss]]: return bosses_by_category -def print_bosses(url: str, bosses: dict[str, list[Boss]]): +def print_bosses(url: str, bosses: dict[str, list[Boss]]) -> None: total = sum(len(i) for i in bosses.values()) print(f"{url} ({total}):") @@ -78,7 +78,7 @@ def convert_bosses_to_only_name(bosses: dict[str, list[Boss]]) -> dict[str, list return bosses_only_name -def export_to_json(file_name, bosses): +def export_to_json(file_name, bosses) -> None: dir_name = os.path.dirname(file_name) os.makedirs(dir_name, exist_ok=True) @@ -90,7 +90,7 @@ def export_to_json(file_name, bosses): ) -def export_to_simple_text(file_name, bosses): +def export_to_simple_text(file_name, bosses) -> None: dir_name = os.path.dirname(file_name) os.makedirs(dir_name, exist_ok=True) diff --git a/for_games/Final_Fantasy_II__upgrade_skills_bot.py b/for_games/Final_Fantasy_II__upgrade_skills_bot.py index 4a64756a3..d28f9f1a8 100644 --- a/for_games/Final_Fantasy_II__upgrade_skills_bot.py +++ b/for_games/Final_Fantasy_II__upgrade_skills_bot.py @@ -44,7 +44,7 @@ def get_logger(name, file="log.txt", encoding="utf-8", log_stdout=True, log_file return log -def change_start(): +def change_start() -> None: DATA["START"] = not DATA["START"] if DATA["START"]: DATA["COUNTER"] = 0 @@ -52,17 +52,17 @@ def change_start(): log.debug("Change START: %s", DATA["START"]) -def set_min_counter(): +def set_min_counter() -> None: DATA["MAX_COUNTER"] = 1 log.debug("Change MAX_COUNTER: %s", DATA["MAX_COUNTER"]) -def set_max_counter(): +def set_max_counter() -> None: DATA["MAX_COUNTER"] = MAX_COUNTER log.debug("Change MAX_COUNTER: %s", DATA["MAX_COUNTER"]) -def change_cancel_all_last(): +def change_cancel_all_last() -> None: DATA["CANCEL_ALL_LAST"] = not DATA["CANCEL_ALL_LAST"] log.debug("Change CANCEL_ALL_LAST: %s", DATA["CANCEL_ALL_LAST"]) diff --git a/for_games/Hollow_Knight/export_to_json.py b/for_games/Hollow_Knight/export_to_json.py index 2a5100126..79d6c03c9 100644 --- a/for_games/Hollow_Knight/export_to_json.py +++ b/for_games/Hollow_Knight/export_to_json.py @@ -14,7 +14,7 @@ def export_to_json_str(bosses: dict[str, list]) -> str: return json.dumps(bosses, ensure_ascii=False, indent=4) -def export_to_json(file_name: str, bosses: dict[str, list]): +def export_to_json(file_name: str, bosses: dict[str, list]) -> None: dir_name = os.path.dirname(file_name) os.makedirs(dir_name, exist_ok=True) diff --git a/for_games/Hollow_Knight/print_bosses.py b/for_games/Hollow_Knight/print_bosses.py index bc1ded54a..68fb34975 100644 --- a/for_games/Hollow_Knight/print_bosses.py +++ b/for_games/Hollow_Knight/print_bosses.py @@ -7,7 +7,7 @@ from utils import get_bosses, Boss -def print_bosses(bosses: dict[str, list[Boss]], only_names=False): +def print_bosses(bosses: dict[str, list[Boss]], only_names=False) -> None: total = sum(len(i) for i in bosses.values()) print(f"Hollow Knight ({total}):") diff --git a/for_games/RMMZ_update_fields_CGMZ_GameInfo.py b/for_games/RMMZ_update_fields_CGMZ_GameInfo.py index 2ceda083d..f48025af3 100644 --- a/for_games/RMMZ_update_fields_CGMZ_GameInfo.py +++ b/for_games/RMMZ_update_fields_CGMZ_GameInfo.py @@ -15,7 +15,7 @@ PATTERN_FIELD_VERSION: re.Pattern = re.compile(r'(?P"Left Text"\s*:\s*)".+?"') -def process(path_dir: Path, forced: bool = False): +def process(path_dir: Path, forced: bool = False) -> None: path_js_plugins: Path = path_dir / "js" / "plugins.js" # If the last commit was in path_js_plugins, then skipping the file change diff --git a/for_games/Salt and Sanctuary parse bosses saltandsanctuary.fandom.com/export_to_json.py b/for_games/Salt and Sanctuary parse bosses saltandsanctuary.fandom.com/export_to_json.py index 2c9f8e7d1..2f81f91e2 100644 --- a/for_games/Salt and Sanctuary parse bosses saltandsanctuary.fandom.com/export_to_json.py +++ b/for_games/Salt and Sanctuary parse bosses saltandsanctuary.fandom.com/export_to_json.py @@ -14,7 +14,7 @@ def export_to_json_str(bosses: dict[str, list[str]]) -> str: return json.dumps(bosses, ensure_ascii=False, indent=4) -def export_to_json(file_name: str, bosses: dict[str, list[str]]): +def export_to_json(file_name: str, bosses: dict[str, list[str]]) -> None: dir_name = os.path.dirname(file_name) os.makedirs(dir_name, exist_ok=True) diff --git a/for_games/Salt and Sanctuary parse bosses saltandsanctuary.fandom.com/print_bosses.py b/for_games/Salt and Sanctuary parse bosses saltandsanctuary.fandom.com/print_bosses.py index b190b08b5..7ce020059 100644 --- a/for_games/Salt and Sanctuary parse bosses saltandsanctuary.fandom.com/print_bosses.py +++ b/for_games/Salt and Sanctuary parse bosses saltandsanctuary.fandom.com/print_bosses.py @@ -7,7 +7,7 @@ from utils import get_bosses, Boss -def print_bosses(bosses: dict[str, list[Boss]], only_names=False): +def print_bosses(bosses: dict[str, list[Boss]], only_names=False) -> None: total = sum(len(i) for i in bosses.values()) print(f"Salt and Sanctuary ({total}):") diff --git a/html_parsing/denuvo__get_games/game_debate_com.py b/for_games/denuvo__get_games/game_debate_com.py similarity index 100% rename from html_parsing/denuvo__get_games/game_debate_com.py rename to for_games/denuvo__get_games/game_debate_com.py diff --git a/html_parsing/denuvo__get_games/gamicus_fandom_com__wiki__Denuvo.py b/for_games/denuvo__get_games/gamicus_fandom_com__wiki__Denuvo.py similarity index 100% rename from html_parsing/denuvo__get_games/gamicus_fandom_com__wiki__Denuvo.py rename to for_games/denuvo__get_games/gamicus_fandom_com__wiki__Denuvo.py diff --git a/html_parsing/denuvo__get_games/store_steampowered_com__curator__26095454_Denuvo_Games__list__38826.py b/for_games/denuvo__get_games/store_steampowered_com__curator__26095454_Denuvo_Games__list__38826.py similarity index 100% rename from html_parsing/denuvo__get_games/store_steampowered_com__curator__26095454_Denuvo_Games__list__38826.py rename to for_games/denuvo__get_games/store_steampowered_com__curator__26095454_Denuvo_Games__list__38826.py diff --git a/html_parsing/exclusive_games/common.py b/for_games/exclusive_games/common.py similarity index 100% rename from html_parsing/exclusive_games/common.py rename to for_games/exclusive_games/common.py diff --git a/html_parsing/exclusive_games/ps3__gematsu_com.py b/for_games/exclusive_games/ps3__gematsu_com.py similarity index 100% rename from html_parsing/exclusive_games/ps3__gematsu_com.py rename to for_games/exclusive_games/ps3__gematsu_com.py diff --git a/html_parsing/exclusive_games/ps4__gematsu_com.py b/for_games/exclusive_games/ps4__gematsu_com.py similarity index 100% rename from html_parsing/exclusive_games/ps4__gematsu_com.py rename to for_games/exclusive_games/ps4__gematsu_com.py diff --git a/html_parsing/exclusive_games/ps4__ru_wikipedia_org.py b/for_games/exclusive_games/ps4__ru_wikipedia_org.py similarity index 100% rename from html_parsing/exclusive_games/ps4__ru_wikipedia_org.py rename to for_games/exclusive_games/ps4__ru_wikipedia_org.py diff --git a/html_parsing/exclusive_games/psp__listal_com.py b/for_games/exclusive_games/psp__listal_com.py similarity index 100% rename from html_parsing/exclusive_games/psp__listal_com.py rename to for_games/exclusive_games/psp__listal_com.py diff --git a/html_parsing/exclusive_games/switch__gematsu_com.py b/for_games/exclusive_games/switch__gematsu_com.py similarity index 100% rename from html_parsing/exclusive_games/switch__gematsu_com.py rename to for_games/exclusive_games/switch__gematsu_com.py diff --git a/html_parsing/exclusive_games/wii_u__gematsu_com.py b/for_games/exclusive_games/wii_u__gematsu_com.py similarity index 100% rename from html_parsing/exclusive_games/wii_u__gematsu_com.py rename to for_games/exclusive_games/wii_u__gematsu_com.py diff --git a/html_parsing/exclusive_games/xbox_360__gematsu_com.py b/for_games/exclusive_games/xbox_360__gematsu_com.py similarity index 100% rename from html_parsing/exclusive_games/xbox_360__gematsu_com.py rename to for_games/exclusive_games/xbox_360__gematsu_com.py diff --git a/html_parsing/exclusive_games/xbox_360__ru_wikipedia_org.py b/for_games/exclusive_games/xbox_360__ru_wikipedia_org.py similarity index 100% rename from html_parsing/exclusive_games/xbox_360__ru_wikipedia_org.py rename to for_games/exclusive_games/xbox_360__ru_wikipedia_org.py diff --git a/html_parsing/exclusive_games/xbox_one__gematsu_com.py b/for_games/exclusive_games/xbox_one__gematsu_com.py similarity index 100% rename from html_parsing/exclusive_games/xbox_one__gematsu_com.py rename to for_games/exclusive_games/xbox_one__gematsu_com.py diff --git a/html_parsing/exclusive_games/xbox_one__ru_wikipedia_org.py b/for_games/exclusive_games/xbox_one__ru_wikipedia_org.py similarity index 100% rename from html_parsing/exclusive_games/xbox_one__ru_wikipedia_org.py rename to for_games/exclusive_games/xbox_one__ru_wikipedia_org.py diff --git a/for_games/fitgirl_RE_Village_with_win10_notify.py b/for_games/fitgirl_RE_Village_with_win10_notify.py index 99ce1dd7b..e0b5e42f8 100644 --- a/for_games/fitgirl_RE_Village_with_win10_notify.py +++ b/for_games/fitgirl_RE_Village_with_win10_notify.py @@ -25,7 +25,7 @@ from run_notify import run_in_thread -def show_notify(name: str): +def show_notify(name: str) -> None: title = f"Уведомление за {datetime.now():%Y/%m/%d %H:%M:%S}" print(f"{title}\n{name}\n") diff --git a/for_games/game__get_random_rarity_item.py b/for_games/game__get_random_rarity_item.py index 6808f27be..b0afc828b 100644 --- a/for_games/game__get_random_rarity_item.py +++ b/for_games/game__get_random_rarity_item.py @@ -7,7 +7,7 @@ import random -def get_random_rarity_item(): +def get_random_rarity_item() -> str: a = random.randrange(1, 1000) if a <= 10: diff --git a/for_games/gamestatus_info__lastcrackedgames.py b/for_games/gamestatus_info__lastcrackedgames.py index 961bc246d..0c5e7ca26 100644 --- a/for_games/gamestatus_info__lastcrackedgames.py +++ b/for_games/gamestatus_info__lastcrackedgames.py @@ -8,6 +8,7 @@ from dataclasses import dataclass from datetime import date +from typing import Any import requests @@ -26,20 +27,23 @@ class Game: title: str url: str protection: str + hacked_groups: str release_date: date crack_date: date @classmethod - def parse_from(cls, data: dict) -> "Game": - # Example: "[\"DENUVO\"]" -> "DENUVO", "denuvo" -> "DENUVO" - protection: str = data["protections"].upper() - if protection.startswith("["): - protection = ", ".join(json.loads(protection)) + def from_dict(cls, data: dict[str, Any]) -> "Game": + def _get_title(key: str) -> str: + title: str = data[key] + if title.startswith("["): + title = ", ".join(json.loads(title)) + return title return cls( title=data["title"], url=f'{URL_BASE}/{data["slug"]}', - protection=protection, + protection=_get_title("protections"), + hacked_groups=_get_title("hacked_groups"), release_date=date.fromisoformat(data["release_date"]), crack_date=date.fromisoformat(data["crack_date"]), ) @@ -49,7 +53,7 @@ def get_games() -> list[Game]: rs = session.get(f"{URL_BASE}/back/api/gameinfo/game/lastcrackedgames/") rs.raise_for_status() - return [Game.parse_from(game) for game in rs.json()["list_crack_games"]] + return [Game.from_dict(game) for game in rs.json()["list_crack_games"]] if __name__ == "__main__": @@ -59,11 +63,13 @@ def get_games() -> list[Game]: print(f"{i}. {game}") """ Games (200): - 1. Game(title='High On Life', url='https://gamestatus.info/high-on-life', protection='STEAM', release_date=datetime.date(2022, 12, 13), crack_date=datetime.date(2022, 12, 13)) - 2. Game(title='CRISIS CORE –FINAL FANTASY VII– REUNION', url='https://gamestatus.info/crisis-core-final-fantasy-vii-reunion', protection='STEAM', release_date=datetime.date(2022, 12, 13), crack_date=datetime.date(2022, 12, 13)) - 3. Game(title='Wavetale', url='https://gamestatus.info/wavetale', protection='STEAM', release_date=datetime.date(2022, 12, 12), crack_date=datetime.date(2022, 12, 12)) + 1. Game(title='RAIDOU Remastered: The Mystery of the Soulless Army', url='https://gamestatus.info/raidou-remastered-the-mystery-of-the-soulless-army', protection='DRM', hacked_groups='DenuvOwO Hypervisor — это обход защиты, при котором обычно необходимо отключить защиту ПК, что делает ваше устройство более уязвимым. Будьте осторожны!', release_date=datetime.date(2025, 6, 18), crack_date=datetime.date(2026, 3, 31)) + 2. Game(title="Sid Meier's Civilization® VII - Founders Edition", url='https://gamestatus.info/sid-meiers-civilization-vii', protection='Denuvo Anti-tamper', hacked_groups='DenuvOwO Hypervisor — это обход защиты, при котором обычно необходимо отключить защиту ПК, что делает ваше устройство более уязвимым. Будьте осторожны!', release_date=datetime.date(2025, 2, 10), crack_date=datetime.date(2026, 3, 31)) + 3. Game(title='Persona 4 Arena Ultimax', url='https://gamestatus.info/persona-4-arena-ultimax', protection='DENUVO', hacked_groups='DenuvOwO Hypervisor — это обход защиты, при котором обычно необходимо отключить защиту ПК, что делает ваше устройство более уязвимым. Будьте осторожны!', release_date=datetime.date(2022, 3, 16), crack_date=datetime.date(2026, 3, 30)) + 4. Game(title='SUPER ROBOT WARS Y', url='https://gamestatus.info/super-robot-wars-y', protection='Denuvo Anti-Tamper', hacked_groups='DenuvOwO Hypervisor — это обход защиты, при котором обычно необходимо отключить защиту ПК, что делает ваше устройство более уязвимым. Будьте осторожны!', release_date=datetime.date(2025, 8, 27), crack_date=datetime.date(2026, 3, 30)) + 5. Game(title='Hozy', url='https://gamestatus.info/hozy', protection='STEAM', hacked_groups='RUNE', release_date=datetime.date(2026, 3, 30), crack_date=datetime.date(2026, 3, 30)) ... - 198. Game(title='Spire of Sorcery', url='https://gamestatus.info/spire-of-sorcery', protection='STEAM', release_date=datetime.date(2021, 10, 21), crack_date=datetime.date(2021, 10, 21)) - 199. Game(title='Inscryption', url='https://gamestatus.info/Inscryption', protection='STEAM', release_date=datetime.date(2021, 10, 19), crack_date=datetime.date(2021, 10, 19)) - 200. Game(title='Youtubers Life 2', url='https://gamestatus.info/youtubers-life-2', protection='STEAM', release_date=datetime.date(2021, 10, 19), crack_date=datetime.date(2021, 10, 19)) + 198. Game(title='Under The Island', url='https://gamestatus.info/under-the-island', protection='GOG', hacked_groups='DRM-Free', release_date=datetime.date(2026, 2, 17), crack_date=datetime.date(2026, 2, 17)) + 199. Game(title='Fisherman Simulator', url='https://gamestatus.info/fisherman-simulator', protection='STEAM', hacked_groups='Tenoke', release_date=datetime.date(2026, 2, 13), crack_date=datetime.date(2026, 2, 17)) + 200. Game(title='Styx: Blades of Greed', url='https://gamestatus.info/styx-blades-of-greed', protection='STEAM', hacked_groups='RUNE', release_date=datetime.date(2026, 2, 19), crack_date=datetime.date(2026, 2, 17)) """ diff --git a/html_parsing/gamesvoice_ru__get_finished.py b/for_games/gamesvoice_ru__get_finished.py similarity index 100% rename from html_parsing/gamesvoice_ru__get_finished.py rename to for_games/gamesvoice_ru__get_finished.py diff --git a/html_parsing/gametime__use_cubiq_ru/extract_all_games.json b/for_games/gametime__use_cubiq_ru/extract_all_games.json similarity index 100% rename from html_parsing/gametime__use_cubiq_ru/extract_all_games.json rename to for_games/gametime__use_cubiq_ru/extract_all_games.json diff --git a/html_parsing/gametime__use_cubiq_ru/extract_all_games.py b/for_games/gametime__use_cubiq_ru/extract_all_games.py similarity index 100% rename from html_parsing/gametime__use_cubiq_ru/extract_all_games.py rename to for_games/gametime__use_cubiq_ru/extract_all_games.py diff --git a/html_parsing/gametime__use_cubiq_ru/extract_all_games__show_the_shortest_time.py b/for_games/gametime__use_cubiq_ru/extract_all_games__show_the_shortest_time.py similarity index 100% rename from html_parsing/gametime__use_cubiq_ru/extract_all_games__show_the_shortest_time.py rename to for_games/gametime__use_cubiq_ru/extract_all_games__show_the_shortest_time.py diff --git a/html_parsing/gametime__use_cubiq_ru/found_from_local_files.py b/for_games/gametime__use_cubiq_ru/found_from_local_files.py similarity index 100% rename from html_parsing/gametime__use_cubiq_ru/found_from_local_files.py rename to for_games/gametime__use_cubiq_ru/found_from_local_files.py diff --git a/html_parsing/gametime__use_cubiq_ru/main.py b/for_games/gametime__use_cubiq_ru/main.py similarity index 100% rename from html_parsing/gametime__use_cubiq_ru/main.py rename to for_games/gametime__use_cubiq_ru/main.py diff --git a/for_games/grid_clicker/grid_clicker.py b/for_games/grid_clicker/grid_clicker.py new file mode 100644 index 000000000..1f99c3c26 --- /dev/null +++ b/for_games/grid_clicker/grid_clicker.py @@ -0,0 +1,204 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +import argparse +import threading +import time +import sys + +# pip install pyautogui==0.9.54 +import pyautogui + +# pip install pynput==1.8.1 +from pynput import mouse + +# pip install screeninfo==0.8.1 +from screeninfo import Monitor, get_monitors + + +pyautogui.FAILSAFE = False + +# Глобальный флаг работы +is_running = True + + +def on_click(x, y, button, pressed) -> bool | None: + global is_running + # Если нажата правая кнопка мыши (любая: нажатие или отпускание) + if button == mouse.Button.right: + print("\n[!] Обнаружен клик правой кнопкой. Останавливаю...") + is_running = False + return False # Останавливает сам слушатель pynput + + +def start_click_listener() -> None: + # Запуск прослушивания мыши в отдельном потоке + with mouse.Listener(on_click=on_click) as listener: + listener.join() + + +def click_all_on_screen( + step: int = 50, + do_click: bool = False, + sleep_time_before_starting_secs: int = 3, + # Режим 1: Прямые координаты + coords: tuple[int, int, int, int] | None = None, # (x1, y1, x2, y2) + # Режим 2: По номеру монитора + monitor_number: int = 1, + sleep_time_between_clicks_ms: int = 10, + offset_top: int = 50, # Защитный отступ сверху + offset_bottom: int = 50, # Защитный отступ снизу + offset_left: int = 50, # Защитный отступ слева + offset_right: int = 50, # Защитный отступ справа +) -> None: + global is_running + + if not do_click: + print("[!] ВНИМАНИЕ: Режим имитации включен, клики производиться не будут.") + + # Запуск потока для-прерывателя + threading.Thread(target=start_click_listener, daemon=True).start() + + # Режим 1: Прямые координаты + if coords: + start_x, start_y, end_x, end_y = coords + print(f"Режим ручных координат: X({start_x}..{end_x}), Y({start_y}..{end_y})") + + # Режим 2: По номеру монитора + else: + monitors = get_monitors() + try: + monitor: Monitor = monitors[monitor_number - 1] + except IndexError: + print(f"[#] Ошибка: Номер монитора должен быть от 1 до {len(monitors)}") + return + + # Определяем границы с учетом отступов + start_x = monitor.x + offset_left + end_x = monitor.x + monitor.width - offset_right + start_y = monitor.y + offset_top + end_y = monitor.y + monitor.height - offset_bottom + print(f"Режим монитора #{monitor_number} с отступами.") + + print(f"Область: X от {start_x} до {end_x}, Y от {start_y} до {end_y}") + print(f"Шаг: {step}px") + + sleep_time_between_clicks_secs: float = sleep_time_between_clicks_ms / 1000 + + time.sleep(sleep_time_before_starting_secs) + + print("Работаю. Нажми ПРАВУЮ кнопку мыши для стопа.") + + for y in range(start_y, end_y, step): + for x in range(start_x, end_x, step): + if not is_running: + print("Программа экстренно завершена.") + return + + pyautogui.moveTo(x, y) + if do_click: + pyautogui.click(x, y) + time.sleep(sleep_time_between_clicks_secs) + + print("Готово!") + + +def main() -> None: + parser = argparse.ArgumentParser( + description="GridClicker: Скрипт для протыкивания экрана по сетке.", + # Этот параметр автоматически добавит (default: ...) в описание каждого аргумента + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + + base_group = parser.add_argument_group("Основные настройки") + base_group.add_argument("-s", "--step", type=int, default=50, help="Шаг сетки") + base_group.add_argument( + "--do-click", + action="store_true", + help="РАЗРЕШИТЬ клики (без этого флага только перемещение курсора)", + ) + + base_group.add_argument( + "-t", + "--sleep_time_before_starting_secs", + type=int, + default=3, + dest="sleep_time_before_starting_secs", + help="Задержка перед началом (сек)", + ) + base_group.add_argument( + "-tc", + "--sleep", + type=int, + default=10, + dest="sleep_time_between_clicks_ms", + help="Задержка (мс)", + ) + + # Новая группа для координат + coord_group = parser.add_argument_group( + "Режим конкретных координат (игнорирует настройки монитора)" + ) + coord_group.add_argument("--x1", type=int, help="Левая граница") + coord_group.add_argument("--y1", type=int, help="Верхняя граница") + coord_group.add_argument("--x2", type=int, help="Правая граница") + coord_group.add_argument("--y2", type=int, help="Нижняя граница") + + monitor_group = parser.add_argument_group( + "Настройки монитора (используются, если не заданы x1,y1,x2,y2)" + ) + monitor_group.add_argument( + "-m", "--monitor", type=int, default=1, dest="monitor_number" + ) + monitor_group.add_argument("--top", type=int, default=50, dest="offset_top") + monitor_group.add_argument("--bottom", type=int, default=50, dest="offset_bottom") + monitor_group.add_argument("--left", type=int, default=50, dest="offset_left") + monitor_group.add_argument("--right", type=int, default=50, dest="offset_right") + + args = parser.parse_args() + + # Если скрипт запущен без аргументов — показываем help и выходим + if len(sys.argv) == 1: + parser.print_help() + sys.exit(0) + + # Собираем координаты в кортеж, если они все указаны + coords: tuple[int, int, int, int] | None = None + if all(v is not None for v in [args.x1, args.y1, args.x2, args.y2]): + coords = args.x1, args.y1, args.x2, args.y2 + + click_all_on_screen( + step=args.step, + do_click=args.do_click, + sleep_time_before_starting_secs=args.sleep_time_before_starting_secs, + sleep_time_between_clicks_ms=args.sleep_time_between_clicks_ms, + coords=coords, + monitor_number=args.monitor_number, + offset_top=args.offset_top, + offset_bottom=args.offset_bottom, + offset_left=args.offset_left, + offset_right=args.offset_right, + ) + + +if __name__ == "__main__": + # NOTE: Пример использования, режим прямых координат + # NOTE: grid_clicker.py --x1=-545 --y1=322 --x2=-42 --y2=1073 + # NOTE: grid_clicker.py --do-click --x1=-545 --y1=322 --x2=-42 --y2=1073 + # click_all_on_screen( + # step=100, + # coords=(-545, 322, -42, 1073), + # ) + + # NOTE: Пример использования, режим монитора + # click_all_on_screen( + # step=100, + # monitor_number=2, + # # sleep_time_between_clicks_ms=0.005, # 5 мс + # offset_bottom=150, + # ) + + main() diff --git a/for_games/grid_clicker/grid_clicker_gui_select_rect.py b/for_games/grid_clicker/grid_clicker_gui_select_rect.py new file mode 100644 index 000000000..eb5a8fff1 --- /dev/null +++ b/for_games/grid_clicker/grid_clicker_gui_select_rect.py @@ -0,0 +1,210 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +import json +import sys + +from pathlib import Path +from typing import Any + +from PyQt5.QtWidgets import ( + QApplication, + QDialog, + QFrame, + QPushButton, + QFormLayout, + QSpinBox, +) +from PyQt5.QtCore import Qt, QRect, QPoint +from PyQt5.QtGui import ( + QPainter, + QColor, + QPen, + QMouseEvent, + QKeyEvent, + QPaintEvent, + QCloseEvent, +) + +from grid_clicker import click_all_on_screen + +DIR: Path = Path(__file__).resolve().parent +PATH_SETTINGS: Path = DIR / "settings.json" + + +class AreaSelectorDialog(QDialog): + def __init__(self) -> None: + super().__init__() + + self.setWindowFlag(Qt.WindowType.FramelessWindowHint) + self.setWindowFlag(Qt.WindowType.WindowStaysOnTopHint) + + self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground) + + self.setCursor(Qt.CursorShape.CrossCursor) + + full_geometry: QRect = QApplication.desktop().geometry() + self.setGeometry(full_geometry) + + self._begin_global: QPoint = QPoint() # Глобальная точка начала + self._end_global: QPoint = QPoint() # Глобальная точка конца + self._is_selecting: bool = False + + self.selected_rect: QRect = QRect() + self.do_click: bool = True + self.need_run_clicker: bool = False + + self.spin_box_step = QSpinBox(value=50) + self.button_run = QPushButton("Run click", clicked=self.on_run_clicked) + self.button_run_test = QPushButton( + "Run TEST click", clicked=self.on_run_test_clicked + ) + self.button_close = QPushButton("Close", clicked=self.close) + + self.control_widget = QFrame(self) + self.control_widget.setCursor(Qt.ArrowCursor) + self.control_widget.setStyleSheet(""" + QFrame { + background-color: rgba(60, 60, 60, 200); + border-radius: 10px; + } + QCheckBox, + QLabel { + color: white; + } + """) + control_layout = QFormLayout(self.control_widget) + control_layout.addRow("&Step:", self.spin_box_step) + control_layout.addRow(self.button_run_test) + control_layout.addRow(self.button_run) + control_layout.addRow(self.button_close) + + if PATH_SETTINGS.exists(): + data: dict[str, Any] = json.loads(PATH_SETTINGS.read_text("UTF-8")) + coords: list[int] | None = data.get("coords") + if coords: + self.selected_rect.setCoords(*coords) + self.update() + + self._move_control_widget() + + def _move_control_widget(self): + if not self.selected_rect: + self.control_widget.hide() + return + + local_begin = self.mapFromGlobal(self.selected_rect.topLeft()) + self.control_widget.move(local_begin) + self.control_widget.show() + + @property + def step(self) -> int: + return self.spin_box_step.value() + + def on_run_test_clicked(self) -> None: + self.do_click = False + self.need_run_clicker = True + self.close() + + def on_run_clicked(self) -> None: + self.do_click = True + self.need_run_clicker = True + self.close() + + def mousePressEvent(self, event: QMouseEvent) -> None: + if event.button() == Qt.LeftButton: + self._begin_global = event.globalPos() + self._end_global = self._begin_global + + self._is_selecting = True + self._move_control_widget() + self.update() + + def mouseMoveEvent(self, event: QMouseEvent) -> None: + if self._is_selecting: + self._end_global = event.globalPos() + + rect = QRect(self._begin_global, self._end_global) + self.selected_rect = rect.normalized() + + self._move_control_widget() + self.update() + + def mouseReleaseEvent(self, event: QMouseEvent) -> None: + if self._is_selecting and event.button() == Qt.LeftButton: + self._is_selecting = False + + def keyPressEvent(self, event: QKeyEvent) -> None: + if event.key() == Qt.Key_Escape: + self.close() + + def paintEvent(self, event: QPaintEvent) -> None: + painter = QPainter(self) + painter.fillRect(self.rect(), QColor(0, 0, 0, 100)) + + if self.selected_rect: + local_rect: QRect = QRect( + self.mapFromGlobal(self.selected_rect.topLeft()), + self.mapFromGlobal(self.selected_rect.bottomRight()), + ) + + painter.setPen(QPen(Qt.red, 2, Qt.SolidLine)) + painter.fillRect(local_rect, QColor(255, 255, 255, 1)) + painter.drawRect(local_rect) + + def closeEvent(self, event: QCloseEvent) -> None: + if self.selected_rect: + data: dict[str, Any] = { + "coords": self.selected_rect.getCoords(), + } + PATH_SETTINGS.write_text( + json.dumps(data), + encoding="UTF-8", + ) + + super().closeEvent(event) + + +if __name__ == "__main__": + # Поддержка высокого DPI (важно для правильных координат на 4K мониторах) + QApplication.setAttribute(Qt.ApplicationAttribute.AA_EnableHighDpiScaling) + + app = QApplication(sys.argv) + + selector = AreaSelectorDialog() + selector.exec() + + selected_rect: QRect = selector.selected_rect + if selector.selected_rect: + w = selected_rect.width() + h = selected_rect.height() + + # Извлекаем границы + x1 = selected_rect.left() + y1 = selected_rect.top() + x2 = selected_rect.right() + y2 = selected_rect.bottom() + + print("--- Координаты ---") + print(f"x1={x1}, y1={y1}, x2={x2}, y2={y2}") + print(f"Tuple: ({x1}, {y1}, {x2}, {y2})") + print(f"Args: --x1={x1} --y1={y1} --x2={x2} --y2={y2}") + print(f"Размер: {w}x{h}") + print("------------------------------") + + if selector.need_run_clicker: + click_all_on_screen( + do_click=selector.do_click, + step=selector.step, + sleep_time_before_starting_secs=1, + coords=(x1, y1, x2, y2), + ) + + else: + print("Выбор отменен.") + + # NOTE: Не нужен для QDialog.exec + # sys.exit(app.exec()) diff --git a/for_games/hotkeys_for_cheats__Disciples_Sacred_Lands/main.py b/for_games/hotkeys_for_cheats__Disciples_Sacred_Lands/main.py index 41db2e1cc..027652d21 100644 --- a/for_games/hotkeys_for_cheats__Disciples_Sacred_Lands/main.py +++ b/for_games/hotkeys_for_cheats__Disciples_Sacred_Lands/main.py @@ -8,7 +8,7 @@ import keyboard -def input_command(text: str): +def input_command(text: str) -> None: keyboard.press_and_release("enter") keyboard.write(text) diff --git a/for_games/input_cheats_starcraft.py b/for_games/input_cheats_starcraft.py index 935349de0..6d9100edf 100644 --- a/for_games/input_cheats_starcraft.py +++ b/for_games/input_cheats_starcraft.py @@ -11,7 +11,7 @@ import keyboard -def write(text: str): +def write(text: str) -> None: print(text) # Удаление символа, который мог попасть при вводе хоткея, например Z, X, C или V diff --git a/for_games/input_cheats_starcraft2.py b/for_games/input_cheats_starcraft2.py index 73b45ea12..771ea44ce 100644 --- a/for_games/input_cheats_starcraft2.py +++ b/for_games/input_cheats_starcraft2.py @@ -13,7 +13,7 @@ import keyboard -def write(text: str): +def write(text: str) -> None: print(text) os.system(f"echo {text}|clip") diff --git a/html_parsing/kanobu_ru__games__collections__igry_s_podderzhkoi_rtx.py b/for_games/kanobu_ru__games__collections__igry_s_podderzhkoi_rtx.py similarity index 98% rename from html_parsing/kanobu_ru__games__collections__igry_s_podderzhkoi_rtx.py rename to for_games/kanobu_ru__games__collections__igry_s_podderzhkoi_rtx.py index 8c726dc48..92f0a55e1 100644 --- a/html_parsing/kanobu_ru__games__collections__igry_s_podderzhkoi_rtx.py +++ b/for_games/kanobu_ru__games__collections__igry_s_podderzhkoi_rtx.py @@ -79,7 +79,7 @@ def get_games() -> list[Game]: return items -def save_as_html(file_name: str, items: list[Game], columns=4): +def save_as_html(file_name: str, items: list[Game], columns=4) -> None: title = "Games with RTX" with open(file_name, "w", encoding="utf-8") as f: diff --git a/for_games/nintendo_switch_emulator__games/common.py b/for_games/nintendo_switch_emulator__games/common.py index b6d41906f..546b0d4cd 100644 --- a/for_games/nintendo_switch_emulator__games/common.py +++ b/for_games/nintendo_switch_emulator__games/common.py @@ -12,7 +12,7 @@ def get_json_file_name(file_name: str) -> str: return Path(file_name).name + ".json" -def dump(file_name: str, games: list, playable_games: list, perfect_games: list): +def dump(file_name: str, games: list, playable_games: list, perfect_games: list) -> None: data = { "perfect_games": { "total": len(perfect_games), diff --git a/for_games/press_release_keys__ScanCodes__for_games.py b/for_games/press_release_keys__ScanCodes__for_games.py index 4ce4075d3..c788e0e6d 100644 --- a/for_games/press_release_keys__ScanCodes__for_games.py +++ b/for_games/press_release_keys__ScanCodes__for_games.py @@ -219,7 +219,7 @@ class Input(ctypes.Structure): ] -def press_key(hex_key_code: int): +def press_key(hex_key_code: int) -> None: extra = ctypes.c_ulong(0) ii_ = Input_I() ii_.ki = KeyBdInput(0, hex_key_code, KEYEVENTF_SCANCODE, 0, ctypes.pointer(extra)) @@ -227,7 +227,7 @@ def press_key(hex_key_code: int): ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x)) -def release_key(hex_key_code: int): +def release_key(hex_key_code: int) -> None: extra = ctypes.c_ulong(0) ii_ = Input_I() ii_.ki = KeyBdInput( @@ -237,7 +237,7 @@ def release_key(hex_key_code: int): ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x)) -def write_key(hex_key_code: int, interval=0.1, pause=None): +def write_key(hex_key_code: int, interval=0.1, pause=None) -> None: press_key(hex_key_code) time.sleep(interval) release_key(hex_key_code) diff --git a/for_games/solutions of games/ELEX__hacking_minigame.py b/for_games/solutions of games/ELEX__hacking_minigame.py index 684003e25..8649ce898 100644 --- a/for_games/solutions of games/ELEX__hacking_minigame.py +++ b/for_games/solutions of games/ELEX__hacking_minigame.py @@ -16,7 +16,7 @@ def run( keys: list[int], fixed_values: list[str | int], need_values: list[str | int], -): +) -> None: while True: items = keys.copy() fixed_items = fixed_values.copy() diff --git a/for_games/solutions of games/FFXIII-2_clock_puzzle_solver/main.py b/for_games/solutions of games/FFXIII-2_clock_puzzle_solver/main.py index 41f559149..087fbfa68 100644 --- a/for_games/solutions of games/FFXIII-2_clock_puzzle_solver/main.py +++ b/for_games/solutions of games/FFXIII-2_clock_puzzle_solver/main.py @@ -27,7 +27,7 @@ def is_fail(clock_data: dict) -> bool: return a == 0 and b == 0 -def click_clock_item(clock_data: dict, selected_index: int): +def click_clock_item(clock_data: dict, selected_index: int) -> None: items = clock_data["items"] move_value = items[selected_index] @@ -48,7 +48,7 @@ def click_clock_item(clock_data: dict, selected_index: int): clock_data["history"].append(deepcopy(clock_data["items"])) -def solve_step(clock_data: dict, index: int, result_win: dict): +def solve_step(clock_data: dict, index: int, result_win: dict) -> None: # Если текущий индекс указывает на уже активированную кнопку if clock_data["items"][index] == 0: return @@ -95,7 +95,7 @@ def solver(clock_items: list) -> list: return list(wins.values()) -def print_extended(clock_data: dict): +def print_extended(clock_data: dict) -> None: num_clock_items = len(clock_data["selected_indexes"]) # Форматирование строки для красивого отображения двухзначных индексов @@ -111,7 +111,7 @@ def print_extended(clock_data: dict): print(fmt_print.format(item, index, value)) -def print_simple(clock_data: dict): +def print_simple(clock_data: dict) -> None: simple_result = zip(clock_data["selected_indexes"], clock_data["selected_values"]) print(" -> ".join(f"{index}({value})" for index, value in simple_result)) diff --git a/for_games/solutions of games/SpongeBob SquarePants Battle for Bikini Bottom - Rehydrated. 8 cylinder puzzle/main.py b/for_games/solutions of games/SpongeBob SquarePants Battle for Bikini Bottom - Rehydrated. 8 cylinder puzzle/main.py index 6416a3aa1..f0c4b1f72 100644 --- a/for_games/solutions of games/SpongeBob SquarePants Battle for Bikini Bottom - Rehydrated. 8 cylinder puzzle/main.py +++ b/for_games/solutions of games/SpongeBob SquarePants Battle for Bikini Bottom - Rehydrated. 8 cylinder puzzle/main.py @@ -7,7 +7,7 @@ import copy -def activate(cylinders: list[bool], index: int): +def activate(cylinders: list[bool], index: int) -> None: left_index = (index - 1) % len(cylinders) right_index = (index + 1) % len(cylinders) @@ -20,7 +20,7 @@ def is_win(cylinders: list[bool]) -> bool: return all(cylinders) -def run(init_cylinders: list[bool]): +def run(init_cylinders: list[bool]) -> None: for start_index in range(len(init_cylinders)): seq = [start_index] diff --git a/for_games/solutions of games/solution_puzzle_from_game_Afterfall_InSanity/main.py b/for_games/solutions of games/solution_puzzle_from_game_Afterfall_InSanity/main.py index d4d5e93fe..4db2fdf4b 100644 --- a/for_games/solutions of games/solution_puzzle_from_game_Afterfall_InSanity/main.py +++ b/for_games/solutions of games/solution_puzzle_from_game_Afterfall_InSanity/main.py @@ -14,7 +14,7 @@ class Button: is_clicked: bool = False -def activate(buttons: list[Button], index: int): +def activate(buttons: list[Button], index: int) -> None: button = buttons[index] if button.is_clicked: return @@ -37,7 +37,7 @@ def is_win(buttons: list[Button]) -> bool: return all(x.value for x in buttons) -def run(init_buttons: list[Button]): +def run(init_buttons: list[Button]) -> None: for start_index in range(len(init_buttons)): seq = [start_index] diff --git a/function_example/function_example.py b/function_example/function_example.py index 26ce1880b..036887abe 100644 --- a/function_example/function_example.py +++ b/function_example/function_example.py @@ -8,12 +8,12 @@ def my_sum(*args): return s -def my_print(**kwargs): +def my_print(**kwargs) -> None: for name, value in kwargs.items(): print("%s=%s(%s)" % (name, value, type(value))) -def sql_insert(table, **kwargs): +def sql_insert(table, **kwargs) -> str: # Example: INSERT INTO users (login, pass) values('TestUser', '123456') columns = kwargs.keys() values = ["'%s'" % x for x in kwargs.values()] @@ -24,7 +24,7 @@ def sql_insert(table, **kwargs): ) -def say_hello(word="World", spl="!"): +def say_hello(word="World", spl="!") -> None: print("Hello, " + word + spl) diff --git a/functor.py b/functor.py index 554f8fa15..05f7a8834 100644 --- a/functor.py +++ b/functor.py @@ -8,7 +8,7 @@ class Foo: - def __call__(self): + def __call__(self) -> int: return 1 @@ -23,14 +23,14 @@ def __call__(self, a, b): class Bar: - def __init__(self, start_value=0): + def __init__(self, start_value=0) -> None: self.value = start_value def __call__(self, *args, **kwargs): self.value += 1 return self - def __str__(self): + def __str__(self) -> str: return f"" diff --git a/games/game__guess_the_number/gui__pyqt/main.py b/games/game__guess_the_number/gui__pyqt/main.py index 7be3bca80..55354089d 100644 --- a/games/game__guess_the_number/gui__pyqt/main.py +++ b/games/game__guess_the_number/gui__pyqt/main.py @@ -11,7 +11,7 @@ from PyQt5.Qt import * -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -25,14 +25,14 @@ def log_uncaught_exceptions(ex_cls, ex, tb): # SOURCE: https://github.com/gil9red/SimplePyScripts/blob/907a596654aabb9948934b68b0f7b1fe392e23bd/qt__pyqt__pyside__pyqode/pyqt__QListWidget__Flow.py class WrapListWidget(QListWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setFlow(QListView.LeftToRight) self.setWrapping(True) self.setUniformItemSizes(True) - def resizeEvent(self, event): + def resizeEvent(self, event) -> None: super().resizeEvent(event) self.setWrapping(self.isWrapping()) @@ -41,7 +41,7 @@ def resizeEvent(self, event): class PageGuessWidget(QWidget): about_prev = pyqtSignal() - def __init__(self): + def __init__(self) -> None: super().__init__() self.lives = 10 @@ -71,11 +71,11 @@ def __init__(self): self._update_states() - def _update_states(self): + def _update_states(self) -> None: self.lbl_lives.setText(f"Жизней: {self.lives}") self.lbl_level.setText(f"Уровень: {self.level}") - def start_game(self, level: int, lives=10): + def start_game(self, level: int, lives=10) -> None: self.lives = lives self.level = level @@ -88,7 +88,7 @@ def start_game(self, level: int, lives=10): self._update_states() - def _on_number_clicked(self, item: QListWidgetItem): + def _on_number_clicked(self, item: QListWidgetItem) -> None: num = int(item.text()) if self.guess_number == num: @@ -122,7 +122,7 @@ def _on_number_clicked(self, item: QListWidgetItem): class PageSelectLevelWidget(QWidget): about_select_level = pyqtSignal(int) - def __init__(self): + def __init__(self) -> None: super().__init__() self.grid_layout = QGridLayout() @@ -140,7 +140,7 @@ def __init__(self): self.setLayout(layout) - def _add_levels(self, levels): + def _add_levels(self, levels) -> None: start_row = self.grid_layout.rowCount() for row, rows in enumerate(levels, start=start_row): @@ -154,7 +154,7 @@ def _add_levels(self, levels): class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Guess the number") @@ -174,7 +174,7 @@ def __init__(self): self.setCentralWidget(self.stack_widget) - def _on_select_level(self, level: int): + def _on_select_level(self, level: int) -> None: # Переключаемся на страницу с игрой self.stack_widget.setCurrentWidget(self.page_guess) diff --git a/games/life/board.py b/games/life/board.py index 6aa894f76..606d9016b 100644 --- a/games/life/board.py +++ b/games/life/board.py @@ -25,7 +25,7 @@ class StepResultEnum(enum.Enum): class Board(QObject): on_update_generation = pyqtSignal(int) - def __init__(self): + def __init__(self) -> None: super().__init__() self.rows = 100 @@ -38,7 +38,7 @@ def __init__(self): self.last_step_result: StepResultEnum = None - def generate(self, seed: str = ""): + def generate(self, seed: str = "") -> None: self.seed = seed if not self.seed: self.seed = get_random_seed() @@ -62,7 +62,7 @@ def generation_number(self) -> int: return self.__generation_number @generation_number.setter - def generation_number(self, value: int): + def generation_number(self, value: int) -> None: self.__generation_number = value self.on_update_generation.emit(self.generation_number) diff --git a/games/life/main_console.py b/games/life/main_console.py index 8402c5fd0..decd1f919 100644 --- a/games/life/main_console.py +++ b/games/life/main_console.py @@ -20,7 +20,7 @@ class MyLateFigletText(StaticRenderer): - def __init__(self, rendered_text_func: Callable[[], str], **kwargs): + def __init__(self, rendered_text_func: Callable[[], str], **kwargs) -> None: super().__init__() self.rendered_text_func = rendered_text_func @@ -45,7 +45,7 @@ def __init__( height: int, width: int, next_scene: str, - ): + ) -> None: self.y = y self.x = x self.height = height @@ -70,7 +70,7 @@ def __init__( self.thread = Thread(target=self._run_timer, daemon=True) - def start(self, timer_ms: int, seed: str): + def start(self, timer_ms: int, seed: str) -> None: self.is_fail = False self.timer_secs = timer_ms / 1000 @@ -81,7 +81,7 @@ def start(self, timer_ms: int, seed: str): # TODO: RuntimeError: threads can only be started once self.thread.start() - def _run_timer(self): + def _run_timer(self) -> None: while self.board.do_step() == StepResultEnum.OK: time.sleep(self.timer_secs) @@ -124,7 +124,7 @@ def __init__( self, screen: Screen, y: int, x: int, height: int, width: int, - ): + ) -> None: self.y = y self.x = x self.height = height @@ -167,7 +167,7 @@ def get_timer_ms(self) -> int: def get_seed(self) -> str: return self.le_seed.value - def _start(self): + def _start(self) -> None: # TODO: validator не работает. Не помогает save и validate self.save(validate=True) @@ -178,7 +178,7 @@ def _start(self): ) -def demo(screen: Screen, scene: Scene): +def demo(screen: Screen, scene: Scene) -> None: menu_widget = MenuWidget( screen, y=0, x=0, diff --git a/games/life/main_gui.py b/games/life/main_gui.py index cebca1a08..0f1d28a1c 100644 --- a/games/life/main_gui.py +++ b/games/life/main_gui.py @@ -25,7 +25,7 @@ from board import Board, StepResultEnum, get_random_seed -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -41,13 +41,13 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class BoardWidget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.board = Board() self.cell_size = 1 - def resizeEvent(self, event): + def resizeEvent(self, event) -> None: super().resizeEvent(event) self.cell_size = min(self.width(), self.height()) // min( @@ -58,14 +58,14 @@ def resizeEvent(self, event): self.update() - def _draw_cell_board(self, painter: QPainter, x: int, y: int, color: QColor): + def _draw_cell_board(self, painter: QPainter, x: int, y: int, color: QColor) -> None: painter.setPen(Qt.NoPen) painter.setBrush(color) painter.drawRect( x * self.cell_size, y * self.cell_size, self.cell_size, self.cell_size ) - def _draw_board(self, painter: QPainter): + def _draw_board(self, painter: QPainter) -> None: painter.save() # Рисование заполненных ячеек @@ -78,7 +78,7 @@ def _draw_board(self, painter: QPainter): painter.restore() - def paintEvent(self, event: QPaintEvent): + def paintEvent(self, event: QPaintEvent) -> None: painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) @@ -90,7 +90,7 @@ class MainWindow(QWidget): TITLE = "Life" - def __init__(self): + def __init__(self) -> None: super().__init__() self.board_widget = BoardWidget() @@ -138,16 +138,16 @@ def __init__(self): self.setLayout(main_layout) self._update_states() - def _do_rand_seed(self): + def _do_rand_seed(self) -> None: self.le_seed.setText(get_random_seed()) - def start(self): + def start(self) -> None: self.board.generate(seed=self.le_seed.text()) self.timer.stop() self.start_pause_timer() - def start_pause_timer(self): + def start_pause_timer(self) -> None: if self.timer.isActive(): self.timer.stop() else: @@ -155,7 +155,7 @@ def start_pause_timer(self): self._update_states() - def _update_states(self): + def _update_states(self) -> None: is_paused = not self.timer.isActive() prefix = "[IS PAUSED] " if is_paused else "" self.setWindowTitle( @@ -168,12 +168,12 @@ def _update_states(self): self.button_timer.setChecked(self.timer.isActive()) - def abort_game(self, reason: str): + def abort_game(self, reason: str) -> None: self.timer.stop() self._update_states() QMessageBox.information(self, "Информация", f"Проигрыш! {reason}") - def _on_logic(self): + def _on_logic(self) -> None: result = self.board.do_step() if result == StepResultEnum.OK: return @@ -190,7 +190,7 @@ def _on_logic(self): self.abort_game(reason) - def _on_tick(self): + def _on_tick(self) -> None: self._on_logic() self._update_states() self.board_widget.update() diff --git a/games/nim/main.py b/games/nim/main.py index 8ed4b5ea7..25d7b1a3c 100644 --- a/games/nim/main.py +++ b/games/nim/main.py @@ -91,7 +91,7 @@ class Game: MAX_STONES: int = 3 MAX_NUMBER: int = 21 - def start(self): + def start(self) -> None: self.player1.game = self self.player2.game = self diff --git a/games/tetris/main_console.py b/games/tetris/main_console.py index a57e128d0..ece99506f 100644 --- a/games/tetris/main_console.py +++ b/games/tetris/main_console.py @@ -35,7 +35,7 @@ class MyLateFigletText(StaticRenderer): - def __init__(self, rendered_text_func: Callable[[], str], **kwargs): + def __init__(self, rendered_text_func: Callable[[], str], **kwargs) -> None: super().__init__() self.rendered_text_func = rendered_text_func @@ -60,7 +60,7 @@ def __init__( height: int, width: int, next_scene: str, - ): + ) -> None: self.y = y self.x = x self.height = height @@ -85,13 +85,13 @@ def __init__( self.thread = Thread(target=self._run_timer, daemon=True) self.thread.start() - def _run_timer(self): + def _run_timer(self) -> None: while self.board.do_step(): time.sleep(0.3) self.is_fail = True - def update(self, frame_no: int): + def update(self, frame_no: int) -> None: super().update(frame_no) if self.is_fail: @@ -159,7 +159,7 @@ def __init__( x: int, height: int, width: int, - ): + ) -> None: self.y = y self.x = x self.height = height @@ -178,7 +178,7 @@ def __init__( self.board = board self.next_piece = self.board.next_piece - def update(self, frame_no: int): + def update(self, frame_no: int) -> None: super().update(frame_no) self.next_piece = self.board.next_piece @@ -208,7 +208,7 @@ def __init__( x: int, height: int, width: int, - ): + ) -> None: self.y = y self.x = x self.height = height @@ -226,7 +226,7 @@ def __init__( self.set_theme("monochrome") self.board = board - def update(self, frame_no: int): + def update(self, frame_no: int) -> None: super().update(frame_no) self.screen.print_at(f"Score: {self.board.score}", self.x, self.y) @@ -239,7 +239,7 @@ def frame_update_count(self) -> int: return 5 -def demo(screen: Screen, scene: Scene): +def demo(screen: Screen, scene: Scene) -> None: board = Board() scenes = [ Scene( diff --git a/games/tetris/main_gui.py b/games/tetris/main_gui.py index 5ed56ccf0..3e7685fab 100644 --- a/games/tetris/main_gui.py +++ b/games/tetris/main_gui.py @@ -39,7 +39,7 @@ from src.gui.piece_widget import PieceWidget -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -95,7 +95,7 @@ def to_dict(self) -> dict[str, Any]: class MainWindow(QWidget): TITLE: str = "Tetris" - def __init__(self): + def __init__(self) -> None: super().__init__() self.high_scores: list[HighScore] = [] @@ -197,15 +197,15 @@ def _add_button(text: str, key: Qt.Key) -> QToolButton: self._update_states() - def _on_before_start(self): + def _on_before_start(self) -> None: self.board_widget.seed = None if self.cb_random.isChecked(): self.board_widget.seed = self.le_seed.text() - def _do_start(self): + def _do_start(self) -> None: self.board_widget.start() - def _on_finish(self): + def _on_finish(self) -> None: self.high_scores.append( HighScore( date_added=datetime.now(), @@ -229,7 +229,7 @@ def get_top_high_scores(self, number: int = 5) -> list[HighScore]: self.high_scores = self.high_scores[:number] return self.high_scores - def _update_states(self): + def _update_states(self) -> None: score: int = self.board_widget.board.score playing_time = ms_to_str(self.board_widget.playing_time_ms) @@ -264,7 +264,7 @@ def _update_states(self): is_started or self.board_widget.status == StatusGameEnum.PAUSED ) - def _fill_high_scores_view(self): + def _fill_high_scores_view(self) -> None: lines = ["High scores (top 5):"] for i, high_score in enumerate(self.get_top_high_scores(), start=1): @@ -278,17 +278,17 @@ def _fill_high_scores_view(self): def get_raw_high_scores(self) -> list[dict[str, Any]]: return [high_score.to_dict() for high_score in self.high_scores] - def set_raw_high_scores(self, items: list[dict[str, Any]]): + def set_raw_high_scores(self, items: list[dict[str, Any]]) -> None: self.high_scores = [HighScore.parse(data) for data in items] self._fill_high_scores_view() - def save_high_scores(self): + def save_high_scores(self) -> None: FILE_HIGH_SCORES.write_text( json.dumps(self.get_raw_high_scores(), indent=4), encoding="utf-8", ) - def load_high_scores(self): + def load_high_scores(self) -> None: if not FILE_HIGH_SCORES.exists(): return @@ -297,7 +297,7 @@ def load_high_scores(self): ) self.set_raw_high_scores(items) - def keyReleaseEvent(self, event: QKeyEvent): + def keyReleaseEvent(self, event: QKeyEvent) -> None: self.board_widget.process_key(event.key()) self._update_states() diff --git a/games/tetris/src/core/board.py b/games/tetris/src/core/board.py index c3a61a3e8..6f4da0d30 100644 --- a/games/tetris/src/core/board.py +++ b/games/tetris/src/core/board.py @@ -18,7 +18,7 @@ class Board(QObject): on_next_piece = pyqtSignal(Piece) on_update_score = pyqtSignal(int) - def __init__(self): + def __init__(self) -> None: super().__init__() self.matrix: list[list[QColor | None]] = [ @@ -35,7 +35,7 @@ def next_piece(self) -> Piece | None: return self.__next_piece @next_piece.setter - def next_piece(self, value: Piece | None): + def next_piece(self, value: Piece | None) -> None: self.__next_piece = value self.on_next_piece.emit(value) @@ -44,23 +44,23 @@ def score(self) -> int: return self.__score @score.setter - def score(self, value: int): + def score(self, value: int) -> None: self.__score = value self.on_update_score.emit(value) - def add_piece(self, piece: Piece): + def add_piece(self, piece: Piece) -> None: logger.debug("[add_piece]") for x, y in piece.get_points(): self.matrix[y][x] = piece.get_color() - def clear(self): + def clear(self) -> None: self.score = 0 for row in self.matrix: for i in range(len(row)): row[i] = None - def _do_make_collapse_of_rows(self): + def _do_make_collapse_of_rows(self) -> None: to_delete: list[list[QColor | None]] = [] for row in reversed(self.matrix): if all(color for color in row): diff --git a/games/tetris/src/core/piece.py b/games/tetris/src/core/piece.py index e4491e17f..1abdbc52a 100644 --- a/games/tetris/src/core/piece.py +++ b/games/tetris/src/core/piece.py @@ -21,7 +21,7 @@ class Piece(abc.ABC): 4: 1, } - def __init__(self, x: int, y: int, parent: "Board" = None): + def __init__(self, x: int, y: int, parent: "Board" = None) -> None: self.x = x self.y = y self.parent = parent @@ -124,10 +124,10 @@ def get_min_y(self) -> int: def get_max_y(self) -> int: return max(y for _, y in self.get_points()) - def go_to_next_state(self): + def go_to_next_state(self) -> None: self.current_state = self.STATES[self.current_state] - def set_points(self, points: list[tuple[int, int]]): + def set_points(self, points: list[tuple[int, int]]) -> None: self.points = points def get_points(self) -> list[tuple[int, int]]: diff --git a/games/tetris/src/gui/board_widget.py b/games/tetris/src/gui/board_widget.py index b1925d279..f93d80b16 100644 --- a/games/tetris/src/gui/board_widget.py +++ b/games/tetris/src/gui/board_widget.py @@ -23,7 +23,7 @@ class BoardWidget(QWidget): on_before_start = pyqtSignal() on_finish = pyqtSignal() - def __init__(self): + def __init__(self) -> None: super().__init__() self.board = Board() @@ -46,7 +46,7 @@ def minimumSizeHint(self) -> QSize: height = (CELL_SIZE * rows) + (self.INDENT * 2) return QSize(width, height) - def _fill_random(self): + def _fill_random(self) -> None: while True: try: self.board.clear() @@ -84,7 +84,7 @@ def _fill_random(self): finally: self.board.score = 0 - def start(self): + def start(self) -> None: if self.status not in [StatusGameEnum.INITED, StatusGameEnum.FINISHED]: return @@ -104,7 +104,7 @@ def status(self) -> StatusGameEnum: return self.__status @status.setter - def status(self, value: StatusGameEnum): + def status(self, value: StatusGameEnum) -> None: if self.__status == value: return @@ -126,14 +126,14 @@ def status(self, value: StatusGameEnum): self.__timer.stop() self.on_finish.emit() - def abort_game(self): + def abort_game(self) -> None: self.status = StatusGameEnum.FINISHED - def _on_logic(self): + def _on_logic(self) -> None: if not self.board.do_step(): self.abort_game() - def _on_tick(self): + def _on_tick(self) -> None: self._on_logic() self.update() @@ -142,7 +142,7 @@ def _on_tick(self): self.on_tick.emit() @painter_context - def _draw_board(self, painter: QPainter): + def _draw_board(self, painter: QPainter) -> None: # Рисование заполненных ячеек for y, row in enumerate(self.board.matrix): for x, cell_color in enumerate(row): @@ -179,7 +179,7 @@ def _draw_board(self, painter: QPainter): x2 += self.cell_size @painter_context - def _draw_current_piece(self, painter: QPainter): + def _draw_current_piece(self, painter: QPainter) -> None: if not self.board.current_piece: return @@ -194,7 +194,7 @@ def _draw_current_piece(self, painter: QPainter): ) @painter_context - def _draw_shadow_of_current_piece(self, painter: QPainter): + def _draw_shadow_of_current_piece(self, painter: QPainter) -> None: if not self.board.current_piece: return @@ -231,7 +231,7 @@ def _draw_shadow_of_current_piece(self, painter: QPainter): ) @painter_context - def _draw_glass(self, painter: QPainter): + def _draw_glass(self, painter: QPainter) -> None: match self.status: case StatusGameEnum.INITED: text = "Press START" @@ -274,7 +274,7 @@ def _draw_glass(self, painter: QPainter): painter.drawRect(self.rect()) painter.drawText(self.rect(), Qt.AlignCenter, text) - def process_key(self, key: int): + def process_key(self, key: int) -> None: if key == Qt.Key_Space and self.status in [ StatusGameEnum.STARTED, StatusGameEnum.PAUSED, @@ -309,7 +309,7 @@ def process_key(self, key: int): self.update() return - def resizeEvent(self, event: QResizeEvent): + def resizeEvent(self, event: QResizeEvent) -> None: super().resizeEvent(event) w_aspect = event.size().width() // self.board.COLS @@ -319,7 +319,7 @@ def resizeEvent(self, event: QResizeEvent): self.update() - def paintEvent(self, event: QPaintEvent): + def paintEvent(self, event: QPaintEvent) -> None: painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) diff --git a/games/tetris/src/gui/common.py b/games/tetris/src/gui/common.py index 3a32ce2e6..1aee93623 100644 --- a/games/tetris/src/gui/common.py +++ b/games/tetris/src/gui/common.py @@ -43,7 +43,7 @@ def draw_cell_board( pen: Qt.GlobalColor = Qt.NoPen, cell_size: int = CELL_SIZE, indent: int = 0, -): +) -> None: painter.setPen(pen) painter.setBrush(color) painter.drawRect( diff --git a/games/tetris/src/gui/piece_widget.py b/games/tetris/src/gui/piece_widget.py index c39a79b76..e57ada03f 100644 --- a/games/tetris/src/gui/piece_widget.py +++ b/games/tetris/src/gui/piece_widget.py @@ -14,12 +14,12 @@ class PieceWidget(QWidget): INDENT: int = 1 - def __init__(self, parent: QWidget | None = None): + def __init__(self, parent: QWidget | None = None) -> None: super().__init__(parent) self.piece: Piece | None = None - def set_piece(self, piece: Piece): + def set_piece(self, piece: Piece) -> None: self.piece = piece self.update() @@ -27,7 +27,7 @@ def minimumSizeHint(self) -> QSize: size = (CELL_SIZE * 4) + (self.INDENT * 2) return QSize(size, size) - def paintEvent(self, event: QPaintEvent): + def paintEvent(self, event: QPaintEvent) -> None: if not self.piece: return diff --git a/games/tic_tac_toe__example.py b/games/tic_tac_toe__example.py index 4afd8c111..85fe6a6a6 100644 --- a/games/tic_tac_toe__example.py +++ b/games/tic_tac_toe__example.py @@ -15,7 +15,7 @@ class Window(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() # Матрица 3 на 3 @@ -26,7 +26,7 @@ def __init__(self): # If True -- X else -- O self._current_figure_flag = True - def _check_win(self): + def _check_win(self) -> None: b = self._board_tic_tac_toe win_X = False win_O = False @@ -80,7 +80,7 @@ def _check_win(self): QMessageBox.information(self, "Winner", "Win O") return - def mouseReleaseEvent(self, e): + def mouseReleaseEvent(self, e) -> None: # Определяем позицию клика i = e.pos().y() // self._size_cell j = e.pos().x() // self._size_cell @@ -97,7 +97,7 @@ def mouseReleaseEvent(self, e): self._check_win() - def paintEvent(self, e): + def paintEvent(self, e) -> None: painter = QPainter(self) painter.setPen(Qt.black) diff --git a/get_actual_news_from_rss_ya/webserver/common.py b/get_actual_news_from_rss_ya/webserver/common.py index 4ec6889cc..6e6bdd67b 100644 --- a/get_actual_news_from_rss_ya/webserver/common.py +++ b/get_actual_news_from_rss_ya/webserver/common.py @@ -24,7 +24,7 @@ def create_connect(): return sqlite3.connect(DB_FILE_NAME) -def init_db(): +def init_db() -> None: # Создание базы и таблицы connect = create_connect() try: @@ -71,10 +71,10 @@ def init_db(): connect.close() -def append_list_news(list_news: [str, str], interest: str): +def append_list_news(list_news: [str, str], interest: str) -> None: connect = create_connect() - def insert_news(title, url, interest): + def insert_news(title, url, interest) -> None: # Для отсеивания дубликатов has = connect.execute("SELECT 1 FROM News WHERE url = ?", (url,)).fetchone() if has: @@ -161,7 +161,7 @@ def get_news_list_and_mark_as_read( connect.close() -def reset_all_is_read(): +def reset_all_is_read() -> None: connect = create_connect() try: diff --git a/get_all_objects_in_memory.py b/get_all_objects_in_memory.py index 42a756ead..ca9390429 100644 --- a/get_all_objects_in_memory.py +++ b/get_all_objects_in_memory.py @@ -14,7 +14,7 @@ # Recursively expand slist's objects # into olist, using seen to track # already processed objects. -def _getr(slist, olist, seen): +def _getr(slist, olist, seen) -> None: for e in slist: if id(e) in seen: continue @@ -47,7 +47,7 @@ def get_all_objects(): print(len(gc.get_objects())) class Foo: - def bar(self): + def bar(self) -> str: return f"Foo(id={hex(id(self))})" items = [Foo() for _ in range(3)] diff --git a/get_cpu_process/get_cpu_process.py b/get_cpu_process/get_cpu_process.py index d498631b1..c03b6151a 100644 --- a/get_cpu_process/get_cpu_process.py +++ b/get_cpu_process/get_cpu_process.py @@ -14,7 +14,7 @@ class ProcessNotFound(Exception): - def __init__(self, name: str): + def __init__(self, name: str) -> None: super().__init__(f"Process {name!r} not found") diff --git a/get_function_caller_name.py b/get_function_caller_name.py index 36bbd295b..52de9833c 100644 --- a/get_function_caller_name.py +++ b/get_function_caller_name.py @@ -14,17 +14,17 @@ def caller_name() -> str: if __name__ == "__main__": - def foo(): + def foo() -> None: print(caller_name()) assert caller_name() == "foo" foo() - def bar(): + def bar() -> None: print(caller_name()) assert caller_name() == "bar" - def zoo(): + def zoo() -> None: print(caller_name()) assert caller_name() == "zoo" diff --git a/get_functions_from_object__module_class_object.py b/get_functions_from_object__module_class_object.py index df7263a0e..38563a639 100644 --- a/get_functions_from_object__module_class_object.py +++ b/get_functions_from_object__module_class_object.py @@ -20,7 +20,7 @@ def get_name_by_func(obj: object) -> dict: print(get_name_by_func(builtins)) class Foo: - def a(self): + def a(self) -> int: return 1 print(get_name_by_func(Foo)) diff --git a/get_md5_file/get_md5_file_gui.py b/get_md5_file/get_md5_file_gui.py index aa1ad0e72..17628e6d5 100644 --- a/get_md5_file/get_md5_file_gui.py +++ b/get_md5_file/get_md5_file_gui.py @@ -45,7 +45,7 @@ from get_md5_file import md5sum -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -61,7 +61,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("get_md5_file_gui") @@ -97,7 +97,7 @@ def __init__(self): self.setCentralWidget(central_widget) - def dragEnterEvent(self, event): + def dragEnterEvent(self, event) -> None: mime = event.mimeData() if mime.hasUrls() and len(mime.urls()) == 1: event.acceptProposedAction() diff --git a/github_api__examples/common.py b/github_api__examples/common.py index a0bba6ed3..b63ea6567 100644 --- a/github_api__examples/common.py +++ b/github_api__examples/common.py @@ -4,6 +4,9 @@ __author__ = "ipetrash" +import os + +from pathlib import Path from dataclasses import dataclass import requests @@ -15,6 +18,21 @@ class User: url: str +DIR: Path = Path(__file__).resolve().parent + +TOKEN_FILE_NAME: Path = DIR / "TOKEN.txt" +try: + TOKEN: str = os.environ.get("TOKEN") or TOKEN_FILE_NAME.read_text("utf-8").strip() +except: + TOKEN: str = "" + + +session = requests.Session() + +if TOKEN: + session.headers["Authorization"] = f"Bearer {TOKEN}" + + def get_users(url: str) -> list[User]: per_page: int = 100 page: int = 1 @@ -23,7 +41,7 @@ def get_users(url: str) -> list[User]: while True: params = dict(per_page=per_page, page=page) - rs = requests.get(url, params=params) + rs = session.get(url, params=params) rs.raise_for_status() result: list[dict] = rs.json() diff --git a/github_api__examples/get_last_commit.py b/github_api__examples/get_last_commit.py index eca7ade5f..1bf85be62 100644 --- a/github_api__examples/get_last_commit.py +++ b/github_api__examples/get_last_commit.py @@ -8,7 +8,7 @@ from datetime import UTC, datetime from typing import Any -import requests +from common import session @dataclass @@ -47,14 +47,14 @@ def parse_from_dict(cls, data: dict[str, Any]) -> "Commit": def get_last_commit(owner: str, repository: str) -> Commit: url: str = f"https://api.github.com/repos/{owner}/{repository}/commits?per_page=1" - rs = requests.get(url) + rs = session.get(url) rs.raise_for_status() result: dict[str, Any] = rs.json()[0] return Commit.parse_from_dict(result) -if __name__ == '__main__': +if __name__ == "__main__": commit = get_last_commit(owner="gil9red", repository="RPG-Maker-MZ-Foo") print(commit) # Commit(sha='816a821788e113fdc80d17190fa1ed743c4b1524', message='Обновление. Улучшение алгоритма шагающей леди', author=CommitUser(name='gil9red', email='ilya.petrash@inbox.ru', date=datetime.datetime(2025, 10, 25, 18, 53, 41, tzinfo=datetime.timezone.utc)), committer=CommitUser(name='gil9red', email='ilya.petrash@inbox.ru', date=datetime.datetime(2025, 10, 25, 18, 53, 41, tzinfo=datetime.timezone.utc))) diff --git a/gitpython_examples/common.py b/gitpython_examples/common.py index ebe0c1da1..49a4e0198 100644 --- a/gitpython_examples/common.py +++ b/gitpython_examples/common.py @@ -31,7 +31,6 @@ def get_repo(): try: return git.Repo(REPO_PATH) - except: return git.Repo.clone_from(URL_GIT, REPO_PATH) @@ -46,7 +45,7 @@ def return_log(reverse=False): return logs -def print_log(reverse=False): +def print_log(reverse=False) -> None: logs = return_log(reverse) print(f"Logs[{len(logs)}]:") diff --git a/gitpython_examples/pull_all_repos.py b/gitpython_examples/pull_all_repos.py index 156cb06d5..db96df41a 100644 --- a/gitpython_examples/pull_all_repos.py +++ b/gitpython_examples/pull_all_repos.py @@ -12,7 +12,7 @@ from common import get_total_commits -def process_repository(repo_path: Path): +def process_repository(repo_path: Path) -> None: print(repo_path) repo = git.Repo(repo_path) @@ -31,7 +31,7 @@ def process_repository(repo_path: Path): print(f"Repository is actual") -def process_all(path: Path, pattern: str = '.git'): +def process_all(path: Path, pattern: str = '.git') -> None: paths: list[Path] = [ p.parent for p in path.rglob(pattern) diff --git a/hex2str/gui.py b/hex2str/gui.py index 002df5707..3ac1a952e 100644 --- a/hex2str/gui.py +++ b/hex2str/gui.py @@ -25,7 +25,7 @@ from hex2str import hex2str, str2hex -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -38,7 +38,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("hex2str") @@ -124,7 +124,7 @@ def __init__(self): self.setLayout(layout) - def _on_input_selection_changed(self): + def _on_input_selection_changed(self) -> None: try: # Нехорошо будет если второй будет вызывать сигналы, например о выделении текста self.text_edit_output.blockSignals(True) @@ -155,7 +155,7 @@ def _on_input_selection_changed(self): finally: self.text_edit_output.blockSignals(False) - def _on_output_selection_changed(self): + def _on_output_selection_changed(self) -> None: try: # Нехорошо будет если второй будет вызывать сигналы, например о выделении текста self.text_edit_input.blockSignals(True) @@ -186,7 +186,7 @@ def _on_output_selection_changed(self): finally: self.text_edit_input.blockSignals(False) - def show_detail_error_massage(self): + def show_detail_error_massage(self) -> None: message = self.last_error_message + "\n\n" + self.last_detail_error_message mb = QErrorMessage() @@ -198,7 +198,7 @@ def show_detail_error_massage(self): mb.exec_() - def _convert(self): + def _convert(self) -> None: self.label_error.clear() self.button_detail_error.hide() diff --git a/howlongtobeat__web_wrapper/api_search.py b/howlongtobeat__web_wrapper/api_search.py index 59c8a4ffe..19645100b 100644 --- a/howlongtobeat__web_wrapper/api_search.py +++ b/howlongtobeat__web_wrapper/api_search.py @@ -12,7 +12,9 @@ # NOTE: https://playwright.dev/python/docs/library#pip # pip install playwright==1.50.0 # playwright install webkit -from playwright.sync_api import sync_playwright, Response +from playwright.sync_api import Response, TimeoutError, sync_playwright + +DEFAULT_TIMEOUT_MS: int = 30_000 def _is_found_game(game1: str, game2: str) -> bool: @@ -32,30 +34,41 @@ def _process_name(name: str) -> str: def get_api_search_raw(game: str) -> dict[str, Any]: + def is_api_search(rs: Response) -> bool: + url: str = rs.url.lower() + return ( + "/api/" in url + and rs.status == 200 + and ("SEARCHTERMS" in str(rs.request.post_data).upper()) + ) + with sync_playwright() as p: - browser = p.webkit.launch() + browser = p.firefox.launch() page = browser.new_page() - page.set_default_timeout(90_000) + page.set_default_timeout(DEFAULT_TIMEOUT_MS) page.goto(f"https://howlongtobeat.com/?q={game}", wait_until="commit") - def is_api_search(rs: Response) -> bool: - url: str = rs.url.lower() - return ( - "/api/" in url - and rs.status == 200 - and ("SEARCHTERMS" in str(rs.request.post_data).upper()) - ) - with page.expect_response(is_api_search) as response_info: return response_info.value.json() -def search_game(game: str) -> dict[str, Any] | None: +def search_game(game: str, max_attempts: int = 5) -> dict[str, Any] | None: game: str = re.sub("[©®™–]", "", game).replace("`", "'") - result: dict[str, Any] = get_api_search_raw(game) + result: dict[str, Any] | None = None + for attempt in range(1, max_attempts + 1): + try: + result = get_api_search_raw(game) + break + except TimeoutError as e: + if attempt >= max_attempts: + raise e + + if not result or "data" not in result: + return + for obj in result["data"]: if ( _is_found_game(game, obj["game_name"]) @@ -69,43 +82,43 @@ def search_game(game: str) -> dict[str, Any] | None: if __name__ == "__main__": - game = "Warhammer 40,000: Space Marine 2" - result = search_game(game) - print(game, result) - assert "Warhammer 40,000: Space Marine II" == result["game_name"] - game = "Half-Life 2" result = search_game(game) print(game, result) assert game == result["game_name"] - game = "Marc Eckō's Getting Up: Contents Under Pressure" - result = search_game(game) - print(game, result) - assert "Marc Ecko's Getting Up: Contents Under Pressure" == result["game_name"] - - game = "Nightmares from the Deep 2: The Siren`s Call" - result = search_game(game) - print(game, result) - assert "Nightmares from the Deep 2: The Siren's Call" == result["game_name"] - - print() - - game = search_game("Half-Life") - print(game) - assert game - - game = search_game("Final Fantasy IX") - print(game) - assert game - - game = search_game("Final Fantasy 9") - print(game) - assert game - - game = search_game("Final Fantasy VII") - print(game) - assert game + # game = "Warhammer 40,000: Space Marine 2" + # result = search_game(game) + # print(game, result) + # assert "Warhammer 40,000: Space Marine II" == result["game_name"] + # + # game = "Marc Eckō's Getting Up: Contents Under Pressure" + # result = search_game(game) + # print(game, result) + # assert "Marc Ecko's Getting Up: Contents Under Pressure" == result["game_name"] + # + # game = "Nightmares from the Deep 2: The Siren`s Call" + # result = search_game(game) + # print(game, result) + # assert "Nightmares from the Deep 2: The Siren's Call" == result["game_name"] + # + # print() + # + # game = search_game("Half-Life") + # print(game) + # assert game + # + # game = search_game("Final Fantasy IX") + # print(game) + # assert game + # + # game = search_game("Final Fantasy 9") + # print(game) + # assert game + # + # game = search_game("Final Fantasy VII") + # print(game) + # assert game # from multiprocessing.dummy import Pool as ThreadPool # diff --git a/html_parsing/risens_team__berserk.py b/html_parsing/.deprecated/risens_team__berserk.py similarity index 100% rename from html_parsing/risens_team__berserk.py rename to html_parsing/.deprecated/risens_team__berserk.py diff --git a/html_parsing/yummyanime_club__anime_updates.py b/html_parsing/.deprecated/yummyanime_club__anime_updates.py similarity index 97% rename from html_parsing/yummyanime_club__anime_updates.py rename to html_parsing/.deprecated/yummyanime_club__anime_updates.py index 4a8312d0b..df45253a1 100644 --- a/html_parsing/yummyanime_club__anime_updates.py +++ b/html_parsing/.deprecated/yummyanime_club__anime_updates.py @@ -15,7 +15,7 @@ def get_text(el: Tag) -> str: return text.replace("\xa0", " ") -def parse_update_anime(update_el: Tag): +def parse_update_anime(update_el: Tag) -> None: title = get_text(update_el.select_one(".update-title")) update_date = get_text(update_el.select_one(".update-date")) update_info = get_text(update_el.select_one(".update-info")) diff --git a/html_parsing/yummyanime_club__posts.py b/html_parsing/.deprecated/yummyanime_club__posts.py similarity index 98% rename from html_parsing/yummyanime_club__posts.py rename to html_parsing/.deprecated/yummyanime_club__posts.py index 16573f761..ffdedeb93 100644 --- a/html_parsing/yummyanime_club__posts.py +++ b/html_parsing/.deprecated/yummyanime_club__posts.py @@ -15,7 +15,7 @@ def get_text(el: Tag) -> str: return text.replace("\xa0", " ") -def parse_post_block(post_block: Tag): +def parse_post_block(post_block: Tag) -> None: title_el = post_block.select_one(".post-title") url_post = urljoin(URL, title_el["href"]) title = get_text(title_el) diff --git a/html_parsing/Time_magazine_covers/main.py b/html_parsing/Time_magazine_covers/main.py index f62fddf5c..e5953953a 100644 --- a/html_parsing/Time_magazine_covers/main.py +++ b/html_parsing/Time_magazine_covers/main.py @@ -92,7 +92,7 @@ def dump_covers( out_dir="out", need_zip=False, remove_out_covers=False, -): +) -> None: covers = get_covers(year) out_dir = normpath(abspath(out_dir + f"/{year}")) diff --git a/html_parsing/com_x_life__berserk_chapters.py b/html_parsing/com_x_life__berserk_chapters.py new file mode 100644 index 000000000..dd212762e --- /dev/null +++ b/html_parsing/com_x_life__berserk_chapters.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +import json +import re +import time + +from dataclasses import dataclass +from datetime import datetime, date +from typing import Any, Self + +from playwright.sync_api import sync_playwright + + +HOST: str = "https://com-x.life" +URL: str = f"{HOST}/2789-berserk-read-online.html#chapters" + + +@dataclass +class Chapter: + title: str + url: str + pages: int + date: date + + @classmethod + def from_dict(cls, chapter_id: int, d: dict[str, Any]) -> Self: + return cls( + title=d["title"], + url=f"{HOST}/reader/{chapter_id}/{d['id']}", + pages=d["pages"], + date=datetime.strptime(d["date"], "%d.%m.%Y").date(), + ) + + +def get_chapters() -> list[Chapter]: + chapters: list[Chapter] = [] + + with sync_playwright() as p: + browser = p.firefox.launch() + page = browser.new_page() + + page.goto(URL) + + for _ in range(10): + time.sleep(1) + + text: str = page.content() + + m = re.search(r"window.__DATA__\s*=\s*(\{.+?\});", text) + if not m: + continue + + data: dict[str, Any] = json.loads(m.group(1)) + chapter_id: int = data["news_id"] + chapters = [ + Chapter.from_dict(chapter_id, chapter) + for chapter in data["chapters"] + ] + break + + if not chapters: + raise Exception("Не удалось найти главы!") + + return chapters + + +if __name__ == "__main__": + chapters = get_chapters() + print(f"Chapters ({len(chapters)}):") + print(*chapters[:5], sep="\n") + print("...") + print(*chapters[-5:], sep="\n") + """ + Chapters (400): + Chapter(title='Глава 383. Неведение безначально', url='https://com-x.life/reader/2789/741667', pages=24, date=datetime.date(2025, 9, 11)) + Chapter(title='Глава 382. Усыпальница', url='https://com-x.life/reader/2789/719111', pages=22, date=datetime.date(2025, 6, 26)) + Chapter(title='Глава 381. Полумесяц освещающий спину изгнанника', url='https://com-x.life/reader/2789/715388', pages=23, date=datetime.date(2025, 6, 13)) + Chapter(title='Глава 380. Тени умирают дважды.', url='https://com-x.life/reader/2789/662311', pages=20, date=datetime.date(2025, 2, 28)) + Chapter(title='379', url='https://com-x.life/reader/2789/656178', pages=22, date=datetime.date(2025, 2, 14)) + ... + Chapter(title='Том 2. Глава 0D Хранители желаний II', url='https://com-x.life/reader/2789/417510', pages=125, date=datetime.date(2024, 2, 15)) + Chapter(title='Том 1. Глава 0С Хранители желаний I', url='https://com-x.life/reader/2789/417509', pages=60, date=datetime.date(2024, 2, 15)) + Chapter(title='Том 1. Глава 0B Клеймо', url='https://com-x.life/reader/2789/417508', pages=69, date=datetime.date(2024, 2, 15)) + Chapter(title='Том 1. Глава 0А Чёрный Мечник', url='https://com-x.life/reader/2789/417507', pages=96, date=datetime.date(2024, 2, 15)) + Chapter(title='Том 1. Глава 00 Прототип', url='https://com-x.life/reader/2789/417459', pages=46, date=datetime.date(2024, 2, 14)) + """ diff --git a/html_parsing/encyclopedia_perumov_club__category__dose/db.py b/html_parsing/encyclopedia_perumov_club__category__dose/db.py index b45f1162a..fd822418f 100644 --- a/html_parsing/encyclopedia_perumov_club__category__dose/db.py +++ b/html_parsing/encyclopedia_perumov_club__category__dose/db.py @@ -20,7 +20,7 @@ DB_FILE_NAME = str(pathlib.Path(__file__).resolve().parent / "database.sqlite") -def db_create_backup(backup_dir="backup"): +def db_create_backup(backup_dir="backup") -> None: os.makedirs(backup_dir, exist_ok=True) file_name = str(dt.datetime.today().date()) + ".sqlite" @@ -43,7 +43,7 @@ class Dossier(BaseModel): url = TextField(unique=True) date = DateField(default=dt.date.today) - def __str__(self): + def __str__(self) -> str: return ( f"{self.__class__.__name__}(id={self.id}, title={self.title!r}, date={self.date}, " f"url={self.url!r}, total_items={len(self.items)})" @@ -55,7 +55,7 @@ class QuestionAnswer(BaseModel): question_text = TextField() answer_text = TextField() - def __str__(self): + def __str__(self) -> str: return ( f"{self.__class__.__name__}(id={self.id}, dossier_id={self.dossier.id}, " f"question_text={shorten(self.question_text)!r}), answer_text={shorten(self.answer_text)!r})" diff --git a/html_parsing/encyclopedia_perumov_club__category__dose/gui.py b/html_parsing/encyclopedia_perumov_club__category__dose/gui.py index 401e0f7a2..e15f56afe 100644 --- a/html_parsing/encyclopedia_perumov_club__category__dose/gui.py +++ b/html_parsing/encyclopedia_perumov_club__category__dose/gui.py @@ -67,7 +67,7 @@ def get_table_widget(header_labels: list) -> QTableWidget: class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.filter_le = QLineEdit() @@ -123,7 +123,7 @@ def _get_search_pattern(self): except: pass - def fill(self): + def fill(self) -> None: # Удаление строк таблицы while self.table_dossier.rowCount(): self.table_dossier.removeRow(0) @@ -155,7 +155,7 @@ def fill(self): self.table_dossier.setCurrentCell(0, 0) self._on_table_dossier_item_clicked() - def _on_table_dossier_item_clicked(self): + def _on_table_dossier_item_clicked(self) -> None: # Удаление строк таблицы while self.table_items.rowCount(): self.table_items.removeRow(0) @@ -199,7 +199,7 @@ def _on_table_dossier_item_clicked(self): self.table_items.setCurrentCell(0, 0) self._on_table_items_item_clicked() - def _on_table_items_item_clicked(self): + def _on_table_items_item_clicked(self) -> None: item = self.table_items.currentItem() if not item: return diff --git a/html_parsing/foxtrot_com_ua__ru__search/main.py b/html_parsing/foxtrot_com_ua__ru__search/main.py index cd7ba0d27..8368e2bf6 100644 --- a/html_parsing/foxtrot_com_ua__ru__search/main.py +++ b/html_parsing/foxtrot_com_ua__ru__search/main.py @@ -78,7 +78,7 @@ def save_goods( file_name: str | Path, items: list[tuple[str, str, str]], encoding="utf-8", -): +) -> None: df = pd.DataFrame(items, columns=["Name", "Price", "Nal"]) df.to_csv(file_name, encoding=encoding) diff --git a/html_parsing/get_price_game/from_gama-gama.py b/html_parsing/get_price_game/from_gama-gama.py index ba16194a0..46337d083 100644 --- a/html_parsing/get_price_game/from_gama-gama.py +++ b/html_parsing/get_price_game/from_gama-gama.py @@ -16,7 +16,7 @@ # Основа взята из http://stackoverflow.com/a/37755811/5909792 def get_html(url): class ExtractorHtml: - def __init__(self, url): + def __init__(self, url) -> None: _app = QApplication([]) self._page = QWebEnginePage() self._page.loadFinished.connect(self._load_finished_handler) @@ -40,10 +40,10 @@ def __init__(self, url): # Чтобы избежать падений скрипта self._page = None - def _callable(self, data): + def _callable(self, data) -> None: self.html = data - def _load_finished_handler(self, _): + def _load_finished_handler(self, _) -> None: self._counter_finished += 1 if self._counter_finished == 2: diff --git a/html_parsing/get_price_game/from_origin.py b/html_parsing/get_price_game/from_origin.py index 3afb4022c..833aa63e2 100644 --- a/html_parsing/get_price_game/from_origin.py +++ b/html_parsing/get_price_game/from_origin.py @@ -14,7 +14,7 @@ # Основа взята из http://stackoverflow.com/a/37755811/5909792 def get_html(url): class ExtractorHtml: - def __init__(self, url): + def __init__(self, url) -> None: _app = QApplication([]) self._page = QWebEnginePage() @@ -43,10 +43,10 @@ def __init__(self, url): self._page = None - def _callable(self, data): + def _callable(self, data) -> None: self.html = data - def _load_finished_handler(self): + def _load_finished_handler(self) -> None: self._page.toHtml(self._callable) return ExtractorHtml(url).html diff --git a/html_parsing/get_video_list__xcadr.com.py b/html_parsing/get_video_list__xcadr.com.py index a20ac657c..219ab0db6 100644 --- a/html_parsing/get_video_list__xcadr.com.py +++ b/html_parsing/get_video_list__xcadr.com.py @@ -54,7 +54,7 @@ def get_video_list(url) -> list[dict]: items = get_video_list("http://xcadr.com/collection/luchshie-sceny-v-bane/") print("Total:", len(items)) - def print_items(items): + def print_items(items) -> None: for i, item in enumerate(items, 1): print( '{0:2}. "{title}" ({duration} secs, rating: {rating}): {url} [{url_thumb}]'.format( diff --git a/html_parsing/gitmanga_com__get_chapters.py b/html_parsing/gitmanga_com__get_chapters.py index edff54163..002f867dc 100644 --- a/html_parsing/gitmanga_com__get_chapters.py +++ b/html_parsing/gitmanga_com__get_chapters.py @@ -39,7 +39,7 @@ def get_chapters(url: str) -> list[Chapter]: if __name__ == "__main__": - def print_chapter(items: list[Chapter]): + def print_chapter(items: list[Chapter]) -> None: print(f"Chapters ({len(items)}):") print(f" {items[0]}") print(" ...") diff --git a/html_parsing/howlongtobeat_com/common.py b/html_parsing/howlongtobeat_com/common.py index b9c930b71..8c244d9ef 100644 --- a/html_parsing/howlongtobeat_com/common.py +++ b/html_parsing/howlongtobeat_com/common.py @@ -43,7 +43,7 @@ class Game: profile_genres: list[str] = field(default_factory=list) - def __post_init__(self): + def __post_init__(self) -> None: self.duration_main_title = seconds_to_str(self.duration_main_seconds) self.duration_plus_title = seconds_to_str(self.duration_plus_seconds) self.duration_100_title = seconds_to_str(self.duration_100_seconds) diff --git a/html_parsing/howlongtobeat_com/search.py b/html_parsing/howlongtobeat_com/search.py index c9cc9f7f5..8b4abb967 100644 --- a/html_parsing/howlongtobeat_com/search.py +++ b/html_parsing/howlongtobeat_com/search.py @@ -7,6 +7,7 @@ # import re # TODO: Удалить from datetime import datetime + # from urllib.parse import urljoin # TODO: Удалить from typing import Any @@ -67,25 +68,33 @@ def api_search(text: str, page: int = 1) -> dict[str, Any]: # if m_k: # data["searchOptions"]["games"]["gameplay"][k] = m_k.group(1) + # url_api_search = f"{URL_BASE}/api/search" # TODO: Прошлый вариант + # url_api_search = f"{URL_BASE}/api/finder" + # url_api_search = f"{URL_BASE}/api/find" + url_api_search = f"{URL_BASE}/api/bleed" + # NOTE: Получение token. Новая защита rs_token = session.get( - f"{URL_BASE}/api/search/init", + # f"{URL_BASE}/api/search/init", # TODO: Прошлый вариант + # f"{URL_BASE}/api/finder/init", + f"{url_api_search}/init", params={"t": int(datetime.now().timestamp()) * 1000}, headers=headers, ) try: rs_token.raise_for_status() - token: str = rs_token.json()["token"] + token_data: dict[str, Any] = rs_token.json() + token: str = token_data["token"] + hp_key: str = token_data.get("hpKey") + hp_val: str = token_data.get("hpVal") except Exception: token = "" + hp_key = "" + hp_val = "" if not token: raise Exception("Не получен token!") - headers["x-auth-token"] = token - - url_api_search = f"{URL_BASE}/api/search" - - data = { + data: dict[str, Any] = { "searchType": "games", "searchTerms": text.split(), "searchPage": page, @@ -116,6 +125,13 @@ def api_search(text: str, page: int = 1) -> dict[str, Any]: "useCache": True, } + headers["x-auth-token"] = token + if hp_key and hp_val: + headers["x-hp-key"] = hp_key + headers["x-hp-val"] = hp_val + + data[hp_key] = hp_val + rs = session.post( url_api_search, headers=headers, diff --git a/html_parsing/https___lavkagsm_ru__example/gui.py b/html_parsing/https___lavkagsm_ru__example/gui.py index 5d083109d..c338984aa 100644 --- a/html_parsing/https___lavkagsm_ru__example/gui.py +++ b/html_parsing/https___lavkagsm_ru__example/gui.py @@ -11,7 +11,7 @@ class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() headers = ["NAME", "PRICE", "ARTICLE", "URL", "PHOTO_URL"] @@ -26,7 +26,7 @@ def __init__(self): self.setCentralWidget(self.table_widget) - def fill(self): + def fill(self) -> None: url = "https://lavkagsm.ru/catalog/mikroskhemy/?view=blocks&page_count=48&sort=name&by=asc" html_content = get_html_by_url__from_cache(url) root = BeautifulSoup(html_content, "html.parser") @@ -44,7 +44,7 @@ def fill(self): self.table_widget.resizeColumnToContents(0) self.table_widget.resizeColumnToContents(1) - def _on_item_double_click(self, item): + def _on_item_double_click(self, item) -> None: row = item.row() item_url = self.table_widget.item(row, 3) diff --git a/html_parsing/https__www.klinikapawlikowski.pl_cennik/main.py b/html_parsing/https__www.klinikapawlikowski.pl_cennik/main.py index c49413bbe..fe3618832 100644 --- a/html_parsing/https__www.klinikapawlikowski.pl_cennik/main.py +++ b/html_parsing/https__www.klinikapawlikowski.pl_cennik/main.py @@ -60,7 +60,7 @@ def parser(base_url, headers) -> dict: return data -def files_writer(data: dict): +def files_writer(data: dict) -> None: with open("parsed_cennik.csv", "a", encoding="utf-8", newline="") as file: a_pen = csv.writer(file) a_pen.writerow(["Title", "Title_proedure", "Opisanie_procedur", "Ceny"]) diff --git a/html_parsing/kri_dev__speakers.py b/html_parsing/kri_dev__speakers.py new file mode 100644 index 000000000..0e19f8f2e --- /dev/null +++ b/html_parsing/kri_dev__speakers.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +import requests +from bs4 import BeautifulSoup + +rs = requests.get("https://kri.dev/#speakers") +rs.raise_for_status() + +soup = BeautifulSoup(rs.content, features="html.parser") +for i, speaker in enumerate(soup.select(".speakers__card-info"), 1): + name: str = speaker.select_one(".speakers__card-name").get_text(strip=True) + description: str = speaker.select_one(".speakers__card-title").get_text(strip=True) + print(f"{i}. {name!r}: {description!r}") +""" +1. 'Вячеслав Макаров': 'Независимый продюсер, геймдизайнер' +2. 'Максим Николаев': 'Операционный директор ООО "Клокворк драккар"' +3. 'Андрей Воронков': 'Заместитель генерального директора АНО «ИРИ»' +4. 'Гюльнара Агамова': 'Генеральный директор АНО «Агентство креативных индустрий»' +5. 'Александр Компанец': 'Разработчик видеоигр, независимый эксперт' +6. 'Александр Горбаченко': 'Генеральный директор ООО "Фоксхаунд"' +7. 'Дмитрий Карасев': 'Продуктовый менеджер ООО "Фоксхаунд"' +8. 'Александр Михеев': 'Генеральный директор VK Play, генеральный директор АПРИОРИ' +9. 'Олег Доброштан': 'Независимый эксперт игровой индустрии и консультант по менеджменту. Член АПРИОРИ' +10. 'Василий Овчинников': 'Генеральный директор Организации развития видеоигровой индустрии' +11. 'Сергей Русских': 'Директор студии «Сайберия Нова»' +12. 'Михаил Коваленко': 'Старший преподаватель кафедры игровой индустрии РТУ МИРЭА' +13. 'Андрей Пушкарев': 'Соавтор НУБЗ, продюссер ИГРОПРОМ' +14. 'Алена Карасева': 'Руководитель отдела тестирования ООО "ГостТим"' +15. 'Александр Егоров': 'Руководитель медиа и направления инди VK Play' +16. 'Валерия Кирышева': 'Руководитель направления, КД НТИ' +17. 'Владимир Обручев': 'Главный по видеоиграм в издательстве "Бомбора"' +18. 'Александр Толкач': 'Директор "Студии СПН"' +19. 'Алексей Яровит': 'Основатель и глава студии и продюсерского центра Kin-Dza-Dza Games' +20. 'Иван Смирнов': 'Smirnov School' +21. 'Илья Чех': 'Технологический предприниматель и инвесторв, Со-Основатель игровой экосистемы OG' +22. 'Евгений Миркин': 'Редактор игрового направления RuStore' +23. 'Егор Томский': 'Генеральный директор, основатель студии WATT' +24. 'Дмитрий Кунгуров': 'Основатель RULER Productions' +25. 'Максим Милязев': 'Продюсер RULER Productions' +26. 'Василий Гальперов': 'Продюсер RULER Productions' +27. 'Семён Окороков': 'Режиссер трейлеров RULER Productions' +28. 'Мария Кочакова': 'Нарраторика' +29. 'Денис Поздняков': 'Нарраторика' +""" diff --git a/html_parsing/mangalib_me/get_chapters.py b/html_parsing/mangalib_me/get_chapters.py new file mode 100644 index 000000000..a6192527f --- /dev/null +++ b/html_parsing/mangalib_me/get_chapters.py @@ -0,0 +1,263 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +from dataclasses import dataclass +from datetime import datetime +from typing import Any, Self +from urllib.parse import urlparse + +import requests + + +HOST_API: str = "https://api.cdnlibs.org" + +session = requests.Session() +session.headers[ + "User-Agent" +] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:148.0) Gecko/20100101 Firefox/148.0" + + +@dataclass +class Cover: + filename: str + thumbnail: str + default: str + md: str + + @classmethod + def from_dict(cls, data: dict[str, Any]) -> Self: + return cls( + filename=data["filename"], + thumbnail=data["thumbnail"], + default=data["default"], + md=data["md"], + ) + + +@dataclass +class Team: + id: int + slug: str + slug_url: str + model: str + name: str + cover: Cover + + @classmethod + def from_dict(cls, data: dict[str, Any]) -> Self: + return cls( + id=data["id"], + slug=data["slug"], + slug_url=data["slug_url"], + model=data["model"], + name=data["name"], + cover=Cover.from_dict(data["cover"]), + ) + + +@dataclass +class User: + id: int + username: str + + @classmethod + def from_dict(cls, data: dict[str, Any]) -> Self: + return cls( + id=data["id"], + username=data["username"], + ) + + +@dataclass +class RestrictedView: + is_open: bool + expired_at: datetime + price: int | None + + @classmethod + def from_dict(cls, data: dict[str, Any]) -> Self: + return cls( + is_open=data["is_open"], + expired_at=datetime.fromisoformat(data["expired_at"]), + price=data["price"], + ) + + +@dataclass +class Branch: + id: int + branch_id: int + created_at: datetime + teams: list[Team] + expired_type: int + user: User + restricted_view: RestrictedView | None = None + + @classmethod + def from_dict(cls, data: dict[str, Any]) -> Self: + rv_data = data.get("restricted_view") + return cls( + id=data["id"], + branch_id=data["branch_id"], + created_at=datetime.fromisoformat(data["created_at"]), + teams=[Team.from_dict(t) for t in data["teams"]], + expired_type=data["expired_type"], + user=User.from_dict(data["user"]), + restricted_view=RestrictedView.from_dict(rv_data) if rv_data else None, + ) + + +@dataclass +class Chapter: + id: int + index: int + item_number: int + volume: str + number: str + number_secondary: str + name: str + title: str + url: str + branches_count: int + branches: list[Branch] + bundle_id: int | None = None + + @classmethod + def from_dict( + cls, + data: dict[str, Any], + host: str, + lang: str, + manga_slug: str, + ) -> Self: + branches: list[Branch] = [Branch.from_dict(b) for b in data.get("branches", [])] + + name: str = data["name"] + volume: str = data["volume"] + number: str = data["number"] + url: str = f"{host}/{lang}/{manga_slug}/read/v{volume}/c{number}" + + is_locked: bool = branches and branches[0].restricted_view is not None + status: str = "🔒 " if is_locked else "" + title: str = f"{status}Том {volume} Глава {number}" + if name: + title = f"{title} - {name}" + + return cls( + id=data["id"], + index=data["index"], + item_number=data["item_number"], + volume=volume, + number=number, + number_secondary=data["number_secondary"], + name=name, + title=title, + url=url, + branches_count=data["branches_count"], + branches=branches, + bundle_id=data["bundle_id"], + ) + + +def get_chapters(url: str) -> list[Chapter]: + result = urlparse(url) + host: str = f"{result.scheme}://{result.netloc}" + + # Example: "/ru/manga/1234--foo" -> lang="ru", slug="1234--foo" + uri: str = result.path.strip("/") + lang: str = uri.split("/")[0] + slug: str = uri.split("/")[-1] + + url_api: str = f"{HOST_API}/api/manga/{slug}/chapters" + + headers = { + "Referer": host, + "Content-Type": "application/json", + "Origin": host, + } + rs = session.get(url_api, headers=headers) + rs.raise_for_status() + + data: list[dict[str, Any]] = rs.json()["data"] + return [ + Chapter.from_dict(item, host=host, lang=lang, manga_slug=slug) for item in data + ] + + +if __name__ == "__main__": + import time + + url = "https://mangalib.me/ru/manga/12123--mieru-ko-chan" + print(url) + chapters: list[Chapter] = get_chapters(url) + print("Last added 10 chapters:") + for c in sorted(chapters, key=lambda c: c.branches[0].created_at, reverse=True)[:10]: + print(f" {c}") + print("\n" + "-"*10+"\n") + + time.sleep(1) + + def _get_chapters(chapters: list[Chapter]) -> list[str]: + return [f" {c.title}: {c.url}" for c in chapters] + + for url in [ + "https://mangalib.me/ru/manga/12123--mieru-ko-chan", + "https://mangalib.me/ru/manga/206--one-piece?from=catalog", + "https://mangalib.me/ru/manga/162253--geim-sog-babalian-eulo-sal-anamgi?from=catalog§ion=chapters&ui=5961682", + ]: + print(url) + + chapters: list[Chapter] = get_chapters(url) + print(f"Chapters ({len(chapters)}):") + print(*_get_chapters(chapters[:5]), sep="\n") + print(" ...") + print(*_get_chapters(chapters[-5:]), sep="\n") + print() + + time.sleep(1) + """ + https://mangalib.me/ru/manga/12123--mieru-ko-chan + Chapters (80): + Том 1 Глава 1: https://mangalib.me/ru/12123--mieru-ko-chan/read/v1/c1 + Том 1 Глава 2: https://mangalib.me/ru/12123--mieru-ko-chan/read/v1/c2 + Том 1 Глава 3: https://mangalib.me/ru/12123--mieru-ko-chan/read/v1/c3 + Том 1 Глава 4: https://mangalib.me/ru/12123--mieru-ko-chan/read/v1/c4 + Том 1 Глава 5: https://mangalib.me/ru/12123--mieru-ko-chan/read/v1/c5 + ... + Том 13 Глава 65: https://mangalib.me/ru/12123--mieru-ko-chan/read/v13/c65 + Том 13 Глава 66: https://mangalib.me/ru/12123--mieru-ko-chan/read/v13/c66 + Том 13 Глава 67: https://mangalib.me/ru/12123--mieru-ko-chan/read/v13/c67 + Том 13 Глава 68: https://mangalib.me/ru/12123--mieru-ko-chan/read/v13/c68 + Том 14 Глава 69: https://mangalib.me/ru/12123--mieru-ko-chan/read/v14/c69 + + https://mangalib.me/ru/manga/206--one-piece?from=catalog + Chapters (1184): + Том 1 Глава 0 - Рассвет романтики: https://mangalib.me/ru/206--one-piece/read/v1/c0 + Том 1 Глава 0.5 - Strong World: https://mangalib.me/ru/206--one-piece/read/v1/c0.5 + Том 1 Глава 1 - На заре приключений: https://mangalib.me/ru/206--one-piece/read/v1/c1 + Том 1 Глава 2 - Луффи Соломенная шляпа: https://mangalib.me/ru/206--one-piece/read/v1/c2 + Том 1 Глава 3 - Первая встреча: Охотник на пиратов Зоро: https://mangalib.me/ru/206--one-piece/read/v1/c3 + ... + Том 108 Глава 1174 - Сильнейшее чувство в мире: https://mangalib.me/ru/206--one-piece/read/v108/c1174 + Том 108 Глава 1175 - Нидхегг: https://mangalib.me/ru/206--one-piece/read/v108/c1175 + Том 108 Глава 1176 - С гордостью: https://mangalib.me/ru/206--one-piece/read/v108/c1176 + Том 108 Глава 1177 - Гнев: https://mangalib.me/ru/206--one-piece/read/v108/c1177 + Том 108 Глава 1178 - Кошмар закончился: https://mangalib.me/ru/206--one-piece/read/v108/c1178 + + https://mangalib.me/ru/manga/162253--geim-sog-babalian-eulo-sal-anamgi?from=catalog§ion=chapters&ui=5961682 + Chapters (146): + Том 1 Глава 1: https://mangalib.me/ru/162253--geim-sog-babalian-eulo-sal-anamgi/read/v1/c1 + Том 1 Глава 2: https://mangalib.me/ru/162253--geim-sog-babalian-eulo-sal-anamgi/read/v1/c2 + Том 1 Глава 3: https://mangalib.me/ru/162253--geim-sog-babalian-eulo-sal-anamgi/read/v1/c3 + Том 1 Глава 4: https://mangalib.me/ru/162253--geim-sog-babalian-eulo-sal-anamgi/read/v1/c4 + Том 1 Глава 5: https://mangalib.me/ru/162253--geim-sog-babalian-eulo-sal-anamgi/read/v1/c5 + ... + Том 3 Глава 142: https://mangalib.me/ru/162253--geim-sog-babalian-eulo-sal-anamgi/read/v3/c142 + 🔒 Том 3 Глава 143: https://mangalib.me/ru/162253--geim-sog-babalian-eulo-sal-anamgi/read/v3/c143 + 🔒 Том 3 Глава 144: https://mangalib.me/ru/162253--geim-sog-babalian-eulo-sal-anamgi/read/v3/c144 + 🔒 Том 3 Глава 145: https://mangalib.me/ru/162253--geim-sog-babalian-eulo-sal-anamgi/read/v3/c145 + 🔒 Том 3 Глава 146: https://mangalib.me/ru/162253--geim-sog-babalian-eulo-sal-anamgi/read/v3/c146 + """ diff --git a/html_parsing/mywishlist_ru/collect_wishes.py b/html_parsing/mywishlist_ru/collect_wishes.py index 944bb549d..6049e7196 100644 --- a/html_parsing/mywishlist_ru/collect_wishes.py +++ b/html_parsing/mywishlist_ru/collect_wishes.py @@ -72,7 +72,7 @@ def get_inherited_models(cls) -> list[Type["BaseModel"]]: return sorted(cls.__subclasses__(), key=lambda x: x.__name__) @classmethod - def print_count_of_tables(cls): + def print_count_of_tables(cls) -> None: items = [] for sub_cls in cls.get_inherited_models(): name = sub_cls.__name__ @@ -81,7 +81,7 @@ def print_count_of_tables(cls): print(", ".join(items)) - def __str__(self): + def __str__(self) -> str: fields = [] for k, field in self._meta.fields.items(): v = getattr(self, k) @@ -107,7 +107,7 @@ class Wish(BaseModel): db.create_tables(BaseModel.get_inherited_models()) -def run(): +def run() -> None: wish_id = 1 last_id_wish = get_mandatory_last_id_wish() diff --git a/html_parsing/mywishlist_ru/common.py b/html_parsing/mywishlist_ru/common.py index d02ad9fa5..0689cd0d3 100644 --- a/html_parsing/mywishlist_ru/common.py +++ b/html_parsing/mywishlist_ru/common.py @@ -122,7 +122,7 @@ class Api: last_soup: BeautifulSoup = field(init=False, repr=False, default=None) log: logging.Logger = field(repr=False, default=None) - def __post_init__(self): + def __post_init__(self) -> None: if not self.log: self.log = get_logger( name=__file__, @@ -130,12 +130,12 @@ def __post_init__(self): log_file=False, ) - def _do_get(self, url: str, *args, **kwargs): + def _do_get(self, url: str, *args, **kwargs) -> None: self.log.debug(f"GET. url: {url}, args: {args}, kwargs: {kwargs}") self.last_rs, self.last_soup = do_get(url, *args, **kwargs) self.log.debug(f"GET. response url: {self.last_rs.url}") - def _do_post(self, url: str, *args, **kwargs): + def _do_post(self, url: str, *args, **kwargs) -> None: self.log.debug(f"POST. url: {url}, args: {args}, kwargs: {kwargs}") self.last_rs, self.last_soup = do_post(url, *args, **kwargs) self.log.debug(f"POST. response url: {self.last_rs.url}") diff --git a/html_parsing/mywishlist_ru/process_wish_with_error.py b/html_parsing/mywishlist_ru/process_wish_with_error.py index c3b1ec100..2ac1b0c6b 100644 --- a/html_parsing/mywishlist_ru/process_wish_with_error.py +++ b/html_parsing/mywishlist_ru/process_wish_with_error.py @@ -7,7 +7,7 @@ from collect_wishes import Wish, WishInfo, get_wish_data -def run(): +def run() -> None: for wish in Wish.select().where(Wish.error.is_null(False)): try: wish_info = WishInfo.parse_from(wish.id) diff --git a/html_parsing/news_google_com__covid19__map.py b/html_parsing/news_google_com__covid19__map.py index fae723d47..ab4a9874e 100644 --- a/html_parsing/news_google_com__covid19__map.py +++ b/html_parsing/news_google_com__covid19__map.py @@ -10,7 +10,7 @@ import requests -def parse(): +def parse() -> None: url = "https://news.google.com/covid19/map?hl=ru&gl=RU&ceid=RU:ru" headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0" diff --git a/html_parsing/ollama_com/common.py b/html_parsing/ollama_com/common.py new file mode 100644 index 000000000..3ea61dacd --- /dev/null +++ b/html_parsing/ollama_com/common.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +from pathlib import Path +import requests + + +DIR: Path = Path(__file__).resolve().parent + +DIR_DUMPS: Path = DIR / "dumps" +DIR_DUMPS.mkdir(parents=True, exist_ok=True) + +session = requests.Session() diff --git a/html_parsing/ollama_com/dump_model_tags.py b/html_parsing/ollama_com/dump_model_tags.py new file mode 100644 index 000000000..ab64ba8e6 --- /dev/null +++ b/html_parsing/ollama_com/dump_model_tags.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +import json +import re + +from dataclasses import dataclass, asdict +from pathlib import Path +from typing import Self +from urllib.parse import urljoin + +import requests +from bs4 import BeautifulSoup, Tag + +from common import DIR_DUMPS, session + + +FILE_NAME: Path = Path(__file__).resolve() + + +@dataclass +class Model: + title: str + url: str + size: str + context: str + input: str + id_hash: str + last_modified: str + + @classmethod + def parse_from(cls, item: Tag, base_url: str) -> Self: + first_div, second_div = item.find_all("div", recursive=False) + + cell_name, cell_size, cell_context, cell_input = first_div.find_all( + recursive=False + ) + + id_hash, last_modified = re.split(r"·", second_div.get_text(strip=True)) + id_hash = id_hash.strip() + last_modified = last_modified.strip() + + return cls( + title=cell_name.a.get_text(strip=True), + url=urljoin(base_url, cell_name.a["href"]), + size=cell_size.get_text(strip=True), + context=cell_context.get_text(strip=True), + input=cell_input.get_text(strip=True), + id_hash=id_hash, + last_modified=last_modified, + ) + + +session = requests.Session() + + +def process(name: str, file_name: Path): + url: str = f"https://ollama.com/library/{name}/tags" + print(f"Load: {url}") + + rs = session.get(url) + rs.raise_for_status() + + soup = BeautifulSoup(rs.content, "html.parser") + + items: list[Model] = [] + for item in soup.select("div.group > div:has(a)"): + model = Model.parse_from(item, base_url=rs.url) + print(model) + items.append(model) + + print(f"Writing to file: {FILE_NAME}") + with open(file_name, "w", encoding="UTF-8") as f: + for model in sorted(items, key=lambda x: x.title): + f.write(json.dumps(asdict(model), ensure_ascii=False) + "\n") + + +if __name__ == "__main__": + import time + + for name in [ + "qwen3.5", + "qwen3-vl", + "qwen3", + "qwen", + "bge-m3", + "granite3.2-vision", + ]: + path_dump: Path = DIR_DUMPS / f"{FILE_NAME.name}_{name}.jsonl" + process(name=name, file_name=path_dump) + print() + + time.sleep(1) diff --git a/html_parsing/ollama_com/dump_models.py b/html_parsing/ollama_com/dump_models.py new file mode 100644 index 000000000..5266d77e3 --- /dev/null +++ b/html_parsing/ollama_com/dump_models.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +import json +import time + +from dataclasses import dataclass, asdict +from pathlib import Path +from typing import Self +from urllib.parse import urljoin + +from bs4 import BeautifulSoup, Tag + +from common import DIR_DUMPS, session + + +FILE_NAME: Path = Path(__file__).resolve() +PATH_DUMP: Path = DIR_DUMPS / f"{FILE_NAME.name}.jsonl" + + +@dataclass +class Model: + title: str + url: str + description: str + tags: list[str] + pull_count: str + tag_count: int + updated: str + + @classmethod + def parse_from(cls, item: Tag, base_url: str) -> Self: + title_el = item.select_one("[x-test-search-response-title]") + description: str = ( + title_el.find_next("p").get_text(strip=True) if title_el else "" + ) + + return cls( + title=title_el.get_text(strip=True), + url=urljoin(base_url, item["href"]), + description=description, + tags=[ + tag_el.get_text(strip=True) + for tag_el in item.select("div:first-child span") + ], + pull_count=item.select_one("[x-test-pull-count]").get_text(strip=True), + tag_count=int(item.select_one("[x-test-tag-count]").get_text(strip=True)), + updated=item.select_one("[x-test-updated]").get_text(strip=True), + ) + + +url: str = "https://ollama.com/search" + +items: list[Model] = [] +while True: + print(f"Load: {url}") + + rs = session.get(url) + rs.raise_for_status() + + soup = BeautifulSoup(rs.content, "html.parser") + + for item in soup.select("li[x-test-model] > a:has([x-test-search-response-title])"): + model = Model.parse_from(item, base_url=rs.url) + print(model) + items.append(model) + + next_page_el: Tag | None = soup.select_one("[hx-trigger=revealed][hx-get]") + if not next_page_el: + break + + url = urljoin(rs.url, next_page_el["hx-get"]) + time.sleep(1) + +print(f"Writing to file: {FILE_NAME}") +with open(PATH_DUMP, "w", encoding="UTF-8") as f: + for model in sorted(items, key=lambda x: x.title): + f.write(json.dumps(asdict(model), ensure_ascii=False) + "\n") diff --git a/html_parsing/ollama_com/dumps/dump_model_tags.py_bge-m3.jsonl b/html_parsing/ollama_com/dumps/dump_model_tags.py_bge-m3.jsonl new file mode 100644 index 000000000..20f6bf289 --- /dev/null +++ b/html_parsing/ollama_com/dumps/dump_model_tags.py_bge-m3.jsonl @@ -0,0 +1,3 @@ +{"title": "bge-m3:567m", "url": "https://ollama.com/library/bge-m3:567m", "size": "1.2GB", "context": "8K", "input": "Text", "id_hash": "790764642607", "last_modified": "1 year ago"} +{"title": "bge-m3:567m-fp16", "url": "https://ollama.com/library/bge-m3:567m-fp16", "size": "1.2GB", "context": "8K", "input": "Text", "id_hash": "790764642607", "last_modified": "1 year ago"} +{"title": "bge-m3:latest", "url": "https://ollama.com/library/bge-m3:latest", "size": "1.2GB", "context": "8K", "input": "Text", "id_hash": "790764642607", "last_modified": "1 year ago"} diff --git a/html_parsing/ollama_com/dumps/dump_model_tags.py_granite3.2-vision.jsonl b/html_parsing/ollama_com/dumps/dump_model_tags.py_granite3.2-vision.jsonl new file mode 100644 index 000000000..18e86066f --- /dev/null +++ b/html_parsing/ollama_com/dumps/dump_model_tags.py_granite3.2-vision.jsonl @@ -0,0 +1,5 @@ +{"title": "granite3.2-vision:2b", "url": "https://ollama.com/library/granite3.2-vision:2b", "size": "2.4GB", "context": "16K", "input": "Text, Image", "id_hash": "3be41a661804", "last_modified": "1 year ago"} +{"title": "granite3.2-vision:2b-fp16", "url": "https://ollama.com/library/granite3.2-vision:2b-fp16", "size": "6.0GB", "context": "16K", "input": "Text, Image", "id_hash": "17ca6aa97bd9", "last_modified": "1 year ago"} +{"title": "granite3.2-vision:2b-q4_K_M", "url": "https://ollama.com/library/granite3.2-vision:2b-q4_K_M", "size": "2.4GB", "context": "16K", "input": "Text, Image", "id_hash": "3be41a661804", "last_modified": "1 year ago"} +{"title": "granite3.2-vision:2b-q8_0", "url": "https://ollama.com/library/granite3.2-vision:2b-q8_0", "size": "3.6GB", "context": "16K", "input": "Text, Image", "id_hash": "9b6204ce60f6", "last_modified": "1 year ago"} +{"title": "granite3.2-vision:latest", "url": "https://ollama.com/library/granite3.2-vision:latest", "size": "2.4GB", "context": "16K", "input": "Text, Image", "id_hash": "3be41a661804", "last_modified": "1 year ago"} diff --git a/html_parsing/ollama_com/dumps/dump_model_tags.py_qwen.jsonl b/html_parsing/ollama_com/dumps/dump_model_tags.py_qwen.jsonl new file mode 100644 index 000000000..e62cc26b7 --- /dev/null +++ b/html_parsing/ollama_com/dumps/dump_model_tags.py_qwen.jsonl @@ -0,0 +1,379 @@ +{"title": "qwen:0.5b", "url": "https://ollama.com/library/qwen:0.5b", "size": "395MB", "context": "32K", "input": "Text", "id_hash": "b5dc5e784f2a", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-chat", "url": "https://ollama.com/library/qwen:0.5b-chat", "size": "395MB", "context": "32K", "input": "Text", "id_hash": "b5dc5e784f2a", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-chat-v1.5-fp16", "url": "https://ollama.com/library/qwen:0.5b-chat-v1.5-fp16", "size": "1.2GB", "context": "32K", "input": "Text", "id_hash": "967f7a3593ba", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-chat-v1.5-q2_K", "url": "https://ollama.com/library/qwen:0.5b-chat-v1.5-q2_K", "size": "298MB", "context": "32K", "input": "Text", "id_hash": "a16189bc79c0", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-chat-v1.5-q3_K_L", "url": "https://ollama.com/library/qwen:0.5b-chat-v1.5-q3_K_L", "size": "364MB", "context": "32K", "input": "Text", "id_hash": "d184d2901228", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-chat-v1.5-q3_K_M", "url": "https://ollama.com/library/qwen:0.5b-chat-v1.5-q3_K_M", "size": "350MB", "context": "32K", "input": "Text", "id_hash": "b18e5c255a90", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-chat-v1.5-q3_K_S", "url": "https://ollama.com/library/qwen:0.5b-chat-v1.5-q3_K_S", "size": "333MB", "context": "32K", "input": "Text", "id_hash": "0bcee5f34ad7", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-chat-v1.5-q4_0", "url": "https://ollama.com/library/qwen:0.5b-chat-v1.5-q4_0", "size": "395MB", "context": "32K", "input": "Text", "id_hash": "b5dc5e784f2a", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-chat-v1.5-q4_1", "url": "https://ollama.com/library/qwen:0.5b-chat-v1.5-q4_1", "size": "424MB", "context": "32K", "input": "Text", "id_hash": "1bf15c40f38e", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-chat-v1.5-q4_K_M", "url": "https://ollama.com/library/qwen:0.5b-chat-v1.5-q4_K_M", "size": "407MB", "context": "32K", "input": "Text", "id_hash": "e1c9c6192a7e", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-chat-v1.5-q4_K_S", "url": "https://ollama.com/library/qwen:0.5b-chat-v1.5-q4_K_S", "size": "397MB", "context": "32K", "input": "Text", "id_hash": "5d85925638c3", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-chat-v1.5-q5_0", "url": "https://ollama.com/library/qwen:0.5b-chat-v1.5-q5_0", "size": "453MB", "context": "32K", "input": "Text", "id_hash": "60ea3fa139a6", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-chat-v1.5-q5_1", "url": "https://ollama.com/library/qwen:0.5b-chat-v1.5-q5_1", "size": "482MB", "context": "32K", "input": "Text", "id_hash": "a60a006869f5", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-chat-v1.5-q5_K_M", "url": "https://ollama.com/library/qwen:0.5b-chat-v1.5-q5_K_M", "size": "459MB", "context": "32K", "input": "Text", "id_hash": "743996dfe09d", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-chat-v1.5-q5_K_S", "url": "https://ollama.com/library/qwen:0.5b-chat-v1.5-q5_K_S", "size": "453MB", "context": "32K", "input": "Text", "id_hash": "1cf5f7bb58c9", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-chat-v1.5-q6_K", "url": "https://ollama.com/library/qwen:0.5b-chat-v1.5-q6_K", "size": "515MB", "context": "32K", "input": "Text", "id_hash": "0d79ae8737db", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-chat-v1.5-q8_0", "url": "https://ollama.com/library/qwen:0.5b-chat-v1.5-q8_0", "size": "665MB", "context": "32K", "input": "Text", "id_hash": "38781999773b", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-text", "url": "https://ollama.com/library/qwen:0.5b-text", "size": "395MB", "context": "32K", "input": "Text", "id_hash": "f92ac32068ca", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-text-v1.5-fp16", "url": "https://ollama.com/library/qwen:0.5b-text-v1.5-fp16", "size": "1.2GB", "context": "32K", "input": "Text", "id_hash": "9cedb3d846db", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-text-v1.5-q2_K", "url": "https://ollama.com/library/qwen:0.5b-text-v1.5-q2_K", "size": "298MB", "context": "32K", "input": "Text", "id_hash": "6be7d85c1f37", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-text-v1.5-q3_K_L", "url": "https://ollama.com/library/qwen:0.5b-text-v1.5-q3_K_L", "size": "364MB", "context": "32K", "input": "Text", "id_hash": "49837f2c5b03", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-text-v1.5-q3_K_M", "url": "https://ollama.com/library/qwen:0.5b-text-v1.5-q3_K_M", "size": "350MB", "context": "32K", "input": "Text", "id_hash": "7b641307e2fe", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-text-v1.5-q3_K_S", "url": "https://ollama.com/library/qwen:0.5b-text-v1.5-q3_K_S", "size": "333MB", "context": "32K", "input": "Text", "id_hash": "37eeb0d10fd8", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-text-v1.5-q4_0", "url": "https://ollama.com/library/qwen:0.5b-text-v1.5-q4_0", "size": "395MB", "context": "32K", "input": "Text", "id_hash": "f92ac32068ca", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-text-v1.5-q4_1", "url": "https://ollama.com/library/qwen:0.5b-text-v1.5-q4_1", "size": "424MB", "context": "32K", "input": "Text", "id_hash": "8634f265be16", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-text-v1.5-q4_K_M", "url": "https://ollama.com/library/qwen:0.5b-text-v1.5-q4_K_M", "size": "407MB", "context": "32K", "input": "Text", "id_hash": "d8d0c86b10cd", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-text-v1.5-q4_K_S", "url": "https://ollama.com/library/qwen:0.5b-text-v1.5-q4_K_S", "size": "397MB", "context": "32K", "input": "Text", "id_hash": "b0702a4235ed", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-text-v1.5-q5_0", "url": "https://ollama.com/library/qwen:0.5b-text-v1.5-q5_0", "size": "453MB", "context": "32K", "input": "Text", "id_hash": "3822065b797a", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-text-v1.5-q5_1", "url": "https://ollama.com/library/qwen:0.5b-text-v1.5-q5_1", "size": "482MB", "context": "32K", "input": "Text", "id_hash": "9f7ae5e6520b", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-text-v1.5-q5_K_M", "url": "https://ollama.com/library/qwen:0.5b-text-v1.5-q5_K_M", "size": "459MB", "context": "32K", "input": "Text", "id_hash": "dcedf0beaf7e", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-text-v1.5-q5_K_S", "url": "https://ollama.com/library/qwen:0.5b-text-v1.5-q5_K_S", "size": "453MB", "context": "32K", "input": "Text", "id_hash": "4ea8ddc7c860", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-text-v1.5-q6_K", "url": "https://ollama.com/library/qwen:0.5b-text-v1.5-q6_K", "size": "515MB", "context": "32K", "input": "Text", "id_hash": "c8c2e4f579df", "last_modified": "2 years ago"} +{"title": "qwen:0.5b-text-v1.5-q8_0", "url": "https://ollama.com/library/qwen:0.5b-text-v1.5-q8_0", "size": "665MB", "context": "32K", "input": "Text", "id_hash": "c92fe3f525ea", "last_modified": "2 years ago"} +{"title": "qwen:1.8b", "url": "https://ollama.com/library/qwen:1.8b", "size": "1.1GB", "context": "32K", "input": "Text", "id_hash": "b6e8ec2e7126", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat", "url": "https://ollama.com/library/qwen:1.8b-chat", "size": "1.1GB", "context": "32K", "input": "Text", "id_hash": "b6e8ec2e7126", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-fp16", "url": "https://ollama.com/library/qwen:1.8b-chat-fp16", "size": "3.7GB", "context": "8K", "input": "Text", "id_hash": "7b9c77c7b5b6", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-q2_K", "url": "https://ollama.com/library/qwen:1.8b-chat-q2_K", "size": "853MB", "context": "8K", "input": "Text", "id_hash": "467dbacce487", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-q3_K_L", "url": "https://ollama.com/library/qwen:1.8b-chat-q3_K_L", "size": "1.1GB", "context": "8K", "input": "Text", "id_hash": "e3d057690a37", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-q3_K_M", "url": "https://ollama.com/library/qwen:1.8b-chat-q3_K_M", "size": "1.0GB", "context": "8K", "input": "Text", "id_hash": "f7be0cbb0c5c", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-q3_K_S", "url": "https://ollama.com/library/qwen:1.8b-chat-q3_K_S", "size": "970MB", "context": "8K", "input": "Text", "id_hash": "9c807784e6fb", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-q4_0", "url": "https://ollama.com/library/qwen:1.8b-chat-q4_0", "size": "1.1GB", "context": "8K", "input": "Text", "id_hash": "ef087b004e83", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-q4_1", "url": "https://ollama.com/library/qwen:1.8b-chat-q4_1", "size": "1.2GB", "context": "8K", "input": "Text", "id_hash": "e422a7c56e8a", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-q4_K_M", "url": "https://ollama.com/library/qwen:1.8b-chat-q4_K_M", "size": "1.2GB", "context": "8K", "input": "Text", "id_hash": "9c250efbd096", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-q4_K_S", "url": "https://ollama.com/library/qwen:1.8b-chat-q4_K_S", "size": "1.2GB", "context": "8K", "input": "Text", "id_hash": "d04762cf1457", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-q5_0", "url": "https://ollama.com/library/qwen:1.8b-chat-q5_0", "size": "1.3GB", "context": "8K", "input": "Text", "id_hash": "39b08d9c553f", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-q5_1", "url": "https://ollama.com/library/qwen:1.8b-chat-q5_1", "size": "1.4GB", "context": "8K", "input": "Text", "id_hash": "ac833a41e88c", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-q5_K_M", "url": "https://ollama.com/library/qwen:1.8b-chat-q5_K_M", "size": "1.4GB", "context": "8K", "input": "Text", "id_hash": "8341fb324ce5", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-q5_K_S", "url": "https://ollama.com/library/qwen:1.8b-chat-q5_K_S", "size": "1.3GB", "context": "8K", "input": "Text", "id_hash": "857ae180d71f", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-q6_K", "url": "https://ollama.com/library/qwen:1.8b-chat-q6_K", "size": "1.6GB", "context": "8K", "input": "Text", "id_hash": "6068eacf7eab", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-q8_0", "url": "https://ollama.com/library/qwen:1.8b-chat-q8_0", "size": "2.0GB", "context": "8K", "input": "Text", "id_hash": "761057adac8d", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-v1.5-fp16", "url": "https://ollama.com/library/qwen:1.8b-chat-v1.5-fp16", "size": "3.7GB", "context": "32K", "input": "Text", "id_hash": "e3562f7740ef", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-v1.5-q2_K", "url": "https://ollama.com/library/qwen:1.8b-chat-v1.5-q2_K", "size": "863MB", "context": "32K", "input": "Text", "id_hash": "5ec5deec0331", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-v1.5-q3_K_L", "url": "https://ollama.com/library/qwen:1.8b-chat-v1.5-q3_K_L", "size": "1.1GB", "context": "32K", "input": "Text", "id_hash": "7e69fb050fc6", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-v1.5-q3_K_M", "url": "https://ollama.com/library/qwen:1.8b-chat-v1.5-q3_K_M", "size": "1.0GB", "context": "32K", "input": "Text", "id_hash": "1e7a582ce4d6", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-v1.5-q3_K_S", "url": "https://ollama.com/library/qwen:1.8b-chat-v1.5-q3_K_S", "size": "970MB", "context": "32K", "input": "Text", "id_hash": "45631575b031", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-v1.5-q4_0", "url": "https://ollama.com/library/qwen:1.8b-chat-v1.5-q4_0", "size": "1.1GB", "context": "32K", "input": "Text", "id_hash": "b6e8ec2e7126", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-v1.5-q4_1", "url": "https://ollama.com/library/qwen:1.8b-chat-v1.5-q4_1", "size": "1.2GB", "context": "32K", "input": "Text", "id_hash": "5520d901c708", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-v1.5-q4_K_M", "url": "https://ollama.com/library/qwen:1.8b-chat-v1.5-q4_K_M", "size": "1.2GB", "context": "32K", "input": "Text", "id_hash": "27cd5d607aa3", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-v1.5-q4_K_S", "url": "https://ollama.com/library/qwen:1.8b-chat-v1.5-q4_K_S", "size": "1.2GB", "context": "32K", "input": "Text", "id_hash": "318bbcfbbcb1", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-v1.5-q5_0", "url": "https://ollama.com/library/qwen:1.8b-chat-v1.5-q5_0", "size": "1.3GB", "context": "32K", "input": "Text", "id_hash": "942791d6df80", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-v1.5-q5_1", "url": "https://ollama.com/library/qwen:1.8b-chat-v1.5-q5_1", "size": "1.4GB", "context": "32K", "input": "Text", "id_hash": "5cb573856803", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-v1.5-q5_K_M", "url": "https://ollama.com/library/qwen:1.8b-chat-v1.5-q5_K_M", "size": "1.4GB", "context": "32K", "input": "Text", "id_hash": "c3c9b43d0ae7", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-v1.5-q5_K_S", "url": "https://ollama.com/library/qwen:1.8b-chat-v1.5-q5_K_S", "size": "1.3GB", "context": "32K", "input": "Text", "id_hash": "63a97b074a77", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-v1.5-q6_K", "url": "https://ollama.com/library/qwen:1.8b-chat-v1.5-q6_K", "size": "1.6GB", "context": "32K", "input": "Text", "id_hash": "1b54bd2ede5d", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-chat-v1.5-q8_0", "url": "https://ollama.com/library/qwen:1.8b-chat-v1.5-q8_0", "size": "2.0GB", "context": "32K", "input": "Text", "id_hash": "2af802a8e3c4", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text", "url": "https://ollama.com/library/qwen:1.8b-text", "size": "1.1GB", "context": "32K", "input": "Text", "id_hash": "617cceb63756", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-fp16", "url": "https://ollama.com/library/qwen:1.8b-text-fp16", "size": "3.7GB", "context": "8K", "input": "Text", "id_hash": "f4bf3caa7f4c", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-q2_K", "url": "https://ollama.com/library/qwen:1.8b-text-q2_K", "size": "853MB", "context": "8K", "input": "Text", "id_hash": "25e8928e67d8", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-q3_K_L", "url": "https://ollama.com/library/qwen:1.8b-text-q3_K_L", "size": "1.1GB", "context": "8K", "input": "Text", "id_hash": "b6d15127867d", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-q3_K_M", "url": "https://ollama.com/library/qwen:1.8b-text-q3_K_M", "size": "1.0GB", "context": "8K", "input": "Text", "id_hash": "2d9bc3e28126", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-q3_K_S", "url": "https://ollama.com/library/qwen:1.8b-text-q3_K_S", "size": "970MB", "context": "8K", "input": "Text", "id_hash": "6d276d0b0e4d", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-q4_0", "url": "https://ollama.com/library/qwen:1.8b-text-q4_0", "size": "1.1GB", "context": "8K", "input": "Text", "id_hash": "03dc8b7a4353", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-q4_1", "url": "https://ollama.com/library/qwen:1.8b-text-q4_1", "size": "1.2GB", "context": "8K", "input": "Text", "id_hash": "9d03e4ff6283", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-q4_K_M", "url": "https://ollama.com/library/qwen:1.8b-text-q4_K_M", "size": "1.2GB", "context": "8K", "input": "Text", "id_hash": "8f4011c63861", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-q4_K_S", "url": "https://ollama.com/library/qwen:1.8b-text-q4_K_S", "size": "1.2GB", "context": "8K", "input": "Text", "id_hash": "35417f1033ba", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-q5_0", "url": "https://ollama.com/library/qwen:1.8b-text-q5_0", "size": "1.3GB", "context": "8K", "input": "Text", "id_hash": "5dee62f8b270", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-q5_1", "url": "https://ollama.com/library/qwen:1.8b-text-q5_1", "size": "1.4GB", "context": "8K", "input": "Text", "id_hash": "1ace6d0d6868", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-q5_K_M", "url": "https://ollama.com/library/qwen:1.8b-text-q5_K_M", "size": "1.4GB", "context": "8K", "input": "Text", "id_hash": "ba3f032feb07", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-q5_K_S", "url": "https://ollama.com/library/qwen:1.8b-text-q5_K_S", "size": "1.3GB", "context": "8K", "input": "Text", "id_hash": "fc7b98d4110c", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-q6_K", "url": "https://ollama.com/library/qwen:1.8b-text-q6_K", "size": "1.6GB", "context": "8K", "input": "Text", "id_hash": "60c274911b01", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-q8_0", "url": "https://ollama.com/library/qwen:1.8b-text-q8_0", "size": "2.0GB", "context": "8K", "input": "Text", "id_hash": "fb7576710ad5", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-v1.5-fp16", "url": "https://ollama.com/library/qwen:1.8b-text-v1.5-fp16", "size": "3.7GB", "context": "32K", "input": "Text", "id_hash": "5b31a65f7476", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-v1.5-q2_K", "url": "https://ollama.com/library/qwen:1.8b-text-v1.5-q2_K", "size": "863MB", "context": "32K", "input": "Text", "id_hash": "9fbae281c54a", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-v1.5-q3_K_L", "url": "https://ollama.com/library/qwen:1.8b-text-v1.5-q3_K_L", "size": "1.1GB", "context": "32K", "input": "Text", "id_hash": "55006f44ba8f", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-v1.5-q3_K_M", "url": "https://ollama.com/library/qwen:1.8b-text-v1.5-q3_K_M", "size": "1.0GB", "context": "32K", "input": "Text", "id_hash": "1e00ca7ca1af", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-v1.5-q3_K_S", "url": "https://ollama.com/library/qwen:1.8b-text-v1.5-q3_K_S", "size": "970MB", "context": "32K", "input": "Text", "id_hash": "cfddca3d7609", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-v1.5-q4_0", "url": "https://ollama.com/library/qwen:1.8b-text-v1.5-q4_0", "size": "1.1GB", "context": "32K", "input": "Text", "id_hash": "617cceb63756", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-v1.5-q4_1", "url": "https://ollama.com/library/qwen:1.8b-text-v1.5-q4_1", "size": "1.2GB", "context": "32K", "input": "Text", "id_hash": "9c3064af8a6a", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-v1.5-q4_K_M", "url": "https://ollama.com/library/qwen:1.8b-text-v1.5-q4_K_M", "size": "1.2GB", "context": "32K", "input": "Text", "id_hash": "2120d6a01bc3", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-v1.5-q4_K_S", "url": "https://ollama.com/library/qwen:1.8b-text-v1.5-q4_K_S", "size": "1.2GB", "context": "32K", "input": "Text", "id_hash": "9de4291d63b0", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-v1.5-q5_0", "url": "https://ollama.com/library/qwen:1.8b-text-v1.5-q5_0", "size": "1.3GB", "context": "32K", "input": "Text", "id_hash": "fbc1dd7dbb3f", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-v1.5-q5_1", "url": "https://ollama.com/library/qwen:1.8b-text-v1.5-q5_1", "size": "1.4GB", "context": "32K", "input": "Text", "id_hash": "110bb7065fe0", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-v1.5-q5_K_M", "url": "https://ollama.com/library/qwen:1.8b-text-v1.5-q5_K_M", "size": "1.4GB", "context": "32K", "input": "Text", "id_hash": "e2aedf4a65d7", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-v1.5-q5_K_S", "url": "https://ollama.com/library/qwen:1.8b-text-v1.5-q5_K_S", "size": "1.3GB", "context": "32K", "input": "Text", "id_hash": "b12f16343645", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-v1.5-q6_K", "url": "https://ollama.com/library/qwen:1.8b-text-v1.5-q6_K", "size": "1.6GB", "context": "32K", "input": "Text", "id_hash": "e7be77cc89a1", "last_modified": "2 years ago"} +{"title": "qwen:1.8b-text-v1.5-q8_0", "url": "https://ollama.com/library/qwen:1.8b-text-v1.5-q8_0", "size": "2.0GB", "context": "32K", "input": "Text", "id_hash": "48d0284fc9fe", "last_modified": "2 years ago"} +{"title": "qwen:110b", "url": "https://ollama.com/library/qwen:110b", "size": "63GB", "context": "32K", "input": "Text", "id_hash": "7fed4b7787da", "last_modified": "1 year ago"} +{"title": "qwen:110b-chat", "url": "https://ollama.com/library/qwen:110b-chat", "size": "63GB", "context": "32K", "input": "Text", "id_hash": "7fed4b7787da", "last_modified": "1 year ago"} +{"title": "qwen:110b-chat-v1.5-fp16", "url": "https://ollama.com/library/qwen:110b-chat-v1.5-fp16", "size": "222GB", "context": "32K", "input": "Text", "id_hash": "ba695125f554", "last_modified": "1 year ago"} +{"title": "qwen:110b-chat-v1.5-q2_K", "url": "https://ollama.com/library/qwen:110b-chat-v1.5-q2_K", "size": "41GB", "context": "32K", "input": "Text", "id_hash": "1e7acfd0a780", "last_modified": "1 year ago"} +{"title": "qwen:110b-chat-v1.5-q3_K_L", "url": "https://ollama.com/library/qwen:110b-chat-v1.5-q3_K_L", "size": "58GB", "context": "32K", "input": "Text", "id_hash": "38eec5a3a415", "last_modified": "1 year ago"} +{"title": "qwen:110b-chat-v1.5-q3_K_M", "url": "https://ollama.com/library/qwen:110b-chat-v1.5-q3_K_M", "size": "54GB", "context": "32K", "input": "Text", "id_hash": "e1dea48c9e67", "last_modified": "1 year ago"} +{"title": "qwen:110b-chat-v1.5-q3_K_S", "url": "https://ollama.com/library/qwen:110b-chat-v1.5-q3_K_S", "size": "48GB", "context": "32K", "input": "Text", "id_hash": "a2f6e6c88111", "last_modified": "1 year ago"} +{"title": "qwen:110b-chat-v1.5-q4_0", "url": "https://ollama.com/library/qwen:110b-chat-v1.5-q4_0", "size": "63GB", "context": "32K", "input": "Text", "id_hash": "7fed4b7787da", "last_modified": "1 year ago"} +{"title": "qwen:110b-chat-v1.5-q4_1", "url": "https://ollama.com/library/qwen:110b-chat-v1.5-q4_1", "size": "70GB", "context": "32K", "input": "Text", "id_hash": "6122c3a9ed71", "last_modified": "1 year ago"} +{"title": "qwen:110b-chat-v1.5-q4_K_M", "url": "https://ollama.com/library/qwen:110b-chat-v1.5-q4_K_M", "size": "67GB", "context": "32K", "input": "Text", "id_hash": "b9cfda07d6f6", "last_modified": "1 year ago"} +{"title": "qwen:110b-chat-v1.5-q4_K_S", "url": "https://ollama.com/library/qwen:110b-chat-v1.5-q4_K_S", "size": "63GB", "context": "32K", "input": "Text", "id_hash": "89cc28d3008f", "last_modified": "1 year ago"} +{"title": "qwen:110b-chat-v1.5-q5_0", "url": "https://ollama.com/library/qwen:110b-chat-v1.5-q5_0", "size": "77GB", "context": "32K", "input": "Text", "id_hash": "34209c9810a9", "last_modified": "1 year ago"} +{"title": "qwen:110b-chat-v1.5-q5_1", "url": "https://ollama.com/library/qwen:110b-chat-v1.5-q5_1", "size": "84GB", "context": "32K", "input": "Text", "id_hash": "e74e5965cc23", "last_modified": "1 year ago"} +{"title": "qwen:110b-chat-v1.5-q5_K_M", "url": "https://ollama.com/library/qwen:110b-chat-v1.5-q5_K_M", "size": "79GB", "context": "32K", "input": "Text", "id_hash": "98574b6ea163", "last_modified": "1 year ago"} +{"title": "qwen:110b-chat-v1.5-q5_K_S", "url": "https://ollama.com/library/qwen:110b-chat-v1.5-q5_K_S", "size": "77GB", "context": "32K", "input": "Text", "id_hash": "7ba26ace3df0", "last_modified": "1 year ago"} +{"title": "qwen:110b-chat-v1.5-q6_K", "url": "https://ollama.com/library/qwen:110b-chat-v1.5-q6_K", "size": "91GB", "context": "32K", "input": "Text", "id_hash": "1e57b2da94fa", "last_modified": "1 year ago"} +{"title": "qwen:110b-chat-v1.5-q8_0", "url": "https://ollama.com/library/qwen:110b-chat-v1.5-q8_0", "size": "118GB", "context": "32K", "input": "Text", "id_hash": "a7b94c2ca097", "last_modified": "1 year ago"} +{"title": "qwen:110b-text-v1.5-fp16", "url": "https://ollama.com/library/qwen:110b-text-v1.5-fp16", "size": "222GB", "context": "32K", "input": "Text", "id_hash": "db7af5aa87cf", "last_modified": "1 year ago"} +{"title": "qwen:110b-text-v1.5-q2_K", "url": "https://ollama.com/library/qwen:110b-text-v1.5-q2_K", "size": "41GB", "context": "32K", "input": "Text", "id_hash": "0c0dc39aeb62", "last_modified": "1 year ago"} +{"title": "qwen:110b-text-v1.5-q3_K_L", "url": "https://ollama.com/library/qwen:110b-text-v1.5-q3_K_L", "size": "58GB", "context": "32K", "input": "Text", "id_hash": "d600eac4b5ea", "last_modified": "1 year ago"} +{"title": "qwen:110b-text-v1.5-q3_K_M", "url": "https://ollama.com/library/qwen:110b-text-v1.5-q3_K_M", "size": "54GB", "context": "32K", "input": "Text", "id_hash": "354ef171b532", "last_modified": "1 year ago"} +{"title": "qwen:110b-text-v1.5-q3_K_S", "url": "https://ollama.com/library/qwen:110b-text-v1.5-q3_K_S", "size": "48GB", "context": "32K", "input": "Text", "id_hash": "f47bf7b34be3", "last_modified": "1 year ago"} +{"title": "qwen:110b-text-v1.5-q4_0", "url": "https://ollama.com/library/qwen:110b-text-v1.5-q4_0", "size": "63GB", "context": "32K", "input": "Text", "id_hash": "641bc60e9274", "last_modified": "1 year ago"} +{"title": "qwen:110b-text-v1.5-q4_1", "url": "https://ollama.com/library/qwen:110b-text-v1.5-q4_1", "size": "70GB", "context": "32K", "input": "Text", "id_hash": "88fd1ce3561e", "last_modified": "1 year ago"} +{"title": "qwen:110b-text-v1.5-q4_K_M", "url": "https://ollama.com/library/qwen:110b-text-v1.5-q4_K_M", "size": "67GB", "context": "32K", "input": "Text", "id_hash": "b66e1e01042f", "last_modified": "1 year ago"} +{"title": "qwen:110b-text-v1.5-q4_K_S", "url": "https://ollama.com/library/qwen:110b-text-v1.5-q4_K_S", "size": "63GB", "context": "32K", "input": "Text", "id_hash": "29294418d682", "last_modified": "1 year ago"} +{"title": "qwen:110b-text-v1.5-q5_0", "url": "https://ollama.com/library/qwen:110b-text-v1.5-q5_0", "size": "77GB", "context": "32K", "input": "Text", "id_hash": "818ee5b08aa2", "last_modified": "1 year ago"} +{"title": "qwen:110b-text-v1.5-q5_1", "url": "https://ollama.com/library/qwen:110b-text-v1.5-q5_1", "size": "84GB", "context": "32K", "input": "Text", "id_hash": "19c32c34f04a", "last_modified": "1 year ago"} +{"title": "qwen:110b-text-v1.5-q5_K_M", "url": "https://ollama.com/library/qwen:110b-text-v1.5-q5_K_M", "size": "79GB", "context": "32K", "input": "Text", "id_hash": "db245b9a7f62", "last_modified": "1 year ago"} +{"title": "qwen:110b-text-v1.5-q5_K_S", "url": "https://ollama.com/library/qwen:110b-text-v1.5-q5_K_S", "size": "77GB", "context": "32K", "input": "Text", "id_hash": "358e654339d6", "last_modified": "1 year ago"} +{"title": "qwen:110b-text-v1.5-q6_K", "url": "https://ollama.com/library/qwen:110b-text-v1.5-q6_K", "size": "91GB", "context": "32K", "input": "Text", "id_hash": "446cabb2ebd6", "last_modified": "1 year ago"} +{"title": "qwen:110b-text-v1.5-q8_0", "url": "https://ollama.com/library/qwen:110b-text-v1.5-q8_0", "size": "118GB", "context": "32K", "input": "Text", "id_hash": "53bc7e72b768", "last_modified": "1 year ago"} +{"title": "qwen:14b", "url": "https://ollama.com/library/qwen:14b", "size": "8.2GB", "context": "32K", "input": "Text", "id_hash": "80362ced6553", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat", "url": "https://ollama.com/library/qwen:14b-chat", "size": "8.2GB", "context": "32K", "input": "Text", "id_hash": "80362ced6553", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-fp16", "url": "https://ollama.com/library/qwen:14b-chat-fp16", "size": "28GB", "context": "8K", "input": "Text", "id_hash": "13c401be87d4", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-q2_K", "url": "https://ollama.com/library/qwen:14b-chat-q2_K", "size": "6.0GB", "context": "8K", "input": "Text", "id_hash": "fd1a3ccd26ec", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-q3_K_L", "url": "https://ollama.com/library/qwen:14b-chat-q3_K_L", "size": "8.0GB", "context": "8K", "input": "Text", "id_hash": "8b5eb6ea106d", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-q3_K_M", "url": "https://ollama.com/library/qwen:14b-chat-q3_K_M", "size": "7.7GB", "context": "8K", "input": "Text", "id_hash": "f3e7aa8567ed", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-q3_K_S", "url": "https://ollama.com/library/qwen:14b-chat-q3_K_S", "size": "6.9GB", "context": "8K", "input": "Text", "id_hash": "79c06fc56da4", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-q4_0", "url": "https://ollama.com/library/qwen:14b-chat-q4_0", "size": "8.2GB", "context": "8K", "input": "Text", "id_hash": "e5a75212c4d4", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-q4_1", "url": "https://ollama.com/library/qwen:14b-chat-q4_1", "size": "9.0GB", "context": "8K", "input": "Text", "id_hash": "282ce204bb6b", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-q4_K_M", "url": "https://ollama.com/library/qwen:14b-chat-q4_K_M", "size": "9.4GB", "context": "8K", "input": "Text", "id_hash": "f845925f8d90", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-q4_K_S", "url": "https://ollama.com/library/qwen:14b-chat-q4_K_S", "size": "8.6GB", "context": "8K", "input": "Text", "id_hash": "dc341a2db63b", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-q5_0", "url": "https://ollama.com/library/qwen:14b-chat-q5_0", "size": "9.9GB", "context": "8K", "input": "Text", "id_hash": "ee17956b87cc", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-q5_1", "url": "https://ollama.com/library/qwen:14b-chat-q5_1", "size": "11GB", "context": "8K", "input": "Text", "id_hash": "248b0b25c47e", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-q5_K_M", "url": "https://ollama.com/library/qwen:14b-chat-q5_K_M", "size": "11GB", "context": "8K", "input": "Text", "id_hash": "240a4381badd", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-q5_K_S", "url": "https://ollama.com/library/qwen:14b-chat-q5_K_S", "size": "10GB", "context": "8K", "input": "Text", "id_hash": "91f5698531f7", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-q6_K", "url": "https://ollama.com/library/qwen:14b-chat-q6_K", "size": "12GB", "context": "8K", "input": "Text", "id_hash": "5967f08cc189", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-q8_0", "url": "https://ollama.com/library/qwen:14b-chat-q8_0", "size": "15GB", "context": "8K", "input": "Text", "id_hash": "66f562724bd2", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-v1.5-fp16", "url": "https://ollama.com/library/qwen:14b-chat-v1.5-fp16", "size": "28GB", "context": "32K", "input": "Text", "id_hash": "cb20f077361d", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-v1.5-q2_K", "url": "https://ollama.com/library/qwen:14b-chat-v1.5-q2_K", "size": "6.1GB", "context": "32K", "input": "Text", "id_hash": "42f07244d30a", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-v1.5-q3_K_L", "url": "https://ollama.com/library/qwen:14b-chat-v1.5-q3_K_L", "size": "7.8GB", "context": "32K", "input": "Text", "id_hash": "0eca84ada344", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-v1.5-q3_K_M", "url": "https://ollama.com/library/qwen:14b-chat-v1.5-q3_K_M", "size": "7.4GB", "context": "32K", "input": "Text", "id_hash": "319f64f95f85", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-v1.5-q3_K_S", "url": "https://ollama.com/library/qwen:14b-chat-v1.5-q3_K_S", "size": "6.9GB", "context": "32K", "input": "Text", "id_hash": "3ad40beca67d", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-v1.5-q4_0", "url": "https://ollama.com/library/qwen:14b-chat-v1.5-q4_0", "size": "8.2GB", "context": "32K", "input": "Text", "id_hash": "80362ced6553", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-v1.5-q4_1", "url": "https://ollama.com/library/qwen:14b-chat-v1.5-q4_1", "size": "9.0GB", "context": "32K", "input": "Text", "id_hash": "4f50c5079631", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-v1.5-q4_K_M", "url": "https://ollama.com/library/qwen:14b-chat-v1.5-q4_K_M", "size": "9.2GB", "context": "32K", "input": "Text", "id_hash": "128a75c88e2f", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-v1.5-q4_K_S", "url": "https://ollama.com/library/qwen:14b-chat-v1.5-q4_K_S", "size": "8.6GB", "context": "32K", "input": "Text", "id_hash": "e6c0570ce501", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-v1.5-q5_0", "url": "https://ollama.com/library/qwen:14b-chat-v1.5-q5_0", "size": "9.9GB", "context": "32K", "input": "Text", "id_hash": "d06d5137e584", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-v1.5-q5_1", "url": "https://ollama.com/library/qwen:14b-chat-v1.5-q5_1", "size": "11GB", "context": "32K", "input": "Text", "id_hash": "a16ff3fb4f19", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-v1.5-q5_K_M", "url": "https://ollama.com/library/qwen:14b-chat-v1.5-q5_K_M", "size": "11GB", "context": "32K", "input": "Text", "id_hash": "ba0e61d66b27", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-v1.5-q5_K_S", "url": "https://ollama.com/library/qwen:14b-chat-v1.5-q5_K_S", "size": "10GB", "context": "32K", "input": "Text", "id_hash": "85650ef588d4", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-v1.5-q6_K", "url": "https://ollama.com/library/qwen:14b-chat-v1.5-q6_K", "size": "12GB", "context": "32K", "input": "Text", "id_hash": "9378d98cce24", "last_modified": "2 years ago"} +{"title": "qwen:14b-chat-v1.5-q8_0", "url": "https://ollama.com/library/qwen:14b-chat-v1.5-q8_0", "size": "15GB", "context": "32K", "input": "Text", "id_hash": "f1954a35f7ce", "last_modified": "2 years ago"} +{"title": "qwen:14b-text", "url": "https://ollama.com/library/qwen:14b-text", "size": "8.2GB", "context": "32K", "input": "Text", "id_hash": "06e198d562c8", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-fp16", "url": "https://ollama.com/library/qwen:14b-text-fp16", "size": "28GB", "context": "8K", "input": "Text", "id_hash": "c49a8e18017a", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-q2_K", "url": "https://ollama.com/library/qwen:14b-text-q2_K", "size": "6.0GB", "context": "8K", "input": "Text", "id_hash": "490383e818bc", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-q3_K_L", "url": "https://ollama.com/library/qwen:14b-text-q3_K_L", "size": "8.0GB", "context": "8K", "input": "Text", "id_hash": "e706cfc43d67", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-q3_K_M", "url": "https://ollama.com/library/qwen:14b-text-q3_K_M", "size": "7.7GB", "context": "8K", "input": "Text", "id_hash": "35babf7c6752", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-q3_K_S", "url": "https://ollama.com/library/qwen:14b-text-q3_K_S", "size": "6.9GB", "context": "8K", "input": "Text", "id_hash": "7b6da3dbc02c", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-q4_0", "url": "https://ollama.com/library/qwen:14b-text-q4_0", "size": "8.2GB", "context": "8K", "input": "Text", "id_hash": "856ff95ace9a", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-q4_1", "url": "https://ollama.com/library/qwen:14b-text-q4_1", "size": "9.0GB", "context": "8K", "input": "Text", "id_hash": "fb080c3f9385", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-q4_K_M", "url": "https://ollama.com/library/qwen:14b-text-q4_K_M", "size": "9.4GB", "context": "8K", "input": "Text", "id_hash": "9a20ad8849dc", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-q4_K_S", "url": "https://ollama.com/library/qwen:14b-text-q4_K_S", "size": "8.6GB", "context": "8K", "input": "Text", "id_hash": "074ac9031894", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-q5_0", "url": "https://ollama.com/library/qwen:14b-text-q5_0", "size": "9.9GB", "context": "8K", "input": "Text", "id_hash": "7f52ab937912", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-q5_1", "url": "https://ollama.com/library/qwen:14b-text-q5_1", "size": "11GB", "context": "8K", "input": "Text", "id_hash": "9a711abdb0ca", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-q5_K_M", "url": "https://ollama.com/library/qwen:14b-text-q5_K_M", "size": "11GB", "context": "8K", "input": "Text", "id_hash": "2acf4c66179b", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-q5_K_S", "url": "https://ollama.com/library/qwen:14b-text-q5_K_S", "size": "10GB", "context": "8K", "input": "Text", "id_hash": "8c818d039803", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-q6_K", "url": "https://ollama.com/library/qwen:14b-text-q6_K", "size": "12GB", "context": "8K", "input": "Text", "id_hash": "e653065c8329", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-q8_0", "url": "https://ollama.com/library/qwen:14b-text-q8_0", "size": "15GB", "context": "8K", "input": "Text", "id_hash": "3c3330be50fe", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-v1.5-fp16", "url": "https://ollama.com/library/qwen:14b-text-v1.5-fp16", "size": "28GB", "context": "32K", "input": "Text", "id_hash": "6a5ff630639c", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-v1.5-q2_K", "url": "https://ollama.com/library/qwen:14b-text-v1.5-q2_K", "size": "6.1GB", "context": "32K", "input": "Text", "id_hash": "b29e82a9291d", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-v1.5-q3_K_L", "url": "https://ollama.com/library/qwen:14b-text-v1.5-q3_K_L", "size": "7.8GB", "context": "32K", "input": "Text", "id_hash": "e5feaa6b570f", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-v1.5-q3_K_M", "url": "https://ollama.com/library/qwen:14b-text-v1.5-q3_K_M", "size": "7.4GB", "context": "32K", "input": "Text", "id_hash": "8ba10671f72c", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-v1.5-q3_K_S", "url": "https://ollama.com/library/qwen:14b-text-v1.5-q3_K_S", "size": "6.9GB", "context": "32K", "input": "Text", "id_hash": "79262f8761eb", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-v1.5-q4_0", "url": "https://ollama.com/library/qwen:14b-text-v1.5-q4_0", "size": "8.2GB", "context": "32K", "input": "Text", "id_hash": "06e198d562c8", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-v1.5-q4_1", "url": "https://ollama.com/library/qwen:14b-text-v1.5-q4_1", "size": "9.0GB", "context": "32K", "input": "Text", "id_hash": "3514cc84da3f", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-v1.5-q4_K_M", "url": "https://ollama.com/library/qwen:14b-text-v1.5-q4_K_M", "size": "9.2GB", "context": "32K", "input": "Text", "id_hash": "4a22e598c7c9", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-v1.5-q4_K_S", "url": "https://ollama.com/library/qwen:14b-text-v1.5-q4_K_S", "size": "8.6GB", "context": "32K", "input": "Text", "id_hash": "ab6680a741b8", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-v1.5-q5_0", "url": "https://ollama.com/library/qwen:14b-text-v1.5-q5_0", "size": "9.9GB", "context": "32K", "input": "Text", "id_hash": "c9413c9c81d5", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-v1.5-q5_1", "url": "https://ollama.com/library/qwen:14b-text-v1.5-q5_1", "size": "11GB", "context": "32K", "input": "Text", "id_hash": "5f196042dc74", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-v1.5-q5_K_M", "url": "https://ollama.com/library/qwen:14b-text-v1.5-q5_K_M", "size": "11GB", "context": "32K", "input": "Text", "id_hash": "1564ba9fc84c", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-v1.5-q5_K_S", "url": "https://ollama.com/library/qwen:14b-text-v1.5-q5_K_S", "size": "10GB", "context": "32K", "input": "Text", "id_hash": "a31ed924fdab", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-v1.5-q6_K", "url": "https://ollama.com/library/qwen:14b-text-v1.5-q6_K", "size": "12GB", "context": "32K", "input": "Text", "id_hash": "d65ba73d052f", "last_modified": "2 years ago"} +{"title": "qwen:14b-text-v1.5-q8_0", "url": "https://ollama.com/library/qwen:14b-text-v1.5-q8_0", "size": "15GB", "context": "32K", "input": "Text", "id_hash": "5cc57127891d", "last_modified": "2 years ago"} +{"title": "qwen:32b", "url": "https://ollama.com/library/qwen:32b", "size": "18GB", "context": "32K", "input": "Text", "id_hash": "26e7e8447f5d", "last_modified": "1 year ago"} +{"title": "qwen:32b-chat", "url": "https://ollama.com/library/qwen:32b-chat", "size": "18GB", "context": "32K", "input": "Text", "id_hash": "26e7e8447f5d", "last_modified": "1 year ago"} +{"title": "qwen:32b-chat-v1.5-fp16", "url": "https://ollama.com/library/qwen:32b-chat-v1.5-fp16", "size": "65GB", "context": "32K", "input": "Text", "id_hash": "bb930ce340f6", "last_modified": "1 year ago"} +{"title": "qwen:32b-chat-v1.5-q2_K", "url": "https://ollama.com/library/qwen:32b-chat-v1.5-q2_K", "size": "12GB", "context": "32K", "input": "Text", "id_hash": "cae8aaeddda8", "last_modified": "1 year ago"} +{"title": "qwen:32b-chat-v1.5-q3_K_L", "url": "https://ollama.com/library/qwen:32b-chat-v1.5-q3_K_L", "size": "17GB", "context": "32K", "input": "Text", "id_hash": "d3bd7dde094e", "last_modified": "1 year ago"} +{"title": "qwen:32b-chat-v1.5-q3_K_M", "url": "https://ollama.com/library/qwen:32b-chat-v1.5-q3_K_M", "size": "16GB", "context": "32K", "input": "Text", "id_hash": "ecaa1f67c173", "last_modified": "1 year ago"} +{"title": "qwen:32b-chat-v1.5-q3_K_S", "url": "https://ollama.com/library/qwen:32b-chat-v1.5-q3_K_S", "size": "14GB", "context": "32K", "input": "Text", "id_hash": "1d172657e5a4", "last_modified": "1 year ago"} +{"title": "qwen:32b-chat-v1.5-q4_0", "url": "https://ollama.com/library/qwen:32b-chat-v1.5-q4_0", "size": "18GB", "context": "32K", "input": "Text", "id_hash": "26e7e8447f5d", "last_modified": "1 year ago"} +{"title": "qwen:32b-chat-v1.5-q4_1", "url": "https://ollama.com/library/qwen:32b-chat-v1.5-q4_1", "size": "20GB", "context": "32K", "input": "Text", "id_hash": "7fe1bf3d215e", "last_modified": "1 year ago"} +{"title": "qwen:32b-chat-v1.5-q4_K_M", "url": "https://ollama.com/library/qwen:32b-chat-v1.5-q4_K_M", "size": "20GB", "context": "32K", "input": "Text", "id_hash": "7975942ff0b1", "last_modified": "1 year ago"} +{"title": "qwen:32b-chat-v1.5-q4_K_S", "url": "https://ollama.com/library/qwen:32b-chat-v1.5-q4_K_S", "size": "19GB", "context": "32K", "input": "Text", "id_hash": "4016dd0cf4e1", "last_modified": "1 year ago"} +{"title": "qwen:32b-chat-v1.5-q5_0", "url": "https://ollama.com/library/qwen:32b-chat-v1.5-q5_0", "size": "22GB", "context": "32K", "input": "Text", "id_hash": "828e952fda6b", "last_modified": "1 year ago"} +{"title": "qwen:32b-chat-v1.5-q5_1", "url": "https://ollama.com/library/qwen:32b-chat-v1.5-q5_1", "size": "24GB", "context": "32K", "input": "Text", "id_hash": "f3d3a42b3783", "last_modified": "1 year ago"} +{"title": "qwen:32b-chat-v1.5-q5_K_M", "url": "https://ollama.com/library/qwen:32b-chat-v1.5-q5_K_M", "size": "23GB", "context": "32K", "input": "Text", "id_hash": "380f376a451a", "last_modified": "1 year ago"} +{"title": "qwen:32b-chat-v1.5-q5_K_S", "url": "https://ollama.com/library/qwen:32b-chat-v1.5-q5_K_S", "size": "22GB", "context": "32K", "input": "Text", "id_hash": "e67b35358286", "last_modified": "1 year ago"} +{"title": "qwen:32b-chat-v1.5-q6_K", "url": "https://ollama.com/library/qwen:32b-chat-v1.5-q6_K", "size": "27GB", "context": "32K", "input": "Text", "id_hash": "af95b2a2409c", "last_modified": "1 year ago"} +{"title": "qwen:32b-chat-v1.5-q8_0", "url": "https://ollama.com/library/qwen:32b-chat-v1.5-q8_0", "size": "35GB", "context": "32K", "input": "Text", "id_hash": "33c6cb647280", "last_modified": "1 year ago"} +{"title": "qwen:32b-text", "url": "https://ollama.com/library/qwen:32b-text", "size": "18GB", "context": "32K", "input": "Text", "id_hash": "e0618f6f0310", "last_modified": "1 year ago"} +{"title": "qwen:32b-text-v1.5-q2_K", "url": "https://ollama.com/library/qwen:32b-text-v1.5-q2_K", "size": "12GB", "context": "32K", "input": "Text", "id_hash": "95302f736724", "last_modified": "1 year ago"} +{"title": "qwen:32b-text-v1.5-q3_K_L", "url": "https://ollama.com/library/qwen:32b-text-v1.5-q3_K_L", "size": "17GB", "context": "32K", "input": "Text", "id_hash": "1a047023c341", "last_modified": "1 year ago"} +{"title": "qwen:32b-text-v1.5-q3_K_M", "url": "https://ollama.com/library/qwen:32b-text-v1.5-q3_K_M", "size": "16GB", "context": "32K", "input": "Text", "id_hash": "24ea7d162ce2", "last_modified": "1 year ago"} +{"title": "qwen:32b-text-v1.5-q3_K_S", "url": "https://ollama.com/library/qwen:32b-text-v1.5-q3_K_S", "size": "14GB", "context": "32K", "input": "Text", "id_hash": "1d103fa3fd6e", "last_modified": "1 year ago"} +{"title": "qwen:32b-text-v1.5-q4_0", "url": "https://ollama.com/library/qwen:32b-text-v1.5-q4_0", "size": "18GB", "context": "32K", "input": "Text", "id_hash": "e0618f6f0310", "last_modified": "1 year ago"} +{"title": "qwen:32b-text-v1.5-q4_1", "url": "https://ollama.com/library/qwen:32b-text-v1.5-q4_1", "size": "20GB", "context": "32K", "input": "Text", "id_hash": "cefaaea22fea", "last_modified": "1 year ago"} +{"title": "qwen:32b-text-v1.5-q4_K_S", "url": "https://ollama.com/library/qwen:32b-text-v1.5-q4_K_S", "size": "19GB", "context": "32K", "input": "Text", "id_hash": "b68f170dbfd9", "last_modified": "1 year ago"} +{"title": "qwen:32b-text-v1.5-q5_0", "url": "https://ollama.com/library/qwen:32b-text-v1.5-q5_0", "size": "22GB", "context": "32K", "input": "Text", "id_hash": "8ab0ebc4b274", "last_modified": "1 year ago"} +{"title": "qwen:32b-text-v1.5-q5_1", "url": "https://ollama.com/library/qwen:32b-text-v1.5-q5_1", "size": "24GB", "context": "32K", "input": "Text", "id_hash": "577251d3ca12", "last_modified": "1 year ago"} +{"title": "qwen:32b-text-v1.5-q8_0", "url": "https://ollama.com/library/qwen:32b-text-v1.5-q8_0", "size": "35GB", "context": "32K", "input": "Text", "id_hash": "60a90eb7a7da", "last_modified": "1 year ago"} +{"title": "qwen:4b", "url": "https://ollama.com/library/qwen:4b", "size": "2.3GB", "context": "32K", "input": "Text", "id_hash": "d53d04290064", "last_modified": "2 years ago"} +{"title": "qwen:4b-chat", "url": "https://ollama.com/library/qwen:4b-chat", "size": "2.3GB", "context": "32K", "input": "Text", "id_hash": "d53d04290064", "last_modified": "2 years ago"} +{"title": "qwen:4b-chat-v1.5-fp16", "url": "https://ollama.com/library/qwen:4b-chat-v1.5-fp16", "size": "7.9GB", "context": "32K", "input": "Text", "id_hash": "86621ca225c4", "last_modified": "2 years ago"} +{"title": "qwen:4b-chat-v1.5-q2_K", "url": "https://ollama.com/library/qwen:4b-chat-v1.5-q2_K", "size": "1.6GB", "context": "32K", "input": "Text", "id_hash": "e6c11802c6ad", "last_modified": "2 years ago"} +{"title": "qwen:4b-chat-v1.5-q3_K_L", "url": "https://ollama.com/library/qwen:4b-chat-v1.5-q3_K_L", "size": "2.2GB", "context": "32K", "input": "Text", "id_hash": "373625817e6f", "last_modified": "2 years ago"} +{"title": "qwen:4b-chat-v1.5-q3_K_M", "url": "https://ollama.com/library/qwen:4b-chat-v1.5-q3_K_M", "size": "2.0GB", "context": "32K", "input": "Text", "id_hash": "da9fe589f9b3", "last_modified": "2 years ago"} +{"title": "qwen:4b-chat-v1.5-q3_K_S", "url": "https://ollama.com/library/qwen:4b-chat-v1.5-q3_K_S", "size": "1.9GB", "context": "32K", "input": "Text", "id_hash": "d75968a2b37c", "last_modified": "2 years ago"} +{"title": "qwen:4b-chat-v1.5-q4_0", "url": "https://ollama.com/library/qwen:4b-chat-v1.5-q4_0", "size": "2.3GB", "context": "32K", "input": "Text", "id_hash": "d53d04290064", "last_modified": "2 years ago"} +{"title": "qwen:4b-chat-v1.5-q4_1", "url": "https://ollama.com/library/qwen:4b-chat-v1.5-q4_1", "size": "2.6GB", "context": "32K", "input": "Text", "id_hash": "8d4b987199fe", "last_modified": "2 years ago"} +{"title": "qwen:4b-chat-v1.5-q4_K_M", "url": "https://ollama.com/library/qwen:4b-chat-v1.5-q4_K_M", "size": "2.5GB", "context": "32K", "input": "Text", "id_hash": "84dd8780ab54", "last_modified": "2 years ago"} +{"title": "qwen:4b-chat-v1.5-q4_K_S", "url": "https://ollama.com/library/qwen:4b-chat-v1.5-q4_K_S", "size": "2.3GB", "context": "32K", "input": "Text", "id_hash": "1f33fcfdb4b1", "last_modified": "2 years ago"} +{"title": "qwen:4b-chat-v1.5-q5_0", "url": "https://ollama.com/library/qwen:4b-chat-v1.5-q5_0", "size": "2.8GB", "context": "32K", "input": "Text", "id_hash": "1a7d31503b2a", "last_modified": "2 years ago"} +{"title": "qwen:4b-chat-v1.5-q5_1", "url": "https://ollama.com/library/qwen:4b-chat-v1.5-q5_1", "size": "3.0GB", "context": "32K", "input": "Text", "id_hash": "061afe4b95b5", "last_modified": "2 years ago"} +{"title": "qwen:4b-chat-v1.5-q5_K_M", "url": "https://ollama.com/library/qwen:4b-chat-v1.5-q5_K_M", "size": "2.8GB", "context": "32K", "input": "Text", "id_hash": "0f701078af82", "last_modified": "2 years ago"} +{"title": "qwen:4b-chat-v1.5-q5_K_S", "url": "https://ollama.com/library/qwen:4b-chat-v1.5-q5_K_S", "size": "2.8GB", "context": "32K", "input": "Text", "id_hash": "4a434490ef35", "last_modified": "2 years ago"} +{"title": "qwen:4b-chat-v1.5-q6_K", "url": "https://ollama.com/library/qwen:4b-chat-v1.5-q6_K", "size": "3.2GB", "context": "32K", "input": "Text", "id_hash": "13f15e36187d", "last_modified": "2 years ago"} +{"title": "qwen:4b-chat-v1.5-q8_0", "url": "https://ollama.com/library/qwen:4b-chat-v1.5-q8_0", "size": "4.2GB", "context": "32K", "input": "Text", "id_hash": "7dfc4f0660c0", "last_modified": "2 years ago"} +{"title": "qwen:4b-text", "url": "https://ollama.com/library/qwen:4b-text", "size": "2.3GB", "context": "32K", "input": "Text", "id_hash": "a1332f1a62c4", "last_modified": "2 years ago"} +{"title": "qwen:4b-text-v1.5-fp16", "url": "https://ollama.com/library/qwen:4b-text-v1.5-fp16", "size": "7.9GB", "context": "32K", "input": "Text", "id_hash": "bd8bb0558fba", "last_modified": "2 years ago"} +{"title": "qwen:4b-text-v1.5-q2_K", "url": "https://ollama.com/library/qwen:4b-text-v1.5-q2_K", "size": "1.6GB", "context": "32K", "input": "Text", "id_hash": "9f5aaac70cb0", "last_modified": "2 years ago"} +{"title": "qwen:4b-text-v1.5-q3_K_L", "url": "https://ollama.com/library/qwen:4b-text-v1.5-q3_K_L", "size": "2.2GB", "context": "32K", "input": "Text", "id_hash": "34cd35706e60", "last_modified": "2 years ago"} +{"title": "qwen:4b-text-v1.5-q3_K_M", "url": "https://ollama.com/library/qwen:4b-text-v1.5-q3_K_M", "size": "2.0GB", "context": "32K", "input": "Text", "id_hash": "b446af0b99f1", "last_modified": "2 years ago"} +{"title": "qwen:4b-text-v1.5-q3_K_S", "url": "https://ollama.com/library/qwen:4b-text-v1.5-q3_K_S", "size": "1.9GB", "context": "32K", "input": "Text", "id_hash": "8a41ec56a16b", "last_modified": "2 years ago"} +{"title": "qwen:4b-text-v1.5-q4_0", "url": "https://ollama.com/library/qwen:4b-text-v1.5-q4_0", "size": "2.3GB", "context": "32K", "input": "Text", "id_hash": "a1332f1a62c4", "last_modified": "2 years ago"} +{"title": "qwen:4b-text-v1.5-q4_1", "url": "https://ollama.com/library/qwen:4b-text-v1.5-q4_1", "size": "2.6GB", "context": "32K", "input": "Text", "id_hash": "0139d9637b43", "last_modified": "2 years ago"} +{"title": "qwen:4b-text-v1.5-q4_K_M", "url": "https://ollama.com/library/qwen:4b-text-v1.5-q4_K_M", "size": "2.5GB", "context": "32K", "input": "Text", "id_hash": "ba6453687014", "last_modified": "2 years ago"} +{"title": "qwen:4b-text-v1.5-q4_K_S", "url": "https://ollama.com/library/qwen:4b-text-v1.5-q4_K_S", "size": "2.3GB", "context": "32K", "input": "Text", "id_hash": "a569a7c9c36b", "last_modified": "2 years ago"} +{"title": "qwen:4b-text-v1.5-q5_0", "url": "https://ollama.com/library/qwen:4b-text-v1.5-q5_0", "size": "2.8GB", "context": "32K", "input": "Text", "id_hash": "9c5c32de923f", "last_modified": "2 years ago"} +{"title": "qwen:4b-text-v1.5-q5_1", "url": "https://ollama.com/library/qwen:4b-text-v1.5-q5_1", "size": "3.0GB", "context": "32K", "input": "Text", "id_hash": "33f576bd435a", "last_modified": "2 years ago"} +{"title": "qwen:4b-text-v1.5-q5_K_M", "url": "https://ollama.com/library/qwen:4b-text-v1.5-q5_K_M", "size": "2.8GB", "context": "32K", "input": "Text", "id_hash": "55b9362ae113", "last_modified": "2 years ago"} +{"title": "qwen:4b-text-v1.5-q5_K_S", "url": "https://ollama.com/library/qwen:4b-text-v1.5-q5_K_S", "size": "2.8GB", "context": "32K", "input": "Text", "id_hash": "dc8f41c10a81", "last_modified": "2 years ago"} +{"title": "qwen:4b-text-v1.5-q6_K", "url": "https://ollama.com/library/qwen:4b-text-v1.5-q6_K", "size": "3.2GB", "context": "32K", "input": "Text", "id_hash": "e40c4d6f1e33", "last_modified": "2 years ago"} +{"title": "qwen:4b-text-v1.5-q8_0", "url": "https://ollama.com/library/qwen:4b-text-v1.5-q8_0", "size": "4.2GB", "context": "32K", "input": "Text", "id_hash": "e3bafc3eec84", "last_modified": "2 years ago"} +{"title": "qwen:72b", "url": "https://ollama.com/library/qwen:72b", "size": "41GB", "context": "32K", "input": "Text", "id_hash": "e1c64582de5c", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat", "url": "https://ollama.com/library/qwen:72b-chat", "size": "41GB", "context": "32K", "input": "Text", "id_hash": "e1c64582de5c", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-fp16", "url": "https://ollama.com/library/qwen:72b-chat-fp16", "size": "145GB", "context": "32K", "input": "Text", "id_hash": "123c97eccf0d", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-q2_K", "url": "https://ollama.com/library/qwen:72b-chat-q2_K", "size": "27GB", "context": "32K", "input": "Text", "id_hash": "244e559ab857", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-q3_K_L", "url": "https://ollama.com/library/qwen:72b-chat-q3_K_L", "size": "39GB", "context": "32K", "input": "Text", "id_hash": "227bc5757311", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-q3_K_M", "url": "https://ollama.com/library/qwen:72b-chat-q3_K_M", "size": "37GB", "context": "32K", "input": "Text", "id_hash": "2142023c2267", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-q3_K_S", "url": "https://ollama.com/library/qwen:72b-chat-q3_K_S", "size": "32GB", "context": "32K", "input": "Text", "id_hash": "e69b5490aa6d", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-q4_0", "url": "https://ollama.com/library/qwen:72b-chat-q4_0", "size": "41GB", "context": "32K", "input": "Text", "id_hash": "bf2a98cf5f68", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-q4_1", "url": "https://ollama.com/library/qwen:72b-chat-q4_1", "size": "45GB", "context": "32K", "input": "Text", "id_hash": "4d7d270862ce", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-q4_K_M", "url": "https://ollama.com/library/qwen:72b-chat-q4_K_M", "size": "45GB", "context": "32K", "input": "Text", "id_hash": "d1f376d8aaa7", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-q4_K_S", "url": "https://ollama.com/library/qwen:72b-chat-q4_K_S", "size": "41GB", "context": "32K", "input": "Text", "id_hash": "5c65776c1c19", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-q5_0", "url": "https://ollama.com/library/qwen:72b-chat-q5_0", "size": "50GB", "context": "32K", "input": "Text", "id_hash": "7363152de4ba", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-q5_1", "url": "https://ollama.com/library/qwen:72b-chat-q5_1", "size": "54GB", "context": "32K", "input": "Text", "id_hash": "d3f70b712d5c", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-q5_K_M", "url": "https://ollama.com/library/qwen:72b-chat-q5_K_M", "size": "53GB", "context": "32K", "input": "Text", "id_hash": "29453752b3f1", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-q5_K_S", "url": "https://ollama.com/library/qwen:72b-chat-q5_K_S", "size": "50GB", "context": "32K", "input": "Text", "id_hash": "f9a9015181f4", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-q6_K", "url": "https://ollama.com/library/qwen:72b-chat-q6_K", "size": "59GB", "context": "32K", "input": "Text", "id_hash": "5d2b88c19b53", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-q8_0", "url": "https://ollama.com/library/qwen:72b-chat-q8_0", "size": "77GB", "context": "32K", "input": "Text", "id_hash": "030f5b2af0ff", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-v1.5-fp16", "url": "https://ollama.com/library/qwen:72b-chat-v1.5-fp16", "size": "145GB", "context": "32K", "input": "Text", "id_hash": "28d7b95e342e", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-v1.5-q2_K", "url": "https://ollama.com/library/qwen:72b-chat-v1.5-q2_K", "size": "28GB", "context": "32K", "input": "Text", "id_hash": "26d588038b9d", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-v1.5-q3_K_L", "url": "https://ollama.com/library/qwen:72b-chat-v1.5-q3_K_L", "size": "38GB", "context": "32K", "input": "Text", "id_hash": "1a4a7d398f67", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-v1.5-q3_K_M", "url": "https://ollama.com/library/qwen:72b-chat-v1.5-q3_K_M", "size": "36GB", "context": "32K", "input": "Text", "id_hash": "8c8712c6e79c", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-v1.5-q3_K_S", "url": "https://ollama.com/library/qwen:72b-chat-v1.5-q3_K_S", "size": "33GB", "context": "32K", "input": "Text", "id_hash": "a3f91495a290", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-v1.5-q4_0", "url": "https://ollama.com/library/qwen:72b-chat-v1.5-q4_0", "size": "41GB", "context": "32K", "input": "Text", "id_hash": "e1c64582de5c", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-v1.5-q4_1", "url": "https://ollama.com/library/qwen:72b-chat-v1.5-q4_1", "size": "45GB", "context": "32K", "input": "Text", "id_hash": "a5a048009124", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-v1.5-q4_K_M", "url": "https://ollama.com/library/qwen:72b-chat-v1.5-q4_K_M", "size": "44GB", "context": "32K", "input": "Text", "id_hash": "92daf708b997", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-v1.5-q4_K_S", "url": "https://ollama.com/library/qwen:72b-chat-v1.5-q4_K_S", "size": "42GB", "context": "32K", "input": "Text", "id_hash": "7e941773ce08", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-v1.5-q5_0", "url": "https://ollama.com/library/qwen:72b-chat-v1.5-q5_0", "size": "50GB", "context": "32K", "input": "Text", "id_hash": "7ff940bf7ddc", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-v1.5-q5_1", "url": "https://ollama.com/library/qwen:72b-chat-v1.5-q5_1", "size": "54GB", "context": "32K", "input": "Text", "id_hash": "8432bf6237b9", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-v1.5-q5_K_M", "url": "https://ollama.com/library/qwen:72b-chat-v1.5-q5_K_M", "size": "51GB", "context": "32K", "input": "Text", "id_hash": "13a773260811", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-v1.5-q5_K_S", "url": "https://ollama.com/library/qwen:72b-chat-v1.5-q5_K_S", "size": "50GB", "context": "32K", "input": "Text", "id_hash": "f92117215877", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-v1.5-q6_K", "url": "https://ollama.com/library/qwen:72b-chat-v1.5-q6_K", "size": "59GB", "context": "32K", "input": "Text", "id_hash": "5e3a83c19698", "last_modified": "2 years ago"} +{"title": "qwen:72b-chat-v1.5-q8_0", "url": "https://ollama.com/library/qwen:72b-chat-v1.5-q8_0", "size": "77GB", "context": "32K", "input": "Text", "id_hash": "d9fd9f90f55b", "last_modified": "2 years ago"} +{"title": "qwen:72b-text", "url": "https://ollama.com/library/qwen:72b-text", "size": "63GB", "context": "32K", "input": "Text", "id_hash": "641bc60e9274", "last_modified": "1 year ago"} +{"title": "qwen:72b-text-fp16", "url": "https://ollama.com/library/qwen:72b-text-fp16", "size": "145GB", "context": "32K", "input": "Text", "id_hash": "34db8c6fcc66", "last_modified": "2 years ago"} +{"title": "qwen:72b-text-q2_K", "url": "https://ollama.com/library/qwen:72b-text-q2_K", "size": "27GB", "context": "32K", "input": "Text", "id_hash": "23b4e03b0625", "last_modified": "2 years ago"} +{"title": "qwen:72b-text-q3_K_L", "url": "https://ollama.com/library/qwen:72b-text-q3_K_L", "size": "39GB", "context": "32K", "input": "Text", "id_hash": "a7cdeaeb4dc6", "last_modified": "2 years ago"} +{"title": "qwen:72b-text-q3_K_M", "url": "https://ollama.com/library/qwen:72b-text-q3_K_M", "size": "37GB", "context": "32K", "input": "Text", "id_hash": "1c5d6fd01ff9", "last_modified": "2 years ago"} +{"title": "qwen:72b-text-q3_K_S", "url": "https://ollama.com/library/qwen:72b-text-q3_K_S", "size": "32GB", "context": "32K", "input": "Text", "id_hash": "325a8011ee4b", "last_modified": "2 years ago"} +{"title": "qwen:72b-text-q4_0", "url": "https://ollama.com/library/qwen:72b-text-q4_0", "size": "41GB", "context": "32K", "input": "Text", "id_hash": "1cd3d5885ed6", "last_modified": "2 years ago"} +{"title": "qwen:72b-text-q4_1", "url": "https://ollama.com/library/qwen:72b-text-q4_1", "size": "45GB", "context": "32K", "input": "Text", "id_hash": "b466cc1b68b6", "last_modified": "2 years ago"} +{"title": "qwen:72b-text-q4_K_M", "url": "https://ollama.com/library/qwen:72b-text-q4_K_M", "size": "45GB", "context": "32K", "input": "Text", "id_hash": "17d08105327a", "last_modified": "2 years ago"} +{"title": "qwen:72b-text-q4_K_S", "url": "https://ollama.com/library/qwen:72b-text-q4_K_S", "size": "41GB", "context": "32K", "input": "Text", "id_hash": "66750638e89b", "last_modified": "2 years ago"} +{"title": "qwen:72b-text-q5_0", "url": "https://ollama.com/library/qwen:72b-text-q5_0", "size": "50GB", "context": "32K", "input": "Text", "id_hash": "d552a292aad1", "last_modified": "2 years ago"} +{"title": "qwen:72b-text-q5_1", "url": "https://ollama.com/library/qwen:72b-text-q5_1", "size": "54GB", "context": "32K", "input": "Text", "id_hash": "d8d15961dfea", "last_modified": "2 years ago"} +{"title": "qwen:72b-text-q5_K_M", "url": "https://ollama.com/library/qwen:72b-text-q5_K_M", "size": "53GB", "context": "32K", "input": "Text", "id_hash": "5a9b21fe4698", "last_modified": "2 years ago"} +{"title": "qwen:72b-text-q5_K_S", "url": "https://ollama.com/library/qwen:72b-text-q5_K_S", "size": "50GB", "context": "32K", "input": "Text", "id_hash": "c47f6138bc77", "last_modified": "2 years ago"} +{"title": "qwen:72b-text-q6_K", "url": "https://ollama.com/library/qwen:72b-text-q6_K", "size": "59GB", "context": "32K", "input": "Text", "id_hash": "025578f7c6ba", "last_modified": "2 years ago"} +{"title": "qwen:72b-text-q8_0", "url": "https://ollama.com/library/qwen:72b-text-q8_0", "size": "77GB", "context": "32K", "input": "Text", "id_hash": "5c8b151ce1ed", "last_modified": "2 years ago"} +{"title": "qwen:72b-text-v1.5-fp16", "url": "https://ollama.com/library/qwen:72b-text-v1.5-fp16", "size": "145GB", "context": "32K", "input": "Text", "id_hash": "e45fb69e7592", "last_modified": "2 years ago"} +{"title": "qwen:72b-text-v1.5-q2_K", "url": "https://ollama.com/library/qwen:72b-text-v1.5-q2_K", "size": "28GB", "context": "32K", "input": "Text", "id_hash": "197347e6f44a", "last_modified": "2 years ago"} +{"title": "qwen:72b-text-v1.5-q3_K_L", "url": "https://ollama.com/library/qwen:72b-text-v1.5-q3_K_L", "size": "38GB", "context": "32K", "input": "Text", "id_hash": "12d317b5786e", "last_modified": "2 years ago"} +{"title": "qwen:72b-text-v1.5-q3_K_M", "url": "https://ollama.com/library/qwen:72b-text-v1.5-q3_K_M", "size": "36GB", "context": "32K", "input": "Text", "id_hash": "0369ae92fbbb", "last_modified": "2 years ago"} +{"title": "qwen:72b-text-v1.5-q3_K_S", "url": "https://ollama.com/library/qwen:72b-text-v1.5-q3_K_S", "size": "33GB", "context": "32K", "input": "Text", "id_hash": "543046c80b47", "last_modified": "2 years ago"} +{"title": "qwen:72b-text-v1.5-q4_0", "url": "https://ollama.com/library/qwen:72b-text-v1.5-q4_0", "size": "41GB", "context": "32K", "input": "Text", "id_hash": "d5c16df7f831", "last_modified": "2 years ago"} +{"title": "qwen:72b-text-v1.5-q4_1", "url": "https://ollama.com/library/qwen:72b-text-v1.5-q4_1", "size": "45GB", "context": "32K", "input": "Text", "id_hash": "c43dd2a16f0f", "last_modified": "2 years ago"} +{"title": "qwen:72b-text-v1.5-q4_K_M", "url": "https://ollama.com/library/qwen:72b-text-v1.5-q4_K_M", "size": "44GB", "context": "32K", "input": "Text", "id_hash": "b6c1eefce0a6", "last_modified": "2 years ago"} +{"title": "qwen:72b-text-v1.5-q4_K_S", "url": "https://ollama.com/library/qwen:72b-text-v1.5-q4_K_S", "size": "42GB", "context": "32K", "input": "Text", "id_hash": "c395d71df009", "last_modified": "2 years ago"} +{"title": "qwen:72b-text-v1.5-q5_0", "url": "https://ollama.com/library/qwen:72b-text-v1.5-q5_0", "size": "50GB", "context": "32K", "input": "Text", "id_hash": "ce956e731751", "last_modified": "2 years ago"} +{"title": "qwen:72b-text-v1.5-q5_1", "url": "https://ollama.com/library/qwen:72b-text-v1.5-q5_1", "size": "54GB", "context": "32K", "input": "Text", "id_hash": "e61f727ecdb2", "last_modified": "2 years ago"} +{"title": "qwen:72b-text-v1.5-q5_K_M", "url": "https://ollama.com/library/qwen:72b-text-v1.5-q5_K_M", "size": "51GB", "context": "32K", "input": "Text", "id_hash": "ea68416fee98", "last_modified": "2 years ago"} +{"title": "qwen:72b-text-v1.5-q5_K_S", "url": "https://ollama.com/library/qwen:72b-text-v1.5-q5_K_S", "size": "50GB", "context": "32K", "input": "Text", "id_hash": "8c427eabb6e1", "last_modified": "2 years ago"} +{"title": "qwen:72b-text-v1.5-q6_K", "url": "https://ollama.com/library/qwen:72b-text-v1.5-q6_K", "size": "59GB", "context": "32K", "input": "Text", "id_hash": "c75eef5a9035", "last_modified": "2 years ago"} +{"title": "qwen:72b-text-v1.5-q8_0", "url": "https://ollama.com/library/qwen:72b-text-v1.5-q8_0", "size": "77GB", "context": "32K", "input": "Text", "id_hash": "da7cc3b6659a", "last_modified": "2 years ago"} +{"title": "qwen:7b", "url": "https://ollama.com/library/qwen:7b", "size": "4.5GB", "context": "32K", "input": "Text", "id_hash": "2091ee8c8d8f", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat", "url": "https://ollama.com/library/qwen:7b-chat", "size": "4.5GB", "context": "32K", "input": "Text", "id_hash": "2091ee8c8d8f", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-fp16", "url": "https://ollama.com/library/qwen:7b-chat-fp16", "size": "15GB", "context": "32K", "input": "Text", "id_hash": "496130f8bb9c", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-q2_K", "url": "https://ollama.com/library/qwen:7b-chat-q2_K", "size": "3.0GB", "context": "32K", "input": "Text", "id_hash": "b1e83e951244", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-q3_K_L", "url": "https://ollama.com/library/qwen:7b-chat-q3_K_L", "size": "4.3GB", "context": "32K", "input": "Text", "id_hash": "6c760e557c98", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-q3_K_M", "url": "https://ollama.com/library/qwen:7b-chat-q3_K_M", "size": "4.1GB", "context": "32K", "input": "Text", "id_hash": "981740748bb1", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-q3_K_S", "url": "https://ollama.com/library/qwen:7b-chat-q3_K_S", "size": "3.6GB", "context": "32K", "input": "Text", "id_hash": "6ee05062598c", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-q4_0", "url": "https://ollama.com/library/qwen:7b-chat-q4_0", "size": "4.5GB", "context": "32K", "input": "Text", "id_hash": "8a759e224c54", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-q4_1", "url": "https://ollama.com/library/qwen:7b-chat-q4_1", "size": "5.0GB", "context": "32K", "input": "Text", "id_hash": "e70d79f49f09", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-q4_K_M", "url": "https://ollama.com/library/qwen:7b-chat-q4_K_M", "size": "4.9GB", "context": "32K", "input": "Text", "id_hash": "6c6f9fb7cb7b", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-q4_K_S", "url": "https://ollama.com/library/qwen:7b-chat-q4_K_S", "size": "4.5GB", "context": "32K", "input": "Text", "id_hash": "670c5afa68d5", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-q5_0", "url": "https://ollama.com/library/qwen:7b-chat-q5_0", "size": "5.4GB", "context": "32K", "input": "Text", "id_hash": "940f9af7bba7", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-q5_1", "url": "https://ollama.com/library/qwen:7b-chat-q5_1", "size": "5.8GB", "context": "32K", "input": "Text", "id_hash": "71556ed81da3", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-q5_K_M", "url": "https://ollama.com/library/qwen:7b-chat-q5_K_M", "size": "5.7GB", "context": "32K", "input": "Text", "id_hash": "eb70368f4555", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-q5_K_S", "url": "https://ollama.com/library/qwen:7b-chat-q5_K_S", "size": "5.4GB", "context": "32K", "input": "Text", "id_hash": "82f7b355c834", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-q6_K", "url": "https://ollama.com/library/qwen:7b-chat-q6_K", "size": "6.3GB", "context": "32K", "input": "Text", "id_hash": "be7c8c5aee85", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-q8_0", "url": "https://ollama.com/library/qwen:7b-chat-q8_0", "size": "8.2GB", "context": "32K", "input": "Text", "id_hash": "75224d9ec839", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-v1.5-fp16", "url": "https://ollama.com/library/qwen:7b-chat-v1.5-fp16", "size": "15GB", "context": "32K", "input": "Text", "id_hash": "39e2b1482d7d", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-v1.5-q2_K", "url": "https://ollama.com/library/qwen:7b-chat-v1.5-q2_K", "size": "3.1GB", "context": "32K", "input": "Text", "id_hash": "faee39b0b827", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-v1.5-q3_K_L", "url": "https://ollama.com/library/qwen:7b-chat-v1.5-q3_K_L", "size": "4.2GB", "context": "32K", "input": "Text", "id_hash": "c78b559835da", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-v1.5-q3_K_M", "url": "https://ollama.com/library/qwen:7b-chat-v1.5-q3_K_M", "size": "3.9GB", "context": "32K", "input": "Text", "id_hash": "dfd589fd9f3b", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-v1.5-q3_K_S", "url": "https://ollama.com/library/qwen:7b-chat-v1.5-q3_K_S", "size": "3.6GB", "context": "32K", "input": "Text", "id_hash": "ef462b8bc3ca", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-v1.5-q4_0", "url": "https://ollama.com/library/qwen:7b-chat-v1.5-q4_0", "size": "4.5GB", "context": "32K", "input": "Text", "id_hash": "2091ee8c8d8f", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-v1.5-q4_1", "url": "https://ollama.com/library/qwen:7b-chat-v1.5-q4_1", "size": "5.0GB", "context": "32K", "input": "Text", "id_hash": "3dc4f8204e32", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-v1.5-q4_K_M", "url": "https://ollama.com/library/qwen:7b-chat-v1.5-q4_K_M", "size": "4.8GB", "context": "32K", "input": "Text", "id_hash": "315448cc7b99", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-v1.5-q4_K_S", "url": "https://ollama.com/library/qwen:7b-chat-v1.5-q4_K_S", "size": "4.5GB", "context": "32K", "input": "Text", "id_hash": "1b769918d6f3", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-v1.5-q5_0", "url": "https://ollama.com/library/qwen:7b-chat-v1.5-q5_0", "size": "5.4GB", "context": "32K", "input": "Text", "id_hash": "76b41a9e206c", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-v1.5-q5_1", "url": "https://ollama.com/library/qwen:7b-chat-v1.5-q5_1", "size": "5.8GB", "context": "32K", "input": "Text", "id_hash": "80b5a8dd99a2", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-v1.5-q5_K_M", "url": "https://ollama.com/library/qwen:7b-chat-v1.5-q5_K_M", "size": "5.5GB", "context": "32K", "input": "Text", "id_hash": "44ca6b3fda9d", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-v1.5-q5_K_S", "url": "https://ollama.com/library/qwen:7b-chat-v1.5-q5_K_S", "size": "5.4GB", "context": "32K", "input": "Text", "id_hash": "94f4b35970c7", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-v1.5-q6_K", "url": "https://ollama.com/library/qwen:7b-chat-v1.5-q6_K", "size": "6.3GB", "context": "32K", "input": "Text", "id_hash": "6b5b161d1076", "last_modified": "2 years ago"} +{"title": "qwen:7b-chat-v1.5-q8_0", "url": "https://ollama.com/library/qwen:7b-chat-v1.5-q8_0", "size": "8.2GB", "context": "32K", "input": "Text", "id_hash": "3985a6e61dfa", "last_modified": "2 years ago"} +{"title": "qwen:7b-fp16", "url": "https://ollama.com/library/qwen:7b-fp16", "size": "15GB", "context": "32K", "input": "Text", "id_hash": "bdb4603ac3f3", "last_modified": "2 years ago"} +{"title": "qwen:7b-q2_K", "url": "https://ollama.com/library/qwen:7b-q2_K", "size": "3.0GB", "context": "32K", "input": "Text", "id_hash": "afe0b73c064a", "last_modified": "2 years ago"} +{"title": "qwen:7b-q3_K_L", "url": "https://ollama.com/library/qwen:7b-q3_K_L", "size": "4.3GB", "context": "32K", "input": "Text", "id_hash": "2a971f9c4019", "last_modified": "2 years ago"} +{"title": "qwen:7b-q3_K_M", "url": "https://ollama.com/library/qwen:7b-q3_K_M", "size": "4.1GB", "context": "32K", "input": "Text", "id_hash": "407571073d23", "last_modified": "2 years ago"} +{"title": "qwen:7b-q3_K_S", "url": "https://ollama.com/library/qwen:7b-q3_K_S", "size": "3.6GB", "context": "32K", "input": "Text", "id_hash": "e770768ad724", "last_modified": "2 years ago"} +{"title": "qwen:7b-q4_0", "url": "https://ollama.com/library/qwen:7b-q4_0", "size": "4.5GB", "context": "32K", "input": "Text", "id_hash": "a602ed3d295f", "last_modified": "2 years ago"} +{"title": "qwen:7b-q4_1", "url": "https://ollama.com/library/qwen:7b-q4_1", "size": "5.0GB", "context": "32K", "input": "Text", "id_hash": "aced3b622251", "last_modified": "2 years ago"} +{"title": "qwen:7b-q4_K_M", "url": "https://ollama.com/library/qwen:7b-q4_K_M", "size": "4.9GB", "context": "32K", "input": "Text", "id_hash": "e6124c271f88", "last_modified": "2 years ago"} +{"title": "qwen:7b-q4_K_S", "url": "https://ollama.com/library/qwen:7b-q4_K_S", "size": "4.5GB", "context": "32K", "input": "Text", "id_hash": "13660ea6e426", "last_modified": "2 years ago"} +{"title": "qwen:7b-q5_0", "url": "https://ollama.com/library/qwen:7b-q5_0", "size": "5.4GB", "context": "32K", "input": "Text", "id_hash": "82a77b5d2839", "last_modified": "2 years ago"} +{"title": "qwen:7b-q5_1", "url": "https://ollama.com/library/qwen:7b-q5_1", "size": "5.8GB", "context": "32K", "input": "Text", "id_hash": "3a554a4eca23", "last_modified": "2 years ago"} +{"title": "qwen:7b-q5_K_M", "url": "https://ollama.com/library/qwen:7b-q5_K_M", "size": "5.7GB", "context": "32K", "input": "Text", "id_hash": "ee14f131c864", "last_modified": "2 years ago"} +{"title": "qwen:7b-q5_K_S", "url": "https://ollama.com/library/qwen:7b-q5_K_S", "size": "5.4GB", "context": "32K", "input": "Text", "id_hash": "48ac7dcf12ec", "last_modified": "2 years ago"} +{"title": "qwen:7b-q6_K", "url": "https://ollama.com/library/qwen:7b-q6_K", "size": "6.3GB", "context": "32K", "input": "Text", "id_hash": "733a6dcda35a", "last_modified": "2 years ago"} +{"title": "qwen:7b-q8_0", "url": "https://ollama.com/library/qwen:7b-q8_0", "size": "8.2GB", "context": "32K", "input": "Text", "id_hash": "ea380ed299dd", "last_modified": "2 years ago"} +{"title": "qwen:7b-text", "url": "https://ollama.com/library/qwen:7b-text", "size": "4.5GB", "context": "32K", "input": "Text", "id_hash": "952dc7c77fea", "last_modified": "2 years ago"} +{"title": "qwen:7b-text-v1.5-fp16", "url": "https://ollama.com/library/qwen:7b-text-v1.5-fp16", "size": "15GB", "context": "32K", "input": "Text", "id_hash": "ba1ea7856323", "last_modified": "2 years ago"} +{"title": "qwen:7b-text-v1.5-q2_K", "url": "https://ollama.com/library/qwen:7b-text-v1.5-q2_K", "size": "3.1GB", "context": "32K", "input": "Text", "id_hash": "7c798100fec5", "last_modified": "2 years ago"} +{"title": "qwen:7b-text-v1.5-q3_K_L", "url": "https://ollama.com/library/qwen:7b-text-v1.5-q3_K_L", "size": "4.2GB", "context": "32K", "input": "Text", "id_hash": "c103abc28f47", "last_modified": "2 years ago"} +{"title": "qwen:7b-text-v1.5-q3_K_M", "url": "https://ollama.com/library/qwen:7b-text-v1.5-q3_K_M", "size": "3.9GB", "context": "32K", "input": "Text", "id_hash": "fab4b0426e2d", "last_modified": "2 years ago"} +{"title": "qwen:7b-text-v1.5-q3_K_S", "url": "https://ollama.com/library/qwen:7b-text-v1.5-q3_K_S", "size": "3.6GB", "context": "32K", "input": "Text", "id_hash": "59ff1e9f7a72", "last_modified": "2 years ago"} +{"title": "qwen:7b-text-v1.5-q4_0", "url": "https://ollama.com/library/qwen:7b-text-v1.5-q4_0", "size": "4.5GB", "context": "32K", "input": "Text", "id_hash": "952dc7c77fea", "last_modified": "2 years ago"} +{"title": "qwen:7b-text-v1.5-q4_1", "url": "https://ollama.com/library/qwen:7b-text-v1.5-q4_1", "size": "5.0GB", "context": "32K", "input": "Text", "id_hash": "1c67239d76ac", "last_modified": "2 years ago"} +{"title": "qwen:7b-text-v1.5-q4_K_M", "url": "https://ollama.com/library/qwen:7b-text-v1.5-q4_K_M", "size": "4.8GB", "context": "32K", "input": "Text", "id_hash": "a2e8ed289a56", "last_modified": "2 years ago"} +{"title": "qwen:7b-text-v1.5-q4_K_S", "url": "https://ollama.com/library/qwen:7b-text-v1.5-q4_K_S", "size": "4.5GB", "context": "32K", "input": "Text", "id_hash": "05bb240791f0", "last_modified": "2 years ago"} +{"title": "qwen:7b-text-v1.5-q5_0", "url": "https://ollama.com/library/qwen:7b-text-v1.5-q5_0", "size": "5.4GB", "context": "32K", "input": "Text", "id_hash": "2074857a59f8", "last_modified": "2 years ago"} +{"title": "qwen:7b-text-v1.5-q5_1", "url": "https://ollama.com/library/qwen:7b-text-v1.5-q5_1", "size": "5.8GB", "context": "32K", "input": "Text", "id_hash": "0945490c2698", "last_modified": "2 years ago"} +{"title": "qwen:7b-text-v1.5-q5_K_M", "url": "https://ollama.com/library/qwen:7b-text-v1.5-q5_K_M", "size": "5.5GB", "context": "32K", "input": "Text", "id_hash": "4bf2de545437", "last_modified": "2 years ago"} +{"title": "qwen:7b-text-v1.5-q5_K_S", "url": "https://ollama.com/library/qwen:7b-text-v1.5-q5_K_S", "size": "5.4GB", "context": "32K", "input": "Text", "id_hash": "6d3df3af15c9", "last_modified": "2 years ago"} +{"title": "qwen:7b-text-v1.5-q6_K", "url": "https://ollama.com/library/qwen:7b-text-v1.5-q6_K", "size": "6.3GB", "context": "32K", "input": "Text", "id_hash": "989f69b773a3", "last_modified": "2 years ago"} +{"title": "qwen:7b-text-v1.5-q8_0", "url": "https://ollama.com/library/qwen:7b-text-v1.5-q8_0", "size": "8.2GB", "context": "32K", "input": "Text", "id_hash": "968572e9757d", "last_modified": "2 years ago"} +{"title": "qwen:latest", "url": "https://ollama.com/library/qwen:latest", "size": "2.3GB", "context": "32K", "input": "Text", "id_hash": "d53d04290064", "last_modified": "2 years ago"} diff --git a/html_parsing/ollama_com/dumps/dump_model_tags.py_qwen3-vl.jsonl b/html_parsing/ollama_com/dumps/dump_model_tags.py_qwen3-vl.jsonl new file mode 100644 index 000000000..1a8548522 --- /dev/null +++ b/html_parsing/ollama_com/dumps/dump_model_tags.py_qwen3-vl.jsonl @@ -0,0 +1,59 @@ +{"title": "qwen3-vl:235b", "url": "https://ollama.com/library/qwen3-vl:235b", "size": "143GB", "context": "256K", "input": "Text, Image", "id_hash": "dc44c5b88b17", "last_modified": "4 months ago"} +{"title": "qwen3-vl:235b-a22b", "url": "https://ollama.com/library/qwen3-vl:235b-a22b", "size": "143GB", "context": "256K", "input": "Text, Image", "id_hash": "dc44c5b88b17", "last_modified": "4 months ago"} +{"title": "qwen3-vl:235b-a22b-instruct", "url": "https://ollama.com/library/qwen3-vl:235b-a22b-instruct", "size": "143GB", "context": "256K", "input": "Text, Image", "id_hash": "f5a03319651d", "last_modified": "4 months ago"} +{"title": "qwen3-vl:235b-a22b-instruct-bf16", "url": "https://ollama.com/library/qwen3-vl:235b-a22b-instruct-bf16", "size": "471GB", "context": "256K", "input": "Text, Image", "id_hash": "f9d397f6f0db", "last_modified": "4 months ago"} +{"title": "qwen3-vl:235b-a22b-instruct-q4_K_M", "url": "https://ollama.com/library/qwen3-vl:235b-a22b-instruct-q4_K_M", "size": "143GB", "context": "256K", "input": "Text, Image", "id_hash": "f5a03319651d", "last_modified": "4 months ago"} +{"title": "qwen3-vl:235b-a22b-instruct-q8_0", "url": "https://ollama.com/library/qwen3-vl:235b-a22b-instruct-q8_0", "size": "251GB", "context": "256K", "input": "Text, Image", "id_hash": "9b028966853a", "last_modified": "4 months ago"} +{"title": "qwen3-vl:235b-a22b-thinking", "url": "https://ollama.com/library/qwen3-vl:235b-a22b-thinking", "size": "143GB", "context": "256K", "input": "Text, Image", "id_hash": "dc44c5b88b17", "last_modified": "4 months ago"} +{"title": "qwen3-vl:235b-a22b-thinking-bf16", "url": "https://ollama.com/library/qwen3-vl:235b-a22b-thinking-bf16", "size": "471GB", "context": "256K", "input": "Text, Image", "id_hash": "f78566ff0c56", "last_modified": "4 months ago"} +{"title": "qwen3-vl:235b-a22b-thinking-q4_K_M", "url": "https://ollama.com/library/qwen3-vl:235b-a22b-thinking-q4_K_M", "size": "143GB", "context": "256K", "input": "Text, Image", "id_hash": "dc44c5b88b17", "last_modified": "4 months ago"} +{"title": "qwen3-vl:235b-a22b-thinking-q8_0", "url": "https://ollama.com/library/qwen3-vl:235b-a22b-thinking-q8_0", "size": "251GB", "context": "256K", "input": "Text, Image", "id_hash": "01dc46352af0", "last_modified": "4 months ago"} +{"title": "qwen3-vl:235b-cloud", "url": "https://ollama.com/library/qwen3-vl:235b-cloud", "size": "-", "context": "256K", "input": "Text, Image", "id_hash": "86b3322ec200", "last_modified": "4 months ago"} +{"title": "qwen3-vl:235b-instruct-cloud", "url": "https://ollama.com/library/qwen3-vl:235b-instruct-cloud", "size": "-", "context": "256K", "input": "Text, Image", "id_hash": "2bf9522f6961", "last_modified": "4 months ago"} +{"title": "qwen3-vl:2b", "url": "https://ollama.com/library/qwen3-vl:2b", "size": "1.9GB", "context": "256K", "input": "Text, Image", "id_hash": "0635d9d857d4", "last_modified": "4 months ago"} +{"title": "qwen3-vl:2b-instruct", "url": "https://ollama.com/library/qwen3-vl:2b-instruct", "size": "1.9GB", "context": "256K", "input": "Text, Image", "id_hash": "ea422f1e7365", "last_modified": "4 months ago"} +{"title": "qwen3-vl:2b-instruct-bf16", "url": "https://ollama.com/library/qwen3-vl:2b-instruct-bf16", "size": "4.3GB", "context": "256K", "input": "Text, Image", "id_hash": "fc3633fe6782", "last_modified": "4 months ago"} +{"title": "qwen3-vl:2b-instruct-q4_K_M", "url": "https://ollama.com/library/qwen3-vl:2b-instruct-q4_K_M", "size": "1.9GB", "context": "256K", "input": "Text, Image", "id_hash": "ea422f1e7365", "last_modified": "4 months ago"} +{"title": "qwen3-vl:2b-instruct-q8_0", "url": "https://ollama.com/library/qwen3-vl:2b-instruct-q8_0", "size": "2.6GB", "context": "256K", "input": "Text, Image", "id_hash": "9674b2259d72", "last_modified": "4 months ago"} +{"title": "qwen3-vl:2b-thinking", "url": "https://ollama.com/library/qwen3-vl:2b-thinking", "size": "1.9GB", "context": "256K", "input": "Text, Image", "id_hash": "0635d9d857d4", "last_modified": "4 months ago"} +{"title": "qwen3-vl:2b-thinking-bf16", "url": "https://ollama.com/library/qwen3-vl:2b-thinking-bf16", "size": "4.3GB", "context": "256K", "input": "Text, Image", "id_hash": "0d2c70920874", "last_modified": "4 months ago"} +{"title": "qwen3-vl:2b-thinking-q4_K_M", "url": "https://ollama.com/library/qwen3-vl:2b-thinking-q4_K_M", "size": "1.9GB", "context": "256K", "input": "Text, Image", "id_hash": "0635d9d857d4", "last_modified": "4 months ago"} +{"title": "qwen3-vl:2b-thinking-q8_0", "url": "https://ollama.com/library/qwen3-vl:2b-thinking-q8_0", "size": "2.6GB", "context": "256K", "input": "Text, Image", "id_hash": "d73b897fb9aa", "last_modified": "4 months ago"} +{"title": "qwen3-vl:30b", "url": "https://ollama.com/library/qwen3-vl:30b", "size": "20GB", "context": "256K", "input": "Text, Image", "id_hash": "eda0be100877", "last_modified": "4 months ago"} +{"title": "qwen3-vl:30b-a3b", "url": "https://ollama.com/library/qwen3-vl:30b-a3b", "size": "20GB", "context": "256K", "input": "Text, Image", "id_hash": "eda0be100877", "last_modified": "4 months ago"} +{"title": "qwen3-vl:30b-a3b-instruct", "url": "https://ollama.com/library/qwen3-vl:30b-a3b-instruct", "size": "20GB", "context": "256K", "input": "Text, Image", "id_hash": "c871fc73fabc", "last_modified": "4 months ago"} +{"title": "qwen3-vl:30b-a3b-instruct-bf16", "url": "https://ollama.com/library/qwen3-vl:30b-a3b-instruct-bf16", "size": "62GB", "context": "256K", "input": "Text, Image", "id_hash": "d4cad104e81d", "last_modified": "4 months ago"} +{"title": "qwen3-vl:30b-a3b-instruct-q4_K_M", "url": "https://ollama.com/library/qwen3-vl:30b-a3b-instruct-q4_K_M", "size": "20GB", "context": "256K", "input": "Text, Image", "id_hash": "c871fc73fabc", "last_modified": "4 months ago"} +{"title": "qwen3-vl:30b-a3b-instruct-q8_0", "url": "https://ollama.com/library/qwen3-vl:30b-a3b-instruct-q8_0", "size": "34GB", "context": "256K", "input": "Text, Image", "id_hash": "e274c055d4d6", "last_modified": "4 months ago"} +{"title": "qwen3-vl:30b-a3b-thinking", "url": "https://ollama.com/library/qwen3-vl:30b-a3b-thinking", "size": "20GB", "context": "256K", "input": "Text, Image", "id_hash": "eda0be100877", "last_modified": "4 months ago"} +{"title": "qwen3-vl:30b-a3b-thinking-bf16", "url": "https://ollama.com/library/qwen3-vl:30b-a3b-thinking-bf16", "size": "62GB", "context": "256K", "input": "Text, Image", "id_hash": "ae3f9633ff7f", "last_modified": "4 months ago"} +{"title": "qwen3-vl:30b-a3b-thinking-q4_K_M", "url": "https://ollama.com/library/qwen3-vl:30b-a3b-thinking-q4_K_M", "size": "20GB", "context": "256K", "input": "Text, Image", "id_hash": "eda0be100877", "last_modified": "4 months ago"} +{"title": "qwen3-vl:30b-a3b-thinking-q8_0", "url": "https://ollama.com/library/qwen3-vl:30b-a3b-thinking-q8_0", "size": "34GB", "context": "256K", "input": "Text, Image", "id_hash": "1f8c2d354be6", "last_modified": "4 months ago"} +{"title": "qwen3-vl:32b", "url": "https://ollama.com/library/qwen3-vl:32b", "size": "21GB", "context": "256K", "input": "Text, Image", "id_hash": "ff2e46876908", "last_modified": "4 months ago"} +{"title": "qwen3-vl:32b-instruct", "url": "https://ollama.com/library/qwen3-vl:32b-instruct", "size": "21GB", "context": "256K", "input": "Text, Image", "id_hash": "c9a60b1a1a13", "last_modified": "4 months ago"} +{"title": "qwen3-vl:32b-instruct-bf16", "url": "https://ollama.com/library/qwen3-vl:32b-instruct-bf16", "size": "67GB", "context": "256K", "input": "Text, Image", "id_hash": "b8e3027ef0f8", "last_modified": "4 months ago"} +{"title": "qwen3-vl:32b-instruct-q4_K_M", "url": "https://ollama.com/library/qwen3-vl:32b-instruct-q4_K_M", "size": "21GB", "context": "256K", "input": "Text, Image", "id_hash": "c9a60b1a1a13", "last_modified": "4 months ago"} +{"title": "qwen3-vl:32b-instruct-q8_0", "url": "https://ollama.com/library/qwen3-vl:32b-instruct-q8_0", "size": "36GB", "context": "256K", "input": "Text, Image", "id_hash": "2d0a26462393", "last_modified": "4 months ago"} +{"title": "qwen3-vl:32b-thinking", "url": "https://ollama.com/library/qwen3-vl:32b-thinking", "size": "21GB", "context": "256K", "input": "Text, Image", "id_hash": "ff2e46876908", "last_modified": "4 months ago"} +{"title": "qwen3-vl:32b-thinking-bf16", "url": "https://ollama.com/library/qwen3-vl:32b-thinking-bf16", "size": "67GB", "context": "256K", "input": "Text, Image", "id_hash": "11c4702a61b1", "last_modified": "4 months ago"} +{"title": "qwen3-vl:32b-thinking-q4_K_M", "url": "https://ollama.com/library/qwen3-vl:32b-thinking-q4_K_M", "size": "21GB", "context": "256K", "input": "Text, Image", "id_hash": "ff2e46876908", "last_modified": "4 months ago"} +{"title": "qwen3-vl:32b-thinking-q8_0", "url": "https://ollama.com/library/qwen3-vl:32b-thinking-q8_0", "size": "36GB", "context": "256K", "input": "Text, Image", "id_hash": "76a7fcb8a3c0", "last_modified": "4 months ago"} +{"title": "qwen3-vl:4b", "url": "https://ollama.com/library/qwen3-vl:4b", "size": "3.3GB", "context": "256K", "input": "Text, Image", "id_hash": "1343d82ebee3", "last_modified": "4 months ago"} +{"title": "qwen3-vl:4b-instruct", "url": "https://ollama.com/library/qwen3-vl:4b-instruct", "size": "3.3GB", "context": "256K", "input": "Text, Image", "id_hash": "ee4b975b58c1", "last_modified": "4 months ago"} +{"title": "qwen3-vl:4b-instruct-bf16", "url": "https://ollama.com/library/qwen3-vl:4b-instruct-bf16", "size": "8.9GB", "context": "256K", "input": "Text, Image", "id_hash": "a074ff293a12", "last_modified": "4 months ago"} +{"title": "qwen3-vl:4b-instruct-q4_K_M", "url": "https://ollama.com/library/qwen3-vl:4b-instruct-q4_K_M", "size": "3.3GB", "context": "256K", "input": "Text, Image", "id_hash": "ee4b975b58c1", "last_modified": "4 months ago"} +{"title": "qwen3-vl:4b-instruct-q8_0", "url": "https://ollama.com/library/qwen3-vl:4b-instruct-q8_0", "size": "5.1GB", "context": "256K", "input": "Text, Image", "id_hash": "3c4e71051a81", "last_modified": "4 months ago"} +{"title": "qwen3-vl:4b-thinking", "url": "https://ollama.com/library/qwen3-vl:4b-thinking", "size": "3.3GB", "context": "256K", "input": "Text, Image", "id_hash": "1343d82ebee3", "last_modified": "4 months ago"} +{"title": "qwen3-vl:4b-thinking-bf16", "url": "https://ollama.com/library/qwen3-vl:4b-thinking-bf16", "size": "8.9GB", "context": "256K", "input": "Text, Image", "id_hash": "b04bc96a3a84", "last_modified": "4 months ago"} +{"title": "qwen3-vl:4b-thinking-q4_K_M", "url": "https://ollama.com/library/qwen3-vl:4b-thinking-q4_K_M", "size": "3.3GB", "context": "256K", "input": "Text, Image", "id_hash": "1343d82ebee3", "last_modified": "4 months ago"} +{"title": "qwen3-vl:4b-thinking-q8_0", "url": "https://ollama.com/library/qwen3-vl:4b-thinking-q8_0", "size": "5.1GB", "context": "256K", "input": "Text, Image", "id_hash": "5b16d3ac6a65", "last_modified": "4 months ago"} +{"title": "qwen3-vl:8b", "url": "https://ollama.com/library/qwen3-vl:8b", "size": "6.1GB", "context": "256K", "input": "Text, Image", "id_hash": "901cae732162", "last_modified": "4 months ago"} +{"title": "qwen3-vl:8b-instruct", "url": "https://ollama.com/library/qwen3-vl:8b-instruct", "size": "6.1GB", "context": "256K", "input": "Text, Image", "id_hash": "0533d74300e4", "last_modified": "4 months ago"} +{"title": "qwen3-vl:8b-instruct-bf16", "url": "https://ollama.com/library/qwen3-vl:8b-instruct-bf16", "size": "18GB", "context": "256K", "input": "Text, Image", "id_hash": "55aa31bad4e2", "last_modified": "4 months ago"} +{"title": "qwen3-vl:8b-instruct-q4_K_M", "url": "https://ollama.com/library/qwen3-vl:8b-instruct-q4_K_M", "size": "6.1GB", "context": "256K", "input": "Text, Image", "id_hash": "0533d74300e4", "last_modified": "4 months ago"} +{"title": "qwen3-vl:8b-instruct-q8_0", "url": "https://ollama.com/library/qwen3-vl:8b-instruct-q8_0", "size": "9.8GB", "context": "256K", "input": "Text, Image", "id_hash": "eff3eb825b32", "last_modified": "4 months ago"} +{"title": "qwen3-vl:8b-thinking", "url": "https://ollama.com/library/qwen3-vl:8b-thinking", "size": "6.1GB", "context": "256K", "input": "Text, Image", "id_hash": "901cae732162", "last_modified": "4 months ago"} +{"title": "qwen3-vl:8b-thinking-bf16", "url": "https://ollama.com/library/qwen3-vl:8b-thinking-bf16", "size": "18GB", "context": "256K", "input": "Text, Image", "id_hash": "a86052dd9262", "last_modified": "4 months ago"} +{"title": "qwen3-vl:8b-thinking-q4_K_M", "url": "https://ollama.com/library/qwen3-vl:8b-thinking-q4_K_M", "size": "6.1GB", "context": "256K", "input": "Text, Image", "id_hash": "901cae732162", "last_modified": "4 months ago"} +{"title": "qwen3-vl:8b-thinking-q8_0", "url": "https://ollama.com/library/qwen3-vl:8b-thinking-q8_0", "size": "9.8GB", "context": "256K", "input": "Text, Image", "id_hash": "9e9bbfc77186", "last_modified": "4 months ago"} +{"title": "qwen3-vl:latest", "url": "https://ollama.com/library/qwen3-vl:latest", "size": "6.1GB", "context": "256K", "input": "Text, Image", "id_hash": "901cae732162", "last_modified": "4 months ago"} diff --git a/html_parsing/ollama_com/dumps/dump_model_tags.py_qwen3.5.jsonl b/html_parsing/ollama_com/dumps/dump_model_tags.py_qwen3.5.jsonl new file mode 100644 index 000000000..4146f890f --- /dev/null +++ b/html_parsing/ollama_com/dumps/dump_model_tags.py_qwen3.5.jsonl @@ -0,0 +1,30 @@ +{"title": "qwen3.5:0.8b", "url": "https://ollama.com/library/qwen3.5:0.8b", "size": "1.0GB", "context": "256K", "input": "Text, Image", "id_hash": "f3817196d142", "last_modified": "1 week ago"} +{"title": "qwen3.5:0.8b-bf16", "url": "https://ollama.com/library/qwen3.5:0.8b-bf16", "size": "1.8GB", "context": "256K", "input": "Text, Image", "id_hash": "81a0b6550a2d", "last_modified": "1 week ago"} +{"title": "qwen3.5:0.8b-q8_0", "url": "https://ollama.com/library/qwen3.5:0.8b-q8_0", "size": "1.0GB", "context": "256K", "input": "Text, Image", "id_hash": "f3817196d142", "last_modified": "1 week ago"} +{"title": "qwen3.5:122b", "url": "https://ollama.com/library/qwen3.5:122b", "size": "81GB", "context": "256K", "input": "Text, Image", "id_hash": "8b9d11d807c5", "last_modified": "2 weeks ago"} +{"title": "qwen3.5:122b-a10b", "url": "https://ollama.com/library/qwen3.5:122b-a10b", "size": "81GB", "context": "256K", "input": "Text, Image", "id_hash": "8b9d11d807c5", "last_modified": "2 weeks ago"} +{"title": "qwen3.5:122b-a10b-q4_K_M", "url": "https://ollama.com/library/qwen3.5:122b-a10b-q4_K_M", "size": "81GB", "context": "256K", "input": "Text, Image", "id_hash": "8b9d11d807c5", "last_modified": "2 weeks ago"} +{"title": "qwen3.5:27b", "url": "https://ollama.com/library/qwen3.5:27b", "size": "17GB", "context": "256K", "input": "Text, Image", "id_hash": "7653528ba5cb", "last_modified": "1 week ago"} +{"title": "qwen3.5:27b-bf16", "url": "https://ollama.com/library/qwen3.5:27b-bf16", "size": "56GB", "context": "256K", "input": "Text, Image", "id_hash": "f9ebcd0c9957", "last_modified": "1 week ago"} +{"title": "qwen3.5:27b-q4_K_M", "url": "https://ollama.com/library/qwen3.5:27b-q4_K_M", "size": "17GB", "context": "256K", "input": "Text, Image", "id_hash": "7653528ba5cb", "last_modified": "1 week ago"} +{"title": "qwen3.5:27b-q8_0", "url": "https://ollama.com/library/qwen3.5:27b-q8_0", "size": "30GB", "context": "256K", "input": "Text, Image", "id_hash": "728880d65c32", "last_modified": "1 week ago"} +{"title": "qwen3.5:2b", "url": "https://ollama.com/library/qwen3.5:2b", "size": "2.7GB", "context": "256K", "input": "Text, Image", "id_hash": "324d162be6ca", "last_modified": "1 week ago"} +{"title": "qwen3.5:2b-bf16", "url": "https://ollama.com/library/qwen3.5:2b-bf16", "size": "4.6GB", "context": "256K", "input": "Text, Image", "id_hash": "64148169aba8", "last_modified": "1 week ago"} +{"title": "qwen3.5:2b-q4_K_M", "url": "https://ollama.com/library/qwen3.5:2b-q4_K_M", "size": "1.9GB", "context": "256K", "input": "Text, Image", "id_hash": "124a03c34777", "last_modified": "1 week ago"} +{"title": "qwen3.5:2b-q8_0", "url": "https://ollama.com/library/qwen3.5:2b-q8_0", "size": "2.7GB", "context": "256K", "input": "Text, Image", "id_hash": "324d162be6ca", "last_modified": "1 week ago"} +{"title": "qwen3.5:35b", "url": "https://ollama.com/library/qwen3.5:35b", "size": "24GB", "context": "256K", "input": "Text, Image", "id_hash": "3460ffeede54", "last_modified": "1 week ago"} +{"title": "qwen3.5:35b-a3b", "url": "https://ollama.com/library/qwen3.5:35b-a3b", "size": "24GB", "context": "256K", "input": "Text, Image", "id_hash": "3460ffeede54", "last_modified": "1 week ago"} +{"title": "qwen3.5:35b-a3b-bf16", "url": "https://ollama.com/library/qwen3.5:35b-a3b-bf16", "size": "72GB", "context": "256K", "input": "Text, Image", "id_hash": "85eaedff99c3", "last_modified": "1 week ago"} +{"title": "qwen3.5:35b-a3b-q4_K_M", "url": "https://ollama.com/library/qwen3.5:35b-a3b-q4_K_M", "size": "24GB", "context": "256K", "input": "Text, Image", "id_hash": "3460ffeede54", "last_modified": "1 week ago"} +{"title": "qwen3.5:35b-a3b-q8_0", "url": "https://ollama.com/library/qwen3.5:35b-a3b-q8_0", "size": "39GB", "context": "256K", "input": "Text, Image", "id_hash": "655d273ede3a", "last_modified": "1 week ago"} +{"title": "qwen3.5:397b-cloud", "url": "https://ollama.com/library/qwen3.5:397b-cloud", "size": "-", "context": "256K", "input": "Text, Image", "id_hash": "a7bf6f7891c3", "last_modified": "3 weeks ago"} +{"title": "qwen3.5:4b", "url": "https://ollama.com/library/qwen3.5:4b", "size": "3.4GB", "context": "256K", "input": "Text, Image", "id_hash": "2a654d98e6fb", "last_modified": "1 week ago"} +{"title": "qwen3.5:4b-bf16", "url": "https://ollama.com/library/qwen3.5:4b-bf16", "size": "9.3GB", "context": "256K", "input": "Text, Image", "id_hash": "d7207ebcf0be", "last_modified": "1 week ago"} +{"title": "qwen3.5:4b-q4_K_M", "url": "https://ollama.com/library/qwen3.5:4b-q4_K_M", "size": "3.4GB", "context": "256K", "input": "Text, Image", "id_hash": "2a654d98e6fb", "last_modified": "1 week ago"} +{"title": "qwen3.5:4b-q8_0", "url": "https://ollama.com/library/qwen3.5:4b-q8_0", "size": "5.3GB", "context": "256K", "input": "Text, Image", "id_hash": "8722f47c2791", "last_modified": "1 week ago"} +{"title": "qwen3.5:9b", "url": "https://ollama.com/library/qwen3.5:9b", "size": "6.6GB", "context": "256K", "input": "Text, Image", "id_hash": "6488c96fa5fa", "last_modified": "1 week ago"} +{"title": "qwen3.5:9b-bf16", "url": "https://ollama.com/library/qwen3.5:9b-bf16", "size": "19GB", "context": "256K", "input": "Text, Image", "id_hash": "df2b035304ec", "last_modified": "1 week ago"} +{"title": "qwen3.5:9b-q4_K_M", "url": "https://ollama.com/library/qwen3.5:9b-q4_K_M", "size": "6.6GB", "context": "256K", "input": "Text, Image", "id_hash": "6488c96fa5fa", "last_modified": "1 week ago"} +{"title": "qwen3.5:9b-q8_0", "url": "https://ollama.com/library/qwen3.5:9b-q8_0", "size": "11GB", "context": "256K", "input": "Text, Image", "id_hash": "441ec31e4d2a", "last_modified": "1 week ago"} +{"title": "qwen3.5:cloud", "url": "https://ollama.com/library/qwen3.5:cloud", "size": "-", "context": "256K", "input": "Text, Image", "id_hash": "a7bf6f7891c3", "last_modified": "3 weeks ago"} +{"title": "qwen3.5:latest", "url": "https://ollama.com/library/qwen3.5:latest", "size": "6.6GB", "context": "256K", "input": "Text, Image", "id_hash": "6488c96fa5fa", "last_modified": "1 week ago"} diff --git a/html_parsing/ollama_com/dumps/dump_model_tags.py_qwen3.jsonl b/html_parsing/ollama_com/dumps/dump_model_tags.py_qwen3.jsonl new file mode 100644 index 000000000..53338094c --- /dev/null +++ b/html_parsing/ollama_com/dumps/dump_model_tags.py_qwen3.jsonl @@ -0,0 +1,58 @@ +{"title": "qwen3:0.6b", "url": "https://ollama.com/library/qwen3:0.6b", "size": "523MB", "context": "40K", "input": "Text", "id_hash": "7df6b6e09427", "last_modified": "9 months ago"} +{"title": "qwen3:0.6b-fp16", "url": "https://ollama.com/library/qwen3:0.6b-fp16", "size": "1.5GB", "context": "40K", "input": "Text", "id_hash": "626c9556a80f", "last_modified": "9 months ago"} +{"title": "qwen3:0.6b-q4_K_M", "url": "https://ollama.com/library/qwen3:0.6b-q4_K_M", "size": "523MB", "context": "40K", "input": "Text", "id_hash": "7df6b6e09427", "last_modified": "9 months ago"} +{"title": "qwen3:0.6b-q8_0", "url": "https://ollama.com/library/qwen3:0.6b-q8_0", "size": "832MB", "context": "40K", "input": "Text", "id_hash": "f6358994266d", "last_modified": "9 months ago"} +{"title": "qwen3:1.7b", "url": "https://ollama.com/library/qwen3:1.7b", "size": "1.4GB", "context": "40K", "input": "Text", "id_hash": "8f68893c685c", "last_modified": "9 months ago"} +{"title": "qwen3:1.7b-fp16", "url": "https://ollama.com/library/qwen3:1.7b-fp16", "size": "4.1GB", "context": "40K", "input": "Text", "id_hash": "e9354f6174db", "last_modified": "9 months ago"} +{"title": "qwen3:1.7b-q4_K_M", "url": "https://ollama.com/library/qwen3:1.7b-q4_K_M", "size": "1.4GB", "context": "40K", "input": "Text", "id_hash": "8f68893c685c", "last_modified": "9 months ago"} +{"title": "qwen3:1.7b-q8_0", "url": "https://ollama.com/library/qwen3:1.7b-q8_0", "size": "2.2GB", "context": "40K", "input": "Text", "id_hash": "29b6a7a420a4", "last_modified": "9 months ago"} +{"title": "qwen3:14b", "url": "https://ollama.com/library/qwen3:14b", "size": "9.3GB", "context": "40K", "input": "Text", "id_hash": "bdbd181c33f2", "last_modified": "9 months ago"} +{"title": "qwen3:14b-fp16", "url": "https://ollama.com/library/qwen3:14b-fp16", "size": "30GB", "context": "40K", "input": "Text", "id_hash": "a5be4baba030", "last_modified": "9 months ago"} +{"title": "qwen3:14b-q4_K_M", "url": "https://ollama.com/library/qwen3:14b-q4_K_M", "size": "9.3GB", "context": "40K", "input": "Text", "id_hash": "bdbd181c33f2", "last_modified": "9 months ago"} +{"title": "qwen3:14b-q8_0", "url": "https://ollama.com/library/qwen3:14b-q8_0", "size": "16GB", "context": "40K", "input": "Text", "id_hash": "304bf7349c71", "last_modified": "9 months ago"} +{"title": "qwen3:235b", "url": "https://ollama.com/library/qwen3:235b", "size": "142GB", "context": "256K", "input": "Text", "id_hash": "754a872f1290", "last_modified": "5 months ago"} +{"title": "qwen3:235b-a22b", "url": "https://ollama.com/library/qwen3:235b-a22b", "size": "142GB", "context": "256K", "input": "Text", "id_hash": "754a872f1290", "last_modified": "5 months ago"} +{"title": "qwen3:235b-a22b-fp16", "url": "https://ollama.com/library/qwen3:235b-a22b-fp16", "size": "470GB", "context": "40K", "input": "Text", "id_hash": "4dc3ade61929", "last_modified": "9 months ago"} +{"title": "qwen3:235b-a22b-instruct-2507-q4_K_M", "url": "https://ollama.com/library/qwen3:235b-a22b-instruct-2507-q4_K_M", "size": "142GB", "context": "256K", "input": "Text", "id_hash": "88c401cdc877", "last_modified": "5 months ago"} +{"title": "qwen3:235b-a22b-instruct-2507-q8_0", "url": "https://ollama.com/library/qwen3:235b-a22b-instruct-2507-q8_0", "size": "250GB", "context": "256K", "input": "Text", "id_hash": "714b4861493d", "last_modified": "5 months ago"} +{"title": "qwen3:235b-a22b-q4_K_M", "url": "https://ollama.com/library/qwen3:235b-a22b-q4_K_M", "size": "142GB", "context": "40K", "input": "Text", "id_hash": "cf5635fabe3c", "last_modified": "9 months ago"} +{"title": "qwen3:235b-a22b-q8_0", "url": "https://ollama.com/library/qwen3:235b-a22b-q8_0", "size": "250GB", "context": "40K", "input": "Text", "id_hash": "37e8cf5bfc74", "last_modified": "9 months ago"} +{"title": "qwen3:235b-a22b-thinking-2507-fp16", "url": "https://ollama.com/library/qwen3:235b-a22b-thinking-2507-fp16", "size": "470GB", "context": "256K", "input": "Text", "id_hash": "6b430a7e3d29", "last_modified": "5 months ago"} +{"title": "qwen3:235b-a22b-thinking-2507-q4_K_M", "url": "https://ollama.com/library/qwen3:235b-a22b-thinking-2507-q4_K_M", "size": "142GB", "context": "256K", "input": "Text", "id_hash": "754a872f1290", "last_modified": "5 months ago"} +{"title": "qwen3:235b-a22b-thinking-2507-q8_0", "url": "https://ollama.com/library/qwen3:235b-a22b-thinking-2507-q8_0", "size": "250GB", "context": "256K", "input": "Text", "id_hash": "c4d308613f81", "last_modified": "5 months ago"} +{"title": "qwen3:235b-instruct", "url": "https://ollama.com/library/qwen3:235b-instruct", "size": "142GB", "context": "256K", "input": "Text", "id_hash": "88c401cdc877", "last_modified": "5 months ago"} +{"title": "qwen3:235b-thinking", "url": "https://ollama.com/library/qwen3:235b-thinking", "size": "142GB", "context": "256K", "input": "Text", "id_hash": "754a872f1290", "last_modified": "5 months ago"} +{"title": "qwen3:30b", "url": "https://ollama.com/library/qwen3:30b", "size": "19GB", "context": "256K", "input": "Text", "id_hash": "ad815644918f", "last_modified": "5 months ago"} +{"title": "qwen3:30b-a3b", "url": "https://ollama.com/library/qwen3:30b-a3b", "size": "19GB", "context": "256K", "input": "Text", "id_hash": "ad815644918f", "last_modified": "5 months ago"} +{"title": "qwen3:30b-a3b-fp16", "url": "https://ollama.com/library/qwen3:30b-a3b-fp16", "size": "61GB", "context": "40K", "input": "Text", "id_hash": "a46ad892011c", "last_modified": "9 months ago"} +{"title": "qwen3:30b-a3b-instruct-2507-fp16", "url": "https://ollama.com/library/qwen3:30b-a3b-instruct-2507-fp16", "size": "61GB", "context": "256K", "input": "Text", "id_hash": "2ad425bc080c", "last_modified": "5 months ago"} +{"title": "qwen3:30b-a3b-instruct-2507-q4_K_M", "url": "https://ollama.com/library/qwen3:30b-a3b-instruct-2507-q4_K_M", "size": "19GB", "context": "256K", "input": "Text", "id_hash": "19e422b02313", "last_modified": "5 months ago"} +{"title": "qwen3:30b-a3b-instruct-2507-q8_0", "url": "https://ollama.com/library/qwen3:30b-a3b-instruct-2507-q8_0", "size": "32GB", "context": "256K", "input": "Text", "id_hash": "528dfe43328b", "last_modified": "5 months ago"} +{"title": "qwen3:30b-a3b-q4_K_M", "url": "https://ollama.com/library/qwen3:30b-a3b-q4_K_M", "size": "19GB", "context": "40K", "input": "Text", "id_hash": "0b28110b7a33", "last_modified": "9 months ago"} +{"title": "qwen3:30b-a3b-q8_0", "url": "https://ollama.com/library/qwen3:30b-a3b-q8_0", "size": "33GB", "context": "40K", "input": "Text", "id_hash": "a43c3bd181ce", "last_modified": "9 months ago"} +{"title": "qwen3:30b-a3b-thinking-2507-fp16", "url": "https://ollama.com/library/qwen3:30b-a3b-thinking-2507-fp16", "size": "61GB", "context": "256K", "input": "Text", "id_hash": "063924ed7f52", "last_modified": "5 months ago"} +{"title": "qwen3:30b-a3b-thinking-2507-q4_K_M", "url": "https://ollama.com/library/qwen3:30b-a3b-thinking-2507-q4_K_M", "size": "19GB", "context": "256K", "input": "Text", "id_hash": "ad815644918f", "last_modified": "5 months ago"} +{"title": "qwen3:30b-a3b-thinking-2507-q8_0", "url": "https://ollama.com/library/qwen3:30b-a3b-thinking-2507-q8_0", "size": "32GB", "context": "256K", "input": "Text", "id_hash": "67e5f89a2a5d", "last_modified": "5 months ago"} +{"title": "qwen3:30b-instruct", "url": "https://ollama.com/library/qwen3:30b-instruct", "size": "19GB", "context": "256K", "input": "Text", "id_hash": "19e422b02313", "last_modified": "5 months ago"} +{"title": "qwen3:30b-thinking", "url": "https://ollama.com/library/qwen3:30b-thinking", "size": "19GB", "context": "256K", "input": "Text", "id_hash": "ad815644918f", "last_modified": "5 months ago"} +{"title": "qwen3:32b", "url": "https://ollama.com/library/qwen3:32b", "size": "20GB", "context": "40K", "input": "Text", "id_hash": "030ee887880f", "last_modified": "9 months ago"} +{"title": "qwen3:32b-fp16", "url": "https://ollama.com/library/qwen3:32b-fp16", "size": "66GB", "context": "40K", "input": "Text", "id_hash": "00dc0cb60a08", "last_modified": "9 months ago"} +{"title": "qwen3:32b-q4_K_M", "url": "https://ollama.com/library/qwen3:32b-q4_K_M", "size": "20GB", "context": "40K", "input": "Text", "id_hash": "030ee887880f", "last_modified": "9 months ago"} +{"title": "qwen3:32b-q8_0", "url": "https://ollama.com/library/qwen3:32b-q8_0", "size": "35GB", "context": "40K", "input": "Text", "id_hash": "a46beca077e5", "last_modified": "9 months ago"} +{"title": "qwen3:4b", "url": "https://ollama.com/library/qwen3:4b", "size": "2.5GB", "context": "256K", "input": "Text", "id_hash": "359d7dd4bcda", "last_modified": "5 months ago"} +{"title": "qwen3:4b-fp16", "url": "https://ollama.com/library/qwen3:4b-fp16", "size": "8.1GB", "context": "40K", "input": "Text", "id_hash": "c2a4b6294479", "last_modified": "9 months ago"} +{"title": "qwen3:4b-instruct", "url": "https://ollama.com/library/qwen3:4b-instruct", "size": "2.5GB", "context": "256K", "input": "Text", "id_hash": "0edcdef34593", "last_modified": "5 months ago"} +{"title": "qwen3:4b-instruct-2507-fp16", "url": "https://ollama.com/library/qwen3:4b-instruct-2507-fp16", "size": "8.1GB", "context": "256K", "input": "Text", "id_hash": "259cbeb0f33b", "last_modified": "5 months ago"} +{"title": "qwen3:4b-instruct-2507-q4_K_M", "url": "https://ollama.com/library/qwen3:4b-instruct-2507-q4_K_M", "size": "2.5GB", "context": "256K", "input": "Text", "id_hash": "0edcdef34593", "last_modified": "5 months ago"} +{"title": "qwen3:4b-instruct-2507-q8_0", "url": "https://ollama.com/library/qwen3:4b-instruct-2507-q8_0", "size": "4.3GB", "context": "256K", "input": "Text", "id_hash": "aa7252f68dda", "last_modified": "5 months ago"} +{"title": "qwen3:4b-q4_K_M", "url": "https://ollama.com/library/qwen3:4b-q4_K_M", "size": "2.6GB", "context": "40K", "input": "Text", "id_hash": "2bfd38a7daaf", "last_modified": "9 months ago"} +{"title": "qwen3:4b-q8_0", "url": "https://ollama.com/library/qwen3:4b-q8_0", "size": "4.4GB", "context": "40K", "input": "Text", "id_hash": "6461746fd6b5", "last_modified": "9 months ago"} +{"title": "qwen3:4b-thinking", "url": "https://ollama.com/library/qwen3:4b-thinking", "size": "2.5GB", "context": "256K", "input": "Text", "id_hash": "359d7dd4bcda", "last_modified": "5 months ago"} +{"title": "qwen3:4b-thinking-2507-fp16", "url": "https://ollama.com/library/qwen3:4b-thinking-2507-fp16", "size": "8.1GB", "context": "256K", "input": "Text", "id_hash": "c0b9500a47bb", "last_modified": "5 months ago"} +{"title": "qwen3:4b-thinking-2507-q4_K_M", "url": "https://ollama.com/library/qwen3:4b-thinking-2507-q4_K_M", "size": "2.5GB", "context": "256K", "input": "Text", "id_hash": "359d7dd4bcda", "last_modified": "5 months ago"} +{"title": "qwen3:4b-thinking-2507-q8_0", "url": "https://ollama.com/library/qwen3:4b-thinking-2507-q8_0", "size": "4.3GB", "context": "256K", "input": "Text", "id_hash": "446474631042", "last_modified": "5 months ago"} +{"title": "qwen3:8b", "url": "https://ollama.com/library/qwen3:8b", "size": "5.2GB", "context": "40K", "input": "Text", "id_hash": "500a1f067a9f", "last_modified": "9 months ago"} +{"title": "qwen3:8b-fp16", "url": "https://ollama.com/library/qwen3:8b-fp16", "size": "16GB", "context": "40K", "input": "Text", "id_hash": "0b358e6e9d8c", "last_modified": "9 months ago"} +{"title": "qwen3:8b-q4_K_M", "url": "https://ollama.com/library/qwen3:8b-q4_K_M", "size": "5.2GB", "context": "40K", "input": "Text", "id_hash": "500a1f067a9f", "last_modified": "9 months ago"} +{"title": "qwen3:8b-q8_0", "url": "https://ollama.com/library/qwen3:8b-q8_0", "size": "8.9GB", "context": "40K", "input": "Text", "id_hash": "e56358ca25dd", "last_modified": "9 months ago"} +{"title": "qwen3:latest", "url": "https://ollama.com/library/qwen3:latest", "size": "5.2GB", "context": "40K", "input": "Text", "id_hash": "500a1f067a9f", "last_modified": "9 months ago"} diff --git a/html_parsing/ollama_com/dumps/dump_models.py.jsonl b/html_parsing/ollama_com/dumps/dump_models.py.jsonl new file mode 100644 index 000000000..d54b44bcd --- /dev/null +++ b/html_parsing/ollama_com/dumps/dump_models.py.jsonl @@ -0,0 +1,215 @@ +{"title": "alfred", "url": "https://ollama.com/library/alfred", "description": "A robust conversational model designed to be used for both chat and instruct use cases.", "tags": ["alfred", "40b"], "pull_count": "128.8K", "tag_count": 7, "updated": "2 years ago"} +{"title": "all-minilm", "url": "https://ollama.com/library/all-minilm", "description": "Embedding models on very large sentence level datasets.", "tags": ["all-minilm", "embedding", "22m", "33m"], "pull_count": "2.6M", "tag_count": 10, "updated": "1 year ago"} +{"title": "athene-v2", "url": "https://ollama.com/library/athene-v2", "description": "Athene-V2 is a 72B parameter model which excels at code completion, mathematics, and log extraction tasks.", "tags": ["athene-v2", "tools", "72b"], "pull_count": "311.7K", "tag_count": 17, "updated": "1 year ago"} +{"title": "aya", "url": "https://ollama.com/library/aya", "description": "Aya 23, released by Cohere, is a new family of state-of-the-art, multilingual models that support 23 languages.", "tags": ["aya", "8b", "35b"], "pull_count": "525.2K", "tag_count": 33, "updated": "1 year ago"} +{"title": "aya-expanse", "url": "https://ollama.com/library/aya-expanse", "description": "Cohere For AI's language models trained to perform well across 23 different languages.", "tags": ["aya-expanse", "tools", "8b", "32b"], "pull_count": "448.2K", "tag_count": 33, "updated": "1 year ago"} +{"title": "bakllava", "url": "https://ollama.com/library/bakllava", "description": "BakLLaVA is a multimodal model consisting of the Mistral 7B base model augmented with the LLaVA architecture.", "tags": ["bakllava", "vision", "7b"], "pull_count": "572K", "tag_count": 17, "updated": "2 years ago"} +{"title": "bespoke-minicheck", "url": "https://ollama.com/library/bespoke-minicheck", "description": "A state-of-the-art fact-checking model developed by Bespoke Labs.", "tags": ["bespoke-minicheck", "7b"], "pull_count": "253.9K", "tag_count": 17, "updated": "1 year ago"} +{"title": "bge-large", "url": "https://ollama.com/library/bge-large", "description": "Embedding model from BAAI mapping texts to vectors.", "tags": ["bge-large", "embedding", "335m"], "pull_count": "211.3K", "tag_count": 3, "updated": "1 year ago"} +{"title": "bge-m3", "url": "https://ollama.com/library/bge-m3", "description": "BGE-M3 is a new model from BAAI distinguished for its versatility in Multi-Functionality, Multi-Linguality, and Multi-Granularity.", "tags": ["bge-m3", "embedding", "567m"], "pull_count": "3.5M", "tag_count": 3, "updated": "1 year ago"} +{"title": "codebooga", "url": "https://ollama.com/library/codebooga", "description": "A high-performing code instruct model created by merging two existing code models.", "tags": ["codebooga", "34b"], "pull_count": "243.8K", "tag_count": 16, "updated": "2 years ago"} +{"title": "codegeex4", "url": "https://ollama.com/library/codegeex4", "description": "A versatile model for AI software development scenarios, including code completion.", "tags": ["codegeex4", "9b"], "pull_count": "401.2K", "tag_count": 17, "updated": "1 year ago"} +{"title": "codegemma", "url": "https://ollama.com/library/codegemma", "description": "CodeGemma is a collection of powerful, lightweight models that can perform a variety of coding tasks like fill-in-the-middle code completion, code generation, natural language understanding, mathematical reasoning, and instruction following.", "tags": ["codegemma", "2b", "7b"], "pull_count": "2.3M", "tag_count": 85, "updated": "1 year ago"} +{"title": "codellama", "url": "https://ollama.com/library/codellama", "description": "A large language model that can use text prompts to generate and discuss code.", "tags": ["codellama", "7b", "13b", "34b", "70b"], "pull_count": "4.5M", "tag_count": 199, "updated": "1 year ago"} +{"title": "codeqwen", "url": "https://ollama.com/library/codeqwen", "description": "CodeQwen1.5 is a large language model pretrained on a large amount of code data.", "tags": ["codeqwen", "7b"], "pull_count": "543.7K", "tag_count": 30, "updated": "1 year ago"} +{"title": "codestral", "url": "https://ollama.com/library/codestral", "description": "Codestral is Mistral AI’s first-ever code model designed for code generation tasks.", "tags": ["codestral", "22b"], "pull_count": "892.5K", "tag_count": 17, "updated": "1 year ago"} +{"title": "codeup", "url": "https://ollama.com/library/codeup", "description": "Great code generation model based on Llama2.", "tags": ["codeup", "13b"], "pull_count": "284.7K", "tag_count": 19, "updated": "2 years ago"} +{"title": "cogito", "url": "https://ollama.com/library/cogito", "description": "Cogito v1 Preview is a family of hybrid reasoning models by Deep Cogito that outperform the best available open models of the same size, including counterparts from LLaMA, DeepSeek, and Qwen across most standard benchmarks.", "tags": ["cogito", "tools", "3b", "8b", "14b", "32b", "70b"], "pull_count": "1.5M", "tag_count": 20, "updated": "11 months ago"} +{"title": "cogito-2.1", "url": "https://ollama.com/library/cogito-2.1", "description": "The Cogito v2.1 LLMs are instruction tuned generative models. All models are released under MIT license for commercial use.", "tags": ["cogito-2.1", "cloud", "671b"], "pull_count": "91K", "tag_count": 6, "updated": "3 months ago"} +{"title": "command-a", "url": "https://ollama.com/library/command-a", "description": "111 billion parameter model optimized for demanding enterprises that require fast, secure, and high-quality AI", "tags": ["command-a", "tools", "111b"], "pull_count": "144K", "tag_count": 5, "updated": "1 year ago"} +{"title": "command-r", "url": "https://ollama.com/library/command-r", "description": "Command R is a Large Language Model optimized for conversational interaction and long context tasks.", "tags": ["command-r", "tools", "35b"], "pull_count": "808.3K", "tag_count": 32, "updated": "1 year ago"} +{"title": "command-r-plus", "url": "https://ollama.com/library/command-r-plus", "description": "Command R+ is a powerful, scalable large language model purpose-built to excel at real-world enterprise use cases.", "tags": ["command-r-plus", "tools", "104b"], "pull_count": "438.9K", "tag_count": 21, "updated": "1 year ago"} +{"title": "command-r7b", "url": "https://ollama.com/library/command-r7b", "description": "The smallest model in Cohere's R series delivers top-tier speed, efficiency, and quality to build powerful AI applications on commodity GPUs and edge devices.", "tags": ["command-r7b", "tools", "7b"], "pull_count": "173.2K", "tag_count": 5, "updated": "1 year ago"} +{"title": "command-r7b-arabic", "url": "https://ollama.com/library/command-r7b-arabic", "description": "A new state-of-the-art version of the lightweight Command R7B model that excels in advanced Arabic language capabilities for enterprises in the Middle East and Northern Africa.", "tags": ["command-r7b-arabic", "tools", "7b"], "pull_count": "102K", "tag_count": 5, "updated": "1 year ago"} +{"title": "dbrx", "url": "https://ollama.com/library/dbrx", "description": "DBRX is an open, general-purpose LLM created by Databricks.", "tags": ["dbrx", "132b"], "pull_count": "210.1K", "tag_count": 7, "updated": "1 year ago"} +{"title": "deepcoder", "url": "https://ollama.com/library/deepcoder", "description": "DeepCoder is a fully open-Source 14B coder model at O3-mini level, with a 1.5B version also available.", "tags": ["deepcoder", "1.5b", "14b"], "pull_count": "698.2K", "tag_count": 9, "updated": "11 months ago"} +{"title": "deepscaler", "url": "https://ollama.com/library/deepscaler", "description": "A fine-tuned version of Deepseek-R1-Distilled-Qwen-1.5B that surpasses the performance of OpenAI’s o1-preview with just 1.5B parameters on popular math evaluations.", "tags": ["deepscaler", "1.5b"], "pull_count": "1.1M", "tag_count": 5, "updated": "1 year ago"} +{"title": "deepseek-coder", "url": "https://ollama.com/library/deepseek-coder", "description": "DeepSeek Coder is a capable coding model trained on two trillion code and natural language tokens.", "tags": ["deepseek-coder", "1.3b", "6.7b", "33b"], "pull_count": "3.2M", "tag_count": 102, "updated": "2 years ago"} +{"title": "deepseek-coder-v2", "url": "https://ollama.com/library/deepseek-coder-v2", "description": "An open-source Mixture-of-Experts code language model that achieves performance comparable to GPT4-Turbo in code-specific tasks.", "tags": ["deepseek-coder-v2", "16b", "236b"], "pull_count": "1.7M", "tag_count": 64, "updated": "1 year ago"} +{"title": "deepseek-llm", "url": "https://ollama.com/library/deepseek-llm", "description": "An advanced language model crafted with 2 trillion bilingual tokens.", "tags": ["deepseek-llm", "7b", "67b"], "pull_count": "573.1K", "tag_count": 64, "updated": "2 years ago"} +{"title": "deepseek-ocr", "url": "https://ollama.com/library/deepseek-ocr", "description": "DeepSeek-OCR is a vision-language model that can perform token-efficient OCR.", "tags": ["deepseek-ocr", "vision", "3b"], "pull_count": "332K", "tag_count": 3, "updated": "3 months ago"} +{"title": "deepseek-r1", "url": "https://ollama.com/library/deepseek-r1", "description": "DeepSeek-R1 is a family of open reasoning models with performance approaching that of leading models, such as O3 and Gemini 2.5 Pro.", "tags": ["deepseek-r1", "tools", "thinking", "1.5b", "7b", "8b", "14b", "32b", "70b", "671b"], "pull_count": "79.7M", "tag_count": 35, "updated": "8 months ago"} +{"title": "deepseek-v2", "url": "https://ollama.com/library/deepseek-v2", "description": "A strong, economical, and efficient Mixture-of-Experts language model.", "tags": ["deepseek-v2", "16b", "236b"], "pull_count": "571K", "tag_count": 34, "updated": "1 year ago"} +{"title": "deepseek-v2.5", "url": "https://ollama.com/library/deepseek-v2.5", "description": "An upgraded version of DeekSeek-V2 that integrates the general and coding abilities of both DeepSeek-V2-Chat and DeepSeek-Coder-V2-Instruct.", "tags": ["deepseek-v2.5", "236b"], "pull_count": "173.1K", "tag_count": 7, "updated": "1 year ago"} +{"title": "deepseek-v3", "url": "https://ollama.com/library/deepseek-v3", "description": "A strong Mixture-of-Experts (MoE) language model with 671B total parameters with 37B activated for each token.", "tags": ["deepseek-v3", "671b"], "pull_count": "3.6M", "tag_count": 5, "updated": "1 year ago"} +{"title": "deepseek-v3.1", "url": "https://ollama.com/library/deepseek-v3.1", "description": "DeepSeek-V3.1-Terminus is a hybrid model that supports both thinking mode and non-thinking mode.", "tags": ["deepseek-v3.1", "tools", "thinking", "cloud", "671b"], "pull_count": "441.3K", "tag_count": 8, "updated": "5 months ago"} +{"title": "deepseek-v3.2", "url": "https://ollama.com/library/deepseek-v3.2", "description": "DeepSeek-V3.2, a model that harmonizes high computational efficiency with superior reasoning and agent performance.", "tags": ["deepseek-v3.2", "cloud"], "pull_count": "46.5K", "tag_count": 1, "updated": "2 months ago"} +{"title": "devstral", "url": "https://ollama.com/library/devstral", "description": "Devstral: the best open source model for coding agents", "tags": ["devstral", "tools", "24b"], "pull_count": "808K", "tag_count": 5, "updated": "8 months ago"} +{"title": "devstral-2", "url": "https://ollama.com/library/devstral-2", "description": "123B model that excels at using tools to explore codebases, editing multiple files and power software engineering agents.", "tags": ["devstral-2", "tools", "cloud", "123b"], "pull_count": "110.8K", "tag_count": 6, "updated": "3 months ago"} +{"title": "devstral-small-2", "url": "https://ollama.com/library/devstral-small-2", "description": "24B model that excels at using tools to explore codebases, editing multiple files and power software engineering agents.", "tags": ["devstral-small-2", "vision", "tools", "cloud", "24b"], "pull_count": "619.2K", "tag_count": 6, "updated": "3 months ago"} +{"title": "dolphin-llama3", "url": "https://ollama.com/library/dolphin-llama3", "description": "Dolphin 2.9 is a new model with 8B and 70B sizes by Eric Hartford based on Llama 3 that has a variety of instruction, conversational, and coding skills.", "tags": ["dolphin-llama3", "8b", "70b"], "pull_count": "1.2M", "tag_count": 53, "updated": "1 year ago"} +{"title": "dolphin-mistral", "url": "https://ollama.com/library/dolphin-mistral", "description": "The uncensored Dolphin model based on Mistral that excels at coding tasks. Updated to version 2.8.", "tags": ["dolphin-mistral", "7b"], "pull_count": "845.7K", "tag_count": 120, "updated": "1 year ago"} +{"title": "dolphin-mixtral", "url": "https://ollama.com/library/dolphin-mixtral", "description": "Uncensored, 8x7b and 8x22b fine-tuned models based on the Mixtral mixture of experts models that excels at coding tasks. Created by Eric Hartford.", "tags": ["dolphin-mixtral", "8x7b", "8x22b"], "pull_count": "1.2M", "tag_count": 70, "updated": "1 year ago"} +{"title": "dolphin-phi", "url": "https://ollama.com/library/dolphin-phi", "description": "2.7B uncensored Dolphin model by Eric Hartford, based on the Phi language model by Microsoft Research.", "tags": ["dolphin-phi", "2.7b"], "pull_count": "1.3M", "tag_count": 15, "updated": "2 years ago"} +{"title": "dolphin3", "url": "https://ollama.com/library/dolphin3", "description": "Dolphin 3.0 Llama 3.1 8B 🐬 is the next generation of the Dolphin series of instruct-tuned models designed to be the ultimate general purpose local model, enabling coding, math, agentic, function calling, and general use cases.", "tags": ["dolphin3", "8b"], "pull_count": "3.7M", "tag_count": 5, "updated": "1 year ago"} +{"title": "dolphincoder", "url": "https://ollama.com/library/dolphincoder", "description": "A 7B and 15B uncensored variant of the Dolphin model family that excels at coding, based on StarCoder2.", "tags": ["dolphincoder", "7b", "15b"], "pull_count": "472.6K", "tag_count": 35, "updated": "1 year ago"} +{"title": "duckdb-nsql", "url": "https://ollama.com/library/duckdb-nsql", "description": "7B parameter text-to-SQL model made by MotherDuck and Numbers Station.", "tags": ["duckdb-nsql", "7b"], "pull_count": "256.9K", "tag_count": 17, "updated": "2 years ago"} +{"title": "embeddinggemma", "url": "https://ollama.com/library/embeddinggemma", "description": "EmbeddingGemma is a 300M parameter embedding model from Google.", "tags": ["embeddinggemma", "embedding", "300m"], "pull_count": "628.7K", "tag_count": 5, "updated": "6 months ago"} +{"title": "everythinglm", "url": "https://ollama.com/library/everythinglm", "description": "Uncensored Llama2 based model with support for a 16K context window.", "tags": ["everythinglm", "13b"], "pull_count": "275.7K", "tag_count": 18, "updated": "2 years ago"} +{"title": "exaone-deep", "url": "https://ollama.com/library/exaone-deep", "description": "EXAONE Deep exhibits superior capabilities in various reasoning tasks including math and coding benchmarks, ranging from 2.4B to 32B parameters developed and released by LG AI Research.", "tags": ["exaone-deep", "2.4b", "7.8b", "32b"], "pull_count": "536.1K", "tag_count": 13, "updated": "11 months ago"} +{"title": "exaone3.5", "url": "https://ollama.com/library/exaone3.5", "description": "EXAONE 3.5 is a collection of instruction-tuned bilingual (English and Korean) generative models ranging from 2.4B to 32B parameters, developed and released by LG AI Research.", "tags": ["exaone3.5", "2.4b", "7.8b", "32b"], "pull_count": "300.8K", "tag_count": 13, "updated": "1 year ago"} +{"title": "falcon", "url": "https://ollama.com/library/falcon", "description": "A large language model built by the Technology Innovation Institute (TII) for use in summarization, text generation, and chat bots.", "tags": ["falcon", "7b", "40b", "180b"], "pull_count": "569.3K", "tag_count": 38, "updated": "2 years ago"} +{"title": "falcon2", "url": "https://ollama.com/library/falcon2", "description": "Falcon2 is an 11B parameters causal decoder-only model built by TII and trained over 5T tokens.", "tags": ["falcon2", "11b"], "pull_count": "262K", "tag_count": 17, "updated": "1 year ago"} +{"title": "falcon3", "url": "https://ollama.com/library/falcon3", "description": "A family of efficient AI models under 10B parameters performant in science, math, and coding through innovative training techniques.", "tags": ["falcon3", "1b", "3b", "7b", "10b"], "pull_count": "2.2M", "tag_count": 17, "updated": "1 year ago"} +{"title": "firefunction-v2", "url": "https://ollama.com/library/firefunction-v2", "description": "An open weights function calling model based on Llama 3, competitive with GPT-4o function calling capabilities.", "tags": ["firefunction-v2", "tools", "70b"], "pull_count": "247.9K", "tag_count": 17, "updated": "1 year ago"} +{"title": "functiongemma", "url": "https://ollama.com/library/functiongemma", "description": "FunctionGemma is a specialized version of Google's Gemma 3 270M model fine-tuned explicitly for function calling.", "tags": ["functiongemma", "tools", "270m"], "pull_count": "87.1K", "tag_count": 4, "updated": "2 months ago"} +{"title": "gemini-3-flash-preview", "url": "https://ollama.com/library/gemini-3-flash-preview", "description": "Gemini 3 Flash offers frontier intelligence built for speed at a fraction of the cost.", "tags": ["gemini-3-flash-preview", "cloud"], "pull_count": "80.3K", "tag_count": 2, "updated": "2 months ago"} +{"title": "gemma", "url": "https://ollama.com/library/gemma", "description": "Gemma is a family of lightweight, state-of-the-art open models built by Google DeepMind. Updated to version 1.1", "tags": ["gemma", "2b", "7b"], "pull_count": "6M", "tag_count": 102, "updated": "1 year ago"} +{"title": "gemma2", "url": "https://ollama.com/library/gemma2", "description": "Google Gemma 2 is a high-performing and efficient model available in three sizes: 2B, 9B, and 27B.", "tags": ["gemma2", "2b", "9b", "27b"], "pull_count": "17.5M", "tag_count": 94, "updated": "1 year ago"} +{"title": "gemma3", "url": "https://ollama.com/library/gemma3", "description": "The current, most capable model that runs on a single GPU.", "tags": ["gemma3", "vision", "cloud", "270m", "1b", "4b", "12b", "27b"], "pull_count": "33.2M", "tag_count": 29, "updated": "3 months ago"} +{"title": "gemma3n", "url": "https://ollama.com/library/gemma3n", "description": "Gemma 3n models are designed for efficient execution on everyday devices such as laptops, tablets or phones.", "tags": ["gemma3n", "e2b", "e4b"], "pull_count": "1.3M", "tag_count": 9, "updated": "8 months ago"} +{"title": "glm-4.6", "url": "https://ollama.com/library/glm-4.6", "description": "Advanced agentic, reasoning and coding capabilities.", "tags": ["glm-4.6", "cloud"], "pull_count": "84.1K", "tag_count": 1, "updated": "4 months ago"} +{"title": "glm-4.7", "url": "https://ollama.com/library/glm-4.7", "description": "Advancing the Coding Capability", "tags": ["glm-4.7", "cloud"], "pull_count": "64.4K", "tag_count": 1, "updated": "2 months ago"} +{"title": "glm-4.7-flash", "url": "https://ollama.com/library/glm-4.7-flash", "description": "As the strongest model in the 30B class, GLM-4.7-Flash offers a new option for lightweight deployment that balances performance and efficiency.", "tags": ["glm-4.7-flash", "tools", "thinking"], "pull_count": "464.8K", "tag_count": 4, "updated": "1 month ago"} +{"title": "glm-5", "url": "https://ollama.com/library/glm-5", "description": "A strong reasoning and agentic model from Z.ai with 744B total parameters (40B active), built for complex systems engineering and long-horizon tasks.", "tags": ["glm-5", "cloud"], "pull_count": "102.9K", "tag_count": 1, "updated": "4 weeks ago"} +{"title": "glm-ocr", "url": "https://ollama.com/library/glm-ocr", "description": "GLM-OCR is a multimodal OCR model for complex document understanding, built on the GLM-V encoder–decoder architecture.", "tags": ["glm-ocr", "vision", "tools"], "pull_count": "105.1K", "tag_count": 3, "updated": "1 month ago"} +{"title": "glm4", "url": "https://ollama.com/library/glm4", "description": "A strong multi-lingual general language model with competitive performance to Llama 3.", "tags": ["glm4", "9b"], "pull_count": "560.9K", "tag_count": 32, "updated": "1 year ago"} +{"title": "goliath", "url": "https://ollama.com/library/goliath", "description": "A language model created by combining two fine-tuned Llama 2 70B models into one.", "tags": ["goliath"], "pull_count": "229.4K", "tag_count": 16, "updated": "2 years ago"} +{"title": "gpt-oss", "url": "https://ollama.com/library/gpt-oss", "description": "OpenAI’s open-weight models designed for powerful reasoning, agentic tasks, and versatile developer use cases.", "tags": ["gpt-oss", "tools", "thinking", "cloud", "20b", "120b"], "pull_count": "7.6M", "tag_count": 5, "updated": "5 months ago"} +{"title": "gpt-oss-safeguard", "url": "https://ollama.com/library/gpt-oss-safeguard", "description": "gpt-oss-safeguard-20b and gpt-oss-safeguard-120b are safety reasoning models built-upon gpt-oss", "tags": ["gpt-oss-safeguard", "tools", "thinking", "20b", "120b"], "pull_count": "86.4K", "tag_count": 3, "updated": "4 months ago"} +{"title": "granite-code", "url": "https://ollama.com/library/granite-code", "description": "A family of open foundation models by IBM for Code Intelligence", "tags": ["granite-code", "3b", "8b", "20b", "34b"], "pull_count": "775.6K", "tag_count": 162, "updated": "1 year ago"} +{"title": "granite-embedding", "url": "https://ollama.com/library/granite-embedding", "description": "The IBM Granite Embedding 30M and 278M models models are text-only dense biencoder embedding models, with 30M available in English only and 278M serving multilingual use cases.", "tags": ["granite-embedding", "embedding", "30m", "278m"], "pull_count": "231.3K", "tag_count": 6, "updated": "1 year ago"} +{"title": "granite3-dense", "url": "https://ollama.com/library/granite3-dense", "description": "The IBM Granite 2B and 8B models are designed to support tool-based use cases and support for retrieval augmented generation (RAG), streamlining code generation, translation and bug fixing.", "tags": ["granite3-dense", "tools", "2b", "8b"], "pull_count": "484.2K", "tag_count": 33, "updated": "1 year ago"} +{"title": "granite3-guardian", "url": "https://ollama.com/library/granite3-guardian", "description": "The IBM Granite Guardian 3.0 2B and 8B models are designed to detect risks in prompts and/or responses.", "tags": ["granite3-guardian", "2b", "8b"], "pull_count": "173.2K", "tag_count": 10, "updated": "1 year ago"} +{"title": "granite3-moe", "url": "https://ollama.com/library/granite3-moe", "description": "The IBM Granite 1B and 3B models are the first mixture of experts (MoE) Granite models from IBM designed for low latency usage.", "tags": ["granite3-moe", "tools", "1b", "3b"], "pull_count": "443.1K", "tag_count": 33, "updated": "1 year ago"} +{"title": "granite3.1-dense", "url": "https://ollama.com/library/granite3.1-dense", "description": "The IBM Granite 2B and 8B models are text-only dense LLMs trained on over 12 trillion tokens of data, demonstrated significant improvements over their predecessors in performance and speed in IBM’s initial testing.", "tags": ["granite3.1-dense", "tools", "2b", "8b"], "pull_count": "482.8K", "tag_count": 33, "updated": "1 year ago"} +{"title": "granite3.1-moe", "url": "https://ollama.com/library/granite3.1-moe", "description": "The IBM Granite 1B and 3B models are long-context mixture of experts (MoE) Granite models from IBM designed for low latency usage.", "tags": ["granite3.1-moe", "tools", "1b", "3b"], "pull_count": "2.3M", "tag_count": 33, "updated": "1 year ago"} +{"title": "granite3.2", "url": "https://ollama.com/library/granite3.2", "description": "Granite-3.2 is a family of long-context AI models from IBM Granite fine-tuned for thinking capabilities.", "tags": ["granite3.2", "tools", "2b", "8b"], "pull_count": "297.9K", "tag_count": 9, "updated": "1 year ago"} +{"title": "granite3.2-vision", "url": "https://ollama.com/library/granite3.2-vision", "description": "A compact and efficient vision-language model, specifically designed for visual document understanding, enabling automated content extraction from tables, charts, infographics, plots, diagrams, and more.", "tags": ["granite3.2-vision", "vision", "tools", "2b"], "pull_count": "797.3K", "tag_count": 5, "updated": "1 year ago"} +{"title": "granite3.3", "url": "https://ollama.com/library/granite3.3", "description": "IBM Granite 2B and 8B models are 128K context length language models that have been fine-tuned for improved reasoning and instruction-following capabilities.", "tags": ["granite3.3", "tools", "2b", "8b"], "pull_count": "926K", "tag_count": 3, "updated": "11 months ago"} +{"title": "granite4", "url": "https://ollama.com/library/granite4", "description": "Granite 4 features improved instruction following (IF) and tool-calling capabilities, making them more effective in enterprise applications.", "tags": ["granite4", "tools", "350m", "1b", "3b"], "pull_count": "804.5K", "tag_count": 17, "updated": "4 months ago"} +{"title": "hermes3", "url": "https://ollama.com/library/hermes3", "description": "Hermes 3 is the latest version of the flagship Hermes series of LLMs by Nous Research", "tags": ["hermes3", "tools", "3b", "8b", "70b", "405b"], "pull_count": "720.9K", "tag_count": 65, "updated": "1 year ago"} +{"title": "internlm2", "url": "https://ollama.com/library/internlm2", "description": "InternLM2.5 is a 7B parameter model tailored for practical scenarios with outstanding reasoning capability.", "tags": ["internlm2", "1m", "1.8b", "7b", "20b"], "pull_count": "461.6K", "tag_count": 65, "updated": "1 year ago"} +{"title": "kimi-k2", "url": "https://ollama.com/library/kimi-k2", "description": "A state-of-the-art mixture-of-experts (MoE) language model. Kimi K2-Instruct-0905 demonstrates significant improvements in performance on public benchmarks and real-world coding agent tasks.", "tags": ["kimi-k2", "cloud"], "pull_count": "44.5K", "tag_count": 1, "updated": "5 months ago"} +{"title": "kimi-k2-thinking", "url": "https://ollama.com/library/kimi-k2-thinking", "description": "Kimi K2 Thinking, Moonshot AI's best open-source thinking model.", "tags": ["kimi-k2-thinking", "cloud"], "pull_count": "36.7K", "tag_count": 1, "updated": "4 months ago"} +{"title": "kimi-k2.5", "url": "https://ollama.com/library/kimi-k2.5", "description": "Kimi K2.5 is an open-source, native multimodal agentic model that seamlessly integrates vision and language understanding with advanced agentic capabilities, instant and thinking modes, as well as conversational and agentic paradigms.", "tags": ["kimi-k2.5", "cloud"], "pull_count": "146.7K", "tag_count": 1, "updated": "1 month ago"} +{"title": "lfm2", "url": "https://ollama.com/library/lfm2", "description": "LFM2 is a family of hybrid models designed for on-device deployment. LFM2-24B-A2B is the largest model in the family, scaling the architecture to 24 billion parameters while keeping inference efficient.", "tags": ["lfm2", "tools", "24b"], "pull_count": "942.4K", "tag_count": 6, "updated": "2 weeks ago"} +{"title": "lfm2.5-thinking", "url": "https://ollama.com/library/lfm2.5-thinking", "description": "LFM2.5 is a new family of hybrid models designed for on-device deployment.", "tags": ["lfm2.5-thinking", "tools", "1.2b"], "pull_count": "963.4K", "tag_count": 5, "updated": "1 month ago"} +{"title": "llama-guard3", "url": "https://ollama.com/library/llama-guard3", "description": "Llama Guard 3 is a series of models fine-tuned for content safety classification of LLM inputs and responses.", "tags": ["llama-guard3", "1b", "8b"], "pull_count": "460.4K", "tag_count": 33, "updated": "1 year ago"} +{"title": "llama-pro", "url": "https://ollama.com/library/llama-pro", "description": "An expansion of Llama 2 that specializes in integrating both general language understanding and domain-specific knowledge, particularly in programming and mathematics.", "tags": ["llama-pro"], "pull_count": "409K", "tag_count": 33, "updated": "2 years ago"} +{"title": "llama2", "url": "https://ollama.com/library/llama2", "description": "Llama 2 is a collection of foundation language models ranging from 7B to 70B parameters.", "tags": ["llama2", "7b", "13b", "70b"], "pull_count": "5.7M", "tag_count": 102, "updated": "2 years ago"} +{"title": "llama2-chinese", "url": "https://ollama.com/library/llama2-chinese", "description": "Llama 2 based model fine tuned to improve Chinese dialogue ability.", "tags": ["llama2-chinese", "7b", "13b"], "pull_count": "518.8K", "tag_count": 35, "updated": "2 years ago"} +{"title": "llama2-uncensored", "url": "https://ollama.com/library/llama2-uncensored", "description": "Uncensored Llama 2 model by George Sung and Jarrad Hope.", "tags": ["llama2-uncensored", "7b", "70b"], "pull_count": "1.9M", "tag_count": 34, "updated": "2 years ago"} +{"title": "llama3", "url": "https://ollama.com/library/llama3", "description": "Meta Llama 3: The most capable openly available LLM to date", "tags": ["llama3", "8b", "70b"], "pull_count": "18.5M", "tag_count": 68, "updated": "1 year ago"} +{"title": "llama3-chatqa", "url": "https://ollama.com/library/llama3-chatqa", "description": "A model from NVIDIA based on Llama 3 that excels at conversational question answering (QA) and retrieval-augmented generation (RAG).", "tags": ["llama3-chatqa", "8b", "70b"], "pull_count": "485.3K", "tag_count": 35, "updated": "1 year ago"} +{"title": "llama3-gradient", "url": "https://ollama.com/library/llama3-gradient", "description": "This model extends LLama-3 8B's context length from 8k to over 1m tokens.", "tags": ["llama3-gradient", "8b", "70b"], "pull_count": "471.4K", "tag_count": 35, "updated": "1 year ago"} +{"title": "llama3-groq-tool-use", "url": "https://ollama.com/library/llama3-groq-tool-use", "description": "A series of models from Groq that represent a significant advancement in open-source AI capabilities for tool use/function calling.", "tags": ["llama3-groq-tool-use", "tools", "8b", "70b"], "pull_count": "460.9K", "tag_count": 33, "updated": "1 year ago"} +{"title": "llama3.1", "url": "https://ollama.com/library/llama3.1", "description": "Llama 3.1 is a new state-of-the-art model from Meta available in 8B, 70B and 405B parameter sizes.", "tags": ["llama3.1", "tools", "8b", "70b", "405b"], "pull_count": "111.2M", "tag_count": 93, "updated": "1 year ago"} +{"title": "llama3.2", "url": "https://ollama.com/library/llama3.2", "description": "Meta's Llama 3.2 goes small with 1B and 3B models.", "tags": ["llama3.2", "tools", "1b", "3b"], "pull_count": "60.2M", "tag_count": 63, "updated": "1 year ago"} +{"title": "llama3.2-vision", "url": "https://ollama.com/library/llama3.2-vision", "description": "Llama 3.2 Vision is a collection of instruction-tuned image reasoning generative models in 11B and 90B sizes.", "tags": ["llama3.2-vision", "vision", "11b", "90b"], "pull_count": "3.9M", "tag_count": 9, "updated": "9 months ago"} +{"title": "llama3.3", "url": "https://ollama.com/library/llama3.3", "description": "New state of the art 70B model. Llama 3.3 70B offers similar performance compared to the Llama 3.1 405B model.", "tags": ["llama3.3", "tools", "70b"], "pull_count": "3.4M", "tag_count": 14, "updated": "1 year ago"} +{"title": "llama4", "url": "https://ollama.com/library/llama4", "description": "Meta's latest collection of multimodal models.", "tags": ["llama4", "vision", "tools", "16x17b", "128x17b"], "pull_count": "1.3M", "tag_count": 11, "updated": "8 months ago"} +{"title": "llava", "url": "https://ollama.com/library/llava", "description": "🌋 LLaVA is a novel end-to-end trained large multimodal model that combines a vision encoder and Vicuna for general-purpose visual and language understanding. Updated to version 1.6.", "tags": ["llava", "vision", "7b", "13b", "34b"], "pull_count": "13M", "tag_count": 98, "updated": "2 years ago"} +{"title": "llava-llama3", "url": "https://ollama.com/library/llava-llama3", "description": "A LLaVA model fine-tuned from Llama 3 Instruct with better scores in several benchmarks.", "tags": ["llava-llama3", "vision", "8b"], "pull_count": "2.2M", "tag_count": 4, "updated": "1 year ago"} +{"title": "llava-phi3", "url": "https://ollama.com/library/llava-phi3", "description": "A new small LLaVA model fine-tuned from Phi 3 Mini.", "tags": ["llava-phi3", "vision", "3.8b"], "pull_count": "212.2K", "tag_count": 4, "updated": "1 year ago"} +{"title": "magicoder", "url": "https://ollama.com/library/magicoder", "description": "🎩 Magicoder is a family of 7B parameter models trained on 75K synthetic instruction data using OSS-Instruct, a novel approach to enlightening LLMs with open-source code snippets.", "tags": ["magicoder", "7b"], "pull_count": "265.8K", "tag_count": 18, "updated": "2 years ago"} +{"title": "magistral", "url": "https://ollama.com/library/magistral", "description": "Magistral is a small, efficient reasoning model with 24B parameters.", "tags": ["magistral", "tools", "thinking", "24b"], "pull_count": "1.2M", "tag_count": 5, "updated": "8 months ago"} +{"title": "marco-o1", "url": "https://ollama.com/library/marco-o1", "description": "An open large reasoning model for real-world solutions by the Alibaba International Digital Commerce Group (AIDC-AI).", "tags": ["marco-o1", "7b"], "pull_count": "132.3K", "tag_count": 5, "updated": "1 year ago"} +{"title": "mathstral", "url": "https://ollama.com/library/mathstral", "description": "MathΣtral: a 7B model designed for math reasoning and scientific discovery by Mistral AI.", "tags": ["mathstral", "7b"], "pull_count": "269.6K", "tag_count": 17, "updated": "1 year ago"} +{"title": "meditron", "url": "https://ollama.com/library/meditron", "description": "Open-source medical large language model adapted from Llama 2 to the medical domain.", "tags": ["meditron", "7b", "70b"], "pull_count": "362K", "tag_count": 22, "updated": "2 years ago"} +{"title": "medllama2", "url": "https://ollama.com/library/medllama2", "description": "Fine-tuned Llama 2 model to answer medical questions based on an open source medical dataset.", "tags": ["medllama2", "7b"], "pull_count": "289.8K", "tag_count": 17, "updated": "2 years ago"} +{"title": "megadolphin", "url": "https://ollama.com/library/megadolphin", "description": "MegaDolphin-2.2-120b is a transformation of Dolphin-2.2-70b created by interleaving the model with itself.", "tags": ["megadolphin", "120b"], "pull_count": "265.2K", "tag_count": 19, "updated": "2 years ago"} +{"title": "minicpm-v", "url": "https://ollama.com/library/minicpm-v", "description": "A series of multimodal LLMs (MLLMs) designed for vision-language understanding.", "tags": ["minicpm-v", "vision", "8b"], "pull_count": "4.6M", "tag_count": 17, "updated": "1 year ago"} +{"title": "minimax-m2", "url": "https://ollama.com/library/minimax-m2", "description": "MiniMax M2 is a high-efficiency large language model built for coding and agentic workflows.", "tags": ["minimax-m2", "cloud"], "pull_count": "78.3K", "tag_count": 1, "updated": "4 months ago"} +{"title": "minimax-m2.1", "url": "https://ollama.com/library/minimax-m2.1", "description": "Exceptional multilingual capabilities to elevate code engineering", "tags": ["minimax-m2.1", "cloud"], "pull_count": "23.8K", "tag_count": 1, "updated": "2 months ago"} +{"title": "minimax-m2.5", "url": "https://ollama.com/library/minimax-m2.5", "description": "MiniMax-M2.5 is a state-of-the-art large language model designed for real-world productivity and coding tasks.", "tags": ["minimax-m2.5", "cloud"], "pull_count": "123.1K", "tag_count": 1, "updated": "4 weeks ago"} +{"title": "ministral-3", "url": "https://ollama.com/library/ministral-3", "description": "The Ministral 3 family is designed for edge deployment, capable of running on a wide range of hardware.", "tags": ["ministral-3", "vision", "tools", "cloud", "3b", "8b", "14b"], "pull_count": "591K", "tag_count": 16, "updated": "3 months ago"} +{"title": "mistral", "url": "https://ollama.com/library/mistral", "description": "The 7B model released by Mistral AI, updated to version 0.3.", "tags": ["mistral", "tools", "7b"], "pull_count": "26.3M", "tag_count": 84, "updated": "8 months ago"} +{"title": "mistral-large", "url": "https://ollama.com/library/mistral-large", "description": "Mistral Large 2 is Mistral's new flagship model that is significantly more capable in code generation, mathematics, and reasoning with 128k context window and support for dozens of languages.", "tags": ["mistral-large", "tools", "123b"], "pull_count": "640.6K", "tag_count": 32, "updated": "1 year ago"} +{"title": "mistral-large-3", "url": "https://ollama.com/library/mistral-large-3", "description": "A general-purpose multimodal mixture-of-experts model for production-grade tasks and enterprise workloads.", "tags": ["mistral-large-3", "cloud"], "pull_count": "24.7K", "tag_count": 1, "updated": "3 months ago"} +{"title": "mistral-nemo", "url": "https://ollama.com/library/mistral-nemo", "description": "A state-of-the-art 12B model with 128k context length, built by Mistral AI in collaboration with NVIDIA.", "tags": ["mistral-nemo", "tools", "12b"], "pull_count": "3.5M", "tag_count": 17, "updated": "7 months ago"} +{"title": "mistral-openorca", "url": "https://ollama.com/library/mistral-openorca", "description": "Mistral OpenOrca is a 7 billion parameter model, fine-tuned on top of the Mistral 7B model using the OpenOrca dataset.", "tags": ["mistral-openorca", "7b"], "pull_count": "399.3K", "tag_count": 17, "updated": "2 years ago"} +{"title": "mistral-small", "url": "https://ollama.com/library/mistral-small", "description": "Mistral Small 3 sets a new benchmark in the “small” Large Language Models category below 70B.", "tags": ["mistral-small", "tools", "22b", "24b"], "pull_count": "2.5M", "tag_count": 21, "updated": "1 year ago"} +{"title": "mistral-small3.1", "url": "https://ollama.com/library/mistral-small3.1", "description": "Building upon Mistral Small 3, Mistral Small 3.1 (2503) adds state-of-the-art vision understanding and enhances long context capabilities up to 128k tokens without compromising text performance.", "tags": ["mistral-small3.1", "vision", "tools", "24b"], "pull_count": "632.3K", "tag_count": 5, "updated": "11 months ago"} +{"title": "mistral-small3.2", "url": "https://ollama.com/library/mistral-small3.2", "description": "An update to Mistral Small that improves on function calling, instruction following, and less repetition errors.", "tags": ["mistral-small3.2", "vision", "tools", "24b"], "pull_count": "1.4M", "tag_count": 5, "updated": "8 months ago"} +{"title": "mistrallite", "url": "https://ollama.com/library/mistrallite", "description": "MistralLite is a fine-tuned model based on Mistral with enhanced capabilities of processing long contexts.", "tags": ["mistrallite", "7b"], "pull_count": "254.4K", "tag_count": 17, "updated": "2 years ago"} +{"title": "mixtral", "url": "https://ollama.com/library/mixtral", "description": "A set of Mixture of Experts (MoE) model with open weights by Mistral AI in 8x7b and 8x22b parameter sizes.", "tags": ["mixtral", "tools", "8x7b", "8x22b"], "pull_count": "2M", "tag_count": 70, "updated": "1 year ago"} +{"title": "moondream", "url": "https://ollama.com/library/moondream", "description": "moondream2 is a small vision language model designed to run efficiently on edge devices.", "tags": ["moondream", "vision", "1.8b"], "pull_count": "712.8K", "tag_count": 18, "updated": "1 year ago"} +{"title": "mxbai-embed-large", "url": "https://ollama.com/library/mxbai-embed-large", "description": "State-of-the-art large embedding model from mixedbread.ai", "tags": ["mxbai-embed-large", "embedding", "335m"], "pull_count": "8.2M", "tag_count": 4, "updated": "1 year ago"} +{"title": "nemotron", "url": "https://ollama.com/library/nemotron", "description": "Llama-3.1-Nemotron-70B-Instruct is a large language model customized by NVIDIA to improve the helpfulness of LLM generated responses to user queries.", "tags": ["nemotron", "tools", "70b"], "pull_count": "315.1K", "tag_count": 17, "updated": "1 year ago"} +{"title": "nemotron-3-nano", "url": "https://ollama.com/library/nemotron-3-nano", "description": "Nemotron 3 Nano - A new Standard for Efficient, Open, and Intelligent Agentic Models", "tags": ["nemotron-3-nano", "tools", "thinking", "cloud", "30b"], "pull_count": "210.9K", "tag_count": 6, "updated": "2 months ago"} +{"title": "nemotron-3-super", "url": "https://ollama.com/library/nemotron-3-super", "description": "NVIDIA Nemotron 3 Super is a 120B open MoE model activating just 12B parameters to deliver maximum compute efficiency and accuracy for complex multi-agent applications.", "tags": ["nemotron-3-super", "tools", "thinking", "cloud", "120b"], "pull_count": "21.9K", "tag_count": 7, "updated": "2 days ago"} +{"title": "nemotron-mini", "url": "https://ollama.com/library/nemotron-mini", "description": "A commercial-friendly small language model by NVIDIA optimized for roleplay, RAG QA, and function calling.", "tags": ["nemotron-mini", "tools", "4b"], "pull_count": "327.8K", "tag_count": 17, "updated": "1 year ago"} +{"title": "neural-chat", "url": "https://ollama.com/library/neural-chat", "description": "A fine-tuned model based on Mistral with good coverage of domain and language.", "tags": ["neural-chat", "7b"], "pull_count": "513.1K", "tag_count": 50, "updated": "2 years ago"} +{"title": "nexusraven", "url": "https://ollama.com/library/nexusraven", "description": "Nexus Raven is a 13B instruction tuned model for function calling tasks.", "tags": ["nexusraven", "13b"], "pull_count": "403.1K", "tag_count": 32, "updated": "2 years ago"} +{"title": "nomic-embed-text", "url": "https://ollama.com/library/nomic-embed-text", "description": "A high-performing open embedding model with a large token context window.", "tags": ["nomic-embed-text", "embedding"], "pull_count": "57.4M", "tag_count": 3, "updated": "2 years ago"} +{"title": "nomic-embed-text-v2-moe", "url": "https://ollama.com/library/nomic-embed-text-v2-moe", "description": "nomic-embed-text-v2-moe is a multilingual MoE text embedding model that excels at multilingual retrieval.", "tags": ["nomic-embed-text-v2-moe", "embedding"], "pull_count": "100.5K", "tag_count": 1, "updated": "3 months ago"} +{"title": "notus", "url": "https://ollama.com/library/notus", "description": "A 7B chat model fine-tuned with high-quality data and based on Zephyr.", "tags": ["notus", "7b"], "pull_count": "253K", "tag_count": 18, "updated": "2 years ago"} +{"title": "notux", "url": "https://ollama.com/library/notux", "description": "A top-performing mixture of experts model, fine-tuned with high-quality data.", "tags": ["notux", "8x7b"], "pull_count": "253.3K", "tag_count": 18, "updated": "2 years ago"} +{"title": "nous-hermes", "url": "https://ollama.com/library/nous-hermes", "description": "General use models based on Llama and Llama 2 from Nous Research.", "tags": ["nous-hermes", "7b", "13b"], "pull_count": "578.3K", "tag_count": 63, "updated": "2 years ago"} +{"title": "nous-hermes2", "url": "https://ollama.com/library/nous-hermes2", "description": "The powerful family of models by Nous Research that excels at scientific discussion and coding tasks.", "tags": ["nous-hermes2", "10.7b", "34b"], "pull_count": "507.9K", "tag_count": 33, "updated": "2 years ago"} +{"title": "nous-hermes2-mixtral", "url": "https://ollama.com/library/nous-hermes2-mixtral", "description": "The Nous Hermes 2 model from Nous Research, now trained over Mixtral.", "tags": ["nous-hermes2-mixtral", "8x7b"], "pull_count": "298.2K", "tag_count": 18, "updated": "1 year ago"} +{"title": "nuextract", "url": "https://ollama.com/library/nuextract", "description": "A 3.8B model fine-tuned on a private high-quality synthetic dataset for information extraction, based on Phi-3.", "tags": ["nuextract", "3.8b"], "pull_count": "257K", "tag_count": 17, "updated": "1 year ago"} +{"title": "olmo-3", "url": "https://ollama.com/library/olmo-3", "description": "Olmo is a series of Open language models designed to enable the science of language models. These models are pre-trained on the Dolma 3 dataset and post-trained on the Dolci datasets.", "tags": ["olmo-3", "7b", "32b"], "pull_count": "204.8K", "tag_count": 15, "updated": "2 months ago"} +{"title": "olmo-3.1", "url": "https://ollama.com/library/olmo-3.1", "description": "Olmo is a series of Open language models designed to enable the science of language models. These models are pre-trained on the Dolma 3 dataset and post-trained on the Dolci datasets.", "tags": ["olmo-3.1", "tools", "32b"], "pull_count": "125.8K", "tag_count": 10, "updated": "2 months ago"} +{"title": "olmo2", "url": "https://ollama.com/library/olmo2", "description": "OLMo 2 is a new family of 7B and 13B models trained on up to 5T tokens. These models are on par with or better than equivalently sized fully open models, and competitive with open-weight models such as Llama 3.1 on English academic benchmarks.", "tags": ["olmo2", "7b", "13b"], "pull_count": "3.5M", "tag_count": 9, "updated": "1 year ago"} +{"title": "open-orca-platypus2", "url": "https://ollama.com/library/open-orca-platypus2", "description": "Merge of the Open Orca OpenChat model and the Garage-bAInd Platypus 2 model. Designed for chat and code generation.", "tags": ["open-orca-platypus2", "13b"], "pull_count": "242.8K", "tag_count": 17, "updated": "2 years ago"} +{"title": "openchat", "url": "https://ollama.com/library/openchat", "description": "A family of open-source models trained on a wide variety of data, surpassing ChatGPT on various benchmarks. Updated to version 3.5-0106.", "tags": ["openchat", "7b"], "pull_count": "568.2K", "tag_count": 50, "updated": "2 years ago"} +{"title": "opencoder", "url": "https://ollama.com/library/opencoder", "description": "OpenCoder is an open and reproducible code LLM family which includes 1.5B and 8B models, supporting chat in English and Chinese languages.", "tags": ["opencoder", "1.5b", "8b"], "pull_count": "450.5K", "tag_count": 9, "updated": "1 year ago"} +{"title": "openhermes", "url": "https://ollama.com/library/openhermes", "description": "OpenHermes 2.5 is a 7B model fine-tuned by Teknium on Mistral with fully open datasets.", "tags": ["openhermes"], "pull_count": "543.7K", "tag_count": 35, "updated": "2 years ago"} +{"title": "openthinker", "url": "https://ollama.com/library/openthinker", "description": "A fully open-source family of reasoning models built using a dataset derived by distilling DeepSeek-R1.", "tags": ["openthinker", "7b", "32b"], "pull_count": "846.6K", "tag_count": 15, "updated": "11 months ago"} +{"title": "orca-mini", "url": "https://ollama.com/library/orca-mini", "description": "A general-purpose model ranging from 3 billion parameters to 70 billion, suitable for entry-level hardware.", "tags": ["orca-mini", "3b", "7b", "13b", "70b"], "pull_count": "2.1M", "tag_count": 119, "updated": "2 years ago"} +{"title": "orca2", "url": "https://ollama.com/library/orca2", "description": "Orca 2 is built by Microsoft research, and are a fine-tuned version of Meta's Llama 2 models. The model is designed to excel particularly in reasoning.", "tags": ["orca2", "7b", "13b"], "pull_count": "429.7K", "tag_count": 33, "updated": "2 years ago"} +{"title": "paraphrase-multilingual", "url": "https://ollama.com/library/paraphrase-multilingual", "description": "Sentence-transformers model that can be used for tasks like clustering or semantic search.", "tags": ["paraphrase-multilingual", "embedding", "278m"], "pull_count": "593K", "tag_count": 3, "updated": "1 year ago"} +{"title": "phi", "url": "https://ollama.com/library/phi", "description": "Phi-2: a 2.7B language model by Microsoft Research that demonstrates outstanding reasoning and language understanding capabilities.", "tags": ["phi", "2.7b"], "pull_count": "1.1M", "tag_count": 18, "updated": "2 years ago"} +{"title": "phi3", "url": "https://ollama.com/library/phi3", "description": "Phi-3 is a family of lightweight 3B (Mini) and 14B (Medium) state-of-the-art open models by Microsoft.", "tags": ["phi3", "3.8b", "14b"], "pull_count": "16.2M", "tag_count": 72, "updated": "1 year ago"} +{"title": "phi3.5", "url": "https://ollama.com/library/phi3.5", "description": "A lightweight AI model with 3.8 billion parameters with performance overtaking similarly and larger sized models.", "tags": ["phi3.5", "3.8b"], "pull_count": "610.7K", "tag_count": 17, "updated": "1 year ago"} +{"title": "phi4", "url": "https://ollama.com/library/phi4", "description": "Phi-4 is a 14B parameter, state-of-the-art open model from Microsoft.", "tags": ["phi4", "14b"], "pull_count": "7.3M", "tag_count": 5, "updated": "1 year ago"} +{"title": "phi4-mini", "url": "https://ollama.com/library/phi4-mini", "description": "Phi-4-mini brings significant enhancements in multilingual support, reasoning, and mathematics, and now, the long-awaited function calling feature is finally supported.", "tags": ["phi4-mini", "tools", "3.8b"], "pull_count": "943.3K", "tag_count": 5, "updated": "1 year ago"} +{"title": "phi4-mini-reasoning", "url": "https://ollama.com/library/phi4-mini-reasoning", "description": "Phi 4 mini reasoning is a lightweight open model that balances efficiency with advanced reasoning ability.", "tags": ["phi4-mini-reasoning", "3.8b"], "pull_count": "172.4K", "tag_count": 5, "updated": "10 months ago"} +{"title": "phi4-reasoning", "url": "https://ollama.com/library/phi4-reasoning", "description": "Phi 4 reasoning and reasoning plus are 14-billion parameter open-weight reasoning models that rival much larger models on complex reasoning tasks.", "tags": ["phi4-reasoning", "14b"], "pull_count": "1.3M", "tag_count": 9, "updated": "10 months ago"} +{"title": "phind-codellama", "url": "https://ollama.com/library/phind-codellama", "description": "Code generation model based on Code Llama.", "tags": ["phind-codellama", "34b"], "pull_count": "452.6K", "tag_count": 49, "updated": "2 years ago"} +{"title": "qwen", "url": "https://ollama.com/library/qwen", "description": "Qwen 1.5 is a series of large language models by Alibaba Cloud spanning from 0.5B to 110B parameters", "tags": ["qwen", "0.5b", "1.8b", "4b", "7b", "14b", "32b", "72b", "110b"], "pull_count": "5.7M", "tag_count": 379, "updated": "1 year ago"} +{"title": "qwen2", "url": "https://ollama.com/library/qwen2", "description": "Qwen2 is a new series of large language models from Alibaba group", "tags": ["qwen2", "tools", "0.5b", "1.5b", "7b", "72b"], "pull_count": "5M", "tag_count": 97, "updated": "1 year ago"} +{"title": "qwen2-math", "url": "https://ollama.com/library/qwen2-math", "description": "Qwen2 Math is a series of specialized math language models built upon the Qwen2 LLMs, which significantly outperforms the mathematical capabilities of open-source models and even closed-source models (e.g., GPT4o).", "tags": ["qwen2-math", "1.5b", "7b", "72b"], "pull_count": "531.2K", "tag_count": 52, "updated": "1 year ago"} +{"title": "qwen2.5", "url": "https://ollama.com/library/qwen2.5", "description": "Qwen2.5 models are pretrained on Alibaba's latest large-scale dataset, encompassing up to 18 trillion tokens. The model supports up to 128K tokens and has multilingual support.", "tags": ["qwen2.5", "tools", "0.5b", "1.5b", "3b", "7b", "14b", "32b", "72b"], "pull_count": "23.8M", "tag_count": 133, "updated": "1 year ago"} +{"title": "qwen2.5-coder", "url": "https://ollama.com/library/qwen2.5-coder", "description": "The latest series of Code-Specific Qwen models, with significant improvements in code generation, code reasoning, and code fixing.", "tags": ["qwen2.5-coder", "tools", "0.5b", "1.5b", "3b", "7b", "14b", "32b"], "pull_count": "11.9M", "tag_count": 199, "updated": "9 months ago"} +{"title": "qwen2.5vl", "url": "https://ollama.com/library/qwen2.5vl", "description": "Flagship vision-language model of Qwen and also a significant leap from the previous Qwen2-VL.", "tags": ["qwen2.5vl", "vision", "3b", "7b", "32b", "72b"], "pull_count": "1.4M", "tag_count": 17, "updated": "9 months ago"} +{"title": "qwen3", "url": "https://ollama.com/library/qwen3", "description": "Qwen3 is the latest generation of large language models in Qwen series, offering a comprehensive suite of dense and mixture-of-experts (MoE) models.", "tags": ["qwen3", "tools", "thinking", "0.6b", "1.7b", "4b", "8b", "14b", "30b", "32b", "235b"], "pull_count": "23.6M", "tag_count": 58, "updated": "5 months ago"} +{"title": "qwen3-coder", "url": "https://ollama.com/library/qwen3-coder", "description": "Alibaba's performant long context models for agentic and coding tasks.", "tags": ["qwen3-coder", "tools", "cloud", "30b", "480b"], "pull_count": "3.5M", "tag_count": 10, "updated": "5 months ago"} +{"title": "qwen3-coder-next", "url": "https://ollama.com/library/qwen3-coder-next", "description": "Qwen3-Coder-Next is a coding-focused language model from Alibaba's Qwen team, optimized for agentic coding workflows and local development.", "tags": ["qwen3-coder-next", "tools", "cloud"], "pull_count": "770.3K", "tag_count": 4, "updated": "1 month ago"} +{"title": "qwen3-embedding", "url": "https://ollama.com/library/qwen3-embedding", "description": "Building upon the foundational models of the Qwen3 series, Qwen3 Embedding provides a comprehensive range of text embeddings models in various sizes", "tags": ["qwen3-embedding", "embedding", "0.6b", "4b", "8b"], "pull_count": "1.2M", "tag_count": 12, "updated": "5 months ago"} +{"title": "qwen3-next", "url": "https://ollama.com/library/qwen3-next", "description": "The first installment in the Qwen3-Next series with strong performance in terms of both parameter efficiency and inference speed.", "tags": ["qwen3-next", "tools", "thinking", "cloud", "80b"], "pull_count": "376.1K", "tag_count": 10, "updated": "3 months ago"} +{"title": "qwen3-vl", "url": "https://ollama.com/library/qwen3-vl", "description": "The most powerful vision-language model in the Qwen model family to date.", "tags": ["qwen3-vl", "vision", "tools", "thinking", "cloud", "2b", "4b", "8b", "30b", "32b", "235b"], "pull_count": "2M", "tag_count": 59, "updated": "4 months ago"} +{"title": "qwen3.5", "url": "https://ollama.com/library/qwen3.5", "description": "Qwen 3.5 is a family of open-source multimodal models that delivers exceptional utility and performance.", "tags": ["qwen3.5", "vision", "tools", "thinking", "cloud", "0.8b", "2b", "4b", "9b", "27b", "35b", "122b"], "pull_count": "1.6M", "tag_count": 30, "updated": "1 week ago"} +{"title": "qwq", "url": "https://ollama.com/library/qwq", "description": "QwQ is the reasoning model of the Qwen series.", "tags": ["qwq", "tools", "32b"], "pull_count": "2.1M", "tag_count": 8, "updated": "12 months ago"} +{"title": "r1-1776", "url": "https://ollama.com/library/r1-1776", "description": "A version of the DeepSeek-R1 model that has been post trained to provide unbiased, accurate, and factual information by Perplexity.", "tags": ["r1-1776", "70b", "671b"], "pull_count": "272.6K", "tag_count": 9, "updated": "1 year ago"} +{"title": "reader-lm", "url": "https://ollama.com/library/reader-lm", "description": "A series of models that convert HTML content to Markdown content, which is useful for content conversion tasks.", "tags": ["reader-lm", "0.5b", "1.5b"], "pull_count": "417.7K", "tag_count": 33, "updated": "1 year ago"} +{"title": "reflection", "url": "https://ollama.com/library/reflection", "description": "A high-performing model trained with a new technique called Reflection-tuning that teaches a LLM to detect mistakes in its reasoning and correct course.", "tags": ["reflection", "70b"], "pull_count": "333.2K", "tag_count": 17, "updated": "1 year ago"} +{"title": "rnj-1", "url": "https://ollama.com/library/rnj-1", "description": "Rnj-1 is a family of 8B parameter open-weight, dense models trained from scratch by Essential AI, optimized for code and STEM with capabilities on par with SOTA open-weight models.", "tags": ["rnj-1", "tools", "cloud", "8b"], "pull_count": "355.2K", "tag_count": 6, "updated": "3 months ago"} +{"title": "sailor2", "url": "https://ollama.com/library/sailor2", "description": "Sailor2 are multilingual language models made for South-East Asia. Available in 1B, 8B, and 20B parameter sizes.", "tags": ["sailor2", "1b", "8b", "20b"], "pull_count": "201.6K", "tag_count": 13, "updated": "1 year ago"} +{"title": "samantha-mistral", "url": "https://ollama.com/library/samantha-mistral", "description": "A companion assistant trained in philosophy, psychology, and personal relationships. Based on Mistral.", "tags": ["samantha-mistral", "7b"], "pull_count": "467.4K", "tag_count": 49, "updated": "2 years ago"} +{"title": "shieldgemma", "url": "https://ollama.com/library/shieldgemma", "description": "ShieldGemma is set of instruction tuned models for evaluating the safety of text prompt input and text output responses against a set of defined safety policies.", "tags": ["shieldgemma", "2b", "9b", "27b"], "pull_count": "413.9K", "tag_count": 49, "updated": "1 year ago"} +{"title": "smallthinker", "url": "https://ollama.com/library/smallthinker", "description": "A new small reasoning model fine-tuned from the Qwen 2.5 3B Instruct model.", "tags": ["smallthinker", "3b"], "pull_count": "169.7K", "tag_count": 5, "updated": "1 year ago"} +{"title": "smollm", "url": "https://ollama.com/library/smollm", "description": "🪐 A family of small models with 135M, 360M, and 1.7B parameters, trained on a new high-quality dataset.", "tags": ["smollm", "135m", "360m", "1.7b"], "pull_count": "1.1M", "tag_count": 94, "updated": "1 year ago"} +{"title": "smollm2", "url": "https://ollama.com/library/smollm2", "description": "SmolLM2 is a family of compact language models available in three size: 135M, 360M, and 1.7B parameters.", "tags": ["smollm2", "tools", "135m", "360m", "1.7b"], "pull_count": "2.7M", "tag_count": 49, "updated": "1 year ago"} +{"title": "snowflake-arctic-embed", "url": "https://ollama.com/library/snowflake-arctic-embed", "description": "A suite of text embedding models by Snowflake, optimized for performance.", "tags": ["snowflake-arctic-embed", "embedding", "22m", "33m", "110m", "137m", "335m"], "pull_count": "2.3M", "tag_count": 16, "updated": "1 year ago"} +{"title": "snowflake-arctic-embed2", "url": "https://ollama.com/library/snowflake-arctic-embed2", "description": "Snowflake's frontier embedding model. Arctic Embed 2.0 adds multilingual support without sacrificing English performance or scalability.", "tags": ["snowflake-arctic-embed2", "embedding", "568m"], "pull_count": "279.5K", "tag_count": 3, "updated": "1 year ago"} +{"title": "solar", "url": "https://ollama.com/library/solar", "description": "A compact, yet powerful 10.7B large language model designed for single-turn conversation.", "tags": ["solar", "10.7b"], "pull_count": "452.7K", "tag_count": 32, "updated": "2 years ago"} +{"title": "solar-pro", "url": "https://ollama.com/library/solar-pro", "description": "Solar Pro Preview: an advanced large language model (LLM) with 22 billion parameters designed to fit into a single GPU", "tags": ["solar-pro", "22b"], "pull_count": "269.4K", "tag_count": 18, "updated": "1 year ago"} +{"title": "sqlcoder", "url": "https://ollama.com/library/sqlcoder", "description": "SQLCoder is a code completion model fined-tuned on StarCoder for SQL generation tasks", "tags": ["sqlcoder", "7b", "15b"], "pull_count": "501.9K", "tag_count": 48, "updated": "2 years ago"} +{"title": "stable-beluga", "url": "https://ollama.com/library/stable-beluga", "description": "Llama 2 based model fine tuned on an Orca-style dataset. Originally called Free Willy.", "tags": ["stable-beluga", "7b", "13b", "70b"], "pull_count": "422.6K", "tag_count": 49, "updated": "2 years ago"} +{"title": "stable-code", "url": "https://ollama.com/library/stable-code", "description": "Stable Code 3B is a coding model with instruct and code completion variants on par with models such as Code Llama 7B that are 2.5x larger.", "tags": ["stable-code", "3b"], "pull_count": "513.2K", "tag_count": 36, "updated": "1 year ago"} +{"title": "stablelm-zephyr", "url": "https://ollama.com/library/stablelm-zephyr", "description": "A lightweight chat model allowing accurate, and responsive output without requiring high-end hardware.", "tags": ["stablelm-zephyr", "3b"], "pull_count": "260.8K", "tag_count": 17, "updated": "2 years ago"} +{"title": "stablelm2", "url": "https://ollama.com/library/stablelm2", "description": "Stable LM 2 is a state-of-the-art 1.6B and 12B parameter language model trained on multilingual data in English, Spanish, German, Italian, French, Portuguese, and Dutch.", "tags": ["stablelm2", "1.6b", "12b"], "pull_count": "487.5K", "tag_count": 84, "updated": "1 year ago"} +{"title": "starcoder", "url": "https://ollama.com/library/starcoder", "description": "StarCoder is a code generation model trained on 80+ programming languages.", "tags": ["starcoder", "1b", "3b", "7b", "15b"], "pull_count": "586.2K", "tag_count": 100, "updated": "2 years ago"} +{"title": "starcoder2", "url": "https://ollama.com/library/starcoder2", "description": "StarCoder2 is the next generation of transparently trained open code LLMs that comes in three sizes: 3B, 7B and 15B parameters.", "tags": ["starcoder2", "3b", "7b", "15b"], "pull_count": "2.2M", "tag_count": 67, "updated": "1 year ago"} +{"title": "starling-lm", "url": "https://ollama.com/library/starling-lm", "description": "Starling is a large language model trained by reinforcement learning from AI feedback focused on improving chatbot helpfulness.", "tags": ["starling-lm", "7b"], "pull_count": "454.7K", "tag_count": 36, "updated": "1 year ago"} +{"title": "tinydolphin", "url": "https://ollama.com/library/tinydolphin", "description": "An experimental 1.1B parameter model trained on the new Dolphin 2.8 dataset by Eric Hartford and based on TinyLlama.", "tags": ["tinydolphin", "1.1b"], "pull_count": "404.1K", "tag_count": 18, "updated": "2 years ago"} +{"title": "tinyllama", "url": "https://ollama.com/library/tinyllama", "description": "The TinyLlama project is an open endeavor to train a compact 1.1B Llama model on 3 trillion tokens.", "tags": ["tinyllama", "1.1b"], "pull_count": "3.9M", "tag_count": 36, "updated": "2 years ago"} +{"title": "translategemma", "url": "https://ollama.com/library/translategemma", "description": "A new collection of open translation models built on Gemma 3, helping people communicate across 55 languages.", "tags": ["translategemma", "vision", "4b", "12b", "27b"], "pull_count": "593.2K", "tag_count": 13, "updated": "1 month ago"} +{"title": "tulu3", "url": "https://ollama.com/library/tulu3", "description": "Tülu 3 is a leading instruction following model family, offering fully open-source data, code, and recipes by the The Allen Institute for AI.", "tags": ["tulu3", "8b", "70b"], "pull_count": "233.2K", "tag_count": 9, "updated": "1 year ago"} +{"title": "vicuna", "url": "https://ollama.com/library/vicuna", "description": "General use chat model based on Llama and Llama 2 with 2K to 16K context sizes.", "tags": ["vicuna", "7b", "13b", "33b"], "pull_count": "563.2K", "tag_count": 111, "updated": "2 years ago"} +{"title": "wizard-math", "url": "https://ollama.com/library/wizard-math", "description": "Model focused on math and logic problems", "tags": ["wizard-math", "7b", "13b", "70b"], "pull_count": "472K", "tag_count": 64, "updated": "2 years ago"} +{"title": "wizard-vicuna", "url": "https://ollama.com/library/wizard-vicuna", "description": "Wizard Vicuna is a 13B parameter model based on Llama 2 trained by MelodysDreamj.", "tags": ["wizard-vicuna", "13b"], "pull_count": "249.6K", "tag_count": 17, "updated": "2 years ago"} +{"title": "wizard-vicuna-uncensored", "url": "https://ollama.com/library/wizard-vicuna-uncensored", "description": "Wizard Vicuna Uncensored is a 7B, 13B, and 30B parameter model based on Llama 2 uncensored by Eric Hartford.", "tags": ["wizard-vicuna-uncensored", "7b", "13b", "30b"], "pull_count": "633.2K", "tag_count": 49, "updated": "2 years ago"} +{"title": "wizardcoder", "url": "https://ollama.com/library/wizardcoder", "description": "State-of-the-art code generation model", "tags": ["wizardcoder", "33b"], "pull_count": "500.5K", "tag_count": 67, "updated": "2 years ago"} +{"title": "wizardlm", "url": "https://ollama.com/library/wizardlm", "description": "General use model based on Llama 2.", "tags": ["wizardlm"], "pull_count": "395.4K", "tag_count": 73, "updated": "2 years ago"} +{"title": "wizardlm-uncensored", "url": "https://ollama.com/library/wizardlm-uncensored", "description": "Uncensored version of Wizard LM model", "tags": ["wizardlm-uncensored", "13b"], "pull_count": "317.8K", "tag_count": 18, "updated": "2 years ago"} +{"title": "wizardlm2", "url": "https://ollama.com/library/wizardlm2", "description": "State of the art large language model from Microsoft AI with improved performance on complex chat, multilingual, reasoning and agent use cases.", "tags": ["wizardlm2", "7b", "8x22b"], "pull_count": "727.7K", "tag_count": 22, "updated": "1 year ago"} +{"title": "xwinlm", "url": "https://ollama.com/library/xwinlm", "description": "Conversational model based on Llama 2 that performs competitively on various benchmarks.", "tags": ["xwinlm", "7b", "13b"], "pull_count": "449.2K", "tag_count": 80, "updated": "2 years ago"} +{"title": "yarn-llama2", "url": "https://ollama.com/library/yarn-llama2", "description": "An extension of Llama 2 that supports a context of up to 128k tokens.", "tags": ["yarn-llama2", "7b", "13b"], "pull_count": "442.5K", "tag_count": 67, "updated": "2 years ago"} +{"title": "yarn-mistral", "url": "https://ollama.com/library/yarn-mistral", "description": "An extension of Mistral to support context windows of 64K or 128K.", "tags": ["yarn-mistral", "7b"], "pull_count": "405.8K", "tag_count": 33, "updated": "2 years ago"} +{"title": "yi", "url": "https://ollama.com/library/yi", "description": "Yi 1.5 is a high-performing, bilingual language model.", "tags": ["yi", "6b", "9b", "34b"], "pull_count": "669K", "tag_count": 174, "updated": "1 year ago"} +{"title": "yi-coder", "url": "https://ollama.com/library/yi-coder", "description": "Yi-Coder is a series of open-source code language models that delivers state-of-the-art coding performance with fewer than 10 billion parameters.", "tags": ["yi-coder", "1.5b", "9b"], "pull_count": "494.4K", "tag_count": 67, "updated": "1 year ago"} +{"title": "zephyr", "url": "https://ollama.com/library/zephyr", "description": "Zephyr is a series of fine-tuned versions of the Mistral and Mixtral models that are trained to act as helpful assistants.", "tags": ["zephyr", "7b", "141b"], "pull_count": "648.5K", "tag_count": 40, "updated": "1 year ago"} diff --git a/html_parsing/pravicon_com__s/main.py b/html_parsing/pravicon_com__s/main.py index 2bc7c6e8c..d072679fa 100644 --- a/html_parsing/pravicon_com__s/main.py +++ b/html_parsing/pravicon_com__s/main.py @@ -186,7 +186,7 @@ def get_image_url(tag: Tag) -> str | None: return url_join(a["href"]) -def dump_icon(dir_dump: Path, url: str, title: str = None): +def dump_icon(dir_dump: Path, url: str, title: str = None) -> None: dir_name = url.split("/")[-1] + "__" + secure_filename(title) dir_icon = dir_dump / dir_name dir_icon.mkdir(parents=True, exist_ok=True) diff --git a/html_parsing/random_quote_bash_im/bash_im.py b/html_parsing/random_quote_bash_im/bash_im.py index b6759ab78..47756fd3d 100644 --- a/html_parsing/random_quote_bash_im/bash_im.py +++ b/html_parsing/random_quote_bash_im/bash_im.py @@ -71,7 +71,7 @@ def id(self) -> int: def date_str(self) -> str: return self._date_str - def __post_init__(self): + def __post_init__(self) -> None: self._id = int(self.url.rstrip().split("/")[-1]) self._date_str = self.date.strftime(DATE_FORMAT_QUOTE) @@ -174,7 +174,7 @@ def parse_from(url__id__el: Union[str, int, Tag]) -> Optional["Quote"]: return Quote(url, quote_text, date, rating, comics_urls) - def __str__(self): + def __str__(self) -> str: return ( f"{self.__class__.__name__}(id={self.id}, url={self.url}, " f"text({len(self.text)})={shorten(self.text)!r}, " @@ -259,7 +259,7 @@ def parser_health_check(raise_error=False) -> Optional[str]: Если функция вернет None, значит проблем нет, иначе вернется строка с описанием проблемы. """ - def _test_quote(quote: Quote, expected_id: int): + def _test_quote(quote: Quote, expected_id: int) -> None: assert quote, f"Цитата с #{expected_id} должна существовать!" assert ( quote.id == expected_id diff --git a/html_parsing/ranobehub_org/common.py b/html_parsing/ranobehub_org/common.py index 9812bda95..553d1f4a4 100644 --- a/html_parsing/ranobehub_org/common.py +++ b/html_parsing/ranobehub_org/common.py @@ -9,7 +9,7 @@ class TimeoutHTTPAdapter(HTTPAdapter): - def __init__(self, timeout, *args, **kwargs): + def __init__(self, timeout, *args, **kwargs) -> None: self._timeout = timeout super().__init__(*args, **kwargs) diff --git a/html_parsing/ranobehub_org/download_ranobe_images.py b/html_parsing/ranobehub_org/download_ranobe_images.py index fff021f43..9b8accb04 100644 --- a/html_parsing/ranobehub_org/download_ranobe_images.py +++ b/html_parsing/ranobehub_org/download_ranobe_images.py @@ -23,7 +23,7 @@ def get_valid_filename(s: str) -> str: DIR = Path(__file__).resolve().parent -def parse(start_url: str, download_path: Path = DIR): +def parse(start_url: str, download_path: Path = DIR) -> None: url = start_url while True: diff --git a/html_parsing/ranobehub_org/download_reaction_images.py b/html_parsing/ranobehub_org/download_reaction_images.py index 6ed5bc106..1bd036410 100644 --- a/html_parsing/ranobehub_org/download_reaction_images.py +++ b/html_parsing/ranobehub_org/download_reaction_images.py @@ -17,7 +17,7 @@ DIR_IMAGES.mkdir(exist_ok=True, parents=True) -def download_reaction_images(url: str, dir_path: Path = DIR_IMAGES): +def download_reaction_images(url: str, dir_path: Path = DIR_IMAGES) -> None: for x in get_reactions_raw(url)["reactions"]: img_url = x["reaction"]["image"] diff --git a/html_parsing/ranobehub_org/find_all_evolutions/utils.py b/html_parsing/ranobehub_org/find_all_evolutions/utils.py index da924eae5..76a5b8a93 100644 --- a/html_parsing/ranobehub_org/find_all_evolutions/utils.py +++ b/html_parsing/ranobehub_org/find_all_evolutions/utils.py @@ -58,7 +58,7 @@ def get_full_name(self, sep: str = " >> ") -> str: names.reverse() return sep.join(names) - def print(self): + def print(self) -> None: # Проверка на корневой узел if self.name: print(self.get_full_name()) @@ -77,7 +77,7 @@ def add_child(self, name: str, is_last: bool = False) -> TreeNode: def get_child(self, names: list[str]) -> TreeNode | None: return self.root_node.get_child(names=names) - def print(self): + def print(self) -> None: self.root_node.print() diff --git a/html_parsing/rozetka_com_ua__search/main.py b/html_parsing/rozetka_com_ua__search/main.py index 997ceb31d..b707bf65b 100644 --- a/html_parsing/rozetka_com_ua__search/main.py +++ b/html_parsing/rozetka_com_ua__search/main.py @@ -75,7 +75,7 @@ def save_goods( file_name: str | Path, items: list[tuple[str, str, str]], encoding="utf-8", -): +) -> None: df = pd.DataFrame(items, columns=["Name", "Price", "Nal"]) df.to_csv(file_name, encoding=encoding) diff --git a/html_parsing/stopgame_ru/downloads_video/common.py b/html_parsing/stopgame_ru/downloads_video/common.py index efb7dc57e..30db1804e 100644 --- a/html_parsing/stopgame_ru/downloads_video/common.py +++ b/html_parsing/stopgame_ru/downloads_video/common.py @@ -16,7 +16,7 @@ def secure_filename(text: str) -> str: return re.sub(r"[^\w .]", "", text).strip() -def download(dir_video: Path, url: str): +def download(dir_video: Path, url: str) -> None: session = requests.session() session.headers[ "User-Agent" diff --git a/html_parsing/the_most_profitable_dish__sushivkusno.com/main.py b/html_parsing/the_most_profitable_dish__sushivkusno.com/main.py index e6213cb6d..c0276e092 100644 --- a/html_parsing/the_most_profitable_dish__sushivkusno.com/main.py +++ b/html_parsing/the_most_profitable_dish__sushivkusno.com/main.py @@ -30,7 +30,7 @@ DEBUG_LOG = False -def do_page_down(driver: RemoteWebDriver, footer: WebElement): +def do_page_down(driver: RemoteWebDriver, footer: WebElement) -> None: y_position = 0 while True: @@ -45,7 +45,7 @@ def do_page_down(driver: RemoteWebDriver, footer: WebElement): time.sleep(0.5) -def print_the_most_profitable_dish(url: str): +def print_the_most_profitable_dish(url: str) -> None: print(url) options = Options() diff --git a/html_parsing/wikipedia/common.py b/html_parsing/wikipedia/common.py index 48038d652..46606ca97 100644 --- a/html_parsing/wikipedia/common.py +++ b/html_parsing/wikipedia/common.py @@ -6,18 +6,23 @@ import requests - -HTTP_TIMEOUT = 60 +HTTP_TIMEOUT: int = 60 # SOURCE: https://stackoverflow.com/a/47384155/5909792 class TimeoutRequestsSession(requests.Session): def request(self, *args, **kwargs): - kwargs.setdefault('timeout', HTTP_TIMEOUT) + kwargs.setdefault("timeout", HTTP_TIMEOUT) return super().request(*args, **kwargs) session = TimeoutRequestsSession() -session.headers[ - "User-Agent" -] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0" +session.headers.update( + { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0", + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8", + "Accept-Language": "ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3", + "Connection": "keep-alive", + "Upgrade-Insecure-Requests": "1", + } +) diff --git a/html_parsing/www_dns_shop_ru/check_update_price_date__QWebEnginePage_bs4.py b/html_parsing/www_dns_shop_ru/check_update_price_date__QWebEnginePage_bs4.py index 3f01b417c..4b0c8b69e 100644 --- a/html_parsing/www_dns_shop_ru/check_update_price_date__QWebEnginePage_bs4.py +++ b/html_parsing/www_dns_shop_ru/check_update_price_date__QWebEnginePage_bs4.py @@ -20,7 +20,7 @@ from PyQt5.QtWebEngineWidgets import QWebEnginePage -def _callable(html): +def _callable(html) -> None: if "price-list-downloader" not in html: return diff --git a/html_parsing/www_dns_shop_ru/check_update_price_date__requests_bs4.py b/html_parsing/www_dns_shop_ru/check_update_price_date__requests_bs4.py index 72d36a3b5..ce31c8853 100644 --- a/html_parsing/www_dns_shop_ru/check_update_price_date__requests_bs4.py +++ b/html_parsing/www_dns_shop_ru/check_update_price_date__requests_bs4.py @@ -14,7 +14,7 @@ from bs4 import BeautifulSoup -def go(): +def go() -> None: url = "http://www.dns-shop.ru/" rs = requests.get(url) diff --git a/html_parsing/youtube_com/api/search.py b/html_parsing/youtube_com/api/search.py deleted file mode 100644 index 09d9fe58c..000000000 --- a/html_parsing/youtube_com/api/search.py +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -__author__ = "ipetrash" - - -from typing import Generator, Callable, Any -from urllib.parse import urljoin - -from .common import ( - BASE_URL, - Video, - load, - get_generator_raw_video_list_from_data, -) - - -def get_generator_raw_video_list(url: str) -> Generator[dict, None, None]: - rs, data = load(url) - yield from get_generator_raw_video_list_from_data(data, rs) - - -def get_raw_video_list(url: str, maximum_items: int = 1000) -> list[dict]: - items = [] - for i, video in enumerate(get_generator_raw_video_list(url)): - if i >= maximum_items: - break - - items.append(video) - - return items - - -def get_video_list(url: str, *args, **kwargs) -> list[Video]: - return [ - Video.parse_from(video) - for video in get_raw_video_list(url, *args, **kwargs) - if "videoId" in video # NOTE: У плейлистов будет playlistId - ] - - -def search_youtube(text_or_url: str, *args, **kwargs) -> list[Video]: - if text_or_url.startswith("http"): - url = text_or_url - else: - text = text_or_url - url = urljoin(BASE_URL, f"results?search_query={text}") - - return get_video_list(url, *args, **kwargs) - - -def search_youtube_with_filter( - url: str, - sort: bool = False, - filter_func: Callable[[Any], bool] = None, -) -> list[str]: - video_title_list = [video.title for video in search_youtube(url)] - if sort: - video_title_list.sort() - - if callable(filter_func): - video_title_list = list(filter(filter_func, video_title_list)) - - return video_title_list diff --git a/http.server__examples/hello_world.py b/http.server__examples/hello_world.py index 4051c362c..760853fcc 100644 --- a/http.server__examples/hello_world.py +++ b/http.server__examples/hello_world.py @@ -8,13 +8,13 @@ class HttpProcessor(BaseHTTPRequestHandler): - def do_GET(self): + def do_GET(self) -> None: self.send_response(200) self.send_header("content-type", "text/html; charset=utf-8") self.end_headers() self.wfile.write(bytes("Hello!", "utf-8")) - def do_POST(self): + def do_POST(self) -> None: length = int(self.headers["Content-Length"]) post_data = self.rfile.read(length).decode("utf-8") print("post_data:", post_data) diff --git a/http.server__examples/parse_query__run_subprocess_cmd__ipconfig.py b/http.server__examples/parse_query__run_subprocess_cmd__ipconfig.py index d917cf1d8..ed886a280 100644 --- a/http.server__examples/parse_query__run_subprocess_cmd__ipconfig.py +++ b/http.server__examples/parse_query__run_subprocess_cmd__ipconfig.py @@ -11,12 +11,12 @@ class BaseServer(BaseHTTPRequestHandler): - def _set_headers(self): + def _set_headers(self) -> None: self.send_response(200) self.send_header("Content-type", "text/html; charset=utf-8") self.end_headers() - def do_GET(self): + def do_GET(self) -> None: self._set_headers() paths = urlparse(self.path) @@ -29,7 +29,7 @@ def do_GET(self): self.wfile.write(result.encode("utf-8")) -def run(server_class=HTTPServer, handler_class=BaseServer, port=8080): +def run(server_class=HTTPServer, handler_class=BaseServer, port=8080) -> None: print(f"HTTP server running on http://127.0.0.1:{port}") server_address = ("", port) diff --git a/http.server__examples/parse_query_as_json.py b/http.server__examples/parse_query_as_json.py index 49b221e4e..cd43a0815 100644 --- a/http.server__examples/parse_query_as_json.py +++ b/http.server__examples/parse_query_as_json.py @@ -11,12 +11,12 @@ class BaseServer(BaseHTTPRequestHandler): - def _set_headers(self): + def _set_headers(self) -> None: self.send_response(200) self.send_header("Content-type", "text/json; charset=utf-8") self.end_headers() - def do_GET(self): + def do_GET(self) -> None: self._set_headers() paths = urlparse(self.path) @@ -30,7 +30,7 @@ def do_GET(self): ) -def run(server_class=HTTPServer, handler_class=BaseServer, port=8080): +def run(server_class=HTTPServer, handler_class=BaseServer, port=8080) -> None: print(f"HTTP server running on http://127.0.0.1:{port}") server_address = ("", port) diff --git a/http.server__examples/show_your_user_agent.py b/http.server__examples/show_your_user_agent.py index 3db0381a9..97d201046 100644 --- a/http.server__examples/show_your_user_agent.py +++ b/http.server__examples/show_your_user_agent.py @@ -8,7 +8,7 @@ class HttpProcessor(BaseHTTPRequestHandler): - def do_GET(self): + def do_GET(self) -> None: user_agent = self.headers["User-Agent"] print(user_agent) diff --git a/http.server__examples/simple.py b/http.server__examples/simple.py index 3329de7ab..972e3a3d8 100644 --- a/http.server__examples/simple.py +++ b/http.server__examples/simple.py @@ -8,21 +8,21 @@ class BaseServer(BaseHTTPRequestHandler): - def _set_headers(self): + def _set_headers(self) -> None: self.send_response(200) self.send_header("Content-type", "text/html; charset=utf-8") self.end_headers() - def do_GET(self): + def do_GET(self) -> None: self._set_headers() self.wfile.write( "

hello, world!

".encode("utf-8") ) - def do_HEAD(self): + def do_HEAD(self) -> None: self._set_headers() - def do_POST(self): + def do_POST(self) -> None: content_length = int(self.headers["Content-Length"]) post_data = self.rfile.read(content_length) self._set_headers() @@ -32,7 +32,7 @@ def do_POST(self): ) -def run(server_class=HTTPServer, handler_class=BaseServer, port=8080): +def run(server_class=HTTPServer, handler_class=BaseServer, port=8080) -> None: print(f"HTTP server running on http://127.0.0.1:{port}") server_address = ("", port) diff --git a/http.server__examples/simple_http_proxy_server/main.py b/http.server__examples/simple_http_proxy_server/main.py index 06ecb04c3..8841ba159 100644 --- a/http.server__examples/simple_http_proxy_server/main.py +++ b/http.server__examples/simple_http_proxy_server/main.py @@ -9,7 +9,7 @@ class ProxyHandler(SimpleHTTPRequestHandler): - def do_GET(self): + def do_GET(self) -> None: if self.path.startswith("/"): super().do_GET() return @@ -32,7 +32,7 @@ def do_GET(self): self.wfile.write(rs.content) -def http_proxy(host: str, port: int): +def http_proxy(host: str, port: int) -> None: print(f"Server listening at http://{host}:{port}") server_http = HTTPServer((host, port), ProxyHandler) diff --git "a/https_\320\263\320\270\320\261\320\264\320\264_\321\200\321\204__crash_statistics/common.py" "b/https_\320\263\320\270\320\261\320\264\320\264_\321\200\321\204__crash_statistics/common.py" index e21ff7321..39e67bfe1 100644 --- "a/https_\320\263\320\270\320\261\320\264\320\264_\321\200\321\204__crash_statistics/common.py" +++ "b/https_\320\263\320\270\320\261\320\264\320\264_\321\200\321\204__crash_statistics/common.py" @@ -14,6 +14,11 @@ from bs4 import BeautifulSoup import requests +session = requests.session() +session.headers["User-Agent"] = ( + "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:97.0) Gecko/20100101 Firefox/99.0" +) + class CrashStatistics(NamedTuple): date: str @@ -33,7 +38,7 @@ def get_crash_statistics() -> CrashStatistics: :return: Dict """ - rs = requests.get("https://гибдд.рф/") + rs = session.get("https://гибдд.рф/") root = BeautifulSoup(rs.content, "html.parser") table = root.select_one("table.b-crash-stat") @@ -80,11 +85,10 @@ def create_connect(fields_as_dict=False, trace_sql=False) -> sqlite3.Connection: return connect -def init_db(): +def init_db() -> None: # Создание базы и таблицы with create_connect() as connect: - connect.execute( - """ + connect.execute(""" CREATE TABLE IF NOT EXISTS CrashStatistics ( id INTEGER PRIMARY KEY, date TEXT NOT NULL, @@ -96,13 +100,12 @@ def init_db(): CONSTRAINT date_unique UNIQUE (date) ); - """ - ) + """) connect.commit() -def db_create_backup(backup_dir="backup"): +def db_create_backup(backup_dir="backup") -> None: os.makedirs(backup_dir, exist_ok=True) file_name = str(dt.datetime.today().date()) + ".sqlite" @@ -111,7 +114,7 @@ def db_create_backup(backup_dir="backup"): shutil.copy(DB_FILE_NAME, file_name) -def append_crash_statistics_db(crash_statistics: CrashStatistics = None): +def append_crash_statistics_db(crash_statistics: CrashStatistics = None) -> None: db_create_backup() if not crash_statistics: diff --git "a/https_\320\263\320\270\320\261\320\264\320\264_\321\200\321\204_request_main__auto_fill_fields__web_gui/main.py" "b/https_\320\263\320\270\320\261\320\264\320\264_\321\200\321\204_request_main__auto_fill_fields__web_gui/main.py" index b6910fca7..f3278d76b 100644 --- "a/https_\320\263\320\270\320\261\320\264\320\264_\321\200\321\204_request_main__auto_fill_fields__web_gui/main.py" +++ "b/https_\320\263\320\270\320\261\320\264\320\264_\321\200\321\204_request_main__auto_fill_fields__web_gui/main.py" @@ -14,7 +14,7 @@ from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEnginePage -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -69,7 +69,7 @@ def run_js_code(page: QWebEnginePage, code: str) -> object: result_value = {"value": None} - def _on_callback(result: object): + def _on_callback(result: object) -> None: result_value["value"] = result loop.quit() @@ -88,7 +88,7 @@ def javaScriptConsoleMessage( message: str, line_number: int, source_id: str, - ): + ) -> None: print( f"javascript_console_message: {level}, {message}, {line_number}, {source_id}", file=sys.stderr, @@ -120,7 +120,7 @@ def javaScriptConsoleMessage( # page.urlChanged.connect(_on_url_changed) -def _on_load_finished(ok: bool): +def _on_load_finished(ok: bool) -> None: print(page.url().toString()) page.runJavaScript(jquery_text) diff --git a/img_to_base64_html/main.py b/img_to_base64_html/main.py index f8ace4bc6..e123b21d7 100644 --- a/img_to_base64_html/main.py +++ b/img_to_base64_html/main.py @@ -11,7 +11,7 @@ from PIL import Image -def img_to_base64_html(file_name__or__bytes__or__file_object: str | bytes | io.IOBase): +def img_to_base64_html(file_name__or__bytes__or__file_object: str | bytes | io.IOBase) -> str: arg = file_name__or__bytes__or__file_object if isinstance(arg, str): diff --git a/input_email_list.py b/input_email_list.py index 5b35e7dbf..5f365969a 100644 --- a/input_email_list.py +++ b/input_email_list.py @@ -7,7 +7,7 @@ # http://stackoverflow.com/questions/35332611/a-program-which-creates-emails -def fill_list(l, promt): +def fill_list(l, promt) -> None: while True: x = input(promt) if not x: diff --git a/inspect__examples/check_is_empty_function__use__inspect__dis.py b/inspect__examples/check_is_empty_function__use__inspect__dis.py index 3ded44f20..bc9188079 100644 --- a/inspect__examples/check_is_empty_function__use__inspect__dis.py +++ b/inspect__examples/check_is_empty_function__use__inspect__dis.py @@ -8,11 +8,11 @@ from inspect__get_source__function import check_is_empty_function as check_is_empty_function__use_inspect -def foo(): +def foo() -> None: pass -def foo2(): +def foo2() -> int: return 1 diff --git a/inspect__examples/inspect__get_source__function.py b/inspect__examples/inspect__get_source__function.py index 991014847..1f9cbbcba 100644 --- a/inspect__examples/inspect__get_source__function.py +++ b/inspect__examples/inspect__get_source__function.py @@ -14,10 +14,10 @@ def check_is_empty_function(function): if __name__ == "__main__": - def foo(): + def foo() -> None: pass - def foo2(): + def foo2() -> int: return 1 print("Empty:", check_is_empty_function(foo)) diff --git a/inspect__examples/is_function.py b/inspect__examples/is_function.py index 154cde644..ba007dc9c 100644 --- a/inspect__examples/is_function.py +++ b/inspect__examples/is_function.py @@ -8,12 +8,12 @@ -def foo(): +def foo() -> int: return 1 class Foo: - def __call__(self): + def __call__(self) -> int: return 1 diff --git a/is_correct_brackets.py b/is_correct_brackets.py index bcf189019..77bf8f993 100644 --- a/is_correct_brackets.py +++ b/is_correct_brackets.py @@ -4,7 +4,7 @@ __author__ = "ipetrash" -def is_correct_brackets(text): +def is_correct_brackets(text) -> bool: while "()" in text or "[]" in text or "{}" in text: text = text.replace("()", "") text = text.replace("[]", "") diff --git a/is_even__is_odd.py b/is_even__is_odd.py index bdb7e7d61..2228e8c6c 100644 --- a/is_even__is_odd.py +++ b/is_even__is_odd.py @@ -4,15 +4,15 @@ __author__ = "ipetrash" -def is_even(num): +def is_even(num) -> bool: return num % 2 == 0 -def is_odd(num): +def is_odd(num) -> bool: return not is_even(num) -def is_even_2(num): +def is_even_2(num) -> bool: return num & 1 == 0 diff --git a/is_user_admin.py b/is_user_admin.py index dc41bfa70..d1495c90b 100644 --- a/is_user_admin.py +++ b/is_user_admin.py @@ -26,8 +26,7 @@ def is_user_admin() -> bool: try: # WARNING: Requires Windows XP SP2 or higher! return bool(ctypes.windll.shell32.IsUserAnAdmin()) - - except: + except (AttributeError, OSError): traceback.print_exc() print("Admin check failed, assuming not an admin.") return False diff --git a/jazzcinema_ru/show_schedule_gui/main.py b/jazzcinema_ru/show_schedule_gui/main.py index 0c0692bc3..b49e40b43 100644 --- a/jazzcinema_ru/show_schedule_gui/main.py +++ b/jazzcinema_ru/show_schedule_gui/main.py @@ -21,7 +21,7 @@ from qtpy.QtCore import * -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -37,7 +37,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class Movie: - def __init__(self, border): + def __init__(self, border) -> None: a = border.select_one(".movie .title > a") self.movie_url = urljoin(URL, a["href"]) @@ -90,7 +90,7 @@ def __init__(self, border): class MovieInfoWidget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() # TODO: можно и видео добавить @@ -103,7 +103,7 @@ def __init__(self): self.setLayout(layout) - def set_movie(self, movie): + def set_movie(self, movie) -> None: data = dict() # Скачивание обложки и получени base64 @@ -167,7 +167,7 @@ def set_movie(self, movie): class SchedulerMoviePage(QWidget): - def __init__(self, schedule): + def __init__(self, schedule) -> None: super().__init__() self.schedule_date_str = datetime.strptime( @@ -203,7 +203,7 @@ def __init__(self, schedule): class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("show_schedule_gui.py") @@ -219,7 +219,7 @@ def __init__(self): self.setCentralWidget(widget) - def load(self): + def load(self) -> None: with urlopen(URL) as f: root = BeautifulSoup(f.read(), "lxml") diff --git a/job_compassplus/current_job_report/get_worklog.py b/job_compassplus/current_job_report/get_worklog.py index e1cbf5e25..5a80ddd21 100644 --- a/job_compassplus/current_job_report/get_worklog.py +++ b/job_compassplus/current_job_report/get_worklog.py @@ -46,9 +46,9 @@ def get_worklog() -> Worklog: # Отработано фактически (чч:мм:сс) td_list[1].get_text(strip=True), # Зафиксировано трудозатрат (чч:мм) - td_list[2].get_text(strip=True), + td_list[-2].get_text(strip=True), # Процент зафиксированного времени - td_list[3].get_text(strip=True), + td_list[-1].get_text(strip=True), ) ) diff --git a/job_compassplus/current_job_report/main.py b/job_compassplus/current_job_report/main.py index 6a68814cb..eccf2e245 100644 --- a/job_compassplus/current_job_report/main.py +++ b/job_compassplus/current_job_report/main.py @@ -64,7 +64,7 @@ def draw_text_to_bottom_right( # Для отлова всех исключений, которые в слотах Qt могут "затеряться" и привести к тихому падению -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -85,13 +85,13 @@ class CheckJobReportThread(QThread): about_ok = pyqtSignal(bool) about_log = pyqtSignal(str) - def __init__(self): + def __init__(self) -> None: super().__init__() self.last_text = None self.ok = None - def do_run(self): + def do_run(self) -> None: def _get_title(deviation_hours): ok = deviation_hours[0] != "-" return "Переработка" if ok else "Недоработка" @@ -134,7 +134,7 @@ def _get_title(deviation_hours): self.ok = ok self.about_ok.emit(self.ok) - def run(self): + def run(self) -> None: while True: try: # Между 08:00 и 20:00 @@ -150,7 +150,7 @@ def run(self): class JobReportWidget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.info = QLabel() @@ -212,23 +212,23 @@ def __init__(self): button_refresh.clicked.connect(self.refresh) - def set_text(self, text: str): + def set_text(self, text: str) -> None: print(text) self.info.setText(text) - def refresh(self): + def refresh(self) -> None: # Выполнение метода в отдельном потоке, а не в GUI Thread(target=self.thread.do_run, daemon=True).start() - def _set_ok(self, val: bool): + def _set_ok(self, val: bool) -> None: self.ok = val self.update() - def _add_log(self, val: str): + def _add_log(self, val: str) -> None: print(val) self.log.appendPlainText(val) - def paintEvent(self, event): + def paintEvent(self, event) -> None: super().paintEvent(event) if self.ok is None: @@ -248,7 +248,7 @@ def paintEvent(self, event): tray = QSystemTrayIcon(QIcon(TRAY_ICON)) - def _on_about_log_or_ok(value: str | bool): + def _on_about_log_or_ok(value: str | bool) -> None: if isinstance(value, str): text = "🔄" else: diff --git a/job_compassplus/cyr_lat_audit.py b/job_compassplus/cyr_lat_audit.py new file mode 100644 index 000000000..f85977092 --- /dev/null +++ b/job_compassplus/cyr_lat_audit.py @@ -0,0 +1,172 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +import argparse +import re + +from collections import Counter +from datetime import datetime +from pathlib import Path + + +def check_mixed_layout(text: str) -> list[tuple[str, list[str]]]: + words: list[str] = re.findall(r"\b[a-zA-Zа-яА-ЯёЁ]+\b", text) + corrupted_words: list[tuple[str, list[str]]] = [] + + for word in words: + has_lat: bool = bool(re.search(r"[a-zA-Z]", word)) + has_cyr: bool = bool(re.search(r"[а-яА-ЯёЁ]", word)) + + if has_lat and has_cyr: + cyr_letters: list[str] = re.findall(r"[а-яА-ЯёЁ]", word) + corrupted_words.append((word, cyr_letters)) + + return corrupted_words + + +def process( + path: Path, + extensions: set[str], + ignore_words: set[str], + ignore_files: set[str], + ignore_dirs: set[str], +) -> None: + path = path.resolve() + + if not path.is_dir(): + raise Exception(f"Path {str(path)!r} must be a directory") + + total_files_count: int = 0 + checked_files_count: int = 0 + corrupted_files_count: int = 0 + corrupted_words_count: int = 0 + ignored_words_count: int = 0 + + suffix_total_counter: dict[str, int] = Counter() + suffix_checked_counter: dict[str, int] = Counter() + suffix_corrupted_files_counter: dict[str, int] = Counter() + suffix_corrupted_words_counter: dict[str, int] = Counter() + + start_dt: datetime = datetime.now() + + for f in path.rglob("*.*"): + if not f.is_file() or f.name.lower() in ignore_files: + continue + + has_any: bool = any( + parent_dir.name.lower() in ignore_dirs for parent_dir in f.parents + ) + if has_any: + continue + + total_files_count += 1 + suffix_total_counter[f.suffix] += 1 + + if f.suffix not in extensions: + continue + + try: + checked_files_count += 1 + suffix_checked_counter[f.suffix] += 1 + + text: str = f.read_text("utf-8") + corrupted_words: list[tuple[str, list[str]]] = check_mixed_layout(text) + if corrupted_words: + corrupted_files_count += 1 + suffix_corrupted_files_counter[f.suffix] += 1 + + valid_corrupted_words: list[tuple[str, list[str]]] = [] + for word, cyr_letters in corrupted_words: + if word.lower() in ignore_words: + ignored_words_count += 1 + else: + valid_corrupted_words.append((word, cyr_letters)) + + if valid_corrupted_words: + corrupted_words_count += len(valid_corrupted_words) + suffix_corrupted_words_counter[f.suffix] += len( + valid_corrupted_words + ) + + print(f"File: {str(f)!r}") + for word, cyr_letters in valid_corrupted_words: + print(f" Word: {word!r}, letters: {cyr_letters}") + print() + + except UnicodeError as e: + print(f"{f} skip, error: {e}") + + print(f"Elapsed: {datetime.now() - start_dt}") + print() + + print("=== SUMMARY STATISTICS ===") + print(f"Total files found: {total_files_count}") + print(f"Total checked files: {checked_files_count}") + print(f"Files with mixed layout: {corrupted_files_count}") + print(f"Words with mixed layout: {corrupted_words_count}") + print(f"Ignored words: {ignored_words_count}") + print() + print(f"All extensions in path: {dict(suffix_total_counter)}") + print(f"Checked extensions: {dict(suffix_checked_counter)}") + print(f"Corrupted files by suffix: {dict(suffix_corrupted_files_counter)}") + print(f"Corrupted words by suffix: {dict(suffix_corrupted_words_counter)}") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Cyrillic and Latin alphabet audit", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + parser.add_argument( + "path", + metavar="/PATH/TO/DIRECTORY", + type=Path, + help="Path to directory", + ) + parser.add_argument( + "-e", + "--ext", + nargs="+", + default=[".xml", ".java", ".xsd"], + help="File extensions to check", + ) + parser.add_argument( + "-iw", + "--ignore-words", + nargs="+", + default=[], + help="Words to ignore (case-insensitive)", + ) + parser.add_argument( + "-if", + "--ignore-files", + nargs="+", + default=[], + help="Files to ignore (case-insensitive)", + ) + parser.add_argument( + "-id", + "--ignore-dirs", + nargs="+", + default=["build"], + help="Directories to ignore (case-insensitive)", + ) + args = parser.parse_args() + + target_extensions: set[str] = { + ex if ex.startswith(".") else f".{ex}" for ex in args.ext + } + target_ignore_words: set[str] = {word.lower() for word in args.ignore_words} + target_ignore_files: set[str] = {word.lower() for word in args.ignore_files} + target_ignore_dirs: set[str] = {word.lower() for word in args.ignore_dirs} + + process( + path=args.path, + extensions=target_extensions, + ignore_words=target_ignore_words, + ignore_files=target_ignore_files, + ignore_dirs=target_ignore_dirs, + ) diff --git a/job_compassplus/jira_avatars/get_avatars.py b/job_compassplus/jira_avatars/get_avatars.py new file mode 100644 index 000000000..a714a0cde --- /dev/null +++ b/job_compassplus/jira_avatars/get_avatars.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +import sys + +from dataclasses import dataclass +from pathlib import Path +from typing import Any, Self + +DIR = Path(__file__).resolve().parent +ROOT_DIR = DIR.parent + +sys.path.append(str(ROOT_DIR)) +from root_config import JIRA_HOST +from root_common import session + + +# Examples: +""" +{ + "system": [ + {"id":"10122","isSystemAvatar":true,"isSelected":false,"isDeletable":false,"urls":{"48x48":"https://.../useravatar?avatarId=10122","24x24":"https://.../useravatar?size=small&avatarId=10122","16x16":"https://.../useravatar?size=xsmall&avatarId=10122","32x32":"https://.../useravatar?size=medium&avatarId=10122"},"selected":false}, + ... + {"id":"17241","isSystemAvatar":true,"isSelected":true,"isDeletable":false,"urls":{"48x48":"https://.../useravatar?avatarId=17241","24x24":"https://.../useravatar?size=small&avatarId=17241","16x16":"https://.../useravatar?size=xsmall&avatarId=17241","32x32":"https://.../useravatar?size=medium&avatarId=17241"},"selected":true}, + ... + {"id":"17252","isSystemAvatar":true,"isSelected":false,"isDeletable":false,"urls":{"48x48":"https://.../useravatar?avatarId=17252","24x24":"https://.../useravatar?size=small&avatarId=17252","16x16":"https://.../useravatar?size=xsmall&avatarId=17252","32x32":"https://.../useravatar?size=medium&avatarId=17252"},"selected":false}], + "custom": [] +} +""" + + +@dataclass(frozen=True) +class AvatarUrls: + size_48x48: str + size_32x32: str + size_24x24: str + size_16x16: str + + @classmethod + def from_dict(cls, data: dict[str, str]) -> Self: + return cls( + size_48x48=data.get("48x48"), + size_24x24=data.get("24x24"), + size_32x32=data.get("32x32"), + size_16x16=data.get("16x16"), + ) + + +@dataclass(frozen=True) +class JiraAvatar: + id: str + is_system_avatar: bool + is_selected: bool + is_deletable: bool + urls: AvatarUrls + selected: bool # NOTE: Дублирует isSelected + + @classmethod + def from_dict(cls, data: dict[str, Any]) -> Self: + return cls( + id=data["id"], + is_system_avatar=data["isSystemAvatar"], + is_selected=data["isSelected"], + is_deletable=data["isDeletable"], + urls=AvatarUrls.from_dict(data["urls"]), + selected=data["selected"], + ) + + +@dataclass(frozen=True) +class JiraAvatarResponse: + system: list[JiraAvatar] + custom: list[JiraAvatar] + + @classmethod + def from_dict(cls, data: dict[str, list[dict[str, Any]]]) -> Self: + def _get_avatars(key: str) -> list[JiraAvatar]: + return [JiraAvatar.from_dict(d) for d in data[key]] + + return cls( + system=_get_avatars("system"), + custom=_get_avatars("custom"), + ) + + +def get_avatars(username: str) -> JiraAvatarResponse: + url = f"{JIRA_HOST}/rest/api/latest/user/avatars?username={username}" + + rs = session.get(url) + rs.raise_for_status() + + return JiraAvatarResponse.from_dict(rs.json()) + + +if __name__ == "__main__": + rs: JiraAvatarResponse = get_avatars("ipetrash") + + print(f"System ({len(rs.system)}):") + for i, avatar in enumerate(rs.system, 1): + print(f" {i}. {avatar}") + + print() + + print(f"Custom ({len(rs.custom)}):") + for i, avatar in enumerate(rs.custom, 1): + print(f" {i}. {avatar}") diff --git a/job_compassplus/jira_dump_issues.py b/job_compassplus/jira_dump_issues.py new file mode 100644 index 000000000..13a3008dc --- /dev/null +++ b/job_compassplus/jira_dump_issues.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +import time +import sqlite3 + +from pathlib import Path +from typing import Any + +from root_config import JIRA_HOST +from root_common import session + + +DIR: Path = Path(__file__).resolve().parent +FILE_NAME_DB: Path = DIR / "jira_local.sqlite" + +URL_SEARCH = f"{JIRA_HOST}/rest/api/latest/search" + + +def init_sqlite(filename: Path) -> sqlite3.Connection: + conn = sqlite3.connect(filename) + conn.execute( + """ + CREATE TABLE IF NOT EXISTS Task ( + id INTEGER PRIMARY KEY, + key TEXT, + summary TEXT, + description TEXT, + status TEXT, + issue_type TEXT, + created TEXT, + is_indexed INTEGER DEFAULT 0 + ) + """ + ) + conn.commit() + return conn + + +def get_last_id(conn: sqlite3.Connection, project: str) -> int: + res = conn.execute( + "SELECT MAX(id) FROM Task WHERE key LIKE ?", (f"{project}-%",) + ).fetchone() + return res[0] if res[0] else 0 + + +def sync_jira_to_sqlite(conn: sqlite3.Connection, projects: list[str]): + max_results: int = 100 + + for project in projects: + last_id: int = get_last_id(conn, project) + + while True: + print(f"[*] Поиск задач в Jira проекта {projects} от ID > {last_id}...") + + filter_id: str = f"AND id > {last_id}" if last_id > 0 else "" + jql: str = f"project = {project} {filter_id} ORDER BY id ASC" + + query: dict[str, Any] = { + "jql": jql, + "fields": "key,summary,description,status,issuetype,created", + "maxResults": max_results, + } + + rs = session.get(URL_SEARCH, params=query) + try: + rs.raise_for_status() + except Exception as e: + print(rs.json()) + raise e + + issues: list[dict] = rs.json().get("issues") + if not issues: + print("Больше нет задач") + break + + for issue in issues: + print(issue) + + issue_id: int = int(issue["id"]) + issue_key: str = issue["key"] + issue_summary: str = issue["fields"].get("summary", "") + issue_desc: str = str(issue["fields"].get("description")) + issue_status: str = issue["fields"]["status"]["name"] + issue_type: str = issue["fields"]["issuetype"]["name"] + issue_created: str = issue["fields"]["created"] + + conn.execute( + """ + INSERT OR IGNORE INTO Task + (id, key, summary, description, status, issue_type, created) + VALUES + (?, ?, ?, ?, ?, ?, ?) + """, + ( + issue_id, + issue_key, + issue_summary, + issue_desc, + issue_status, + issue_type, + issue_created, + ), + ) + + last_id = issue_id + + conn.commit() + + print(f"[+] Загружено {len(issues)} задач...") + + time.sleep(5) + + +if __name__ == "__main__": + # TODO: Возможность задавать аргументом + projects: list[str] = [ + # "OPTT", + "TXI", + "TWRBS", + "TXCORE", + "TXACQ", + ] + + # TODO: Возможность задавать аргументом путь к БД + # FILE_NAME_DB: Path = DIR / "jira_local_OPTT.sqlite" + + db_conn = init_sqlite(FILE_NAME_DB) + sync_jira_to_sqlite(db_conn, projects) diff --git a/job_compassplus/jira_get_avatars/main.py b/job_compassplus/jira_get_avatars/main.py deleted file mode 100644 index 9a1607ad5..000000000 --- a/job_compassplus/jira_get_avatars/main.py +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -__author__ = "ipetrash" - - -import sys -from pathlib import Path - -DIR = Path(__file__).resolve().parent -ROOT_DIR = DIR.parent - -sys.path.append(str(ROOT_DIR)) -from root_config import JIRA_HOST -from root_common import session - - -url = f"{JIRA_HOST}/rest/api/latest/user/avatars?username=ipetrash" - -rs = session.get(url) -print(rs) -for kind, avatars in rs.json().items(): - print(f"{kind} ({len(avatars)}):") - for item in avatars: - print(f" {item}") diff --git a/job_compassplus/mysite_compassplus_com/get_profile_info_from_web/db.py b/job_compassplus/mysite_compassplus_com/get_profile_info_from_web/db.py index 8a2ccbce5..ca72e6789 100644 --- a/job_compassplus/mysite_compassplus_com/get_profile_info_from_web/db.py +++ b/job_compassplus/mysite_compassplus_com/get_profile_info_from_web/db.py @@ -31,7 +31,7 @@ class NotDefinedParameterException(ValueError): - def __init__(self, parameter_name: str): + def __init__(self, parameter_name: str) -> None: self.parameter_name = parameter_name text = f'Parameter "{self.parameter_name}" must be defined!' @@ -63,7 +63,7 @@ def get_inherited_models(cls) -> list[Type["BaseModel"]]: return sorted(cls.__subclasses__(), key=lambda x: x.__name__) @classmethod - def print_count_of_tables(cls): + def print_count_of_tables(cls) -> None: items = [] for sub_cls in cls.get_inherited_models(): name = sub_cls.__name__ @@ -82,7 +82,7 @@ def count(cls, filters: Iterable = None) -> int: def to_dict(self) -> dict[str, Any]: return model_to_dict(self, recurse=False) - def __str__(self): + def __str__(self) -> str: fields = [] for k, field in self._meta.fields.items(): v = getattr(self, k) @@ -117,6 +117,7 @@ class Person(BaseModel): create_date = DateField(default=date.today) last_check_date = DateField(default=date.today) is_active = BooleanField(default=None, null=True) + prev_name = TextField(default=None, null=True) class Meta: indexes = ( @@ -131,9 +132,23 @@ def get_last_by_name(cls, name: str) -> Optional["Person"]: @classmethod def get_all(cls, name: str) -> list["Person"]: - return list( - cls.select().where(cls.name == name).order_by(cls.id.desc()) - ) + prev_names: set[str] = set() + + persons: set[Person] = set() + for p in cls.select().where(cls.name == name): + persons.add(p) + + if p.prev_name: + prev_names.add(p.prev_name) + + for prev_name in prev_names: + if prev_name in persons: + continue + + for p in Person.get_all(prev_name): + persons.add(p) + + return sorted(persons, key=lambda p: p.id, reverse=True) @classmethod def get_all_name(cls) -> list[str]: @@ -151,3 +166,25 @@ def get_all_name(cls) -> list[str]: if __name__ == "__main__": BaseModel.print_count_of_tables() + print() + + names: list[str] = Person.get_all_name() + persons: list[Person] = [ + Person.get_last_by_name(name) + for name in names + ] + print(f"Total: {len(persons)}") + print(f"Active: {len([p for p in persons if p.is_active])}") + print(f"Non active: {len([p for p in persons if not p.is_active])}") + + # Поиск людей с одинаковой картинкой в профиле + # from collections import defaultdict + # img_by_persons: defaultdict[bytes, set[str]] = defaultdict(set) + # + # for p in Person: + # img_by_persons[p.img].add(p.name) + # + # for img, persons in sorted(img_by_persons.items(), key=lambda x: len(x[1]), reverse=True): + # if len(persons) > 1: + # print(len(persons), persons) + # diff --git a/job_compassplus/mysite_compassplus_com/get_profile_info_from_web/db_backup.py b/job_compassplus/mysite_compassplus_com/get_profile_info_from_web/db_backup.py index 4af9e45a8..3b465039a 100644 --- a/job_compassplus/mysite_compassplus_com/get_profile_info_from_web/db_backup.py +++ b/job_compassplus/mysite_compassplus_com/get_profile_info_from_web/db_backup.py @@ -52,7 +52,7 @@ def backup( return file_name -def do_backup_db(): +def do_backup_db() -> None: prefix: str = "[do_backup_db]" print(f"{prefix} Start") diff --git a/job_compassplus/mysite_compassplus_com/get_profile_info_from_web/db_updater.py b/job_compassplus/mysite_compassplus_com/get_profile_info_from_web/db_updater.py index fd1b64580..3fc3275cf 100644 --- a/job_compassplus/mysite_compassplus_com/get_profile_info_from_web/db_updater.py +++ b/job_compassplus/mysite_compassplus_com/get_profile_info_from_web/db_updater.py @@ -83,7 +83,7 @@ def add_or_get_db(name: str, forced: bool = False) -> db.Person | None: # Создание новой записи с актуальными полями person = create_person_from_info(info) - else: # Если пользователь был в БД, а потом его удалили из mysite + elif person.is_active: # Если пользователь был в БД и активным, а потом его удалили из mysite # Создание новой записи return db.Person.create( name=person.name, @@ -98,7 +98,7 @@ def add_or_get_db(name: str, forced: bool = False) -> db.Person | None: return person -def do_update_db(forced: bool = False): +def do_update_db(forced: bool = False) -> None: prefix: str = "[do_update_db]" print(f"{prefix} Start") @@ -134,6 +134,8 @@ def do_update_db(forced: bool = False): if __name__ == "__main__": - print(add_or_get_db("ipetrash")) + user_name = "akrylov" + print(get_person_info(user_name)) + print(add_or_get_db(user_name, forced=True)) # do_update_db(forced=True) diff --git a/job_compassplus/mysite_compassplus_com/get_profile_info_from_web/migrations/001.py b/job_compassplus/mysite_compassplus_com/get_profile_info_from_web/migrations/001.py new file mode 100644 index 000000000..c428fa821 --- /dev/null +++ b/job_compassplus/mysite_compassplus_com/get_profile_info_from_web/migrations/001.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +# SOURCE: http://docs.peewee-orm.com/en/latest/peewee/playhouse.html#schema-migrations + + +from playhouse.migrate import SqliteDatabase, SqliteMigrator, migrate +from db import TextField, DB_FILE_NAME, Person + + +db = SqliteDatabase(DB_FILE_NAME) +migrator = SqliteMigrator(db) + + +with db.atomic(): + migrate( + migrator.add_column( + Person._meta.table_name, + "prev_name", + TextField(default=None, null=True), + ), + ) diff --git a/job_compassplus/outlook_jira_issues_autoread.py b/job_compassplus/outlook_jira_issues_autoread.py new file mode 100644 index 000000000..eeeecee44 --- /dev/null +++ b/job_compassplus/outlook_jira_issues_autoread.py @@ -0,0 +1,247 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +import argparse +import email +import imaplib +import re +import time + +from dataclasses import dataclass +from datetime import datetime, timedelta +from email.header import decode_header +from email.utils import parseaddr +from typing import Any + +from root_config import JIRA_HOST +from root_common import session + + +PATTERN_JIRA: re.Pattern = re.compile(r"\((\w+-\d+)\)") + + +@dataclass +class IssueInfo: + key: str + is_done: bool + updated: datetime | None + resolution_date: datetime | None + + +def get_issue_info(issue_key: str) -> IssueInfo: + def _get_datetime(value: str) -> datetime | None: + if value: + return datetime.fromisoformat(value).replace(tzinfo=None) + + url_issue: str = f"{JIRA_HOST}/rest/api/latest/issue/{issue_key}" + + rs = session.get(url_issue) + rs.raise_for_status() + + rs_fields: dict[str, Any] = rs.json()["fields"] + + return IssueInfo( + key=issue_key, + is_done=rs_fields["status"]["statusCategory"]["key"] == "done", + updated=_get_datetime(rs_fields.get("updated")), + resolution_date=_get_datetime(rs_fields.get("resolutiondate")), + ) + + +def get_args(): + parser = argparse.ArgumentParser( + description="Скрипт для автоматического прочтения неактуальных писем из Jira в Outlook." + ) + + # Обязательные параметры + parser.add_argument( + "-u", + "--user", + required=True, + help="Логин (email) от почты", + ) + parser.add_argument( + "-p", + "--password", + required=True, + help="Пароль от почты (или пароль приложения)", + ) + parser.add_argument( + "-f", + "--folder", + default="INBOX", + help="Папка для поиска (например, INBOX или 'Jira/Issues', по умолчанию: %(default)s))", + ) + + # Опциональные параметры + parser.add_argument( + "--server", + default="mail.compassplus.com", + help="Адрес IMAP сервера (по умолчанию: %(default)s)", + ) + + parser.add_argument( + "--limit", + type=int, + default=None, + help="Ограничение количества обрабатываемых писем (для тестирования, например 100)", + ) + + # Флаг прочтения (action='store_true' делает его булевым: если указан - True, если нет - False) + parser.add_argument( + "--mark", + action="store_true", + help="Если указан, письма при совпадении условий будут отмечены как прочитанные на сервере", + ) + + return parser.parse_args() + + +def process( + user: str, + password: str, + server: str, + folder: str, + limit: int | None = None, + mark_as_read: bool = False, +) -> None: + print(f"Подключение к {server} для пользователя {user}...") + + mail = imaplib.IMAP4_SSL(server) + mail.login(user, password) + + mail.select(f'"{folder}"') + + # Письма от старых к новым + status, response = mail.search(None, "(UNSEEN)") + + issue_by_info: dict[str, Any] = dict() + + msg_ids = response[0].split() + if limit: + print(f"Лимит обработки: {limit} писем") + msg_ids = msg_ids[:limit] + + for num in msg_ids: + # BODY.PEEK[] - читаем, не меняя статус на "Прочитано" + status, data = mail.fetch(num, "(BODY.PEEK[HEADER])") + raw_email: bytes = data[0][1] + msg = email.message_from_bytes(raw_email) + + # Декодируем заголовок + decoded_parts = decode_header(msg["Subject"]) + + subject = "" + for content, encoding in decoded_parts: + if isinstance(content, bytes): + # Используем кодировку из письма, если её нет — пробуем utf-8 + enc = encoding if encoding else "utf-8" + try: + subject += content.decode(enc) + except (UnicodeDecodeError, LookupError): + # Если всё равно ошибка, декодируем с заменой битых символов + subject += content.decode("utf-8", errors="replace") + else: + # Если это уже строка (например, ASCII) + subject += content + + raw_from: str = msg.get("From") + name, email_address = parseaddr(raw_from) + + raw_date: str = msg.get("Date") + date_tuple = email.utils.parsedate_tz(raw_date) + local_date: datetime | None = None + if date_tuple: + local_date = datetime.fromtimestamp( + email.utils.mktime_tz(date_tuple) + ).replace(tzinfo=None) + else: + print(f"[#] Неправильная дата письма: {raw_date!r}") + + read_it: bool = False + + # NOTE: Можно оптимизировать и не ходить в API Jira, если письмо старше такой-то даты + # Но хочется посмотреть информацию по задачам из писем + m: re.Match | None = PATTERN_JIRA.search(subject) + if m: + issue_key: str = m.group(1) + print( + "[+]", + num, + f"{local_date.strftime('%d.%m.%Y %H:%M:%S') if local_date else None}", + repr(subject), + repr(name), + email_address, + issue_key, + ) + + issue: IssueInfo | None = issue_by_info.get(issue_key) + if not issue: + try: + issue = get_issue_info(issue_key) + issue_by_info[issue_key] = issue + except Exception as e: + print(f"[#] Не удалось получить информацию по задаче {issue_key!r}: {e}") + + time.sleep(1) + + print(f" Информация по задаче: {issue if issue else '<неизвестно>'}") + + if issue: + # Определяем запас времени (например, 10 минут) + buffer = timedelta(minutes=10) + + # Если письма приходили до даты решения задачи, то уже не актуальные + if ( + issue.is_done + and issue.resolution_date + and local_date + # Если дата решения задачи больше даты отправки письма + and (issue.resolution_date - buffer) > local_date + ): + print(" Письмо приходило раньше решения задачи") + read_it = True + + else: + print( + "[?]", + num, + f"{local_date.strftime('%d.%m.%Y %H:%M:%S') if local_date else None}", + repr(subject), + repr(name), + email_address, + ) + + # Если прошло больше 1 месяца + if local_date and (datetime.now() - timedelta(weeks=4)) > local_date: + print(" Прошло больше 1 месяца") + read_it = True + + if read_it: + status_msg = ( + "[ПРОЧИТАНО]" + if mark_as_read + else "[DRY-RUN: БЫЛО БЫ ПРОЧИТАНО С ФЛАГОМ --mark]" + ) + print(f" {status_msg}") + + if mark_as_read: + mail.store(num, "+FLAGS", r"\Seen") + + mail.logout() + + +if __name__ == "__main__": + args = get_args() + + process( + user=args.user, + password=args.password, + server=args.server, + folder=args.folder, + limit=args.limit, + mark_as_read=args.mark, + ) diff --git a/job_compassplus/parse_jira_Assigned_Open_Issues_per_Project/common.py b/job_compassplus/parse_jira_Assigned_Open_Issues_per_Project/common.py index f979e8a88..a653ed575 100644 --- a/job_compassplus/parse_jira_Assigned_Open_Issues_per_Project/common.py +++ b/job_compassplus/parse_jira_Assigned_Open_Issues_per_Project/common.py @@ -25,7 +25,7 @@ def get_table(assigned_open_issues_per_project: dict[str, int]) -> str: ) -def print_table(assigned_open_issues_per_project: dict[str, int]): +def print_table(assigned_open_issues_per_project: dict[str, int]) -> None: print(get_table(assigned_open_issues_per_project)) # PROJECT | Issues # --------+------- diff --git a/job_compassplus/parse_jira_Assigned_Open_Issues_per_Project/db.py b/job_compassplus/parse_jira_Assigned_Open_Issues_per_Project/db.py index 2b9af5efa..5b6f7fe69 100644 --- a/job_compassplus/parse_jira_Assigned_Open_Issues_per_Project/db.py +++ b/job_compassplus/parse_jira_Assigned_Open_Issues_per_Project/db.py @@ -30,7 +30,7 @@ DB_FILE_NAME = str(DIR / "database.sqlite") -def db_create_backup(backup_dir=DIR / "backup"): +def db_create_backup(backup_dir=DIR / "backup") -> None: os.makedirs(backup_dir, exist_ok=True) file_name = str(dt.datetime.today().date()) + ".sqlite" @@ -47,7 +47,7 @@ class BaseModel(Model): class Meta: database = db - def __str__(self): + def __str__(self) -> str: fields = [] for k, field in self._meta.fields.items(): v = getattr(self, k) @@ -75,7 +75,7 @@ def get_total_issues(self) -> int: def get_project_by_issue_numbers(self) -> dict[str, int]: return {issue.project.name: issue.value for issue in self.issue_numbers} - def __str__(self): + def __str__(self) -> str: return f"{self.__class__.__name__}(id={self.id}, date={self.date}, total_issues={self.get_total_issues()})" diff --git a/job_compassplus/parse_jira_Assigned_Open_Issues_per_Project/gui.py b/job_compassplus/parse_jira_Assigned_Open_Issues_per_Project/gui.py index 8f4e7d1a4..11dc03b4d 100644 --- a/job_compassplus/parse_jira_Assigned_Open_Issues_per_Project/gui.py +++ b/job_compassplus/parse_jira_Assigned_Open_Issues_per_Project/gui.py @@ -43,7 +43,7 @@ from chart_line__show_tooltip_on_series__QtChart import ChartViewToolTips -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -95,7 +95,7 @@ class GetAssignedOpenIssuesPerProjectThread(QThread): about_items = pyqtSignal(dict) about_error = pyqtSignal(Exception) - def run(self): + def run(self) -> None: try: items: dict[str, int] = get_assigned_open_issues_per_project() self.about_items.emit(items) @@ -108,7 +108,7 @@ def run(self): class TableWidgetRun(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.table_run = get_table_widget(["DATE", "TOTAL ISSUES"]) @@ -129,7 +129,7 @@ def __init__(self): self.setLayout(main_layout) - def refresh(self, items: list[Run]): + def refresh(self, items: list[Run]) -> None: # Удаление строк таблицы while self.table_run.rowCount(): self.table_run.removeRow(0) @@ -148,7 +148,7 @@ def refresh(self, items: list[Run]): self.table_run.setFocus() self._on_table_run_item_clicked() - def _on_table_run_item_clicked(self): + def _on_table_run_item_clicked(self) -> None: # Удаление строк таблицы while self.table_issues.rowCount(): self.table_issues.removeRow(0) @@ -165,7 +165,7 @@ def _on_table_run_item_clicked(self): class CurrentAssignedOpenIssues(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.table = get_table_widget(["PROJECT", "NUMBER"]) @@ -208,10 +208,10 @@ def __init__(self): self.current_items: dict[str, int] | None = None self._update_total_issues("-") - def _update_total_issues(self, value): + def _update_total_issues(self, value) -> None: self.label_total.setText(f"Total issues: {value}") - def _on_set_items(self, items: dict[str, int]): + def _on_set_items(self, items: dict[str, int]) -> None: self.current_items = items self._update_total_issues(sum(self.current_items.values())) @@ -230,25 +230,25 @@ def _on_set_items(self, items: dict[str, int]): f"Last refresh date: {get_human_datetime()}" ) - def _on_error(self, e: Exception): + def _on_error(self, e: Exception) -> None: tb_str = "".join(traceback.format_tb(e.__traceback__)) print(tb_str) QMessageBox.warning(self, "ERROR", str(e)) - def refresh(self): + def refresh(self) -> None: self.current_items = None self.thread.start() class MyChartViewToolTips(ChartViewToolTips): - def __init__(self, timestamp_by_info: dict[int, dict[str, int]]): + def __init__(self, timestamp_by_info: dict[int, dict[str, int]]) -> None: super().__init__() self._callout_font_family = "Courier" self.timestamp_by_info: dict[int, dict[str, int]] = timestamp_by_info - def show_series_tooltip(self, point, state: bool): + def show_series_tooltip(self, point, state: bool) -> None: # value -> pos point = self.chart().mapToPosition(point) @@ -290,7 +290,7 @@ def show_series_tooltip(self, point, state: bool): class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle(WINDOW_TITLE) @@ -358,7 +358,7 @@ def _get_datetime(self, date: date, delta: timedelta = None) -> datetime: dt += delta return dt - def _fill_chart_filter(self, items: list[Run]): + def _fill_chart_filter(self, items: list[Run]) -> None: years: list[int] = sorted({run.date.year for run in items}) filter_years: list[int] = [ self.cb_chart_filter.itemData(i) @@ -368,7 +368,7 @@ def _fill_chart_filter(self, items: list[Run]): if year not in filter_years: self.cb_chart_filter.addItem(f"{year}", userData=year) - def _fill_chart(self, items: list[Run]): + def _fill_chart(self, items: list[Run]) -> None: # Фильтрация данных из графика year: int = self.cb_chart_filter.currentData() if year: @@ -433,7 +433,7 @@ def _fill_chart(self, items: list[Run]): self.chart_view.clear_all_tooltips() self.chart_view.setChart(chart) - def refresh(self): + def refresh(self) -> None: self.current_assigned_open_issues.refresh() items = list(Run.select()) @@ -449,7 +449,7 @@ def refresh(self): f"{WINDOW_TITLE}. Last refresh date: {get_human_datetime()}" ) - def _on_tray_activated(self, reason: QSystemTrayIcon.ActivationReason): + def _on_tray_activated(self, reason: QSystemTrayIcon.ActivationReason) -> None: # Если запрошено меню if reason == QSystemTrayIcon.Context: return @@ -460,14 +460,14 @@ def _on_tray_activated(self, reason: QSystemTrayIcon.ActivationReason): self.showNormal() self.activateWindow() - def changeEvent(self, event: QEvent): + def changeEvent(self, event: QEvent) -> None: if event.type() == QEvent.WindowStateChange: # Если окно свернули if self.isMinimized(): # Прячем окно с панели задач QTimer.singleShot(0, self.hide) - def closeEvent(self, event: QCloseEvent): + def closeEvent(self, event: QCloseEvent) -> None: self.hide() event.ignore() diff --git a/job_compassplus/portal_compassplus_com/employees_gui/db.py b/job_compassplus/portal_compassplus_com/employees_gui/db.py index dd3439be2..7634add2a 100644 --- a/job_compassplus/portal_compassplus_com/employees_gui/db.py +++ b/job_compassplus/portal_compassplus_com/employees_gui/db.py @@ -134,10 +134,10 @@ def parse(xml, session): return employee - def __str__(self): + def __str__(self) -> str: return f'' - def __repr__(self): + def __repr__(self) -> str: return self.__str__() @@ -162,7 +162,7 @@ def get_session(): db_session = get_session() -def exists(employee_id): +def exists(employee_id) -> bool: return ( db_session.query(Employee).filter(Employee.id == employee_id).scalar() is not None diff --git a/job_compassplus/portal_compassplus_com/employees_gui/main.py b/job_compassplus/portal_compassplus_com/employees_gui/main.py index e35cc673d..d77012be3 100644 --- a/job_compassplus/portal_compassplus_com/employees_gui/main.py +++ b/job_compassplus/portal_compassplus_com/employees_gui/main.py @@ -23,7 +23,7 @@ # Для отлова всех исключений, которые в слотах Qt могут "затеряться" и привести к тихому падению -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -54,7 +54,7 @@ def pixmap_from_base64(base64_text): class EmployeeInfo(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.photo = QLabel() @@ -107,7 +107,7 @@ def __init__(self): for label in self.findChildren(QLabel): label.setTextInteractionFlags(Qt.TextBrowserInteraction) - def set_employee(self, employee): + def set_employee(self, employee) -> None: if not employee: self.photo.setPixmap(pixmap_from_base64(config.PERSON_PLACEHOLDER_PHOTO)) @@ -139,7 +139,7 @@ def set_employee(self, employee): # TODO: ввод с клавы при фокусе на таблицу меняет редактор фильтра class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Compass Plus Employees") @@ -209,7 +209,7 @@ def __init__(self): self.setStatusBar(QStatusBar()) - def refill(self): + def refill(self) -> None: # TODO: можно в отдельный класс вынести dialog = QDialog() dialog.setWindowTitle("Auth and refill database") @@ -267,7 +267,7 @@ def refill(self): self.fill_db(session) self.run_filter() - def fill_db(self, session): + def fill_db(self, session) -> None: page = 1 rs = session.get(get_url(page)) @@ -324,7 +324,7 @@ def fill_db(self, session): progress.setValue(len(employee_list)) - def _item_click(self, item): + def _item_click(self, item) -> None: employee = None if item and self.employees_table.rowCount() > 0: @@ -333,7 +333,7 @@ def _item_click(self, item): self.employee_info.set_employee(employee) - def run_filter(self): + def run_filter(self) -> None: # TODO: лучше использовать модель # TODO: лучше использовать стандартный фильтр qt # TODO: поиграться с делегатами для красивого отображения описания + ссылки на гист @@ -409,7 +409,7 @@ def run_filter(self): item = self.employees_table.item(0, 0) self.employees_table.setCurrentItem(item) - def read_settings(self): + def read_settings(self) -> None: ini = QSettings(config.SETTINGS_FILE_NAME, QSettings.IniFormat) state = ini.value("MainWindow_State") @@ -420,7 +420,7 @@ def read_settings(self): if geometry: self.restoreGeometry(geometry) - def write_settings(self): + def write_settings(self) -> None: ini = QSettings(config.SETTINGS_FILE_NAME, QSettings.IniFormat) ini.setValue("MainWindow_State", self.saveState()) ini.setValue("MainWindow_Geometry", self.saveGeometry()) @@ -434,7 +434,7 @@ def eventFilter(self, object, event): return super().eventFilter(object, event) - def closeEvent(self, _): + def closeEvent(self, _) -> None: self.write_settings() QApplication.instance().quit() diff --git a/job_compassplus/portal_compassplus_com/notify_about_new_employees.py b/job_compassplus/portal_compassplus_com/notify_about_new_employees.py index 20590a38e..737926e0e 100644 --- a/job_compassplus/portal_compassplus_com/notify_about_new_employees.py +++ b/job_compassplus/portal_compassplus_com/notify_about_new_employees.py @@ -24,7 +24,7 @@ raise Exception("URL_NOTIFY environment variable is not set!") -def parse(page: Page, url_portal: str = URL_PORTAL, url_notify: str = URL_NOTIFY): +def parse(page: Page, url_portal: str = URL_PORTAL, url_notify: str = URL_NOTIFY) -> None: print(f"Opening page: {url_portal}") page.goto(url_portal) diff --git a/job_compassplus/print_statistics_by_img.py b/job_compassplus/print_statistics_by_img.py index 2526fe250..c07c1779b 100644 --- a/job_compassplus/print_statistics_by_img.py +++ b/job_compassplus/print_statistics_by_img.py @@ -9,7 +9,7 @@ from pathlib import Path -def process(path: Path): +def process(path: Path) -> None: files: list[Path] = [ p for p in path.glob("*/ads/*/img/*") diff --git a/job_compassplus/tx_parse_xml/gen_svn_ignore_layers.py b/job_compassplus/tx_parse_xml/gen_svn_ignore_layers.py new file mode 100644 index 000000000..9bc577412 --- /dev/null +++ b/job_compassplus/tx_parse_xml/gen_svn_ignore_layers.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +import fnmatch +import argparse + +from pathlib import Path + + +def process( + root_path: Path, + include_glob: str, + exclude_patterns: list[str], + encoding: str = "utf-8", +) -> None: + file_exclude: Path = root_path / "svn_layers_exclude.bat" + file_restore: Path = root_path / "svn_layers_restore.bat" + + print(f"Scanning directory: {root_path.absolute()}") + + target_dirs: list[Path] = [p for p in root_path.glob(include_glob) if p.is_dir()] + if not target_dirs: + print("No matching directories found.") + return + + # Подготавливаем списки строк для записи + lines_exclude: list[str] = ["@echo off"] + lines_restore: list[str] = ["@echo off"] + + for p in target_dirs: + dir_name: str = p.name + is_excluded: bool = any( + fnmatch.fnmatch(dir_name, pat) for pat in exclude_patterns + ) + + prefix: str = "REM " if is_excluded else "" + lines_exclude.append(f"{prefix}svn update --set-depth exclude {dir_name}") + lines_restore.append(f"{prefix}svn update --set-depth infinity {dir_name}") + + file_exclude.write_text("\n".join(lines_exclude) + "\n", encoding=encoding) + file_restore.write_text("\n".join(lines_restore) + "\n", encoding=encoding) + + print(f"Done! Created '{file_exclude.name}' and '{file_restore.name}'") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Generates SVN batch scripts to manage folder depth (exclude/include).", + ) + parser.add_argument( + "path", + metavar="PROJECT_PATH", + type=Path, + help="Path to the project directory", + ) + parser.add_argument( + "--include", + default="com.tranzaxis.*", + help="Glob pattern for directories to process (default: %(default)s)", + ) + parser.add_argument( + "--excludes", + nargs="+", + default=["com.tranzaxis.experimental", "com.tranzaxis.demo"], + help="Globs for directories to comment out in exclude script (default: %(default)s)", + ) + + args = parser.parse_args() + + if not args.path.exists(): + parser.error(f"The path {args.path} does not exist.") + + process(args.path, args.include, args.excludes) diff --git a/job_compassplus/tx_parse_xml/get_layer_version.py b/job_compassplus/tx_parse_xml/get_layer_version.py index 21dfa916c..920a34654 100644 --- a/job_compassplus/tx_parse_xml/get_layer_version.py +++ b/job_compassplus/tx_parse_xml/get_layer_version.py @@ -25,7 +25,7 @@ def get_layer_version(path: Path) -> str: return m.group(1) -def process(path: Path): +def process(path: Path) -> None: print(get_layer_version(path)) diff --git a/job_compassplus/tx_parse_xml/get_project_versions.py b/job_compassplus/tx_parse_xml/get_project_versions.py index 7a348d3e2..2612cc5c6 100644 --- a/job_compassplus/tx_parse_xml/get_project_versions.py +++ b/job_compassplus/tx_parse_xml/get_project_versions.py @@ -226,7 +226,7 @@ def get_project_versions(path: Path) -> TotalProjectInfo: ) -def process(path: Path): +def process(path: Path) -> None: print(f"Информация по версиям из {path}") total_project_info: TotalProjectInfo = get_project_versions(path) @@ -301,7 +301,7 @@ class DiffLayersResult: print() print("Версии:") - def _print_project_info(project_info: ProjectInfo, is_local: bool): + def _print_project_info(project_info: ProjectInfo, is_local: bool) -> None: ind1: str = " " print(ind1 + ("Local:" if is_local else "Remote:")) print(f"{ind1 * 2}Branch: {project_info.branch}") diff --git a/job_compassplus/tx_parse_xml/search_in_locale_files_of_ADS.py b/job_compassplus/tx_parse_xml/search_in_locale_files_of_ADS.py index 4cb8a6bff..710166a3e 100644 --- a/job_compassplus/tx_parse_xml/search_in_locale_files_of_ADS.py +++ b/job_compassplus/tx_parse_xml/search_in_locale_files_of_ADS.py @@ -21,7 +21,7 @@ def get_text(el: ET.Element) -> str: return "".join(text for text in el.itertext()) -def process(path: str, regexp: str): +def process(path: str, regexp: str) -> None: pattern = re.compile(regexp) for p in Path(path).glob("*/ads/*/locale/*/mlb*.xml"): diff --git a/job_compassplus/tx_parse_xml/show_SQL_of_ADS_classes.py b/job_compassplus/tx_parse_xml/show_SQL_of_ADS_classes.py index 9fde0c7e8..f57c651b4 100644 --- a/job_compassplus/tx_parse_xml/show_SQL_of_ADS_classes.py +++ b/job_compassplus/tx_parse_xml/show_SQL_of_ADS_classes.py @@ -276,7 +276,7 @@ def get_ads_list(branch_dir: Path | str) -> dict[str, list[ADS]]: return layer_module_by_ads_list -def process(path: str): +def process(path: str) -> None: indent1 = " " indent2 = indent1 * 2 indent3 = indent1 * 3 diff --git a/job_compassplus/tx_parse_xml/show_duplicates_SQL_of_ADS_classes.py b/job_compassplus/tx_parse_xml/show_duplicates_SQL_of_ADS_classes.py index e2d502623..4cd63df91 100644 --- a/job_compassplus/tx_parse_xml/show_duplicates_SQL_of_ADS_classes.py +++ b/job_compassplus/tx_parse_xml/show_duplicates_SQL_of_ADS_classes.py @@ -315,7 +315,7 @@ def get_ads_list(branch_dir: Path | str) -> dict[str, list[ADS]]: return layer_module_by_ads_list -def process(path: str): +def process(path: str) -> None: indent1 = " " indent2 = indent1 * 2 diff --git a/job_compassplus/tx_remove_hs_err_pid_log/main.py b/job_compassplus/tx_remove_hs_err_pid_log/main.py index 716617ea2..93083d911 100644 --- a/job_compassplus/tx_remove_hs_err_pid_log/main.py +++ b/job_compassplus/tx_remove_hs_err_pid_log/main.py @@ -52,7 +52,7 @@ def get_logger( DIRS = [r"C:\DEV__TX", r"C:\DEV__OPTT", r"C:\DEV__RADIX"] -def run(dirs: list[str | Path]): +def run(dirs: list[str | Path]) -> None: print(f"\nStarted {dt.datetime.today()}") for dir_path in dirs: diff --git a/job_compassplus/tx_remove_java_pid_hprof/main.py b/job_compassplus/tx_remove_java_pid_hprof/main.py index ede2c7ddc..3d84d5697 100644 --- a/job_compassplus/tx_remove_java_pid_hprof/main.py +++ b/job_compassplus/tx_remove_java_pid_hprof/main.py @@ -54,7 +54,7 @@ def get_logger( ) -def run(dirs: list[str | Path]): +def run(dirs: list[str | Path]) -> None: print(f"\nStarted {dt.datetime.today()}") for dir_path in dirs: diff --git a/job_compassplus/visa_base2_tc_counter.py b/job_compassplus/visa_base2_tc_counter.py new file mode 100644 index 000000000..a995cc86d --- /dev/null +++ b/job_compassplus/visa_base2_tc_counter.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +from collections import Counter +from pathlib import Path + + +# TODO: argparser +DIR = Path(r"C:\Users\ipetrash\Desktop\Visa Base 2") + +for path in DIR.rglob("*"): + if not path.is_file() or "errors" in str(path): + continue + + print(path) + + tc_by_counter = Counter() + tc_tcr_by_counter = Counter() + + with open(path, "rb") as f: + for line in f: + is_ctf: bool = len(line.rstrip(b"\n\r")) == 168 + tc_raw: bytes = line[:2] + tcr_raw: bytes = line[3:4] if is_ctf else line[5:6] + # TODO: Support EBCDIC, example b'\xf9\xf0' -> 90 + try: + tc: str = tc_raw.decode("ascii") + except UnicodeDecodeError as e: + print(f" [#] Skip. Error on {tc_raw}: {e}") + break + + try: + tcr: str = tcr_raw.decode("ascii") + except UnicodeDecodeError as e: + print(f" [#] Skip. Error on {tcr_raw}: {e}") + break + + if not tc.strip() or tc in ["90", "91", "92", "00"]: + continue + + tc_by_counter.update([tc]) + tc_tcr_by_counter.update([f"{tc}-{tcr}"]) + + print(" TC: " + ", ".join(f"{k}: {v}" for k, v in tc_by_counter.items())) + print(" TC-TCR: " + ", ".join(f"{k}: {v}" for k, v in tc_tcr_by_counter.items())) diff --git a/job_compassplus/web__show_job_report/main.py b/job_compassplus/web__show_job_report/main.py index efb73347a..c23ea825b 100644 --- a/job_compassplus/web__show_job_report/main.py +++ b/job_compassplus/web__show_job_report/main.py @@ -24,7 +24,7 @@ @app.route("/") -def index(): +def index() -> str: report_dict = get_report_persons_info() try: diff --git a/job_compassplus/web_counter/db.py b/job_compassplus/web_counter/db.py index bf83dc424..260e1d0af 100644 --- a/job_compassplus/web_counter/db.py +++ b/job_compassplus/web_counter/db.py @@ -53,7 +53,7 @@ def get_inherited_models(cls) -> list[Type["BaseModel"]]: return sorted(cls.__subclasses__(), key=lambda x: x.__name__) @classmethod - def print_count_of_tables(cls): + def print_count_of_tables(cls) -> None: items = [] for sub_cls in cls.get_inherited_models(): name = sub_cls.__name__ @@ -72,7 +72,7 @@ def count(cls, filters: Iterable = None) -> int: def to_dict(self) -> dict[str, Any]: return model_to_dict(self, recurse=False) - def __str__(self): + def __str__(self) -> str: fields = [] for k, field in self._meta.fields.items(): v = getattr(self, k) diff --git a/jsonmerge.py b/jsonmerge.py index de8b1dbab..9abd250a6 100644 --- a/jsonmerge.py +++ b/jsonmerge.py @@ -40,7 +40,7 @@ # TODO: нужно тестить, возможно, алгоритм где-то дырявый -def jsonmerge(j1, j2): +def jsonmerge(j1, j2) -> None: for k, v in j2.items(): if k in j1 and isinstance(j1[k], dict) and isinstance(v, dict): jsonmerge(j1[k], v) diff --git a/kivy_examples/generate_form_with_cycle.py b/kivy_examples/generate_form_with_cycle.py index 29de1181c..9cab7a17e 100644 --- a/kivy_examples/generate_form_with_cycle.py +++ b/kivy_examples/generate_form_with_cycle.py @@ -10,7 +10,7 @@ class MyWidget(GridLayout): - def __init__(self, **kwargs): + def __init__(self, **kwargs) -> None: super().__init__(**kwargs) self.cols = 1 diff --git a/kivy_examples/kivymd__example.py b/kivy_examples/kivymd__example.py index 3c6d3cd38..d46d8b185 100644 --- a/kivy_examples/kivymd__example.py +++ b/kivy_examples/kivymd__example.py @@ -22,7 +22,7 @@ class Test(MDApp): def build(self): return Builder.load_string(KV) - def on_start(self): + def on_start(self) -> None: for i in os.listdir(path="."): self.root.ids.container.add_widget( OneLineListItem(text=i, on_release=lambda item, i=i: print(i)) diff --git a/kivy_examples/login_screen.py b/kivy_examples/login_screen.py index 156b62f73..f745d35ed 100644 --- a/kivy_examples/login_screen.py +++ b/kivy_examples/login_screen.py @@ -13,7 +13,7 @@ class LoginScreen(GridLayout): - def __init__(self, **kwargs): + def __init__(self, **kwargs) -> None: super().__init__(**kwargs) self.cols = 2 @@ -32,7 +32,7 @@ def __init__(self, **kwargs): self.add_widget(Button(text="Ok", on_press=self.check)) - def check(self, button): + def check(self, button) -> None: print("auth called") message = "Success!" if self.username.text == "admin" else "Need admin!" diff --git a/kivy_examples/switch_between_widgets.py b/kivy_examples/switch_between_widgets.py index e47389a34..2009ce5a2 100644 --- a/kivy_examples/switch_between_widgets.py +++ b/kivy_examples/switch_between_widgets.py @@ -11,7 +11,7 @@ class ScreenMain(Screen): - def __init__(self, **kwargs): + def __init__(self, **kwargs) -> None: super().__init__(**kwargs) box_layout = BoxLayout(orientation="vertical", spacing=5, padding=[10]) @@ -26,13 +26,13 @@ def __init__(self, **kwargs): box_layout.add_widget(button_new_pasword) self.add_widget(box_layout) - def _on_press_button_new_pasword(self, *args): + def _on_press_button_new_pasword(self, *args) -> None: self.manager.transition.direction = "left" self.manager.current = "len_password" class ScreenLenPassword(Screen): - def __init__(self, **kwargs): + def __init__(self, **kwargs) -> None: super().__init__(**kwargs) box_layout = BoxLayout(orientation="vertical", spacing=5, padding=[10]) @@ -47,7 +47,7 @@ def __init__(self, **kwargs): box_layout.add_widget(button_new_pasword) self.add_widget(box_layout) - def _on_press_button_new_pasword(self, *args): + def _on_press_button_new_pasword(self, *args) -> None: self.manager.transition.direction = "right" self.manager.current = "main_screen" diff --git a/lex_yacc__examples/sly__examples/added_string_and_print.py b/lex_yacc__examples/sly__examples/added_string_and_print.py index 7d4ee70f3..2b69916a5 100644 --- a/lex_yacc__examples/sly__examples/added_string_and_print.py +++ b/lex_yacc__examples/sly__examples/added_string_and_print.py @@ -50,10 +50,10 @@ def TEXT(self, t): ignore_newline = r"\n+" # Extra action for newlines - def ignore_newline(self, t): + def ignore_newline(self, t) -> None: self.lineno += t.value.count("\n") - def error(self, t): + def error(self, t) -> None: print(f"Illegal character '{t.value[0]}'") self.index += 1 @@ -67,11 +67,11 @@ class MyParser(Parser): ("right", UMINUS), ) - def __init__(self): + def __init__(self) -> None: self.names = dict() @_("NAME ASSIGN expr") - def statement(self, p): + def statement(self, p) -> None: self.names[p.NAME] = p.expr @_("expr") @@ -79,7 +79,7 @@ def statement(self, p) -> int | str: return p.expr @_("PRINT expr") - def statement(self, p): + def statement(self, p) -> None: print(p.expr) @_("expr PLUS expr") diff --git a/lex_yacc__examples/sly__examples/added_ternary_operator.py b/lex_yacc__examples/sly__examples/added_ternary_operator.py index f95e2fa46..3ab9e16bc 100644 --- a/lex_yacc__examples/sly__examples/added_ternary_operator.py +++ b/lex_yacc__examples/sly__examples/added_ternary_operator.py @@ -79,10 +79,10 @@ def FALSE(self, t): ignore_newline = r"\n+" # Extra action for newlines - def ignore_newline(self, t): + def ignore_newline(self, t) -> None: self.lineno += t.value.count("\n") - def error(self, t): + def error(self, t) -> None: print(f"Illegal character '{t.value[0]}'") self.index += 1 @@ -99,11 +99,11 @@ class MyParser(Parser): ("right", UMINUS), ) - def __init__(self): + def __init__(self) -> None: self.names = dict() @_("NAME ASSIGN expr") - def statement(self, p): + def statement(self, p) -> None: self.names[p.NAME] = p.expr @_("expr") diff --git a/lex_yacc__examples/sly__examples/calc.py b/lex_yacc__examples/sly__examples/calc.py index 1078f5faa..9441833f6 100644 --- a/lex_yacc__examples/sly__examples/calc.py +++ b/lex_yacc__examples/sly__examples/calc.py @@ -33,10 +33,10 @@ class CalcLexer(Lexer): ignore_newline = r"\n+" # Extra action for newlines - def ignore_newline(self, t): + def ignore_newline(self, t) -> None: self.lineno += t.value.count("\n") - def error(self, t): + def error(self, t) -> None: print(f"Illegal character '{t.value[0]}'") self.index += 1 @@ -50,11 +50,11 @@ class CalcParser(Parser): ("right", UMINUS), ) - def __init__(self): + def __init__(self) -> None: self.names = dict() @_("NAME ASSIGN expr") - def statement(self, p): + def statement(self, p) -> None: self.names[p.NAME] = p.expr @_("expr") diff --git a/lex_yacc__examples/sly__examples/key=value.py b/lex_yacc__examples/sly__examples/key=value.py index 626039e96..5f240181b 100644 --- a/lex_yacc__examples/sly__examples/key=value.py +++ b/lex_yacc__examples/sly__examples/key=value.py @@ -21,10 +21,10 @@ class MyLexer(Lexer): ignore_newline = r"\n+" # Extra action for newlines - def ignore_newline(self, t): + def ignore_newline(self, t) -> None: self.lineno += t.value.count("\n") - def error(self, t): + def error(self, t) -> None: print(f"Illegal character {t.value[0]!r}") self.index += 1 @@ -32,11 +32,11 @@ def error(self, t): class MyParser(Parser): tokens = MyLexer.tokens - def __init__(self): + def __init__(self) -> None: self.names = dict() @_("NAME ASSIGN VALUE") - def statement(self, p): + def statement(self, p) -> None: self.names[p.NAME] = p.VALUE diff --git a/magtu_ru/mgtu_get_students_gui.py b/magtu_ru/mgtu_get_students_gui.py index 4869494a5..ee290cb13 100644 --- a/magtu_ru/mgtu_get_students_gui.py +++ b/magtu_ru/mgtu_get_students_gui.py @@ -18,7 +18,7 @@ class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.lw_dep = QListWidget() @@ -36,7 +36,7 @@ def __init__(self): self.setLayout(layout) - def fill(self): + def fill(self) -> None: self.lw_dep.clear() rs = requests.get( "http://magtu.ru/modules/mod_reiting/mobile.php?action=get_all_department" @@ -51,7 +51,7 @@ def fill(self): item.setData(Qt.UserRole, id_dep) self.lw_dep.addItem(item) - def fill_kaf(self, item_dep): + def fill_kaf(self, item_dep) -> None: self.lw_kaf.clear() id_dep = item_dep.data(Qt.UserRole) @@ -68,7 +68,7 @@ def fill_kaf(self, item_dep): item.setData(Qt.UserRole, id_kaf) self.lw_kaf.addItem(item) - def fill_stu(self, item_kaf): + def fill_stu(self, item_kaf) -> None: self.lw_stu.clear() id_kaf = item_kaf.data(Qt.UserRole) diff --git a/markdown__examples/pyqt5_gui.py b/markdown__examples/pyqt5_gui.py index c78faffd5..237e163bc 100644 --- a/markdown__examples/pyqt5_gui.py +++ b/markdown__examples/pyqt5_gui.py @@ -24,7 +24,7 @@ class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle(Path(__file__).stem) @@ -58,7 +58,7 @@ def __init__(self): self.setLayout(main_layout) - def _on_input_text_markdown(self): + def _on_input_text_markdown(self) -> None: self.edit_result_qt.setMarkdown(self.edit_markdown.toPlainText()) html = markdown.markdown(self.edit_markdown.toPlainText()) diff --git a/markdown__examples/pyqt6_gui.py b/markdown__examples/pyqt6_gui.py index a24f5c452..cb029aef6 100644 --- a/markdown__examples/pyqt6_gui.py +++ b/markdown__examples/pyqt6_gui.py @@ -24,7 +24,7 @@ class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle(Path(__file__).stem) @@ -58,7 +58,7 @@ def __init__(self): self.setLayout(main_layout) - def _on_input_text_markdown(self): + def _on_input_text_markdown(self) -> None: self.edit_result_qt.setMarkdown(self.edit_markdown.toPlainText()) html = markdown.markdown(self.edit_markdown.toPlainText()) diff --git a/matplotlib__examples/examples/exm19.py b/matplotlib__examples/examples/exm19.py index 59e2919ce..a235e2ab9 100644 --- a/matplotlib__examples/examples/exm19.py +++ b/matplotlib__examples/examples/exm19.py @@ -24,7 +24,7 @@ import pylab -def plotGraph(): +def plotGraph() -> None: # Будем рисовать график этой функции def func(x): """ diff --git a/matplotlib__examples/examples/exm20.py b/matplotlib__examples/examples/exm20.py index 9589aeffe..3905c58e2 100644 --- a/matplotlib__examples/examples/exm20.py +++ b/matplotlib__examples/examples/exm20.py @@ -18,7 +18,7 @@ import matplotlib__examples -def plotGraph(): +def plotGraph() -> None: # Будем рисовать график этой функции def func(x): """ diff --git a/matplotlib__examples/examples/exm23_4.py b/matplotlib__examples/examples/exm23_4.py index 530cd4e49..034afcaa3 100644 --- a/matplotlib__examples/examples/exm23_4.py +++ b/matplotlib__examples/examples/exm23_4.py @@ -28,7 +28,7 @@ import matplotlib__examples.ticker -def funcForFormatter(x, pos): +def funcForFormatter(x, pos) -> str: if x < 0: return f"минус {abs(x)}" diff --git a/mock__examples/datetime_now_utcnow.py b/mock__examples/datetime_now_utcnow.py index ac8eb2849..416091557 100644 --- a/mock__examples/datetime_now_utcnow.py +++ b/mock__examples/datetime_now_utcnow.py @@ -10,7 +10,7 @@ import _test_datetime -def test(): +def test() -> None: print("local:", datetime.datetime.now(), datetime.datetime.utcnow()) print("import:", *_test_datetime.get()) print() diff --git a/now_UTC_datetime.py b/now_UTC_datetime.py index e312810a9..7017a5840 100644 --- a/now_UTC_datetime.py +++ b/now_UTC_datetime.py @@ -4,8 +4,13 @@ __author__ = "ipetrash" -from datetime import datetime +from datetime import datetime, timezone +utc_datetime_old = datetime.utcnow().replace(microsecond=0) +print(utc_datetime_old) -utc_datetime = datetime.utcnow() -print(utc_datetime.strftime("%d/%m/%Y %H:%M:%S")) +utc_datetime = datetime.now(timezone.utc).replace(microsecond=0) +print(utc_datetime) + +assert utc_datetime_old != utc_datetime +assert utc_datetime_old == utc_datetime.replace(tzinfo=None) diff --git a/now_UTC_datetime__previous_365_days.py b/now_UTC_datetime__previous_365_days.py index 98a971baa..f08b36aff 100644 --- a/now_UTC_datetime__previous_365_days.py +++ b/now_UTC_datetime__previous_365_days.py @@ -4,10 +4,10 @@ __author__ = "ipetrash" -from datetime import datetime, timedelta +from datetime import datetime, timedelta, timezone -utc_datetime = datetime.utcnow() +utc_datetime = datetime.now(timezone.utc) for i in range(365 + 1): date = utc_datetime - timedelta(days=i) diff --git a/office__excel__openpyxl__xlwt/draw_image_in_sheet/main.py b/office__excel__openpyxl__xlwt/draw_image_in_sheet/main.py index 6ba246541..8a34f582c 100644 --- a/office__excel__openpyxl__xlwt/draw_image_in_sheet/main.py +++ b/office__excel__openpyxl__xlwt/draw_image_in_sheet/main.py @@ -12,7 +12,7 @@ # SOURCE: https://github.com/gil9red/SimplePyScripts/blob/8b69f96d0bd87c10f3d0779ff46b02558c4cca84/excel__openpyxl__xlwt/xlsx__set_row_column_size.py -def set_row_column_size(ws): +def set_row_column_size(ws) -> None: # SOURCE: excel__openpyxl__xlwt\excel\xl\worksheets\sheet1.xml # ws.sheet_format.defaultColWidth = 1.77734375 @@ -42,7 +42,7 @@ def get_pixel_array(img, rgb_hex=False): return pixels -def draw_image(ws, img): +def draw_image(ws, img) -> None: img = img.convert("RGB") # Resize diff --git a/office__excel__openpyxl__xlwt/random_fill_color.py b/office__excel__openpyxl__xlwt/random_fill_color.py index 644b3564e..892a93926 100644 --- a/office__excel__openpyxl__xlwt/random_fill_color.py +++ b/office__excel__openpyxl__xlwt/random_fill_color.py @@ -12,7 +12,7 @@ # SOURCE: https://github.com/gil9red/SimplePyScripts/blob/8b69f96d0bd87c10f3d0779ff46b02558c4cca84/excel__openpyxl__xlwt/xlsx__set_row_column_size.py -def set_row_column_size(ws: Worksheet): +def set_row_column_size(ws: Worksheet) -> None: # SOURCE: excel__openpyxl__xlwt\excel\xl\worksheets\sheet1.xml # ws.sheet_format.defaultColWidth = 1.77734375 @@ -25,7 +25,7 @@ def get_random_hex_color() -> str: return "".join(random.choices("0123456789ABCDEF", k=6)) -def set_fill_color(ws: Worksheet): +def set_fill_color(ws: Worksheet) -> None: size = 250 for i in range(1, size + 1): diff --git a/office__excel__openpyxl__xlwt/xlsx__auto_size__columns.py b/office__excel__openpyxl__xlwt/xlsx__auto_size__columns.py index ed721df66..651585216 100644 --- a/office__excel__openpyxl__xlwt/xlsx__auto_size__columns.py +++ b/office__excel__openpyxl__xlwt/xlsx__auto_size__columns.py @@ -8,7 +8,7 @@ from openpyxl.worksheet.worksheet import Worksheet -def set_column_size(ws: Worksheet): +def set_column_size(ws: Worksheet) -> None: dims: dict[str, int] = dict() for row in ws.rows: @@ -23,7 +23,7 @@ def set_column_size(ws: Worksheet): ws.column_dimensions[col].width = value * 1.15 # Append 15% -def fill_sheet(ws: Worksheet): +def fill_sheet(ws: Worksheet) -> None: columns = ["Language", "Text"] rows = [ ["python", "-" * 10], diff --git a/office__excel__openpyxl__xlwt/xlsx__set_row_column_size.py b/office__excel__openpyxl__xlwt/xlsx__set_row_column_size.py index 45c5afab5..7324565de 100644 --- a/office__excel__openpyxl__xlwt/xlsx__set_row_column_size.py +++ b/office__excel__openpyxl__xlwt/xlsx__set_row_column_size.py @@ -8,7 +8,7 @@ from openpyxl.worksheet.worksheet import Worksheet -def set_row_column_size(ws: Worksheet): +def set_row_column_size(ws: Worksheet) -> None: # SOURCE: excel__openpyxl__xlwt\excel\xl\worksheets\sheet1.xml # ws.sheet_format.defaultColWidth = 1.77734375 diff --git a/office__word__doc_docx/counter_of_font.py b/office__word__doc_docx/counter_of_font.py index 13c2a8cf1..8d61973c3 100644 --- a/office__word__doc_docx/counter_of_font.py +++ b/office__word__doc_docx/counter_of_font.py @@ -70,7 +70,7 @@ def _get_normal_size(size: int | None) -> int | None: return font_name, _get_normal_size(font_size) -def process(path: Path): +def process(path: Path) -> None: for file_name in path.glob("*.docx"): print(file_name) diff --git a/office__word__doc_docx/fill_template/save_style.py b/office__word__doc_docx/fill_template/save_style.py index 632c9dcef..d11db0b6d 100644 --- a/office__word__doc_docx/fill_template/save_style.py +++ b/office__word__doc_docx/fill_template/save_style.py @@ -11,7 +11,7 @@ # SOURCE: https://stackoverflow.com/a/55733040/5909792 -def docx_replace(doc, data): +def docx_replace(doc, data) -> None: paragraphs = list(doc.paragraphs) for t in doc.tables: for row in t.rows: diff --git a/opencv__Color_Detection_Tool/main.py b/opencv__Color_Detection_Tool/main.py index 9f47e065c..2c70c1616 100644 --- a/opencv__Color_Detection_Tool/main.py +++ b/opencv__Color_Detection_Tool/main.py @@ -33,7 +33,7 @@ import numpy as np -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -90,7 +90,7 @@ def numpy_array_to_QImage(numpy_array: np.ndarray) -> QImage | None: class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() uic.loadUi("mainwidget.ui", self) @@ -174,7 +174,7 @@ def on_load(self): self.refresh_HSV() - def show_result(self): + def show_result(self) -> None: if not self.result_img: return @@ -184,12 +184,12 @@ def show_result(self): ) self.lbView.setPixmap(pixmap) - def _update_pen_color(self): + def _update_pen_color(self) -> None: palette = self.pbPenColor.palette() palette.setColor(QPalette.Button, self.pen_color) self.pbPenColor.setPalette(palette) - def _choose_color(self): + def _choose_color(self) -> None: color = QColorDialog.getColor(self.pen_color) if not color.isValid(): return @@ -199,7 +199,7 @@ def _choose_color(self): self._update_pen_color() self.refresh_HSV() - def _draw_contours(self, result_img, contours): + def _draw_contours(self, result_img, contours) -> None: line_size = self.sbPenWidth.value() line_type = self.cbPenStyle.currentData() line_color = self.pen_color @@ -213,7 +213,7 @@ def _draw_contours(self, result_img, contours): p.end() - def refresh_HSV(self): + def refresh_HSV(self) -> None: hue_from = self.slHueFrom.value() hue_to = max(hue_from, self.slHueTo.value()) @@ -302,7 +302,7 @@ def refresh_HSV(self): self.show_result() - def save_settings(self): + def save_settings(self) -> None: settings = QSettings(CONFIG_FILE_NAME, QSettings.IniFormat) settings.setValue(self.objectName(), self.saveGeometry()) @@ -337,7 +337,7 @@ def save_settings(self): settings.setValue("lastLoadPath", self.last_load_path) - def load_settings(self): + def load_settings(self) -> None: settings = QSettings(CONFIG_FILE_NAME, QSettings.IniFormat) geometry = settings.value(self.objectName()) @@ -386,12 +386,12 @@ def load_settings(self): sp.setMaximum(w.maximum()) sp.setValue(w.value()) - def resizeEvent(self, e): + def resizeEvent(self, e) -> None: super().resizeEvent(e) self.show_result() - def closeEvent(self, e): + def closeEvent(self, e) -> None: self.save_settings() super().closeEvent(e) diff --git a/opencv__examples/draw_overlay_current_datetime/main.py b/opencv__examples/draw_overlay_current_datetime/main.py index aa03fc3da..cec6777b6 100644 --- a/opencv__examples/draw_overlay_current_datetime/main.py +++ b/opencv__examples/draw_overlay_current_datetime/main.py @@ -15,7 +15,7 @@ def draw_overlay( img: numpy.ndarray, text: str, color_text=(255, 255, 255), max_text_height_percent=5 -): +) -> None: h, w, _ = img.shape max_text_height = (h / 100) * max_text_height_percent @@ -46,7 +46,7 @@ def draw_overlay_current_datetime( datetime_fmt="%d/%m/%y %H:%M:%S", color_text=(255, 255, 255), max_text_height_percent=5, -): +) -> None: text = dt.datetime.now().strftime(datetime_fmt) draw_overlay(img, text, color_text, max_text_height_percent) diff --git a/opencv__examples/screenshots_in_window.py b/opencv__examples/screenshots_in_window.py index 3b52bf669..9c0229788 100644 --- a/opencv__examples/screenshots_in_window.py +++ b/opencv__examples/screenshots_in_window.py @@ -18,7 +18,7 @@ target_array = None -def go(): +def go() -> None: global target_array while True: if target_array is not None: diff --git a/opencv__examples/show_with_pyqt5.py b/opencv__examples/show_with_pyqt5.py index 42d41303e..b91b975a8 100644 --- a/opencv__examples/show_with_pyqt5.py +++ b/opencv__examples/show_with_pyqt5.py @@ -16,12 +16,12 @@ class ThreadOpenCV(QThread): changePixmap = pyqtSignal(QImage) - def __init__(self, source): + def __init__(self, source) -> None: super().__init__() self.source = source - def run(self): + def run(self) -> None: # SOURCE: https://stackoverflow.com/a/44404713/5909792 cap = cv2.VideoCapture(self.source) while True: @@ -41,7 +41,7 @@ def run(self): class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.label_video = QLabel() @@ -59,10 +59,10 @@ def __init__(self): self.setLayout(main_layout) - def playVideo(self): + def playVideo(self) -> None: self.thread.start() - def setImage(self, image): + def setImage(self, image) -> None: self.label_video.setPixmap(QPixmap.fromImage(image)) diff --git a/pandas__examples/Analysis jira/download_jira_log.py b/pandas__examples/Analysis jira/download_jira_log.py index f95c20732..fab52a3f5 100644 --- a/pandas__examples/Analysis jira/download_jira_log.py +++ b/pandas__examples/Analysis jira/download_jira_log.py @@ -49,14 +49,14 @@ def clear_jira_xml(xml_content: bytes) -> bytes: root = BeautifulSoup(xml_content, "html.parser") - def mask_tag_content(css_selector, attr=None): + def mask_tag_content(css_selector, attr=None) -> None: for x in root.select(css_selector): x.string = "..." if attr: x[attr] = "..." - def delete_tag(css_selector): + def delete_tag(css_selector) -> None: for x in root.select(css_selector): x.decompose() diff --git a/parse_test_progress.py b/parse_test_progress.py index 872148698..306f1b0bd 100644 --- a/parse_test_progress.py +++ b/parse_test_progress.py @@ -7,7 +7,7 @@ import re -def parse(text, append_test_case_list=True): +def parse(text, append_test_case_list=True) -> None: total_value = 0 total_max_value = 0 diff --git a/peewee__examples/SqliteQueueDatabase/db.py b/peewee__examples/SqliteQueueDatabase/db.py index 6f4c221e5..2ea9957cd 100644 --- a/peewee__examples/SqliteQueueDatabase/db.py +++ b/peewee__examples/SqliteQueueDatabase/db.py @@ -61,7 +61,7 @@ def get_inherited_models(cls) -> list[Type[Self]]: return sorted(cls.__subclasses__(), key=lambda x: x.__name__) @classmethod - def print_count_of_tables(cls): + def print_count_of_tables(cls) -> None: items = [] for sub_cls in cls.get_inherited_models(): name = sub_cls.__name__ @@ -80,7 +80,7 @@ def count(cls, filters: Iterable = None) -> int: def to_dict(self) -> dict[str, Any]: return model_to_dict(self, recurse=False) - def __str__(self): + def __str__(self) -> str: fields = [] for k, field in self._meta.fields.items(): v = getattr(self, k) diff --git a/peewee__examples/backup__examples/backup_via_api.py b/peewee__examples/backup__examples/backup_via_api.py index 3ca9ee5c8..bde8de1dd 100644 --- a/peewee__examples/backup__examples/backup_via_api.py +++ b/peewee__examples/backup__examples/backup_via_api.py @@ -10,7 +10,7 @@ from peewee import SqliteDatabase -def backup(db: SqliteDatabase, file_name: Path | str): +def backup(db: SqliteDatabase, file_name: Path | str) -> None: dst = sqlite3.connect(file_name) db.connection().backup(dst) dst.close() diff --git a/peewee__examples/backup__examples/backup_via_vacuum_into.py b/peewee__examples/backup__examples/backup_via_vacuum_into.py index 901700713..522700bce 100644 --- a/peewee__examples/backup__examples/backup_via_vacuum_into.py +++ b/peewee__examples/backup__examples/backup_via_vacuum_into.py @@ -8,7 +8,7 @@ from peewee import SqliteDatabase -def backup(db: SqliteDatabase, file_name: Path | str): +def backup(db: SqliteDatabase, file_name: Path | str) -> None: Path(file_name).unlink(missing_ok=True) db.connection().execute("VACUUM INTO ?", (str(file_name),)) diff --git a/peewee__examples/backup__examples/common.py b/peewee__examples/backup__examples/common.py index dbc371ce0..c1178a22a 100644 --- a/peewee__examples/backup__examples/common.py +++ b/peewee__examples/backup__examples/common.py @@ -23,7 +23,7 @@ class Meta: database = db @classmethod - def fill(cls): + def fill(cls) -> None: count = cls.select().count() for i in range(5): cls.create( @@ -32,12 +32,12 @@ def fill(cls): ) @classmethod - def print(cls): + def print(cls) -> None: for info in cls.select(): print(info) @classmethod - def print_from(cls, file_name: str | Path): + def print_from(cls, file_name: str | Path) -> None: connection = sqlite3.connect(file_name) try: for info in connection.execute(f"SELECT * FROM {cls._meta.table_name}"): @@ -45,14 +45,14 @@ def print_from(cls, file_name: str | Path): except Exception as e: print(f"[#] {e}") - def __str__(self): + def __str__(self) -> str: return f"Info<#{self.id} first_name={self.first_name!r} second_name={self.second_name!r}>" def run_test( backup: Callable, file_name_backup: Path | str, -): +) -> None: print("[db backup] Print:") Info.print_from(file_name_backup) print() diff --git a/peewee__examples/custom_field__EnumField/db_enum_field.py b/peewee__examples/custom_field__EnumField/db_enum_field.py new file mode 100644 index 000000000..ca8c83c1e --- /dev/null +++ b/peewee__examples/custom_field__EnumField/db_enum_field.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +import enum +from typing import Type, Any + +from peewee import CharField + + +class EnumField(CharField): + """ + This class enable an Enum like field for Peewee + """ + + def __init__(self, choices: Type[enum.Enum], *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + + self.choices: Type[enum.Enum] = choices + self.max_length: int = 255 + + def db_value(self, value: Any) -> Any: + if value is None: + return + + if isinstance(value, enum.Enum): + return value.value + + return value + + def python_value(self, value: Any) -> Any: + if value is None: + return + + type_value_enum = type(list(self.choices)[0].value) + value_enum = type_value_enum(value) + return self.choices(value_enum) diff --git a/peewee__examples/custom_field__EnumField/main.py b/peewee__examples/custom_field__EnumField/main.py new file mode 100644 index 000000000..06fb225f5 --- /dev/null +++ b/peewee__examples/custom_field__EnumField/main.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +import enum + +# pip install peewee +from peewee import SqliteDatabase, Model + +from db_enum_field import EnumField + + +@enum.unique +class TaskRunStatusEnum(enum.StrEnum): + PENDING = enum.auto() + RUNNING = enum.auto() + FINISHED = enum.auto() + STOPPED = enum.auto() + UNKNOWN = enum.auto() + ERROR = enum.auto() + + +db = SqliteDatabase(":memory:", pragmas={"foreign_keys": 1}) + + +class BaseModel(Model): + class Meta: + database = db + + +class TaskRun(BaseModel): + status = EnumField(choices=TaskRunStatusEnum, default=TaskRunStatusEnum.PENDING) + + +db.connect() +db.create_tables([TaskRun]) + + +if __name__ == "__main__": + run1 = TaskRun.create() + run2 = TaskRun.create(status=TaskRunStatusEnum.FINISHED) + + query = TaskRun.select().where(TaskRun.status == TaskRunStatusEnum.FINISHED) + print(query) + print(list(query)) + # SELECT "t1"."id", "t1"."status" FROM "taskrun" AS "t1" WHERE ("t1"."status" = 'finished') + # [] + + print() + + query = TaskRun.select().where(TaskRun.status.contains("ING")) + print(query) + print(list(query)) + # SELECT "t1"."id", "t1"."status" FROM "taskrun" AS "t1" WHERE ("t1"."status" LIKE '%ING%') + # [] diff --git a/peewee__examples/custom_func__redefine_upper.py b/peewee__examples/custom_func__redefine_upper.py index d4c49fd37..5fe5d73fd 100644 --- a/peewee__examples/custom_func__redefine_upper.py +++ b/peewee__examples/custom_func__redefine_upper.py @@ -7,7 +7,7 @@ from peewee import SqliteDatabase -def run_sql(connect): +def run_sql(connect) -> None: print(connect.execute("""SELECT "ы", UPPER("ы") """).fetchone()) print(connect.execute("""SELECT "s", UPPER("s") """).fetchone()) print(connect.execute("""SELECT 1 WHERE UPPER("ы") LIKE UPPER("Ы") """).fetchone()) @@ -15,7 +15,7 @@ def run_sql(connect): print(connect.execute("""SELECT 1 WHERE "s" LIKE "S" """).fetchone()) -def db_func(): +def db_func() -> None: print("[db_func]") db = SqliteDatabase(":memory:") @@ -50,7 +50,7 @@ def upper(value: str) -> str | None: """ -def db_create_function(): +def db_create_function() -> None: print("[db_create_function]") db = SqliteDatabase(":memory:") diff --git a/peewee__examples/custom_func__redefine_upper__check_speed.py b/peewee__examples/custom_func__redefine_upper__check_speed.py index 8f1deb9ad..cee35cd06 100644 --- a/peewee__examples/custom_func__redefine_upper__check_speed.py +++ b/peewee__examples/custom_func__redefine_upper__check_speed.py @@ -85,7 +85,7 @@ class Stocks(BaseModel): print() -def run_test(): +def run_test() -> None: elapsed = timeit( stmt="Stocks.select().where(fn.UPPER(Stocks.trans).ilike(fn.UPPER('%SELL%'))).count()", globals=dict(Stocks=Stocks, fn=fn), diff --git a/peewee__examples/db_peewee_meta_model.py b/peewee__examples/db_peewee_meta_model.py index fe4e48497..6564853ef 100644 --- a/peewee__examples/db_peewee_meta_model.py +++ b/peewee__examples/db_peewee_meta_model.py @@ -56,7 +56,7 @@ def get_inherited_models(cls) -> list[Type["MetaModel"]]: return sorted(cls.__subclasses__(), key=lambda x: x.__name__) @classmethod - def print_count_of_tables(cls): + def print_count_of_tables(cls) -> None: items = [] for sub_cls in cls.get_inherited_models(): name = sub_cls.__name__ @@ -75,7 +75,7 @@ def count(cls, filters: Iterable = None) -> int: def to_dict(self) -> dict[str, Any]: return model_to_dict(self, recurse=False) - def __str__(self): + def __str__(self) -> str: fields = [] for k, field in self._meta.fields.items(): v = getattr(self, k) diff --git a/peewee__examples/games_and_genres/main.py b/peewee__examples/games_and_genres/main.py index 3246086fd..08b171d27 100644 --- a/peewee__examples/games_and_genres/main.py +++ b/peewee__examples/games_and_genres/main.py @@ -22,7 +22,7 @@ class Game(BaseModel): def get_genres(self) -> list["Genre"]: return [link.genre for link in self.links_to_genres] - def append_genres(self, *genres: list["Genre"]): + def append_genres(self, *genres: list["Genre"]) -> None: for genre in genres: GameToGenre.get_or_create(game=self, genre=genre) diff --git a/peewee__examples/hello_world/main.py b/peewee__examples/hello_world/main.py index 2de398fd5..c84820266 100644 --- a/peewee__examples/hello_world/main.py +++ b/peewee__examples/hello_world/main.py @@ -19,7 +19,7 @@ class Info(Model): class Meta: database = db - def __str__(self): + def __str__(self) -> str: return f"Info<#{self.id} first_name={self.first_name!r} second_name={self.second_name!r} state={self.state}>" diff --git a/peewee__examples/hello_world__diary/main.py b/peewee__examples/hello_world__diary/main.py index 173628c39..22baaa69d 100644 --- a/peewee__examples/hello_world__diary/main.py +++ b/peewee__examples/hello_world__diary/main.py @@ -28,7 +28,7 @@ class Diary(BaseModel): created_date = DateTimeField(default=dt.datetime.now) @staticmethod - def print_table(search_text: str = None): + def print_table(search_text: str = None) -> None: """Print all diaries""" header_fmt = "{:<3} | {:<50} | {:<19}" @@ -51,7 +51,7 @@ def print_table(search_text: str = None): print() - def __str__(self): + def __str__(self) -> str: return ( f"Diary<" f"#{self.id} " @@ -71,7 +71,7 @@ def __str__(self): Diary.create(content="The quick brown fox jumps over the lazy dog.") -def add_diary(): +def add_diary() -> None: """Add diary""" data = input("Enter your diary: ").strip() @@ -80,7 +80,7 @@ def add_diary(): print("Saved successfully.") -def view_diaries(search_query=None): +def view_diaries(search_query=None) -> None: """View previous diaries""" query = Diary.select().order_by(Diary.created_date.desc()) @@ -105,7 +105,7 @@ def view_diaries(search_query=None): break -def search_diaries(): +def search_diaries() -> None: """Search diaries""" view_diaries(input("Search query: ")) @@ -121,7 +121,7 @@ def search_diaries(): ) -def menu_loop(): +def menu_loop() -> None: choice = None while choice != "q": for key, value in MENU.items(): diff --git a/peewee__examples/hello_world__diary__encryption_AES_key_for_evere_diary__with_master_key/main.py b/peewee__examples/hello_world__diary__encryption_AES_key_for_evere_diary__with_master_key/main.py index 36c59a608..a3cb75b15 100644 --- a/peewee__examples/hello_world__diary__encryption_AES_key_for_evere_diary__with_master_key/main.py +++ b/peewee__examples/hello_world__diary__encryption_AES_key_for_evere_diary__with_master_key/main.py @@ -83,7 +83,7 @@ def get_key(self, master_key: str) -> str: return f"ERROR: {e}" @staticmethod - def print_table(master_key: str = ENCRYPT_MASTER_KEY): + def print_table(master_key: str = ENCRYPT_MASTER_KEY) -> None: """Print all diaries""" header_fmt = "{:<3} | {:<50} | {:<50} | {:<50} | {:<50} | {:<19}" @@ -130,7 +130,7 @@ def print_table(master_key: str = ENCRYPT_MASTER_KEY): ) -def add_diary(master_key: str = ENCRYPT_MASTER_KEY): +def add_diary(master_key: str = ENCRYPT_MASTER_KEY) -> None: """Add diary""" data = input("Enter your diary: ").strip() @@ -140,7 +140,7 @@ def add_diary(master_key: str = ENCRYPT_MASTER_KEY): print() -def view_diaries(master_key: str = ENCRYPT_MASTER_KEY): +def view_diaries(master_key: str = ENCRYPT_MASTER_KEY) -> None: """View previous diaries""" query = Diary.select().order_by(Diary.created_date.desc()) @@ -170,7 +170,7 @@ def view_diaries(master_key: str = ENCRYPT_MASTER_KEY): } -def menu_loop(): +def menu_loop() -> None: choice = None while choice != "q": for key, value in MENU.items(): diff --git a/peewee__examples/hello_world__diary__encryption_all_in_one_AES/main.py b/peewee__examples/hello_world__diary__encryption_all_in_one_AES/main.py index 0e51b2325..892ae1c94 100644 --- a/peewee__examples/hello_world__diary__encryption_all_in_one_AES/main.py +++ b/peewee__examples/hello_world__diary__encryption_all_in_one_AES/main.py @@ -62,7 +62,7 @@ def get_content(self, key: str) -> str: return f"ERROR: {e}" @staticmethod - def print_table(key: str = ENCRYPT_KEY): + def print_table(key: str = ENCRYPT_KEY) -> None: """Print all diaries""" header_fmt = "{:<3} | {:<50} | {:<50} | {:<19}" @@ -95,7 +95,7 @@ def print_table(key: str = ENCRYPT_KEY): ) -def add_diary(key: str = ENCRYPT_KEY): +def add_diary(key: str = ENCRYPT_KEY) -> None: """Add diary""" data = input("Enter your diary: ").strip() @@ -105,7 +105,7 @@ def add_diary(key: str = ENCRYPT_KEY): print() -def view_diaries(key: str = ENCRYPT_KEY): +def view_diaries(key: str = ENCRYPT_KEY) -> None: """View previous diaries""" query = Diary.select().order_by(Diary.created_date.desc()) @@ -135,7 +135,7 @@ def view_diaries(key: str = ENCRYPT_KEY): } -def menu_loop(): +def menu_loop() -> None: choice = None while choice != "q": for key, value in MENU.items(): diff --git a/peewee__examples/hello_world__diary__encryption_all_in_one_AES/utils/security.py b/peewee__examples/hello_world__diary__encryption_all_in_one_AES/utils/security.py index 725bf3de3..c91120fb1 100644 --- a/peewee__examples/hello_world__diary__encryption_all_in_one_AES/utils/security.py +++ b/peewee__examples/hello_world__diary__encryption_all_in_one_AES/utils/security.py @@ -19,7 +19,7 @@ class AuthenticationError(Exception): class CryptoAES: - def __init__(self, key: (str, bytes)): + def __init__(self, key: (str, bytes)) -> None: if isinstance(key, str): key = key.encode("utf-8") diff --git a/peewee__examples/serialization__model_to_dict__dict_to_model/main.py b/peewee__examples/serialization__model_to_dict__dict_to_model/main.py index b87dcc5bf..85a10a0e5 100644 --- a/peewee__examples/serialization__model_to_dict__dict_to_model/main.py +++ b/peewee__examples/serialization__model_to_dict__dict_to_model/main.py @@ -24,7 +24,7 @@ class Person(BaseModel): name = CharField() birthday = DateField() - def __str__(self): + def __str__(self) -> str: return ( f"Person(id={self.id} name={self.name!r} birthday={self.birthday} " f'pets={", ".join(p.name for p in self.pets)!r})' @@ -36,7 +36,7 @@ class Pet(BaseModel): name = CharField() animal_type = CharField() - def __str__(self): + def __str__(self) -> str: return f"Pet(id={self.id} name={self.name!r} owner={self.owner.name!r} self.animal_type={self.animal_type!r})" diff --git a/pens_calcs/pens_calc.py b/pens_calcs/pens_calc.py deleted file mode 100644 index 6d51873a1..000000000 --- a/pens_calcs/pens_calc.py +++ /dev/null @@ -1,555 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -__author__ = 'ipetrash' - - -import common - - -# TODO: сделать -# http://www.pfrf.ru/thm/common/mod/pensCalc/js/public.js -# TODO: добавить аннотации параметрам и возвращаемому значению - -# # Служба в армии -# yearsInArmy, monthInArmy, daysInArmy - -# # Уход за нетрудоспособными -# careYears, careMonth, careDays - -# # Дети, не более 4х -# TODO: посмотреть к каким полям относится и переименвать соответственно и в формулах их использования -# childrenCount1, childrenVac1 - - -# def pens_calc(gender, birthDate, pensionTarif, -# yearsInArmy, monthInArmy, daysInArmy, -# careYears, careMonth, careDays, -# childrenCount1, childrenVac1, -# retireWorkWithoutPension, -# careerLength, -# revenue, -# SZPeriod -# ): - - - -# var pensionForm = $(".calc-form") -# var persionFormInputs = pensionForm.find("input,select") -# var calcResult = $(".pensionCalcResult") -# var calcResultToday = $(".pensionCalcResultToday") -# var socialPensionWarning = $("#socialPensionWarning") -# var socialPensionWarning2 = $("#socialPensionWarning2") -# var combinationWarning = $("#combinationWarning") -# var enterParamsWarning = $("#enterParamsWarning") -# var enterGenderWarning = $("#enterGenderWarning") -# var enterBYWarning = $("#enterBYWarning") -# var enterBYWarning2 = $("#enterBYWarning2") -# var enterBYWarning3 = $("#enterBYWarning3") -# var alreadyPensioneer = $("#alreadyPensioneer") -# var wrongFee = $("#wrongFee") -# var noTarif = $("#noTarif") -# var ending = $(".ending") -# var newCoefSummSmall = $(".newCoefSummSmall") -# var personOSsmall = $(".personOSsmall") -# -# var armySection = pensionForm.find('.army-section') - -# TODO: возможно будет полезно узнать что скрыто в той секции -# armySection.hide() -# persionFormInputs.filter('[type="radio"][name="noArmy"]').click(function () { -# if($(this).val() == 2) { -# armySection.slideDown(150) -# } -# else { -# armySection.slideUp(150) -# } -# }) - -# var textInputs = persionFormInputs.filter("input[type='text']") -# var prevValues = [] - - -# var careerPlanQuestions = $("div.careerPlanQuestions") -# var careerPlanSwitch = $("input[name='careerPlan']") -# -# function revealCPQuestionsBlocks(switchValue) { -# careerPlanQuestions.hide() -# switch(switchValue) { -# case '1': -# //наемный работник -# careerPlanQuestions.filter(".careerPlan1").show() -# break -# case '2': -# //самозанятый -# careerPlanQuestions.filter(".careerPlan2").show() -# break -# case '3': -# //совмещающий -# careerPlanQuestions.show() -# break -# } -# } -# -# revealCPQuestionsBlocks(careerPlanSwitch.filter(':checked').val()) -# careerPlanSwitch.change(function () { -# revealCPQuestionsBlocks($(this).val()) -# }) - - -# TODO: поле в скрипте не имеет значения, вообще -gender = "1" -# if(gender.length < 1) { -# enterGenderWarning.show() -# $(output_area).slideDown() -# return -# } - -# TODO: поле в скрипте не имеет значения, вообще -birthDate = "1992" -# if(!birthDate.match(/\d{4}/)) { -# enterBYWarning.show() -# $(output_area).slideDown() -# return -# } - -# TODO: узнать что скрывается за полем -# TODO: пусть будет пока 0 -pensionTarif = 0 -# var pensionTarif = persionFormInputs.filter('[name="pensionTarif"]:checked') -# if(pensionTarif.length < 1) { -# noTarif.show() -# $(output_area).slideDown() -# return -# } -# pensionTarif = parseInt(pensionTarif.val()) - -# Общий расчет - -# Служба в армии -yearsInArmy = 1 -monthInArmy = 0 -daysInArmy = 0 - -# Стаж в армии -VS = ((((yearsInArmy * 12) + monthInArmy) / 12 * 365) + daysInArmy) / 365 - -# Коэффициент стажа -VSK = VS * common.VSkoef - -# Уход за нетрудоспособными -careYears = 1 -careMonth = 0 -careDays = 0 - -# Стаж ухода за нетрудоспособными -CR = ((((careYears * 12) + careMonth) / 12 * 365) + careDays) / 365 - -# Коэффициент ухода -CRK = CR * common.CRkoef - -# Дети, не более 4х -childrenCount1 = 1 -if childrenCount1 < 0: - childrenCount1 = 0 - -elif childrenCount1 > 4: - childrenCount1 = 4 - -# TODO: узнать что за childrenVac1 -# TODO: и что за стаж -# Стаж -childrenVac1 = 0 -if childrenVac1 < 0: - childrenVac1 = 0 - -elif childrenVac1 > 1.5: - childrenVac1 = 1.5 - - -# NOTE: только внутри кода объявляется -# Коэффициент -KD = 0.0 - -if childrenCount1 > 0: - if childrenCount1 > 0: - KD += 1.8 - - if childrenCount1 > 1: - KD += 3.6 - - if childrenCount1 > 2: - KD += 5.4 - - if childrenCount1 > 3: - KD += 5.4 - - KD *= childrenVac1 - childrenVac1 *= childrenCount1 - -# Коэффициент за нетрудовые периоды -NK = KD + CRK + VSK - -# Стаж за нетрудовые периоды -NS = childrenVac1 + VS + CR - -# NOTE: сколько после пенсионного возраста собираешься работать неполучая пенсию -retireWorkWithoutPension = 5 -if retireWorkWithoutPension > 10: - retireWorkWithoutPension = 10 - -# Расчеты в зависимости от типа занятости -# TODO: узнать возможные варианты значения -careerPlan = '1' - -# Наемный работник -def calcEmpl(fee: int, careerLength: int, pensionTarif: int): - """ - - :param fee: Зарплата - :param careerLength: Стаж - - # TODO: узнать что за тариф такой - :param pensionTarif: - :return: - """ - - if fee < 0: - fee = 0 - - if fee > common.ZPM: - fee = common.ZPM - - if careerLength < 0: - careerLength = 0 - - # TODO: бросать исключение, узнать какой текст тут скрыт - # if careerLength > 60) { - # enterBYWarning3.show() - # $(output_area).slideDown() - # return false - - # TODO: бросать исключение, узнать какой текст тут скрыт - # # Зарплата меньше мрот - # if careerLength > 0 and fee < common.MROT: - # wrongFee.show() - # $(output_area).slideDown() - # return false - # } - - # Пенсионные коэффициенты за трудовой период - IPKtrud = (fee / common.ZPM) * common.KNPG[pensionTarif] * (careerLength * 10) - - # TODO: Проследить за S и заменить - return { - 'S': careerLength, - 'IPKtrud': IPKtrud, - } - -def calcSZ(SZPeriod: int, revenue: int, pensionTarif: int): - """ - - :param revenue: Годовой доход - :param SZPeriod: Стаж - - # TODO: узнать что за тариф такой - :param pensionTarif: - :return: - """ - - if SZPeriod < 0: - SZPeriod = 0 - - if revenue < 0: - revenue = 0 - - # TODO: разобраться какие значения может иметь pensionTarif - SVGDkoeff = 16 if pensionTarif == 0 else 10 - - # Сумма страховых взносов на страховую пенсию, начисленных исходя из размера годового дохода - if revenue < common.GDmax: - SVGD = (SVGDkoeff * (common.MROT * 0.26 * 12)) / 26 - else: - SVGD = (SVGDkoeff * (common.MROT * 0.26 * 12) + ((revenue - common.GDmax) * 0.01)) / 26 - - # Пенсионные коэффициенты за трудовой период - IPKtrud = (SVGD / common.MSSV) * SZPeriod * 10 - - # TODO: отследить и заменить S - return { - 'S': SZPeriod, - 'IPKtrud': IPKtrud - } - -calcPart = None -calcPartEmpl = None -calcPartSZ = None -IPKtrud = None -S = None - -if careerPlan == '1': - # Наемный работник - calcPart = calcEmpl() - # TODO: добавить проверку, проверить какое значение может возвращаться из функции и как влияет - # возврат значения тут - # - # if(calcPart === false) return false - - # Стаж - S = calcPart.S - - # Пенсионные коэффициенты - IPKtrud = calcPart.IPKtrud - -elif careerPlan == '2': - # Самозанятый - calcPart = calcSZ() - - # Стаж - S = calcPart.S - - # Пенсионные коэффициенты - IPKtrud = calcPart.IPKtrud - -elif careerPlan == '3': - # Совмещающий - calcPartEmpl = calcEmpl() - # TODO: добавить проверку, проверить какое значение может возвращаться из функции и как влияет - # возврат значения тут - # - # if(calcPartEmpl === false) return false - - calcPartSZ = calcSZ() - - # Количество пенсионных коэффициентов свыше максимально установленного значения в год, полученных при совмещённой деятельности - combinePeriod = 0 - # TODO: проверить - # if(combinePeriod.length < 1) { - # combinePeriod = 0 - # persionFormInputs.filter('#combinePeriod').val(combinePeriod) - # } - # TODO: проверить - # if combinePeriod > Math.min(calcPartEmpl.S, calcPartSZ.S)) { - # combinationWarning.show() - # $(output_area).slideDown() - # return false - # } - - # Годовой пенсионный коэффициент, получаемый гражданином в года совмещения деятельности - IPKemp = calcPartEmpl.IPKtrud * combinePeriod / calcPartEmpl.S - IPKsz = calcPartSZ.IPKtrud * combinePeriod / calcPartSZ.S - IPKo = (IPKsz + IPKemp) / combinePeriod - if IPKo > 10: - IPKo = 10 - - IPKis = IPKo * combinePeriod - - # Стаж - S = calcPartEmpl.S + calcPartSZ.S - combinePeriod - - # Пенсионные коэффициенты - IPKtrud = (calcPartSZ.IPKtrud - IPKsz) + (calcPartEmpl.IPKtrud - IPKemp) + IPKis - if combinePeriod == 0: - IPKtrud = calcPartSZ.IPKtrud + calcPartEmpl.IPKtrud - - -# Переходный период для наемных и самозанятых -if careerPlan == '1' or careerPlan == '2': - IPKtrud2015 = 0 - IPKtrud2021 = 0 - - fee = 10000 - revenue = 1 - if revenue < 0: - revenue = 0 - - # Сумма страховых взносов на страховую пенсию, начисленных исходя из размера годового дохода - SVGD = 0 - SVGDkoeff = 16 if pensionTarif == 0 else 10 - - if revenue < common.GDmax: - SVGD = (SVGDkoeff * (common.MROT * 0.26 * 12)) / 26 - else: - SVGD = (SVGDkoeff * (common.MROT * 0.26 * 12) + ((revenue - common.GDmax) * 0.01)) / 26 - - if S > 5: - IPKtrud2021 = IPKtrud * ((S - 5) / S) - - if careerPlan == '1': - IPKtrud2015 = fee / common.ZPM * 10 - - elif careerPlan == '2': - IPKtrud2015 = (SVGD / common.MSSV) * 10 - - elif S < 6: - if careerPlan == '1': - IPKtrud2015 = fee / common.ZPM * 10 - - elif careerPlan == '2': - IPKtrud2015 = (SVGD / common.MSSV) * 10 - - # KNPG = 1 - if pensionTarif == '0': - IPKtrud2015 = (S > 0 ? Math.min(8.26, IPKtrud2015) : 0) + (S > 1 ? Math.min(8.70, IPKtrud2015) : 0) + - (S > 2 ? Math.min(9.13, IPKtrud2015) : 0) + (S > 3 ? Math.min(9.57, IPKtrud2015) : 0) - - # KNPG = 0.625 - else: - IPKtrud2015 = (S > 0 ? Math.min(8.26, IPKtrud2015) : 0) + (S > 1 ? Math.min(5.43, IPKtrud2015) : 0) + - (S > 2 ? Math.min(5.71, IPKtrud2015) : 0) + (S > 3 ? Math.min(5.98, IPKtrud2015) : 0) - - IPKtrud = IPKtrud2015 + IPKtrud2021 - - -# TODO: какое-то обнуление значений в редакторе полей -# if(careerPlan == '1') { -# persionFormInputs.filter('#SZPeriod').val(0) -# persionFormInputs.filter('#revenue').val(0) -# } -# else { -# if(careerPlan == '2') { -# persionFormInputs.filter('#careerLength').val(0) -# persionFormInputs.filter('#fee').val(0) -# } -# } - -# Пенсионные коэффициенты -IPK = (IPKtrud + NK) * common.SPKop[retireWorkWithoutPension] - -# Общий стаж -OS = S + NS - -# # NOTE: Установка значений -# newCoefSummSmall.html((Math.round(IPK * 100) / 100).toString()) -# personOSsmall.html((Math.round(OS * 100) / 100).toString()) - - -var WR = OS.toString().substr(-1) - -ending.html('лет') - -if(WR == 1) { - ending.html('год') -} -else { - if(WR >= 2 && WR <= 4) { - ending.html('года') - } -} - -# пересчёт права выхода на пенсию по стажу (каждому году свой минимальный стаж) -$(output_area).hide() -if(S == 0 && OS < 8) { - socialPensionWarning.show() - $(output_area).slideDown() - return false -} - -if(S == 1 && OS < 9) { - socialPensionWarning.show() - $(output_area).slideDown() - return false -} - -if(S == 2 && OS < 10) { - socialPensionWarning.show() - $(output_area).slideDown() - return false -} - -if(S == 3 && OS < 11) { - socialPensionWarning.show() - $(output_area).slideDown() - return false -} - -if(S == 4 && OS < 12) { - socialPensionWarning.show() - $(output_area).slideDown() - return false -} - -if(S == 5 && OS < 13) { - socialPensionWarning.show() - $(output_area).slideDown() - return false -} - -if(S == 6 && OS < 14) { - socialPensionWarning.show() - $(output_area).slideDown() - return false -} - -if(S == 7 && OS < 15) { - socialPensionWarning.show() - $(output_area).slideDown() - return false -} - -//пересчёт права выхода на пенсию по ИПК (каждому году свой минимальный ИПК) -if(S == 0 && IPK < 11.4) { - socialPensionWarning.show() - $(output_area).slideDown() - return false -} - -if(S == 1 && IPK < 13.8) { - socialPensionWarning.show() - $(output_area).slideDown() - return false -} - -if(S == 2 && IPK < 16.2) { - socialPensionWarning.show() - $(output_area).slideDown() - return false -} - -if(S == 3 && IPK < 18.6) { - socialPensionWarning.show() - $(output_area).slideDown() - return false -} - -if(S == 4 && IPK < 21) { - socialPensionWarning2.show() - $(output_area).slideDown() - return false -} - -if(S == 5 && IPK < 23.4) { - socialPensionWarning.show() - $(output_area).slideDown() - return false -} - -if(S == 6 && IPK < 25.8) { - socialPensionWarning.show() - $(output_area).slideDown() - return false -} - -if(S == 7 && IPK < 28.2) { - socialPensionWarning.show() - $(output_area).slideDown() - return false -} - -if(S == 8 && IPK < 30) { - socialPensionWarning.show() - $(output_area).slideDown() - return false -} - -# Страховая пенсия -SP = (common.FIKS * common.BPKop[retireWorkWithoutPension]) + (IPK * common.CPK) - -var newCoefSummCont = $("#newCoefSumm") -newCoefSummCont.html((Math.round(IPK * 100) / 100).toString()) - -var pensionIPartCont = $("#pensionIPart") -pensionIPartCont.html((Math.round(SP * 100) / 100).toString()) - -var personOSCont = $("#personOS") -personOSCont.html((Math.round(OS * 100) / 100).toString()) diff --git a/pikabu_ru/profile_rating__tracking/db.py b/pikabu_ru/profile_rating__tracking/db.py index 0a9089d57..d6f5668d0 100644 --- a/pikabu_ru/profile_rating__tracking/db.py +++ b/pikabu_ru/profile_rating__tracking/db.py @@ -33,7 +33,7 @@ DIR_BACKUP = DIR / "backup" -def db_create_backup(backup_dir=DIR_BACKUP): +def db_create_backup(backup_dir=DIR_BACKUP) -> None: backup_dir.mkdir(parents=True, exist_ok=True) file_name = str(dt.datetime.today().date()) + ".sqlite" @@ -73,7 +73,7 @@ def get_inherited_models(cls) -> list[Type["BaseModel"]]: return sorted(cls.__subclasses__(), key=lambda x: x.__name__) @classmethod - def print_count_of_tables(cls): + def print_count_of_tables(cls) -> None: items = [] for sub_cls in cls.get_inherited_models(): name = sub_cls.__name__ @@ -89,7 +89,7 @@ def count(cls, filters: Iterable = None) -> int: query = query.filter(*filters) return query.count() - def __str__(self): + def __str__(self) -> str: fields = [] for k, field in self._meta.fields.items(): v = getattr(self, k) diff --git a/pixelate_image_gui/main.py b/pixelate_image_gui/main.py index 592f1afc8..cd121acd3 100644 --- a/pixelate_image_gui/main.py +++ b/pixelate_image_gui/main.py @@ -36,7 +36,7 @@ def pixelate(image, pixel_size=9, draw_margin=True): return image -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -52,7 +52,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class MainWindow(Qt.QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle(WINDOW_TITLE) @@ -125,7 +125,7 @@ def __init__(self): self._do_pixelate() - def load(self): + def load(self) -> None: image_filters = "Images (*.jpg *.jpeg *.png *.bmp)" self.file_name = Qt.QFileDialog.getOpenFileName( self, "Load image", self.last_load_path, image_filters @@ -138,7 +138,7 @@ def load(self): self._do_pixelate() - def save_as(self): + def save_as(self) -> None: image_filters = "Images (*.jpg *.jpeg *.png *.bmp)" # C:\Images\img.png -> C:\Images\img_pixelate.png @@ -152,7 +152,7 @@ def save_as(self): self.image_result.save(file_name) - def _do_pixelate(self): + def _do_pixelate(self) -> None: # Виджеты будут доступны только если стоит флаг на Result и картинка загружена ok = self.rb_result.isChecked() and self.image_source is not None self.pb_save_as.setEnabled(ok) @@ -169,7 +169,7 @@ def _do_pixelate(self): self.show_result() - def show_result(self): + def show_result(self) -> None: image_result = self.image_result if self.rb_result.isChecked() else self.image_source if not image_result: return @@ -186,7 +186,7 @@ def show_result(self): title = f"{WINDOW_TITLE}. {width}x{height} ({size.width()}x{size.height()}). {self.file_name}" self.setWindowTitle(title) - def resizeEvent(self, e): + def resizeEvent(self, e) -> None: super().resizeEvent(e) self.show_result() diff --git a/play mp3/pyglet_example.py b/play mp3/pyglet_example.py index d7b20377e..7ee7eeb93 100644 --- a/play mp3/pyglet_example.py +++ b/play mp3/pyglet_example.py @@ -15,7 +15,7 @@ # pyglet.app.run() -def play(file_name): +def play(file_name) -> None: dll_file_name = os.path.join(os.path.dirname(__file__), "avbin") pyglet.lib.load_library(dll_file_name) @@ -25,7 +25,7 @@ def play(file_name): player.play() - def update(dt): + def update(dt) -> None: if not player.playing: # Отпишем функцию, иначе при повторном вызове, иначе # будет двойной вызов при следующем воспроизведении diff --git a/play_audio/play_audio.py b/play_audio/play_audio.py index 027dda01f..a6df2a2f7 100644 --- a/play_audio/play_audio.py +++ b/play_audio/play_audio.py @@ -21,7 +21,7 @@ Phonon.createPath(audio, output) -def play(file_name): +def play(file_name) -> None: audio.setCurrentSource(Phonon.MediaSource(file_name)) audio.play() diff --git a/play_mp3_with_mp3play_module/play.py b/play_mp3_with_mp3play_module/play.py index 89cf0d626..10ac62ca3 100644 --- a/play_mp3_with_mp3play_module/play.py +++ b/play_mp3_with_mp3play_module/play.py @@ -10,7 +10,7 @@ import mp3play -def play(filename): +def play(filename) -> None: clip = mp3play.load(filename) clip.play() diff --git a/play_sound__pyqt/main.py b/play_sound__pyqt/main.py index 5008cc3aa..8229d0c1d 100644 --- a/play_sound__pyqt/main.py +++ b/play_sound__pyqt/main.py @@ -27,7 +27,7 @@ def play(file_name: str): player.setPlaylist(playlist) player.play() - def tick(): + def tick() -> None: if player.state() == QMediaPlayer.StoppedState: app.quit() @@ -38,7 +38,7 @@ def tick(): app.exec() -def play_async(file_name: str): +def play_async(file_name: str) -> None: # from threading import Thread # thread = Thread(target=play, args=(file_name,)) # thread.start() diff --git a/play_url_mp3/play_url_mp3.py b/play_url_mp3/play_url_mp3.py index f0bddd1d8..8a27d6685 100644 --- a/play_url_mp3/play_url_mp3.py +++ b/play_url_mp3/play_url_mp3.py @@ -30,7 +30,7 @@ "https://www.dropbox.com/sh/a4bwzhn0s584u73/AACgDRii1rtCmoL3mXEwlXDga/CallYourName.mp3?dl=1" ) - def play(): + def play() -> None: url = line_edit_url.text() # Выдираем из url имя файла diff --git a/playwright__examples/__init__.py b/playwright__examples/__init__.py new file mode 100644 index 000000000..f6a8eac64 --- /dev/null +++ b/playwright__examples/__init__.py @@ -0,0 +1,5 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + diff --git a/playwright__examples/get_screenshot.py b/playwright__examples/get_screenshot.py new file mode 100644 index 000000000..edd891a28 --- /dev/null +++ b/playwright__examples/get_screenshot.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +from pathlib import Path +from playwright.sync_api import sync_playwright + +DIR: Path = Path(__file__).resolve().parent +DIR_SCREENSHOTS: Path = DIR / "screenshots" +DIR_SCREENSHOTS.mkdir(parents=True, exist_ok=True) + + +with sync_playwright() as p: + for browser_type in [p.chromium, p.firefox, p.webkit]: + print(browser_type.name) + + browser = browser_type.launch() + page = browser.new_page() + + page.goto("https://github.com/gil9red") + + img_date: bytes = page.screenshot() + print(f"img_date: {img_date[:50]}...") + + path_page: Path = DIR_SCREENSHOTS / f"{browser_type.name}_page.png" + page.screenshot(path=path_page) + print(f"path_page: {path_page}") + + path_full_page: Path = DIR_SCREENSHOTS / f"{browser_type.name}_full_page.png" + page.screenshot(path=path_full_page, full_page=True) + print(f"path_full_page: {path_full_page}") + + print() diff --git a/playwright__examples/human_automation/__init__.py b/playwright__examples/human_automation/__init__.py new file mode 100644 index 000000000..3c994a1db --- /dev/null +++ b/playwright__examples/human_automation/__init__.py @@ -0,0 +1,4 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" diff --git a/playwright__examples/human_automation/examples/__init__.py b/playwright__examples/human_automation/examples/__init__.py new file mode 100644 index 000000000..3c994a1db --- /dev/null +++ b/playwright__examples/human_automation/examples/__init__.py @@ -0,0 +1,4 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" diff --git a/playwright__examples/human_automation/examples/github.com_gil9red.py b/playwright__examples/human_automation/examples/github.com_gil9red.py new file mode 100644 index 000000000..dfb200a0f --- /dev/null +++ b/playwright__examples/human_automation/examples/github.com_gil9red.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +# playwright>=1.61.0 +from playwright.sync_api import sync_playwright + +from human_automation.human_automation import HumanAutomation + +URL: str = "https://github.com/gil9red" + + +with sync_playwright() as p: + browser = p.chromium.launch(headless=False) + page = browser.new_page() + + human_automation = HumanAutomation(page) + + page.goto(URL, wait_until="domcontentloaded") + + part_url: str = "tab=repositories" + + def click_on_repositories() -> None: + link_locator = page.locator(f'nav a[href *= "{part_url}"]').first + human_automation.click(link_locator) + + human_automation.ensure_change_url( + action=click_on_repositories, + is_ok_url=lambda url: part_url in url, + ) + + print("\n") + human_automation.wait(300, 600) + + part_url: str = "/SimplePyScripts" + + def find_repository() -> None: + find_selector = 'input[placeholder="Find a repository…"]' + find_locator = page.locator(find_selector) + human_automation.type_text(find_locator, "SimplePyScripts") + + link_selector = ( + f'#user-repositories-list a[itemprop *= "name"][href *= "{part_url}"]' + ) + locator = page.locator(link_selector).first + + human_automation.click(locator) + + human_automation.ensure_change_url( + action=find_repository, + is_ok_url=lambda url: part_url in url, + ) + + human_automation.wait(300, 600) + print("\n") + + human_automation.move_mouse_to_center() + + # Step 1: Go /playwright__examples + part_url: str = "/playwright__examples" + + def click_on_step_1() -> None: + dir_locator = page.get_by_role("link", name=part_url[1:]).first + human_automation.click(dir_locator) + + human_automation.ensure_change_url( + action=click_on_step_1, + is_ok_url=lambda url: part_url in url, + ) + + print("\n") + human_automation.wait(300, 600) + + # Step 2: Go /playwright__examples/screenshots + part_url: str = f"{part_url}/screenshots" + + def click_on_step_2() -> None: + dir_locator = page.locator(f'a[href$="{part_url}"]:visible').first + human_automation.click(dir_locator) + + human_automation.ensure_change_url( + action=click_on_step_2, + is_ok_url=lambda url: url.endswith(part_url), + ) + + print("\n") + human_automation.wait(300, 600) + + # Step 3: Go /playwright__examples/screenshots/stealth + part_url: str = f"{part_url}/stealth" + + def click_on_step_3() -> None: + dir_locator = page.locator(f'a[href$="{part_url}"]:visible').first + human_automation.click(dir_locator) + + human_automation.ensure_change_url( + action=click_on_step_3, + is_ok_url=lambda url: part_url in url, + ) + + print("\n") + human_automation.wait(300, 600) + + # Step 4: Go /playwright__examples/screenshots/stealth/stealth_firefox_page.png + part_url: str = f"{part_url}/stealth_firefox_page.png" + + def click_on_step_4() -> None: + dir_locator = page.locator(f'a[href$="{part_url}"]:visible').first + human_automation.click(dir_locator) + + human_automation.ensure_change_url( + action=click_on_step_4, + is_ok_url=lambda url: part_url in url, + ) + + print("\n") + human_automation.wait(300, 600) + + # Download /playwright__examples/screenshots/stealth/stealth_firefox_page.png + img_locator = page.locator(f'img[src *= "{part_url}"]').first + print(img_locator) + + img_url: str = img_locator.get_attribute("src") + full_url: str = page.evaluate(f"new URL('{img_url}', window.location.href).href") + print(full_url) + + response = page.request.get(full_url) + img_bytes: bytes = response.body() + print(f"img_bytes ({len(img_bytes)} bytes): {img_bytes[:50]}...") + + page.wait_for_timeout(2_000) diff --git a/playwright__examples/human_automation/examples/store_steampowered_com.py b/playwright__examples/human_automation/examples/store_steampowered_com.py new file mode 100644 index 000000000..f5c093484 --- /dev/null +++ b/playwright__examples/human_automation/examples/store_steampowered_com.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +# playwright>=1.61.0 +from playwright.sync_api import sync_playwright + +from human_automation.human_automation import HumanAutomation + +URL: str = "https://store.steampowered.com/" + + +with sync_playwright() as p: + browser = p.chromium.launch(headless=False) + page = browser.new_page() + + human_automation = HumanAutomation(page) + + page.goto(URL, wait_until="domcontentloaded") + + categories_locator = page.get_by_label("Меню магазина").locator( + "button > div:has-text('Категории')" + ) + print(categories_locator) + human_automation.click(categories_locator) + + # View all tags + all_tags_locator = page.locator("a:has-text('Просмотреть все метки')") + print(all_tags_locator) + human_automation.click(all_tags_locator) + + # Free To Play + free_to_play_locator = page.get_by_role("button", name="Бесплатная игра") + print(categories_locator) + human_automation.click(free_to_play_locator) + + go_to_free_to_play_locator = page.get_by_text("Просмотреть все") + print(go_to_free_to_play_locator) + human_automation.click(go_to_free_to_play_locator) + + filters_locator = page.locator("//div[text()='Фильтры']/..").first + print(filters_locator) + human_automation.move_to(filters_locator) + + genres_frame_locator = filters_locator.locator("//div[text()='Жанры']/../..").first + print(genres_frame_locator) + human_automation.move_to(genres_frame_locator) + + genres_locator = genres_frame_locator.locator("//div[text()='Жанры']") + print(genres_locator) + human_automation.click(genres_locator) + + genres_all_locator = genres_frame_locator.locator("//div[text()='Показать больше']") + print(genres_all_locator) + human_automation.click(genres_all_locator) + + genre_shooter_locator = genres_frame_locator.locator("//div/a[text()='Шутер']") + print(genre_shooter_locator) + human_automation.click(genre_shooter_locator) + + sub_genres_frame_locator = filters_locator.locator( + "//div[text()='Поджанры']/../.." + ).first + print(sub_genres_frame_locator) + human_automation.move_to(sub_genres_frame_locator) + + genres_locator = sub_genres_frame_locator.locator("//div[text()='Поджанры']") + print(genres_locator) + human_automation.click(genres_locator) + + sub_genres_all_locator = sub_genres_frame_locator.locator( + "//div[text()='Показать больше']" + ) + print(sub_genres_all_locator) + human_automation.click(sub_genres_all_locator) + + fps_locator = sub_genres_frame_locator.locator( + "//div/a[text()='Шутер от первого лица']" + ) + print(fps_locator) + human_automation.click(fps_locator) + + human_automation.click(page.get_by_role("button", name="Показать больше")) + + human_automation.move_to( + page.locator("a[href *= '/app/'][role='button']:has(img[alt]):visible").first + ) + human_automation.wait(2_000, 4_000) + + for locator in page.locator( + "a[href *= '/app/'][role='button']:has(img[alt]):visible" + ).all(): + print(locator) + + name: str = locator.locator("img[alt]").get_attribute("alt") + URL: str = locator.get_attribute("href") + print(f"{name!r}: {URL}") + + human_automation.move_to(locator) + + print() + + page.wait_for_timeout(5_000) diff --git a/playwright__examples/human_automation/examples/translate_google_ru.py b/playwright__examples/human_automation/examples/translate_google_ru.py new file mode 100644 index 000000000..f3ad0c2bb --- /dev/null +++ b/playwright__examples/human_automation/examples/translate_google_ru.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +from textwrap import dedent + +# playwright>=1.61.0 +from playwright.sync_api import Page, sync_playwright + +from human_automation.human_automation import HumanAutomation + + +def get_text(page: Page, lang: str) -> str: + return "\n".join( + span.text_content().strip() + for span in page.locator(f'span[lang="{lang}"] > span > span').all() + ) + + +URL: str = "https://translate.google.ru/?sl=ru&tl=en&op=translate" + + +with sync_playwright() as p: + browser = p.chromium.launch(headless=False) + page = browser.new_page() + + human_automation = HumanAutomation(page) + + page.goto(URL, wait_until="domcontentloaded") + + input_locator = page.locator('textarea[aria-label="Исходный текст"]') + + human_automation.type_text( + input_locator, + text=dedent(""" + Съешь же ещё этих мягких + французских булок, + да выпей же чаю + """).strip(), + ) + + page.wait_for_timeout(2_000) + + text: str = get_text(page, lang="en") + print(f"Text ({len(text)}):\n{text}") + + page.wait_for_timeout(2_000) + + human_automation.click('button[aria-label *= "Обратный перевод"]:visible') + + page.wait_for_timeout(2_000) + + human_automation.type_text( + input_locator, + text=dedent(""" + The quick brown fox jumps + over the lazy dog + """).strip(), + ) + + page.wait_for_timeout(2_000) + + text: str = get_text(page, lang="ru") + print(f"Text ({len(text)}):\n{text}") + + page.wait_for_timeout(5_000) diff --git a/playwright__examples/human_automation/human_automation.py b/playwright__examples/human_automation/human_automation.py new file mode 100644 index 000000000..85c5bcd23 --- /dev/null +++ b/playwright__examples/human_automation/human_automation.py @@ -0,0 +1,421 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +import functools +import logging +import time +import random +import re +import string + +from typing import Any, Callable, TypedDict + +# playwright>=1.61.0 +from playwright.sync_api import Page, Locator, TimeoutError + +# playwright-stealth>=2.0.3 +from playwright_stealth import Stealth + +# python-ghost-cursor==0.1.1 +from python_ghost_cursor.playwright_sync import create_cursor +from python_ghost_cursor.playwright_sync._spoof import GhostCursor + +type Point = TypedDict("Point", {"x": int, "y": int}) + + +log = logging.getLogger(__name__) +logging.basicConfig(level=logging.INFO) + + +def log_action[**P, R](func: Callable[P, R]) -> Callable[P, R]: + @functools.wraps(func) + def wrapper(*args: P.args, **kwargs: P.kwargs) -> R: + func_name: str = func.__name__ + + locator: Any | None = kwargs.get("locator") + if not locator and len(args) > 1: + locator = args[1] + if not isinstance(locator, str | Locator): + locator = None + locator_str: str = f" to: {locator}" if locator else "" + + log.debug(f"Started {func_name}{locator_str}") + + start_time: float = time.perf_counter() + try: + result: R = func(*args, **kwargs) + + execution_time_ms: int = int((time.perf_counter() - start_time) * 1000) + log.debug(f"Finished {func_name}{locator_str} ({execution_time_ms}ms)") + return result + + except Exception as e: + execution_time_ms: int = int((time.perf_counter() - start_time) * 1000) + log.error( + f"Failed {func_name}{locator_str} after {execution_time_ms}ms. Error: {e}" + ) + raise e + + return wrapper + + +stealth = Stealth() + + +def get_center_page(page: Page) -> Point: + # Get the size of the current browser window + viewport: dict[str, int] | None = page.viewport_size + + base_x: int + base_y: int + if viewport: + base_x = viewport["width"] // 2 + base_y = viewport["height"] // 2 + else: + base_x, base_y = 640, 360 + + offset_x: int = random.randint(-40, 40) + offset_y: int = random.randint(-40, 40) + + target_x: int = base_x + offset_x + target_y: int = base_y + offset_y + + return {"x": target_x, "y": target_y} + + +def inject_cursor(page: Page) -> None: + page.add_init_script(""" + (() => { + const initCursor = () => { + const box = document.createElement('div'); + box.id = 'playwright-fake-cursor'; + box.style.position = 'fixed'; + box.style.top = '0'; + box.style.left = '0'; + box.style.width = '14px'; + box.style.height = '14px'; + box.style.background = 'rgba(255, 0, 0, 0.7)'; + box.style.border = '2px solid white'; + box.style.borderRadius = '50%'; + box.style.pointerEvents = 'none'; + box.style.zIndex = '999999'; + box.style.transform = 'translate(-50%, -50%)'; + document.body.appendChild(box); + + document.addEventListener('mousemove', (e) => { + box.style.left = e.clientX + 'px'; + box.style.top = e.clientY + 'px'; + }); + }; + + // If the DOM has already been loaded (unlikely for init_script, but useful for safety) + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initCursor); + } else { + initCursor(); + } + })(); + """) + + +TYPO_CHAR_SETS: dict[str, str] = { + "eng_lower": string.ascii_lowercase, + "eng_upper": string.ascii_uppercase, + "rus_lower": "абвгдеёжзийклмнопрстуфхцчшщъыьэюя", + "rus_upper": "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ", + "digits": string.digits, + "punctuation": string.punctuation, +} + +WAIT_MS: tuple[int, int] = 100, 250 + + +class HumanAutomation: + page: Page + cursor: GhostCursor + typo_char_sets: dict[str, str] + + def __init__( + self, + page: Page, + typo_char_sets: dict[str, str] | None = None, + ) -> None: + if typo_char_sets is None: + typo_char_sets = TYPO_CHAR_SETS + + self.page = page + self.cursor = create_cursor(page, start=get_center_page(page)) + self.typo_char_sets = typo_char_sets + + stealth.apply_stealth_sync(page) + inject_cursor(page) + + @log_action + def wait(self, min_time_ms: int, max_time_ms: int) -> None: + time_ms: float = random.randint(min_time_ms, max_time_ms) + self.page.wait_for_timeout(time_ms) + + @log_action + def move_to( + self, + locator: Locator | str, + wait_ms: tuple[int, int] = WAIT_MS, + ) -> None: + if isinstance(locator, str): + locator = self.page.locator(locator) + + self.scroll_to_element(locator) + + self.cursor.move(locator) + self.wait(*wait_ms) + + @log_action + def click( + self, + locator: Locator | str, + wait_ms: tuple[int, int] = WAIT_MS, + ) -> None: + if isinstance(locator, str): + locator = self.page.locator(locator) + + # NOTE: move_to is not suitable here - the cursor moves twice + # It internally calls cursor.move, which moves the cursor + # click internally calls cursor.click, which also calls cursor.move + self.scroll_to_element(locator) + + # NOTE: If this is a link, removing the 'target' attribute will prevent opening in a new tab + locator.evaluate("el => el.removeAttribute('target')") + + self.cursor.click(locator) + self.wait(*wait_ms) + + @log_action + def scroll_to_element( + self, + locator: Locator | str, + margin: int = 100, + wait_ms: tuple[int, int] = WAIT_MS, + ) -> None: + """ + Simulates human scrolling. + If the element is fully visible on the screen, no scrolling occurs. + If the element is hidden (at the top or bottom), it will smoothly scroll closer to the center. + """ + + if isinstance(locator, str): + locator = self.page.locator(locator) + + while True: + box: dict[str, float] | None + try: + box = locator.bounding_box(timeout=100) + except TimeoutError: + box = None + + log.debug(f"Box: {box}") + if not box: + # If the element is not in the DOM at all, scroll down randomly + self.page.mouse.wheel(0, random.randint(250, 450)) + self.wait(*wait_ms) + continue + + viewport_height: int = self.page.viewport_size["height"] + log.debug(f"Viewport height: {viewport_height}") + + # Find the boundaries of the element relative to the screen + element_top = box["y"] + element_height = box["height"] + element_bottom = element_top + element_height + + is_top_visible = element_top >= margin + is_bottom_within_viewport = element_bottom <= (viewport_height - margin) + is_too_large = element_height > (viewport_height - (margin * 2)) + is_bottom_visible = is_bottom_within_viewport or is_too_large + if is_top_visible and is_bottom_visible: # The element is perfectly visible + break + + # If the element is not on the screen, calculate the distance to center for scrolling + element_center_y = element_top + (element_height / 2) + screen_center_y = viewport_height / 2 + distance_to_center = element_center_y - screen_center_y + + # If we are already very close to the center, stop + if abs(distance_to_center) < random.randint(40, 80): + break + + scroll_step: int + if distance_to_center > 0: + # Scroll down (target below screen) + scroll_step = random.randint(150, 350) + else: + # Scroll up (target above screen) + scroll_step = random.randint(-350, -150) + + self.page.mouse.wheel(0, scroll_step) + self.wait(*wait_ms) + + self.wait(*wait_ms) + + def _typo_effect( + self, + char: str, + typo_chance: float, + wait_ms: tuple[int, int] = WAIT_MS, + ) -> None: + # Logic for random typo (don't break spaces) + if char == " " or random.random() >= typo_chance: + return + + pool = "" + for s_set in self.typo_char_sets.values(): + if char in s_set: + pool = s_set + break + + # If the symbol is rare and is not in the pools, we create a default list (letters + numbers) + if not pool: + pool: str = self.typo_char_sets["eng_lower"] + self.typo_char_sets["digits"] + + valid_choices: list[str] = [c for c in pool if c != char] + if not valid_choices: + log.warning(f"No valid choices found for character {char!r}.") + return + + wrong_char: str = random.choice(valid_choices) + + self.page.keyboard.type(wrong_char) + self.wait(60, 140) + self.wait(180, 350) # Pause for recognizing the error + self.page.keyboard.press("Backspace") + self.wait(*wait_ms) + + @log_action + def type_text( + self, + locator: Locator | str, + text: str, + typo_chance: float = 0.07, + max_attempts: int = 3, + strict_validation: bool = False, + wait_ms: tuple[int, int] = WAIT_MS, + ) -> bool: + """ + Types text like a human: with unique pauses, random typos, + deletion of them through Backspace and final validation of the input value. + """ + + if isinstance(locator, str): + locator = self.page.locator(locator) + + log.info(f"Typing text ({len(text)}): {text!r}") + + for attempt in range(1, max_attempts + 1): + # Click on the field to bring focus + self.click(locator) + + # Realistically clear the field through keyboard emulation of Ctrl+A -> Backspace + self.page.keyboard.down("Control") + self.page.keyboard.press("a") + self.page.keyboard.up("Control") + self.page.keyboard.press("Backspace") + self.wait(*wait_ms) + + # Typing character by character + for char in text: + self._typo_effect(char, typo_chance=typo_chance, wait_ms=wait_ms) + + # Type correct character + self.page.keyboard.type(char) + + # Typing rhythm (delay between keys) + min_time_ms: int = 50 + max_time_ms: int = 160 + # 4% chance that the person thought about a word in the middle of it + if random.random() < 0.04: + min_time_ms += 350 + max_time_ms += 700 + self.wait(min_time_ms, max_time_ms) + + # Validate the actually typed text in the field + actual_text: str = locator.input_value() or "" + + is_valid: bool + if strict_validation: + is_valid = actual_text == text + else: + + def _remove_all_spaces(text: str) -> str: + return re.sub(r"\s+", "", text) + + is_valid = _remove_all_spaces(actual_text) == _remove_all_spaces(text) + + if is_valid: + return True + + log.warning(f"Expected text {text!r}, but got {actual_text!r}.") + + self.wait(400, 800) + + raise RuntimeError( + f"Failed to correctly type {text!r} after {max_attempts} attempts." + ) + + @log_action + def move_mouse_to_center(self) -> None: + """ + Smoothly moves the mouse cursor to a random area around the center of the screen. + Takes: page (a Playwright page object) + """ + + # Move the cursor along a human-like trajectory + point: Point = get_center_page(self.page) + self.cursor.move_to(point) + + # Simulate a small pause after movement (200-600 ms) + self.wait(200, 600) + + @log_action + def ensure_change_url( + self, + action: Callable[[], None], + is_ok_url: Callable[[str], bool], + max_attempts: int = 3, + ) -> None: + prev_url: str = self.page.url + log.info(f"Current URL: {prev_url!r}") + + attempt: int = 0 + while True: + # If the URL substring is found and the URL has changed + if is_ok_url(self.page.url) and prev_url != self.page.url: + break + + try: + action() + + log.info("Waiting for url load") + self.page.wait_for_url( + is_ok_url, timeout=5_000, wait_until="domcontentloaded" + ) + log.info(f"Page changed! New URL: {self.page.url!r}") + + break + + except Exception: + log.exception("Error:") + log.info("Trying to move the cursor and retry") + attempt += 1 + self.cursor.move_to( + { + "x": 10 + random.randint(-10, 10), + "y": 500 + random.randint(-100, 100), + } + ) + if attempt == max_attempts: + log.info(f"Loading {prev_url!r}") + attempt = 0 + self.page.goto(prev_url) + self.wait(4_000, 5_000) diff --git a/playwright__examples/human_automation/screenshots/github.com_gil9red.gif b/playwright__examples/human_automation/screenshots/github.com_gil9red.gif new file mode 100644 index 000000000..14df4e414 Binary files /dev/null and b/playwright__examples/human_automation/screenshots/github.com_gil9red.gif differ diff --git a/playwright__examples/human_automation/screenshots/store_steampowered_com.gif b/playwright__examples/human_automation/screenshots/store_steampowered_com.gif new file mode 100644 index 000000000..eaa969fa6 Binary files /dev/null and b/playwright__examples/human_automation/screenshots/store_steampowered_com.gif differ diff --git a/playwright__examples/human_automation/screenshots/translate_google_ru.gif b/playwright__examples/human_automation/screenshots/translate_google_ru.gif new file mode 100644 index 000000000..7d25d9d64 Binary files /dev/null and b/playwright__examples/human_automation/screenshots/translate_google_ru.gif differ diff --git a/playwright__examples/screenshots/chromium_full_page.png b/playwright__examples/screenshots/chromium_full_page.png new file mode 100644 index 000000000..547400daa Binary files /dev/null and b/playwright__examples/screenshots/chromium_full_page.png differ diff --git a/playwright__examples/screenshots/chromium_page.png b/playwright__examples/screenshots/chromium_page.png new file mode 100644 index 000000000..632b26e62 Binary files /dev/null and b/playwright__examples/screenshots/chromium_page.png differ diff --git a/playwright__examples/screenshots/firefox_full_page.png b/playwright__examples/screenshots/firefox_full_page.png new file mode 100644 index 000000000..5a2ffe6b0 Binary files /dev/null and b/playwright__examples/screenshots/firefox_full_page.png differ diff --git a/playwright__examples/screenshots/firefox_page.png b/playwright__examples/screenshots/firefox_page.png new file mode 100644 index 000000000..611bc0d79 Binary files /dev/null and b/playwright__examples/screenshots/firefox_page.png differ diff --git a/playwright__examples/screenshots/stealth/normal_chromium_page.png b/playwright__examples/screenshots/stealth/normal_chromium_page.png new file mode 100644 index 000000000..0e2e6c809 Binary files /dev/null and b/playwright__examples/screenshots/stealth/normal_chromium_page.png differ diff --git a/playwright__examples/screenshots/stealth/normal_firefox_page.png b/playwright__examples/screenshots/stealth/normal_firefox_page.png new file mode 100644 index 000000000..f25c69aa1 Binary files /dev/null and b/playwright__examples/screenshots/stealth/normal_firefox_page.png differ diff --git a/playwright__examples/screenshots/stealth/normal_webkit_page.png b/playwright__examples/screenshots/stealth/normal_webkit_page.png new file mode 100644 index 000000000..53f89ea02 Binary files /dev/null and b/playwright__examples/screenshots/stealth/normal_webkit_page.png differ diff --git a/playwright__examples/screenshots/stealth/stealth_chromium_page.png b/playwright__examples/screenshots/stealth/stealth_chromium_page.png new file mode 100644 index 000000000..36d09711d Binary files /dev/null and b/playwright__examples/screenshots/stealth/stealth_chromium_page.png differ diff --git a/playwright__examples/screenshots/stealth/stealth_firefox_page.png b/playwright__examples/screenshots/stealth/stealth_firefox_page.png new file mode 100644 index 000000000..976fe5b9b Binary files /dev/null and b/playwright__examples/screenshots/stealth/stealth_firefox_page.png differ diff --git a/playwright__examples/screenshots/stealth/stealth_webkit_page.png b/playwright__examples/screenshots/stealth/stealth_webkit_page.png new file mode 100644 index 000000000..0c92edfc2 Binary files /dev/null and b/playwright__examples/screenshots/stealth/stealth_webkit_page.png differ diff --git a/playwright__examples/screenshots/webkit_full_page.png b/playwright__examples/screenshots/webkit_full_page.png new file mode 100644 index 000000000..5cd17dee8 Binary files /dev/null and b/playwright__examples/screenshots/webkit_full_page.png differ diff --git a/playwright__examples/screenshots/webkit_page.png b/playwright__examples/screenshots/webkit_page.png new file mode 100644 index 000000000..68cc4d083 Binary files /dev/null and b/playwright__examples/screenshots/webkit_page.png differ diff --git a/playwright__examples/stealth.py b/playwright__examples/stealth.py new file mode 100644 index 000000000..395e6ba4b --- /dev/null +++ b/playwright__examples/stealth.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +from pathlib import Path + +from playwright.sync_api import sync_playwright +from playwright_stealth import Stealth + +DIR: Path = Path(__file__).resolve().parent +DIR_SCREENSHOTS: Path = DIR / "screenshots" / "stealth" +DIR_SCREENSHOTS.mkdir(parents=True, exist_ok=True) + +URL: str = "https://bot.sannysoft.com/" + +stealth = Stealth() + + +with sync_playwright() as p: + for browser_type in [p.chromium, p.firefox, p.webkit]: + print(browser_type.name) + + browser = browser_type.launch() + page = browser.new_page() + + page.goto(URL) + print("navigator.webdriver (default):", page.evaluate("navigator.webdriver")) + + normal_screenshot_path: Path = ( + DIR_SCREENSHOTS / f"normal_{browser_type.name}_page.png" + ) + page.screenshot(path=normal_screenshot_path) + + stealth.apply_stealth_sync(page) + page.goto(URL) + print("navigator.webdriver (stealth):", page.evaluate("navigator.webdriver")) + + stealth_screenshot_path: Path = ( + DIR_SCREENSHOTS / f"stealth_{browser_type.name}_page.png" + ) + page.screenshot(path=stealth_screenshot_path) + + browser.close() # NOTE: Close in loop + print() + +""" +chromium +navigator.webdriver (default): True +navigator.webdriver (stealth): False + +firefox +navigator.webdriver (default): True +navigator.webdriver (stealth): False + +webkit +navigator.webdriver (default): True +navigator.webdriver (stealth): False +""" diff --git a/pretty_html/pretty_html_gui.py b/pretty_html/pretty_html_gui.py index 6ac4d8c5b..97317a60a 100644 --- a/pretty_html/pretty_html_gui.py +++ b/pretty_html/pretty_html_gui.py @@ -64,7 +64,7 @@ from pretty_html import pretty_html -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -77,7 +77,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle(path_split(__file__)[1]) @@ -118,7 +118,7 @@ def __init__(self): self.setLayout(layout) - def input_text_changed(self): + def input_text_changed(self) -> None: self.label_error.clear() self.button_detail_error.hide() @@ -143,7 +143,7 @@ def input_text_changed(self): self.label_error.setText("Error: " + self.last_error_message) - def show_detail_error_message(self): + def show_detail_error_message(self) -> None: message = self.last_error_message + "\n\n" + self.last_detail_error_message mb = QErrorMessage() diff --git a/pretty_xml/pretty_xml_gui.py b/pretty_xml/pretty_xml_gui.py index aa62929e4..9ca28ee36 100644 --- a/pretty_xml/pretty_xml_gui.py +++ b/pretty_xml/pretty_xml_gui.py @@ -28,7 +28,7 @@ from pretty_xml import pretty_xml_lxml as to_pretty_xml -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -41,7 +41,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle(Path(__file__).name) @@ -80,7 +80,7 @@ def __init__(self): layout.addLayout(layout_error) - def input_text_changed(self): + def input_text_changed(self) -> None: self.label_error.clear() self.button_detail_error.hide() @@ -105,7 +105,7 @@ def input_text_changed(self): self.label_error.setText("Error: " + self.last_error_message) - def show_detail_error_message(self): + def show_detail_error_message(self) -> None: message = self.last_error_message + "\n\n" + self.last_detail_error_message mb = QErrorMessage() diff --git a/print_class_name.py b/print_class_name.py index c3d61e13e..945a046c6 100644 --- a/print_class_name.py +++ b/print_class_name.py @@ -14,7 +14,7 @@ class A: class B: - def __init__(self): + def __init__(self) -> None: print(self.__class__.__name__) # B diff --git a/profile__example.py b/profile__example.py index d4f7cb657..22b38634e 100644 --- a/profile__example.py +++ b/profile__example.py @@ -7,12 +7,12 @@ import profile -def foo(number=100): - def _inc_i(): +def foo(number=100) -> None: + def _inc_i() -> None: nonlocal i i += 1 - def _has(value, items): + def _has(value, items) -> bool: return value in items items = ["1234567890" for _ in range(number)] diff --git a/proxy.py__examples/ca_certificate.py b/proxy.py__examples/ca_certificate.py index 9a3209684..878b916fb 100644 --- a/proxy.py__examples/ca_certificate.py +++ b/proxy.py__examples/ca_certificate.py @@ -11,7 +11,7 @@ from config import CA_KEY_FILE_PATH, CA_CERT_FILE_PATH, CA_SIGNING_KEY_FILE_PATH -def main(): +def main() -> None: # Generate CA key os.system( f"python -m proxy.common.pki gen_private_key --private-key-path {CA_KEY_FILE_PATH}" diff --git a/proxy.py__examples/hello_world.py b/proxy.py__examples/hello_world.py index 18776bba4..0a1ecc404 100644 --- a/proxy.py__examples/hello_world.py +++ b/proxy.py__examples/hello_world.py @@ -36,7 +36,7 @@ def on_upstream_connection_close(self) -> None: pass -def main(*args, **kwargs): +def main(*args, **kwargs) -> None: proxy.main( *args, hostname=ipaddress.ip_address("127.0.0.1"), diff --git a/psutil_example/disc_used_DIFF/common.py b/psutil_example/disc_used_DIFF/common.py index ab630faff..2be79686a 100644 --- a/psutil_example/disc_used_DIFF/common.py +++ b/psutil_example/disc_used_DIFF/common.py @@ -58,7 +58,7 @@ def get_disc_total_used(disc_list: List[str]) -> str: return sizeof_fmt(sum(psutil.disk_usage(disk).used for disk in disc_list)) -def write_snapshot_raw_disc_used(disc_list: List[str] = None): +def write_snapshot_raw_disc_used(disc_list: List[str] = None) -> None: with open(FILE_NAME_SNAPSHOT, "w", encoding="utf-8") as f: items = get_disc_used(disc_list, only_raw=True) print("Write snapshot with:", items) diff --git a/psutil_example/on_new_process_handler.py b/psutil_example/on_new_process_handler.py index 988cea131..b2092c618 100644 --- a/psutil_example/on_new_process_handler.py +++ b/psutil_example/on_new_process_handler.py @@ -16,22 +16,22 @@ class OnNewProcessHandler(Thread): - def __init__(self, timeout_secs=1.0): + def __init__(self, timeout_secs=1.0) -> None: super().__init__() self._process = dict() self._listeners: list[ListenerFunc] = [] self._timeout_secs = timeout_secs - def add_listener(self, listener: ListenerFunc): + def add_listener(self, listener: ListenerFunc) -> None: if listener not in self._listeners: self._listeners.append(listener) - def remove_listener(self, listener: ListenerFunc): + def remove_listener(self, listener: ListenerFunc) -> None: if listener in self._listeners: self._listeners.remove(listener) - def remove_all_listener(self): + def remove_all_listener(self) -> None: self._listeners.clear() @staticmethod @@ -48,7 +48,7 @@ def get_process() -> dict: return items - def run(self): + def run(self) -> None: while True: current_process = self.get_process() @@ -71,7 +71,7 @@ def run(self): if __name__ == "__main__": - def print_listener(process_list): + def print_listener(process_list) -> None: result = [] for p in process_list: result.append(f"{p['name']} (pid={p['pid']})") diff --git a/psutil_example/print_all_webservers/get_info_html.py b/psutil_example/print_all_webservers/get_info_html.py index c75a47c69..476373f37 100644 --- a/psutil_example/print_all_webservers/get_info_html.py +++ b/psutil_example/print_all_webservers/get_info_html.py @@ -147,7 +147,7 @@ def get_info_html() -> str: ) -def open_html_file(): +def open_html_file() -> None: with tempfile.NamedTemporaryFile( mode="w", encoding="utf-8", diff --git a/psutil_example/print_all_webservers/web.py b/psutil_example/print_all_webservers/web.py index af8d6b527..0687ee765 100644 --- a/psutil_example/print_all_webservers/web.py +++ b/psutil_example/print_all_webservers/web.py @@ -13,7 +13,7 @@ class HttpProcessor(BaseHTTPRequestHandler): - def do_GET(self): + def do_GET(self) -> None: o = urlsplit(self.path) # Only index @@ -31,7 +31,7 @@ def do_GET(self): self.wfile.write(text.encode("utf-8")) -def run(server_class=HTTPServer, handler_class=HttpProcessor, port=8080): +def run(server_class=HTTPServer, handler_class=HttpProcessor, port=8080) -> None: print(f"HTTP server running on http://127.0.0.1:{port}") server_address = ("", port) diff --git a/psutil_example/print_current_python_webservers/web.py b/psutil_example/print_current_python_webservers/web.py index 0a526e7bc..9b36cc0db 100644 --- a/psutil_example/print_current_python_webservers/web.py +++ b/psutil_example/print_current_python_webservers/web.py @@ -50,7 +50,7 @@ def _get_processes() -> list[dict[str, str | int]]: class HttpProcessor(BaseHTTPRequestHandler): - def do_GET(self): + def do_GET(self) -> None: o = urlsplit(self.path) # Only index @@ -131,7 +131,7 @@ def do_GET(self): self.wfile.write(text.encode("utf-8")) -def run(server_class=HTTPServer, handler_class=HttpProcessor, port=8080): +def run(server_class=HTTPServer, handler_class=HttpProcessor, port=8080) -> None: print(f"HTTP server running on http://127.0.0.1:{port}") server_address = ("", port) diff --git a/psutil_example/process_management/on_terminate__callback.py b/psutil_example/process_management/on_terminate__callback.py index 7049cbed9..36cffe170 100644 --- a/psutil_example/process_management/on_terminate__callback.py +++ b/psutil_example/process_management/on_terminate__callback.py @@ -10,7 +10,7 @@ import time -def func(time_life=4): +def func(time_life=4) -> None: i = 1 while i <= time_life: @@ -39,7 +39,7 @@ def func(time_life=4): print("process2 is_running:", process2.is_running()) print() - def on_terminate(proc): + def on_terminate(proc) -> None: print(f'Process "{proc}" terminated') # waits for multiple processes to terminate diff --git a/psutil_example/process_management/process_control.py b/psutil_example/process_management/process_control.py index d35c1d7cd..66961ef30 100644 --- a/psutil_example/process_management/process_control.py +++ b/psutil_example/process_management/process_control.py @@ -8,7 +8,7 @@ import threading -def func(): +def func() -> None: i = 1 while True: diff --git a/psutil_example/process_management/process_detail_info.py b/psutil_example/process_management/process_detail_info.py index 140993468..b2ff6649b 100644 --- a/psutil_example/process_management/process_detail_info.py +++ b/psutil_example/process_management/process_detail_info.py @@ -10,7 +10,7 @@ import psutil -def print_info(pid): +def print_info(pid) -> None: process = psutil.Process(pid) print("Process:", process) diff --git a/pyautogui__keyboard__examples/Frozen_Throne__auto_select_local_map_and_ai/main.py b/pyautogui__keyboard__examples/Frozen_Throne__auto_select_local_map_and_ai/main.py index 56b09903e..f595ff49f 100644 --- a/pyautogui__keyboard__examples/Frozen_Throne__auto_select_local_map_and_ai/main.py +++ b/pyautogui__keyboard__examples/Frozen_Throne__auto_select_local_map_and_ai/main.py @@ -27,7 +27,7 @@ AI_EASY = "images/ai_easy.png" -def go_local_network(): +def go_local_network() -> bool: pos = pyautogui.locateCenterOnScreen(LOCAL_NETWORK_BUTTON) print("LOCAL_NETWORK_BUTTON:", pos) @@ -41,7 +41,7 @@ def go_local_network(): return False -def go_new_game(): +def go_new_game() -> bool: pos = pyautogui.locateCenterOnScreen(NEW_GAME_BUTTON) print("NEW_GAME_BUTTON:", pos) @@ -55,7 +55,7 @@ def go_new_game(): return False -def go_select_map(): +def go_select_map() -> bool: pos = pyautogui.locateCenterOnScreen(NEW_GAME_BUTTON_SELECT_MAP) print("NEW_GAME_BUTTON_SELECT_MAP:", pos) @@ -69,7 +69,7 @@ def go_select_map(): return False -def bot_says(): +def bot_says() -> None: text = """\ Bot say: -aremnpakulsc @@ -81,7 +81,7 @@ def bot_says(): pyautogui.typewrite(["enter"]) -def select_sentinel_and_scourge(coords_sentinel, coords_scourge): +def select_sentinel_and_scourge(coords_sentinel, coords_scourge) -> None: for rect in coords_sentinel + coords_scourge: pos = pyautogui.center(rect) diff --git a/pyautogui__keyboard__examples/autoclick_in_game__pyautoit.py b/pyautogui__keyboard__examples/autoclick_in_game__pyautoit.py index 6de43e5a3..b618b0b83 100644 --- a/pyautogui__keyboard__examples/autoclick_in_game__pyautoit.py +++ b/pyautogui__keyboard__examples/autoclick_in_game__pyautoit.py @@ -24,14 +24,14 @@ HOTKEY: str = os.environ.get("HOTKEY", "Ctrl+Alt+Space") -def change_start(): +def change_start() -> None: DATA["START"] = not DATA["START"] print("START:", DATA["START"]) winsound.Beep(1000, duration=50) -def process_auto_click(): +def process_auto_click() -> None: while True: if not DATA["START"]: time.sleep(0.100) diff --git a/pyautogui__keyboard__examples/customizable_hotkey.py b/pyautogui__keyboard__examples/customizable_hotkey.py index ed4d3c704..28da7ef28 100644 --- a/pyautogui__keyboard__examples/customizable_hotkey.py +++ b/pyautogui__keyboard__examples/customizable_hotkey.py @@ -15,7 +15,7 @@ print("Shortcut selected:", shortcut) -def on_triggered(): +def on_triggered() -> None: print("Triggered!") diff --git a/pyautogui__keyboard__examples/hotkey__hello_world.py b/pyautogui__keyboard__examples/hotkey__hello_world.py index 6b9a7677f..dd6599df4 100644 --- a/pyautogui__keyboard__examples/hotkey__hello_world.py +++ b/pyautogui__keyboard__examples/hotkey__hello_world.py @@ -8,7 +8,7 @@ import keyboard -def foo(): +def foo() -> None: print("World") diff --git a/pyautogui__keyboard__examples/hotkey__mouse___down_up__sound_beep.py b/pyautogui__keyboard__examples/hotkey__mouse___down_up__sound_beep.py index e392d5a9f..90f540165 100644 --- a/pyautogui__keyboard__examples/hotkey__mouse___down_up__sound_beep.py +++ b/pyautogui__keyboard__examples/hotkey__mouse___down_up__sound_beep.py @@ -13,7 +13,7 @@ import pyautogui -def beep(): +def beep() -> None: winsound.Beep(1000, duration=50) diff --git a/pyautogui__keyboard__examples/hotkey__start_pause_quit.py b/pyautogui__keyboard__examples/hotkey__start_pause_quit.py index 1fd1fa73d..a326f9091 100644 --- a/pyautogui__keyboard__examples/hotkey__start_pause_quit.py +++ b/pyautogui__keyboard__examples/hotkey__start_pause_quit.py @@ -20,12 +20,12 @@ } -def change_start(): +def change_start() -> None: BOT_DATA["START"] = not BOT_DATA["START"] print("START:", BOT_DATA["START"]) -def change_auto_attack(): +def change_auto_attack() -> None: BOT_DATA["AUTO_ATTACK"] = not BOT_DATA["AUTO_ATTACK"] print("AUTO_ATTACK:", BOT_DATA["AUTO_ATTACK"]) diff --git a/pyautogui__keyboard__examples/hotkey_change_state.py b/pyautogui__keyboard__examples/hotkey_change_state.py index 890f36d35..de9ea7729 100644 --- a/pyautogui__keyboard__examples/hotkey_change_state.py +++ b/pyautogui__keyboard__examples/hotkey_change_state.py @@ -19,7 +19,7 @@ } -def change_auto_attack(): +def change_auto_attack() -> None: BOT_DATA["AUTO_ATTACK"] = not BOT_DATA["AUTO_ATTACK"] print("AUTO_ATTACK:", BOT_DATA["AUTO_ATTACK"]) diff --git a/pyautogui__keyboard__examples/hotkey_change_state__multi_thread.py b/pyautogui__keyboard__examples/hotkey_change_state__multi_thread.py index c533f1aca..bf4264347 100644 --- a/pyautogui__keyboard__examples/hotkey_change_state__multi_thread.py +++ b/pyautogui__keyboard__examples/hotkey_change_state__multi_thread.py @@ -20,7 +20,7 @@ } -def change_auto_attack(): +def change_auto_attack() -> None: BOT_DATA["AUTO_ATTACK"] = not BOT_DATA["AUTO_ATTACK"] print("AUTO_ATTACK:", BOT_DATA["AUTO_ATTACK"]) @@ -37,7 +37,7 @@ def change_auto_attack(): print("Start") -def process_auto_attack(): +def process_auto_attack() -> None: i = 1 while True: diff --git a/pyautogui__keyboard__examples/keyboard_hook.py b/pyautogui__keyboard__examples/keyboard_hook.py index 1c7b34aa8..2bc6174c0 100644 --- a/pyautogui__keyboard__examples/keyboard_hook.py +++ b/pyautogui__keyboard__examples/keyboard_hook.py @@ -8,7 +8,7 @@ import keyboard -def print_pressed_keys(e): +def print_pressed_keys(e) -> None: print(e, e.event_type, e.name) diff --git a/pyautogui__keyboard__examples/pressed_keys.py b/pyautogui__keyboard__examples/pressed_keys.py index a1207f96c..520de3dcb 100644 --- a/pyautogui__keyboard__examples/pressed_keys.py +++ b/pyautogui__keyboard__examples/pressed_keys.py @@ -14,7 +14,7 @@ import keyboard -def print_pressed_keys(e): +def print_pressed_keys(e) -> None: line = ", ".join(str(code) for code in keyboard._pressed_events) # '\r' and end='' overwrites the previous line. # ' ' * 40 prints 40 spaces at the end to ensure the previous line is cleared. diff --git a/pyautogui__keyboard__examples/telegram_smile_clicker/main.py b/pyautogui__keyboard__examples/telegram_smile_clicker/main.py index 6dfce37be..7a221651e 100644 --- a/pyautogui__keyboard__examples/telegram_smile_clicker/main.py +++ b/pyautogui__keyboard__examples/telegram_smile_clicker/main.py @@ -15,7 +15,7 @@ import pyautogui -def go(): +def go() -> None: OPEN_SMILE_MENU = "elements/open_smile_menu.png" GROUP_SMILE = "elements/group_smile.png" CLICK_SMILE = "elements/click_smile.png" diff --git a/pyautogui__keyboard__examples/win_calc_clicker/main.py b/pyautogui__keyboard__examples/win_calc_clicker/main.py index 75378b6c2..812b850f0 100644 --- a/pyautogui__keyboard__examples/win_calc_clicker/main.py +++ b/pyautogui__keyboard__examples/win_calc_clicker/main.py @@ -27,7 +27,7 @@ CACHE_POS_BUTTON = dict() -def go(expression): +def go(expression) -> None: for x in expression: if x not in BUTTONS: print(f'Not found: "{x}"') @@ -47,7 +47,7 @@ def go(expression): pyautogui.click(pos) -def show_test_calc(): +def show_test_calc() -> None: os.startfile("calc.exe") time.sleep(1) diff --git a/pycryptodome__examples__AES_DES_RSA/AES_with_password__verify_key.py b/pycryptodome__examples__AES_DES_RSA/AES_with_password__verify_key.py index 5a73e7e38..1c3a930a1 100644 --- a/pycryptodome__examples__AES_DES_RSA/AES_with_password__verify_key.py +++ b/pycryptodome__examples__AES_DES_RSA/AES_with_password__verify_key.py @@ -18,7 +18,7 @@ class AuthenticationError(Exception): class CryptoAES: - def __init__(self, key: str): + def __init__(self, key: str) -> None: self.key = hashlib.sha256(key.encode("utf-8")).digest() def encrypt(self, plain_text: str) -> str: diff --git a/pycryptodome__examples__AES_DES_RSA/info_security.py b/pycryptodome__examples__AES_DES_RSA/info_security.py index 17f4dfaec..4af65909b 100644 --- a/pycryptodome__examples__AES_DES_RSA/info_security.py +++ b/pycryptodome__examples__AES_DES_RSA/info_security.py @@ -19,7 +19,7 @@ # SOURCE: https://github.com/maldevel/gdog/blob/a3a47b17231d0ee3a2d0fa8ac986f7485f3f6b82/gdog.py#L68 class InfoSecurity: - def __init__(self, key: str): + def __init__(self, key: str) -> None: self.bs = 32 self.key = hashlib.sha256(key.encode()).digest() diff --git a/pygame__examples/about_joystick.py b/pygame__examples/about_joystick.py index 2814efa41..5e9864c45 100644 --- a/pygame__examples/about_joystick.py +++ b/pygame__examples/about_joystick.py @@ -19,24 +19,24 @@ # It has nothing to do with the joysticks, just outputting the # information. class TextPrint: - def __init__(self): + def __init__(self) -> None: self.reset() self.font = pygame.font.Font(None, 20) - def print(self, screen, textString): + def print(self, screen, textString) -> None: textBitmap = self.font.render(textString, True, BLACK) screen.blit(textBitmap, [self.x, self.y]) self.y += self.line_height - def reset(self): + def reset(self) -> None: self.x = 10 self.y = 10 self.line_height = 15 - def indent(self): + def indent(self) -> None: self.x += 10 - def unindent(self): + def unindent(self) -> None: self.x -= 10 diff --git a/pygame__examples/buttons__using_pygametext.py b/pygame__examples/buttons__using_pygametext.py index 2406c6ca9..abe72750f 100644 --- a/pygame__examples/buttons__using_pygametext.py +++ b/pygame__examples/buttons__using_pygametext.py @@ -30,7 +30,7 @@ pgt.text(10, 70, "Simple pygametext example.", (0, 120, 0), 20, 0) # Add pgt Text -def update(): # Update & Eventd +def update() -> None: # Update & Eventd global running events = pygame.event.get() @@ -46,7 +46,7 @@ def update(): # Update & Eventd sys.exit() -def draw(): +def draw() -> None: screen.fill((255, 255, 255)) # Clear screen pgt.draw() # Draw all pgt elements from layer 0 diff --git a/pygame__examples/circle_collision.py b/pygame__examples/circle_collision.py index f3a753426..83290096a 100644 --- a/pygame__examples/circle_collision.py +++ b/pygame__examples/circle_collision.py @@ -15,7 +15,7 @@ class Ball(pygame.sprite.Sprite): - def __init__(self, size, pos=(0, 0), color=WHITE): + def __init__(self, size, pos=(0, 0), color=WHITE) -> None: super().__init__() self.image = pygame.Surface([size, size], pygame.SRCALPHA) diff --git a/pygame__examples/complex_balls_with_physics.py b/pygame__examples/complex_balls_with_physics.py index f296dcc42..f6fc2c93a 100644 --- a/pygame__examples/complex_balls_with_physics.py +++ b/pygame__examples/complex_balls_with_physics.py @@ -28,7 +28,7 @@ def add_vectors(angle1, length1, angle2, length2) -> tuple[float, float]: return angle, length -def collide(p1, p2): +def collide(p1, p2) -> None: dx = p1.x - p2.x dy = p1.y - p2.y @@ -60,7 +60,7 @@ def collide(p1, p2): class Particle: - def __init__(self, x, y, size, mass=1): + def __init__(self, x, y, size, mass=1) -> None: self.x = x self.y = y self.size = size @@ -71,17 +71,17 @@ def __init__(self, x, y, size, mass=1): self.mass = mass self.drag = (self.mass / (self.mass + mass_of_air)) ** self.size - def display(self): + def display(self) -> None: pygame.draw.circle( screen, self.colour, (int(self.x), int(self.y)), self.size, self.thickness ) - def move(self): + def move(self) -> None: self.x += math.sin(self.angle) * self.speed self.y -= math.cos(self.angle) * self.speed self.speed *= self.drag - def bounce(self): + def bounce(self) -> None: if self.x > width - self.size: self.x = 2 * (width - self.size) - self.x self.angle = -self.angle diff --git a/pygame__examples/simple_balls.py b/pygame__examples/simple_balls.py index a99d51853..2295a3d57 100644 --- a/pygame__examples/simple_balls.py +++ b/pygame__examples/simple_balls.py @@ -11,7 +11,7 @@ class Ball: - def __init__(self, x, y, r, v_x, v_y, color): + def __init__(self, x, y, r, v_x, v_y, color) -> None: self.x = x self.y = y self.r = r @@ -19,11 +19,11 @@ def __init__(self, x, y, r, v_x, v_y, color): self.v_y = v_y self.color = color - def update(self): + def update(self) -> None: self.x += self.v_x self.y += self.v_y - def draw(self, screen): + def draw(self, screen) -> None: pygame.draw.circle(screen, self.color, self.center, self.r) # Нарисуем поверх первого, прозрачный второй с границей (параметр width) @@ -58,7 +58,7 @@ def __init__( caption="Balls!", background_color=(255, 255, 255), frame_rate=60, - ): + ) -> None: self.width = width self.height = height self.frame_rate = frame_rate @@ -77,12 +77,12 @@ def __init__( self.update_caption() - def update_caption(self): + def update_caption(self) -> None: pygame.display.set_caption( f"{self.caption} [{int(self.clock.get_fps())} fps]" ) - def handle_events(self): + def handle_events(self) -> None: # Получение всех событий for event in pygame.event.get(): # Проверка события "Выход" @@ -94,7 +94,7 @@ def handle_events(self): if is_pressed[pygame.K_ESCAPE]: self.game_active = False - def run(self): + def run(self) -> None: self.game_active = True while self.game_active: @@ -121,7 +121,7 @@ def run(self): self.clock.tick(self.frame_rate) - def append_random_ball(self): + def append_random_ball(self) -> None: def get_random_vector(): pos = 0, 0 # Если pos равен (0, 0), пересчитываем значения, т.к. шарик должен двигаться diff --git a/pyglet_example/main.py b/pyglet_example/main.py index 5ef98bbbe..648220488 100644 --- a/pyglet_example/main.py +++ b/pyglet_example/main.py @@ -14,7 +14,7 @@ class main(pyglet.window.Window): - def __init__(self): + def __init__(self) -> None: super(main, self).__init__(800, 800, fullscreen=False) self.x, self.y = 0, 0 @@ -23,13 +23,13 @@ def __init__(self): self.player = pyglet.media.Player() self.alive = 1 - def on_draw(self): + def on_draw(self) -> None: self.render() - def on_close(self): + def on_close(self) -> None: self.alive = 0 - def on_key_press(self, symbol, modifiers): + def on_key_press(self, symbol, modifiers) -> None: # Do something when a key is pressed? # Pause the audio for instance? # use `if symbol == key.SPACE: ...` @@ -44,7 +44,7 @@ def on_key_press(self, symbol, modifiers): if symbol == key.ESCAPE: # [ESC] self.alive = 0 - def render(self): + def render(self) -> None: self.clear() self.bg.draw() @@ -55,7 +55,7 @@ def render(self): self.flip() - def run(self): + def run(self) -> None: while self.alive == 1: self.render() diff --git a/pyglet_example/using_thread.py b/pyglet_example/using_thread.py index d774bdc36..a5af84548 100644 --- a/pyglet_example/using_thread.py +++ b/pyglet_example/using_thread.py @@ -10,7 +10,7 @@ import pyglet -def play_song(): +def play_song() -> None: song = pyglet.media.load("speak.mp3") song.play() pyglet.app.run() diff --git a/pynput__examples/console_board_game.py b/pynput__examples/console_board_game.py index a9037cb9a..0bc7ec743 100644 --- a/pynput__examples/console_board_game.py +++ b/pynput__examples/console_board_game.py @@ -29,7 +29,7 @@ """.strip() -def clear(): +def clear() -> None: os.system("clear" if os.name == "posix" else "cls") @@ -59,14 +59,14 @@ class Hero(GameObject): class Game: - def __init__(self): + def __init__(self) -> None: self.hero: Hero = Hero() self.board: list[list[GameObject]] = [] self.is_active: bool = False self.listener = keyboard.Listener(on_release=self._on_release) - def _on_release(self, key): + def _on_release(self, key) -> None: self.logic(key) def do_step(self) -> bool: @@ -74,7 +74,7 @@ def do_step(self) -> bool: return self.is_active - def logic(self, key): + def logic(self, key) -> None: pos_x, pos_y = self.hero.pos_x, self.hero.pos_y if key == keyboard.Key.esc: @@ -108,22 +108,22 @@ def logic(self, key): pos_x, pos_y ) # Старое место стало пустым - def draw(self): + def draw(self) -> None: clear() self.draw_board() self.draw_game_info() - def draw_board(self): + def draw_board(self) -> None: for row in self.board: print("".join(game_object.icon for game_object in row)) - def draw_game_info(self): + def draw_game_info(self) -> None: print( f"Hero: position: {self.hero.pos_x}x{self.hero.pos_y}, gold: {self.hero.gold}" ) - def start(self, board_template: str): + def start(self, board_template: str) -> None: self.is_active = True self.board.clear() self.listener.start() @@ -156,7 +156,7 @@ def start(self, board_template: str): self.board[-1].append(game_object) - def finish(self): + def finish(self) -> None: self.is_active = False self.listener.stop() diff --git a/pynput__examples/global_hot_key.py b/pynput__examples/global_hot_key.py index 320e27a91..fe4c26a16 100644 --- a/pynput__examples/global_hot_key.py +++ b/pynput__examples/global_hot_key.py @@ -11,7 +11,7 @@ import pyscreenshot as ImageGrab -def on_release(key): +def on_release(key) -> None: if key == Key.f7: print("screenshot") diff --git a/pynput__examples/key_listener.py b/pynput__examples/key_listener.py index ae6cb68c9..e408ff0fa 100644 --- a/pynput__examples/key_listener.py +++ b/pynput__examples/key_listener.py @@ -8,11 +8,11 @@ from pynput.keyboard import Key, Listener -def on_press(key): +def on_press(key) -> None: print(f"{key} pressed") -def on_release(key): +def on_release(key) -> bool | None: print(f"{key} release") if key == Key.esc: diff --git a/pyscreeze__examples/win_calc_clicker/main.py b/pyscreeze__examples/win_calc_clicker/main.py index 06c32c025..a522ead8a 100644 --- a/pyscreeze__examples/win_calc_clicker/main.py +++ b/pyscreeze__examples/win_calc_clicker/main.py @@ -19,7 +19,7 @@ DIR_BUTTONS = DIR / "buttons" -def click(x, y, sleep_secs: float = 0.01): +def click(x, y, sleep_secs: float = 0.01) -> None: win32api.SetCursorPos((x, y)) win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, x, y, 0, 0) win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, x, y, 0, 0) @@ -30,7 +30,7 @@ def click(x, y, sleep_secs: float = 0.01): BUTTON_BY_POSITION = dict() -def init_button_positions(grayscale: bool = True): +def init_button_positions(grayscale: bool = True) -> None: BUTTON_BY_POSITION.clear() for path in DIR_BUTTONS.glob("*.png"): @@ -44,7 +44,7 @@ def init_button_positions(grayscale: bool = True): BUTTON_BY_POSITION[button] = position -def go(expression: str): +def go(expression: str) -> None: init_button_positions() for button in expression: @@ -61,7 +61,7 @@ def go(expression: str): click(x, y) -def show_test_calc(): +def show_test_calc() -> None: os.startfile("calc.exe") time.sleep(1) diff --git a/python_object_to_json.py b/python_object_to_json.py index e763345e6..339d4b0dc 100644 --- a/python_object_to_json.py +++ b/python_object_to_json.py @@ -5,12 +5,12 @@ class SubField: - def __init__(self): + def __init__(self) -> None: self.flag = True class Field: - def __init__(self, tag1, tag2, sub_field_flag=True): + def __init__(self, tag1, tag2, sub_field_flag=True) -> None: self.tag1 = tag1 self.tag2 = tag2 @@ -22,7 +22,7 @@ class Object: a = 0 b = "123" - def __init__(self): + def __init__(self) -> None: self.c = 3 self.items = [1, 2, 3, 4] self.maps = { diff --git a/pythonnet__examples/OpenHardwareMonitorLib__Sensor_Temperature/main.py b/pythonnet__examples/OpenHardwareMonitorLib__Sensor_Temperature/main.py index 3d1f8bb3f..c30092c25 100644 --- a/pythonnet__examples/OpenHardwareMonitorLib__Sensor_Temperature/main.py +++ b/pythonnet__examples/OpenHardwareMonitorLib__Sensor_Temperature/main.py @@ -57,7 +57,7 @@ def initialize_openhardwaremonitor(): return handle -def fetch_stats(handle): +def fetch_stats(handle) -> None: for i in handle.Hardware: i.Update() @@ -70,7 +70,7 @@ def fetch_stats(handle): parse_sensor(subsensor) -def parse_sensor(sensor): +def parse_sensor(sensor) -> None: if sensor.Value is None: return diff --git a/pytz_vs_zoneinfo__examples/get_tz_from_offset__pytz.py b/pytz_vs_zoneinfo__examples/get_tz_from_offset__pytz.py index 52bc5e325..f673cb92b 100644 --- a/pytz_vs_zoneinfo__examples/get_tz_from_offset__pytz.py +++ b/pytz_vs_zoneinfo__examples/get_tz_from_offset__pytz.py @@ -5,7 +5,7 @@ import re -from datetime import datetime, tzinfo +from datetime import datetime, tzinfo, timezone # pip install pytz==2025.2 import pytz @@ -31,21 +31,17 @@ def get_tz(value: str) -> tzinfo: if __name__ == "__main__": - now_utc = datetime.utcnow() - - tz_etc_0300 = pytz.timezone("Etc/GMT-3") - print(now_utc.astimezone(tz_etc_0300).strftime("%z")) - # +0300 - - tz_offset_0300 = pytz.FixedOffset(offset=3 * 60) - print(now_utc.astimezone(tz_offset_0300).strftime("%z")) - # +0300 - - print(now_utc.astimezone(get_tz("+0300")).strftime("%z")) - # +0300 - - print(now_utc.astimezone(get_tz("+03:00")).strftime("%z")) - # +0300 - - print(now_utc.astimezone(get_tz("-0300")).strftime("%z")) - # -0300 + now_utc = datetime.now(timezone.utc) + + test_cases = [ + (pytz.timezone("Etc/GMT-3"), "+0300"), + (pytz.FixedOffset(offset=3 * 60), "+0300"), + (get_tz("+0300"), "+0300"), + (get_tz("+03:00"), "+0300"), + (get_tz("-0300"), "-0300") + ] + + for tz, expected in test_cases: + result = now_utc.astimezone(tz).strftime("%z") + print(result) + assert result == expected diff --git a/pytz_vs_zoneinfo__examples/get_tz_from_offset__zoneinfo.py b/pytz_vs_zoneinfo__examples/get_tz_from_offset__zoneinfo.py index 81b9f90ef..d213e598f 100644 --- a/pytz_vs_zoneinfo__examples/get_tz_from_offset__zoneinfo.py +++ b/pytz_vs_zoneinfo__examples/get_tz_from_offset__zoneinfo.py @@ -30,21 +30,17 @@ def get_tz(value: str) -> tzinfo: if __name__ == "__main__": import zoneinfo - now_utc = datetime.utcnow() - - tz_etc_0300 = zoneinfo.ZoneInfo("Etc/GMT-3") - print(now_utc.astimezone(tz_etc_0300).strftime("%z")) - # +0300 - - tz_offset_0300 = timezone(offset=timedelta(minutes=3 * 60)) - print(now_utc.astimezone(tz_offset_0300).strftime("%z")) - # +0300 - - print(now_utc.astimezone(get_tz("+0300")).strftime("%z")) - # +0300 - - print(now_utc.astimezone(get_tz("+03:00")).strftime("%z")) - # +0300 - - print(now_utc.astimezone(get_tz("-0300")).strftime("%z")) - # -0300 + now_utc = datetime.now(timezone.utc) + + test_cases = [ + (zoneinfo.ZoneInfo("Etc/GMT-3"), "+0300"), + (timezone(offset=timedelta(minutes=3 * 60)), "+0300"), + (get_tz("+0300"), "+0300"), + (get_tz("+03:00"), "+0300"), + (get_tz("-0300"), "-0300") + ] + + for tz, expected in test_cases: + result = now_utc.astimezone(tz).strftime("%z") + print(result) + assert result == expected diff --git a/qbittorrent_examples/check_changes_in_torrent.py b/qbittorrent_examples/check_changes_in_torrent.py index aa4081567..d6b80645e 100644 --- a/qbittorrent_examples/check_changes_in_torrent.py +++ b/qbittorrent_examples/check_changes_in_torrent.py @@ -45,7 +45,7 @@ def get_rutor_torrent_download_info(torrent_url): return torrent_url.replace("/torrent/", "/download/"), magnet_url, info_hash -def remove_previous_torrent_from_qbittorrent(qb, new_info_hash): +def remove_previous_torrent_from_qbittorrent(qb, new_info_hash) -> None: info_hash_by_name_dict = { torrent["hash"]: torrent["name"] for torrent in qb.torrents() } diff --git a/qbittorrent_examples/common.py b/qbittorrent_examples/common.py index 069751b6e..6691e6592 100644 --- a/qbittorrent_examples/common.py +++ b/qbittorrent_examples/common.py @@ -16,7 +16,7 @@ from config import IP_HOST, USER, PASSWORD -def print_table(rows: list[list[str]], headers: list[str], show_index=True): +def print_table(rows: list[list[str]], headers: list[str], show_index=True) -> None: if show_index: show_index = range(1, len(rows) + 1) @@ -24,7 +24,7 @@ def print_table(rows: list[list[str]], headers: list[str], show_index=True): print(text) -def print_files_table(files: list[dict]): +def print_files_table(files: list[dict]) -> None: rows = [ (file["name"], sizeof_fmt(file["size"])) for file in sorted(files, key=lambda x: x["name"]) @@ -33,7 +33,7 @@ def print_files_table(files: list[dict]): print_table(rows, headers) -def print_torrents(torrents: list[dict]): +def print_torrents(torrents: list[dict]) -> None: total_size = 0 for i, torrent in enumerate(torrents, 1): diff --git a/qbittorrent_examples/torrent_list__table_gui_pyqt.py b/qbittorrent_examples/torrent_list__table_gui_pyqt.py index 1fccb102b..9b0c01f7b 100644 --- a/qbittorrent_examples/torrent_list__table_gui_pyqt.py +++ b/qbittorrent_examples/torrent_list__table_gui_pyqt.py @@ -13,7 +13,7 @@ class TorrentInfoWidget(QTableWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setEditTriggers(QTableWidget.NoEditTriggers) @@ -27,7 +27,7 @@ def __init__(self): self.horizontalHeader().setStretchLastSection(True) self.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents) - def fill(self, torrent_details: dict): + def fill(self, torrent_details: dict) -> None: while self.rowCount(): self.removeRow(0) @@ -40,7 +40,7 @@ def fill(self, torrent_details: dict): class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.table_torrent = QTableWidget() @@ -57,7 +57,7 @@ def __init__(self): self.setCentralWidget(splitter) - def fill_table(self): + def fill_table(self) -> None: qb = get_client() torrents = qb.torrents() if not torrents: @@ -80,7 +80,7 @@ def fill_table(self): self.table_torrent.setItem(row, column, item) - def fill_torrent_info(self): + def fill_torrent_info(self) -> None: items = self.table_torrent.selectedItems() if not items: return diff --git a/qt__pyqt__pyside__pyqode/Auto_widget_placement__using_FlowLayout_QThread.py b/qt__pyqt__pyside__pyqode/Auto_widget_placement__using_FlowLayout_QThread.py index 0f8581695..ccb4e9403 100644 --- a/qt__pyqt__pyside__pyqode/Auto_widget_placement__using_FlowLayout_QThread.py +++ b/qt__pyqt__pyside__pyqode/Auto_widget_placement__using_FlowLayout_QThread.py @@ -27,7 +27,7 @@ # Для отлова всех исключений, которые в слотах Qt могут "затеряться" и привести к тихому падению -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -48,12 +48,12 @@ def seconds_to_str(seconds: int) -> str: class ImgThread(QThread): new_img = pyqtSignal(QImage) - def __init__(self, life_time_seconds=60): + def __init__(self, life_time_seconds=60) -> None: super().__init__() self.life_time_seconds = life_time_seconds - def run(self): + def run(self) -> None: painter = QPainter() painter.setRenderHint(QPainter.Antialiasing) @@ -100,7 +100,7 @@ def run(self): class ImgWidget(QWidget): closed = pyqtSignal() - def __init__(self, life_time_seconds=60): + def __init__(self, life_time_seconds=60) -> None: super().__init__() self._thread = ImgThread(life_time_seconds) @@ -116,21 +116,21 @@ def __init__(self, life_time_seconds=60): self.setLayout(layout) - def _on_new_img(self, img: QImage): + def _on_new_img(self, img: QImage) -> None: if not img: return self.setFixedSize(img.size()) self._label.setPixmap(QPixmap.fromImage(img)) - def closeEvent(self, event): + def closeEvent(self, event) -> None: self.closed.emit() super().closeEvent(event) class Window(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle(__file__.split("/")[-1]) @@ -152,7 +152,7 @@ def __init__(self): self.setLayout(main_layout) - def _on_push_add(self): + def _on_push_add(self) -> None: w = ImgWidget(life_time_seconds=random.randint(10, 100)) w.closed.connect(lambda w=w: self.items_layout.removeWidget(w)) diff --git a/qt__pyqt__pyside__pyqode/CompletingTextEdit__QTextEdit_QCompleter.py b/qt__pyqt__pyside__pyqode/CompletingTextEdit__QTextEdit_QCompleter.py index 8ada87d4a..17fd1fad0 100644 --- a/qt__pyqt__pyside__pyqode/CompletingTextEdit__QTextEdit_QCompleter.py +++ b/qt__pyqt__pyside__pyqode/CompletingTextEdit__QTextEdit_QCompleter.py @@ -18,7 +18,7 @@ ) -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -31,7 +31,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class CompletingTextEdit(QTextEdit): - def __init__(self, parent=None): + def __init__(self, parent=None) -> None: super().__init__(parent) self.completerSequence = QKeySequence("Ctrl+Space") @@ -40,7 +40,7 @@ def __init__(self, parent=None): self._completer.setWidget(self) self._completer.activated.connect(self.insertCompletion) - def insertCompletion(self, completion): + def insertCompletion(self, completion) -> None: if self._completer.widget() is not self: return @@ -57,7 +57,7 @@ def textUnderCursor(self): return tc.selectedText() - def loadFromFile(self, fileName): + def loadFromFile(self, fileName) -> None: f = QFile(fileName) if not f.open(QFile.ReadOnly): model = QStringListModel() @@ -81,11 +81,11 @@ def loadFromFile(self, fileName): model = QStringListModel(words) self._completer.setModel(model) - def loadFromList(self, words): + def loadFromList(self, words) -> None: model = QStringListModel(words) self._completer.setModel(model) - def keyPressEvent(self, e): + def keyPressEvent(self, e) -> None: if self._completer.popup().isVisible(): # The following keys are forwarded by the completer to the widget. if e.key() in ( @@ -139,7 +139,7 @@ def keyPressEvent(self, e): class MainWindow(QMainWindow): - def __init__(self, parent=None): + def __init__(self, parent=None) -> None: super().__init__(parent) self.setWindowTitle("Completer") diff --git a/qt__pyqt__pyside__pyqode/EgoDialog.py b/qt__pyqt__pyside__pyqode/EgoDialog.py index e6bfaab84..d4bbf7b9a 100644 --- a/qt__pyqt__pyside__pyqode/EgoDialog.py +++ b/qt__pyqt__pyside__pyqode/EgoDialog.py @@ -10,7 +10,7 @@ class EgoDialog(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowFlag(Qt.FramelessWindowHint) @@ -29,7 +29,7 @@ def exec(title: str, text: str) -> bool: return ok == QMessageBox.Yes - def paintEvent(self, event): + def paintEvent(self, event) -> None: painter = QPainter(self) painter.setBrush(QColor(0, 0, 0, 127)) painter.drawRect(self.rect()) diff --git a/qt__pyqt__pyside__pyqode/ElidedLabel.py b/qt__pyqt__pyside__pyqode/ElidedLabel.py index ba94d1c58..5b1bdf5ae 100644 --- a/qt__pyqt__pyside__pyqode/ElidedLabel.py +++ b/qt__pyqt__pyside__pyqode/ElidedLabel.py @@ -10,12 +10,12 @@ class ElidedLabel(QLabel): - def __init__(self, *args, **kwargs): + def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self.setMinimumWidth(50) - def paintEvent(self, event): + def paintEvent(self, event) -> None: painter = QPainter(self) metrics = QFontMetrics(self.font()) diff --git a/qt__pyqt__pyside__pyqode/FlowLayout.py b/qt__pyqt__pyside__pyqode/FlowLayout.py index 54a7242d5..c7cf4eb52 100644 --- a/qt__pyqt__pyside__pyqode/FlowLayout.py +++ b/qt__pyqt__pyside__pyqode/FlowLayout.py @@ -103,7 +103,7 @@ def doLayout(self, rect, testOnly): from PyQt5.QtWidgets import QWidget, QPushButton, QApplication class Window(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() flowLayout = FlowLayout() diff --git a/qt__pyqt__pyside__pyqode/GIPHY__gif/main.py b/qt__pyqt__pyside__pyqode/GIPHY__gif/main.py index dd84a7e42..114f44686 100644 --- a/qt__pyqt__pyside__pyqode/GIPHY__gif/main.py +++ b/qt__pyqt__pyside__pyqode/GIPHY__gif/main.py @@ -33,7 +33,7 @@ from config import GIPHY_API_KEY, TEMP_DIR -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -50,7 +50,7 @@ class SearchGifThread(QThread): about_add_gif = pyqtSignal(dict, int, int) - def __init__(self, name_gif=None): + def __init__(self, name_gif=None) -> None: super().__init__() self.name_gif = name_gif @@ -90,7 +90,7 @@ def _process_gif(self, img: dict, index: int) -> dict: } return data - def run(self): + def run(self) -> None: data = self.get_gif() if "error" in data: # TODO: emit error to MainWindow @@ -104,7 +104,7 @@ def run(self): class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.title = "Gif Manager" @@ -117,7 +117,7 @@ def __init__(self): self.init_ui() - def init_ui(self): + def init_ui(self) -> None: self.gif_edit = QLineEdit() self.gif_edit.returnPressed.connect(self.search_gif) self.gif_edit.setPlaceholderText("Enter name gif") @@ -155,15 +155,15 @@ def init_ui(self): root_layout.addWidget(self.info_label) root_layout.addWidget(self.scroll) - def on_finish(self): + def on_finish(self) -> None: self.gif_data_frame.setEnabled(True) - def on_start(self): + def on_start(self) -> None: self.info_label.hide() self.scroll.show() self.gif_data_frame.setEnabled(False) - def search_gif(self): + def search_gif(self) -> None: # TODO: replace on QListWidget for i in range(self.gifs_layout.count()): self.gifs_layout.itemAt(i).widget().deleteLater() @@ -171,7 +171,7 @@ def search_gif(self): self.search_gif_thread.name_gif = self.gif_edit.text() self.search_gif_thread.start() - def add_gif(self, data: dict, num: int, total: int): + def add_gif(self, data: dict, num: int, total: int) -> None: self.setWindowTitle(f"{self.title}. {num} / {total}") if data["error"]: diff --git a/qt__pyqt__pyside__pyqode/ImageLabel__QGraphicsView/main.py b/qt__pyqt__pyside__pyqode/ImageLabel__QGraphicsView/main.py index e23aa43c7..db0860632 100644 --- a/qt__pyqt__pyside__pyqode/ImageLabel__QGraphicsView/main.py +++ b/qt__pyqt__pyside__pyqode/ImageLabel__QGraphicsView/main.py @@ -15,22 +15,22 @@ class ImageLabel(QGraphicsView): - def __init__(self, *args, **kwargs): + def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self.setScene(QGraphicsScene()) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) - def setImage(self, filename: str): + def setImage(self, filename: str) -> None: self.setPixmap(QPixmap(filename)) - def setPixmap(self, pixmap: QPixmap): + def setPixmap(self, pixmap: QPixmap) -> None: item = QGraphicsPixmapItem(pixmap) item.setTransformationMode(Qt.SmoothTransformation) self.scene().addItem(item) - def resizeEvent(self, event): + def resizeEvent(self, event) -> None: super().resizeEvent(event) rect = self.scene().itemsBoundingRect() diff --git a/qt__pyqt__pyside__pyqode/One_ball__in_outer_circle_area__collision_with_mouse__QPainter/main.py b/qt__pyqt__pyside__pyqode/One_ball__in_outer_circle_area__collision_with_mouse__QPainter/main.py index 5eb29cd52..1b5cf743b 100644 --- a/qt__pyqt__pyside__pyqode/One_ball__in_outer_circle_area__collision_with_mouse__QPainter/main.py +++ b/qt__pyqt__pyside__pyqode/One_ball__in_outer_circle_area__collision_with_mouse__QPainter/main.py @@ -11,6 +11,7 @@ import traceback import sys +from dataclasses import dataclass from pathlib import Path from timeit import default_timer @@ -19,7 +20,7 @@ from PyQt5.QtWidgets import QApplication, QMessageBox, QWidget -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}\n" text += "".join(traceback.format_tb(tb)) print(text) @@ -39,19 +40,20 @@ def log_uncaught_exceptions(ex_cls, ex, tb): sys.excepthook = log_uncaught_exceptions +@dataclass class Ball: - r = 50 # Радиус шарика - x = 0 # Координата по х центра шарика - y = 0 # Координата по y центра шарика - speed = 0 # Скорость движения - dir_x = 0 # Компонент x вектора движения шарика - dir_y = 0 # Компонент y вектора движения шарика - damp = 10 # Скорость уменьшения скорости движения (сопротивление) - collision = False # Признак коллизии с внешним кругом - speed_after_collision = 300 # Скорость движения шарика после столкновения + r: float = 50 # Радиус шарика + x: float = 0 # Координата по х центра шарика + y: float = 0 # Координата по y центра шарика + speed: float = 0 # Скорость движения + dir_x: float = 0 # Компонент x вектора движения шарика + dir_y: float = 0 # Компонент y вектора движения шарика + damp: float = 10 # Скорость уменьшения скорости движения (сопротивление) + collision: bool = False # Признак коллизии с внешним кругом + speed_after_collision: float = 300 # Скорость движения шарика после столкновения # Функция, которая проверяет наличие коллизии шарика с внешним кругом - def hit_outer_circle_check(self, outer_circle: int): + def hit_outer_circle_check(self, outer_circle: int) -> None: dr = outer_circle - self.r # Разница радиусов # По теореме пифагора проверяем выход за пределы круга (коллизию) @@ -94,7 +96,7 @@ def hit_outer_circle_check(self, outer_circle: int): self.collision = False # Функция проверки коллизии шарика и мышки - def hit_mouse_check(self, x, y): + def hit_mouse_check(self, x, y) -> None: # Если есть коллизия с внешним кругом игнорируем мышку if self.collision: return @@ -118,7 +120,7 @@ def hit_mouse_check(self, x, y): # Тут осуществляется передвижение # dt - кол-во секунд с прошлого обсчета - def do_move(self, dt: float): + def do_move(self, dt: float) -> None: # К текущей координате прибавляем вектор скорости помноженный # на значение скорости помноженные на прошедшее время self.x += self.dir_x * self.speed * dt @@ -129,7 +131,7 @@ def do_move(self, dt: float): class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() timeout: int = 1000 // 60 @@ -161,12 +163,12 @@ def __init__(self): self.update_window_title() - def update_window_title(self): + def update_window_title(self) -> None: name = Path(__file__).parent.name title = f"{name}. Speed: {self.ball.speed}" self.setWindowTitle(title) - def tick(self): + def tick(self) -> None: # Считаем сколько времени прошло с прошлого обсчета dt = default_timer() - self.t @@ -178,11 +180,11 @@ def tick(self): self.update() - def mouseMoveEvent(self, event): + def mouseMoveEvent(self, event) -> None: self.mouse_center_x = event.pos().x() - (self.width() / 2) self.mouse_center_y = event.pos().y() - (self.height() / 2) - def paintEvent(self, event): + def paintEvent(self, event) -> None: painter = QPainter(self) painter.setRenderHint(QPainter.HighQualityAntialiasing) diff --git a/qt__pyqt__pyside__pyqode/PySide_examples/draw_table/draw_table.py b/qt__pyqt__pyside__pyqode/PySide_examples/draw_table/draw_table.py index 0cc8d00a0..03c97bf5c 100644 --- a/qt__pyqt__pyside__pyqode/PySide_examples/draw_table/draw_table.py +++ b/qt__pyqt__pyside__pyqode/PySide_examples/draw_table/draw_table.py @@ -13,7 +13,7 @@ class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Widget") @@ -34,7 +34,7 @@ def __init__(self): self.setMouseTracking(True) - def resizeEvent(self, event): + def resizeEvent(self, event) -> None: super().resizeEvent(event) w, h = event.size().width(), event.size().height() @@ -42,7 +42,7 @@ def resizeEvent(self, event): self.cell_size = min_size // self.matrix_size - def mouseMoveEvent(self, event): + def mouseMoveEvent(self, event) -> None: super().mouseMoveEvent(event) pos = event.pos() @@ -52,7 +52,7 @@ def mouseMoveEvent(self, event): self.update() - def paintEvent(self, event): + def paintEvent(self, event) -> None: super().paintEvent(event) painter = QPainter(self) diff --git a/qt__pyqt__pyside__pyqode/PySide_examples/e1.py b/qt__pyqt__pyside__pyqode/PySide_examples/e1.py index c7c9a7592..6d43f7ab5 100644 --- a/qt__pyqt__pyside__pyqode/PySide_examples/e1.py +++ b/qt__pyqt__pyside__pyqode/PySide_examples/e1.py @@ -12,7 +12,7 @@ app = QApplication(sys.argv) - def says(): + def says() -> None: print("Hello, Python!") label = QLabel("Hello, PySize!") diff --git a/qt__pyqt__pyside__pyqode/PySide_examples/e2.py b/qt__pyqt__pyside__pyqode/PySide_examples/e2.py index d224bc351..5d60a5f05 100644 --- a/qt__pyqt__pyside__pyqode/PySide_examples/e2.py +++ b/qt__pyqt__pyside__pyqode/PySide_examples/e2.py @@ -11,7 +11,7 @@ class SimpleWindow(QtGui.QWidget): """Просто окно""" - def __init__(self, *args, **kwargs): + def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self.setWindowTitle("Простое окно") @@ -30,7 +30,7 @@ def __init__(self, *args, **kwargs): self.setLayout(layout_main) - def slot_add_log(self): + def slot_add_log(self) -> None: text = self.le_mess.text() if text: self.lw_log.addItem(text) diff --git a/qt__pyqt__pyside__pyqode/PySide_examples/e3.py b/qt__pyqt__pyside__pyqode/PySide_examples/e3.py index 2926ad212..5bdfbe286 100644 --- a/qt__pyqt__pyside__pyqode/PySide_examples/e3.py +++ b/qt__pyqt__pyside__pyqode/PySide_examples/e3.py @@ -5,7 +5,7 @@ class MainWindow(QMainWindow): - def __init__(self, *args, **kwargs): + def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self.editor = QTextEdit() self.setCentralWidget(self.editor) @@ -19,12 +19,12 @@ def __init__(self, *args, **kwargs): self.edit_menu = self.menuBar().addMenu("Правка") self.edit_menu.aboutToShow.connect(self.update_edit_menu) - def update_edit_menu(self): + def update_edit_menu(self) -> None: self.edit_menu.clear() actions = self.editor.createStandardContextMenu().actions() self.edit_menu.addActions(actions) - def slot_save_as(self): + def slot_save_as(self) -> None: file_name = QFileDialog.getSaveFileName()[0] if file_name: with open(file_name, "w") as f: diff --git a/qt__pyqt__pyside__pyqode/PySide_examples/e4.py b/qt__pyqt__pyside__pyqode/PySide_examples/e4.py index ad8000546..736d1b344 100644 --- a/qt__pyqt__pyside__pyqode/PySide_examples/e4.py +++ b/qt__pyqt__pyside__pyqode/PySide_examples/e4.py @@ -24,24 +24,24 @@ def get_confucius_quotes(): class MyThread(Thread): - def __init__(self, log): + def __init__(self, log) -> None: super().__init__() self.log = log - def run(self): + def run(self) -> None: for i, quote in enumerate(get_confucius_quotes(), 1): self.log.append(f'{i}. "{quote}"\n') time.sleep(0.1) # задержка каждые 100 миллисекунд class Window(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.te_quotes = QTextEdit() self.te_quotes.setReadOnly(True) self.setCentralWidget(self.te_quotes) - def slot_refresh(self): + def slot_refresh(self) -> None: self.te_quotes.clear() thread = MyThread(self.te_quotes) thread.start() diff --git a/qt__pyqt__pyside__pyqode/PySide_examples/infinite_input.py b/qt__pyqt__pyside__pyqode/PySide_examples/infinite_input.py index f9af8f2c4..8390f5d6b 100644 --- a/qt__pyqt__pyside__pyqode/PySide_examples/infinite_input.py +++ b/qt__pyqt__pyside__pyqode/PySide_examples/infinite_input.py @@ -9,7 +9,7 @@ class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.layout = QVBoxLayout() @@ -19,14 +19,14 @@ def __init__(self): self._add_line_edit() - def _add_line_edit(self): + def _add_line_edit(self) -> None: line_edit = QLineEdit() line_edit.textEdited.connect(self._text_edited) self.layout.addWidget(line_edit) self.line_edit_list.append(line_edit) - def _text_edited(self, text): + def _text_edited(self, text) -> None: if not self.line_edit_list: return diff --git a/qt__pyqt__pyside__pyqode/QApplication_keyboardModifiers.py b/qt__pyqt__pyside__pyqode/QApplication_keyboardModifiers.py index 3ff44c785..c10d47b94 100644 --- a/qt__pyqt__pyside__pyqode/QApplication_keyboardModifiers.py +++ b/qt__pyqt__pyside__pyqode/QApplication_keyboardModifiers.py @@ -9,7 +9,7 @@ class Window(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.button = QPushButton("Test") @@ -20,13 +20,13 @@ def __init__(self): self.setLayout(main_layout) - def foo(self): + def foo(self) -> None: print("foo") - def bar(self): + def bar(self) -> None: print("bar") - def on_clicked(self): + def on_clicked(self) -> None: modifiers = QApplication.keyboardModifiers() if modifiers == Qt.AltModifier: diff --git a/qt__pyqt__pyside__pyqode/QAxContainer_Word_Application.py b/qt__pyqt__pyside__pyqode/QAxContainer_Word_Application.py index 156f8ec22..69357fd5a 100644 --- a/qt__pyqt__pyside__pyqode/QAxContainer_Word_Application.py +++ b/qt__pyqt__pyside__pyqode/QAxContainer_Word_Application.py @@ -18,7 +18,7 @@ class Window(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Document Word.Application") diff --git a/qt__pyqt__pyside__pyqode/QLabel__enter_leave__with_pixmap/main.py b/qt__pyqt__pyside__pyqode/QLabel__enter_leave__with_pixmap/main.py index a6488abd7..24b062c28 100644 --- a/qt__pyqt__pyside__pyqode/QLabel__enter_leave__with_pixmap/main.py +++ b/qt__pyqt__pyside__pyqode/QLabel__enter_leave__with_pixmap/main.py @@ -9,7 +9,7 @@ class Label(QLabel): - def __init__(self): + def __init__(self) -> None: super().__init__() self.pixmap = QPixmap("52rQ3.png") @@ -18,10 +18,10 @@ def __init__(self): self.setPixmap(self.pixmap_leave) - def enterEvent(self, event): + def enterEvent(self, event) -> None: self.setPixmap(self.pixmap_enter) - def leaveEvent(self, event): + def leaveEvent(self, event) -> None: self.setPixmap(self.pixmap_leave) diff --git a/qt__pyqt__pyside__pyqode/QLabel_setText__in_thread__QThread.py b/qt__pyqt__pyside__pyqode/QLabel_setText__in_thread__QThread.py index d48e38ea9..8fbbf55c1 100644 --- a/qt__pyqt__pyside__pyqode/QLabel_setText__in_thread__QThread.py +++ b/qt__pyqt__pyside__pyqode/QLabel_setText__in_thread__QThread.py @@ -9,14 +9,14 @@ class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.label = QLabel() self.label.setAlignment(Qt.AlignCenter) self.label.setFont(QFont("Courier", 25)) - def loop(): + def loop() -> None: i = 0 while True: @@ -26,7 +26,7 @@ def loop(): time.sleep(1) class Thread(QThread): - def run(self): + def run(self) -> None: loop() self.thread = Thread() diff --git a/qt__pyqt__pyside__pyqode/QLabel_setText__in_thread__threading.py b/qt__pyqt__pyside__pyqode/QLabel_setText__in_thread__threading.py index d7f44cfb4..80d27525b 100644 --- a/qt__pyqt__pyside__pyqode/QLabel_setText__in_thread__threading.py +++ b/qt__pyqt__pyside__pyqode/QLabel_setText__in_thread__threading.py @@ -11,14 +11,14 @@ class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.label = QLabel() self.label.setAlignment(Qt.AlignCenter) self.label.setFont(QFont("Courier", 25)) - def loop(): + def loop() -> None: i = 0 while True: diff --git a/qt__pyqt__pyside__pyqode/QLineEdit__mask.py b/qt__pyqt__pyside__pyqode/QLineEdit__mask.py index 12908ac7e..934c4f95c 100644 --- a/qt__pyqt__pyside__pyqode/QLineEdit__mask.py +++ b/qt__pyqt__pyside__pyqode/QLineEdit__mask.py @@ -11,7 +11,7 @@ class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.mask_qt = QLineEdit("+7([000])[000]-[0000]") @@ -25,7 +25,7 @@ def __init__(self): self.setLayout(layout) - def _on_changed_mask(self, mask): + def _on_changed_mask(self, mask) -> None: text = self.test_input.text() self.test_input.setInputMask(mask) diff --git a/qt__pyqt__pyside__pyqode/QListWidget_with_custom_widgets.py b/qt__pyqt__pyside__pyqode/QListWidget_with_custom_widgets.py index 878175db8..9bf014214 100644 --- a/qt__pyqt__pyside__pyqode/QListWidget_with_custom_widgets.py +++ b/qt__pyqt__pyside__pyqode/QListWidget_with_custom_widgets.py @@ -24,7 +24,7 @@ def __init__( port: int, status: str = "Not checked!", last_check_time: dt.datetime = None, - ): + ) -> None: super().__init__() if not last_check_time: @@ -47,7 +47,7 @@ def __init__( self.setFixedHeight(self.sizeHint().height()) -def add_item(list_widget: QListWidget, host: str, port: int): +def add_item(list_widget: QListWidget, host: str, port: int) -> None: widget = ListItem(host, port) item = QListWidgetItem() diff --git a/qt__pyqt__pyside__pyqode/QML__examples/hello_world_with_widgets.py b/qt__pyqt__pyside__pyqode/QML__examples/hello_world_with_widgets.py index add7e95c3..00fe3caf7 100644 --- a/qt__pyqt__pyside__pyqode/QML__examples/hello_world_with_widgets.py +++ b/qt__pyqt__pyside__pyqode/QML__examples/hello_world_with_widgets.py @@ -17,7 +17,7 @@ class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Hello World! (QML + Qt)") @@ -32,7 +32,7 @@ def __init__(self): main_layout.addWidget(QWidget.createWindowContainer(self.view)) main_layout.addWidget(pb_click) - def _on_clicked(self): + def _on_clicked(self) -> None: qml_hello_text = self.view.rootObject().findChild(QQuickItem, "helloText") qml_hello_text.setProperty("text", f"Now: {datetime.now().time():%H:%M:%S}") diff --git a/qt__pyqt__pyside__pyqode/QMdiSubWindow__hello_world.py b/qt__pyqt__pyside__pyqode/QMdiSubWindow__hello_world.py index bfa3a3c20..8584615d1 100644 --- a/qt__pyqt__pyside__pyqode/QMdiSubWindow__hello_world.py +++ b/qt__pyqt__pyside__pyqode/QMdiSubWindow__hello_world.py @@ -15,7 +15,7 @@ class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.sub_window_1 = QMdiSubWindow() diff --git a/qt__pyqt__pyside__pyqode/QTextEdit__with_font_size_panel.py b/qt__pyqt__pyside__pyqode/QTextEdit__with_font_size_panel.py index 29d23d479..512d88dc0 100644 --- a/qt__pyqt__pyside__pyqode/QTextEdit__with_font_size_panel.py +++ b/qt__pyqt__pyside__pyqode/QTextEdit__with_font_size_panel.py @@ -8,7 +8,7 @@ class MainWindow(Qt.QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.sb_font_size = Qt.QSpinBox() @@ -26,13 +26,13 @@ def __init__(self): self.setCentralWidget(central_widget) - def _on_font_size_changed(self, value): + def _on_font_size_changed(self, value) -> None: text_char_format = Qt.QTextCharFormat() text_char_format.setFontPointSize(value) self.merge_format_on_word_or_selection(text_char_format) - def merge_format_on_word_or_selection(self, text_char_format): + def merge_format_on_word_or_selection(self, text_char_format) -> None: cursor = self.text_edit.textCursor() if not cursor.hasSelection(): cursor.select(Qt.QTextCursor.WordUnderCursor) diff --git a/qt__pyqt__pyside__pyqode/QThreadPool__QRunnable.py b/qt__pyqt__pyside__pyqode/QThreadPool__QRunnable.py index b2b98bc65..af48f9ec5 100644 --- a/qt__pyqt__pyside__pyqode/QThreadPool__QRunnable.py +++ b/qt__pyqt__pyside__pyqode/QThreadPool__QRunnable.py @@ -15,12 +15,12 @@ class HelloWorldTask(QRunnable): - def __init__(self, idx: int): + def __init__(self, idx: int) -> None: super().__init__() self.idx = idx - def run(self): + def run(self) -> None: with lock: print(f"[{self.idx}] Hello world from thread: {threading.current_thread()}") diff --git a/qt__pyqt__pyside__pyqode/QThread_with_pause_and_resume__QWaitCondition.py b/qt__pyqt__pyside__pyqode/QThread_with_pause_and_resume__QWaitCondition.py index 349f4e9a0..405f622ee 100644 --- a/qt__pyqt__pyside__pyqode/QThread_with_pause_and_resume__QWaitCondition.py +++ b/qt__pyqt__pyside__pyqode/QThread_with_pause_and_resume__QWaitCondition.py @@ -19,7 +19,7 @@ class Thread(QThread): - def __init__(self, parent=None): + def __init__(self, parent=None) -> None: super().__init__(parent) self._is_pause = False @@ -30,14 +30,14 @@ def __init__(self, parent=None): def is_pause(self) -> bool: return self._is_pause - def pause(self): + def pause(self) -> None: self._is_pause = True - def resume(self): + def resume(self) -> None: self._is_pause = False self.condition.wakeAll() - def run(self): + def run(self) -> None: while True: self.mutex.lock() if self._is_pause: @@ -48,7 +48,7 @@ def run(self): class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.combobox_thread = QComboBox() @@ -87,7 +87,7 @@ def __init__(self): self._update_states() - def _update_states(self): + def _update_states(self) -> None: threads_num = self.combobox_thread.count() self.setWindowTitle(f"Threads: {threads_num}") @@ -111,11 +111,11 @@ def get_thread(self, idx: int) -> Thread: def get_all_thread(self) -> list[Thread]: return [self.get_thread(i) for i in range(self.combobox_thread.count())] - def update_info(self): + def update_info(self) -> None: total = sum(thread.sum for thread in self.get_all_thread()) self.label_result.setText(f"SUM: {total}") - def add(self): + def add(self) -> None: thread = Thread(self) thread.start() @@ -124,27 +124,27 @@ def add(self): ) self._update_states() - def pause(self): + def pause(self) -> None: thread = self.combobox_thread.currentData() if thread: thread.pause() self._update_states() - def pause_all(self): + def pause_all(self) -> None: for thread in self.get_all_thread(): thread.pause() self._update_states() - def resume(self): + def resume(self) -> None: thread = self.combobox_thread.currentData() if thread: thread.resume() self._update_states() - def resume_all(self): + def resume_all(self) -> None: for thread in self.get_all_thread(): thread.resume() diff --git a/qt__pyqt__pyside__pyqode/QThread_with_pause_and_resume__QWaitCondition_with_QTableWidget.py b/qt__pyqt__pyside__pyqode/QThread_with_pause_and_resume__QWaitCondition_with_QTableWidget.py index ad2dd1bbf..228b77fce 100644 --- a/qt__pyqt__pyside__pyqode/QThread_with_pause_and_resume__QWaitCondition_with_QTableWidget.py +++ b/qt__pyqt__pyside__pyqode/QThread_with_pause_and_resume__QWaitCondition_with_QTableWidget.py @@ -31,7 +31,7 @@ class Thread(QThread): about_pause = pyqtSignal(bool) about_sum = pyqtSignal(int) - def __init__(self, parent=None): + def __init__(self, parent=None) -> None: super().__init__(parent) self._is_pause = False @@ -44,14 +44,14 @@ def sum(self) -> int: return self._sum @sum.setter - def sum(self, value: int): + def sum(self, value: int) -> None: self._sum = value self.about_sum.emit(value) def get_state(self) -> str: return "PAUSED" if self._is_pause else "WORKING" - def set_pause(self, pause: bool): + def set_pause(self, pause: bool) -> None: self._is_pause = pause self.about_pause.emit(pause) @@ -61,13 +61,13 @@ def set_pause(self, pause: bool): def is_pause(self) -> bool: return self._is_pause - def pause(self): + def pause(self) -> None: self.set_pause(True) - def resume(self): + def resume(self) -> None: self.set_pause(False) - def run(self): + def run(self) -> None: while True: self.mutex.lock() if self._is_pause: @@ -80,7 +80,7 @@ def run(self): class MainWindow(QWidget): headers = ["NAME", "STATE", "SUM"] - def __init__(self): + def __init__(self) -> None: super().__init__() self.started: dt.datetime = None @@ -141,7 +141,7 @@ def __init__(self): self._update_states() - def _update_window_title(self): + def _update_window_title(self) -> None: threads_num = self.table_thread.rowCount() if self.started: elapsed = str(dt.datetime.now() - self.started).split(".")[0] @@ -149,7 +149,7 @@ def _update_window_title(self): else: self.setWindowTitle(f"Threads: {threads_num}") - def _update_states(self): + def _update_states(self) -> None: self._update_window_title() row = self.table_thread.currentRow() @@ -173,7 +173,7 @@ def get_thread(self, row: int) -> Thread: def get_all_thread(self) -> list[Thread]: return [self.get_thread(row) for row in range(self.table_thread.rowCount())] - def update_info(self): + def update_info(self) -> None: self._update_window_title() if self.cb_reset_sum.isChecked(): @@ -182,13 +182,13 @@ def update_info(self): self._sum += sum(thread.sum for thread in self.get_all_thread()) self.label_result.setText(f"TOTAL SUM: {get_pretty_int(self._sum)}") - def _on_thread_changed(self, thread: Thread): + def _on_thread_changed(self, thread: Thread) -> None: for row in range(self.table_thread.rowCount()): if thread == self.get_thread(row): self.table_thread.item(row, 1).setText(thread.get_state()) self.table_thread.item(row, 2).setText(get_pretty_int(thread.sum)) - def add(self): + def add(self) -> None: if not self.started: self.started = dt.datetime.now() @@ -218,7 +218,7 @@ def add(self): self._update_states() - def pause(self): + def pause(self) -> None: item = self.table_thread.currentItem() if item: thread = self.get_thread(item.row()) @@ -226,13 +226,13 @@ def pause(self): self._update_states() - def pause_all(self): + def pause_all(self) -> None: for thread in self.get_all_thread(): thread.pause() self._update_states() - def resume(self): + def resume(self) -> None: item = self.table_thread.currentItem() if item: thread = self.get_thread(item.row()) @@ -240,7 +240,7 @@ def resume(self): self._update_states() - def resume_all(self): + def resume_all(self) -> None: for thread in self.get_all_thread(): thread.resume() diff --git a/qt__pyqt__pyside__pyqode/QWebEngineView__load__blank_url.py b/qt__pyqt__pyside__pyqode/QWebEngineView__load__blank_url.py index 088966d28..6f7f69feb 100644 --- a/qt__pyqt__pyside__pyqode/QWebEngineView__load__blank_url.py +++ b/qt__pyqt__pyside__pyqode/QWebEngineView__load__blank_url.py @@ -18,14 +18,14 @@ def createWindow(self, _type): page.urlChanged.connect(self.on_url_changed) return page - def on_url_changed(self, url: QUrl): + def on_url_changed(self, url: QUrl) -> None: page = self.sender() self.setUrl(url) page.deleteLater() class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.browser = QWebEngineView() diff --git a/qt__pyqt__pyside__pyqode/QWebEngine__append_custom_javascript__jQuery/main.py b/qt__pyqt__pyside__pyqode/QWebEngine__append_custom_javascript__jQuery/main.py index f381425d9..3da012a4c 100644 --- a/qt__pyqt__pyside__pyqode/QWebEngine__append_custom_javascript__jQuery/main.py +++ b/qt__pyqt__pyside__pyqode/QWebEngine__append_custom_javascript__jQuery/main.py @@ -20,7 +20,7 @@ view = QWebEngineView() -def _on_load_finished(ok: bool): +def _on_load_finished(ok: bool) -> None: view.page().runJavaScript(jquery_text) # Test jQuery diff --git a/qt__pyqt__pyside__pyqode/QWebEngine__append_custom_javascript__jQuery__with_select_color/main.py b/qt__pyqt__pyside__pyqode/QWebEngine__append_custom_javascript__jQuery__with_select_color/main.py index 8a9881380..6018c88a7 100644 --- a/qt__pyqt__pyside__pyqode/QWebEngine__append_custom_javascript__jQuery__with_select_color/main.py +++ b/qt__pyqt__pyside__pyqode/QWebEngine__append_custom_javascript__jQuery__with_select_color/main.py @@ -10,7 +10,7 @@ class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.view = QWebEngineView() @@ -27,10 +27,10 @@ def __init__(self): self.setCentralWidget(self.view) - def _on_load_finished(self, ok: bool): + def _on_load_finished(self, ok: bool) -> None: self.view.page().runJavaScript(self.jquery_text) - def _change_background_color(self): + def _change_background_color(self) -> None: color = QColorDialog.getColor(Qt.yellow) if not color.isValid(): return diff --git a/qt__pyqt__pyside__pyqode/QWebEngine__fill_form_login__auth__github_com/main.py b/qt__pyqt__pyside__pyqode/QWebEngine__fill_form_login__auth__github_com/main.py index 7100a84af..e5e174f41 100644 --- a/qt__pyqt__pyside__pyqode/QWebEngine__fill_form_login__auth__github_com/main.py +++ b/qt__pyqt__pyside__pyqode/QWebEngine__fill_form_login__auth__github_com/main.py @@ -25,7 +25,7 @@ view.load(QUrl("https://github.com/login")) -def _on_load_finished(ok: bool): +def _on_load_finished(ok: bool) -> None: page = view.page() url = page.url().toString() diff --git a/qt__pyqt__pyside__pyqode/QWebEngine__handler_console_log_javascript/main.py b/qt__pyqt__pyside__pyqode/QWebEngine__handler_console_log_javascript/main.py index a0ba7c4b1..ca05eaeb8 100644 --- a/qt__pyqt__pyside__pyqode/QWebEngine__handler_console_log_javascript/main.py +++ b/qt__pyqt__pyside__pyqode/QWebEngine__handler_console_log_javascript/main.py @@ -18,7 +18,7 @@ def javaScriptConsoleMessage( message: str, line_number: int, source_id: str, - ): + ) -> None: print( f"javascript_console_message: {level}, {message}, {line_number}, {source_id}", file=sys.stderr, @@ -34,7 +34,7 @@ def javaScriptConsoleMessage( view.setPage(page) -def _on_load_finished(ok: bool): +def _on_load_finished(ok: bool) -> None: page = view.page() print(page.url().toString()) diff --git a/qt__pyqt__pyside__pyqode/QWebEngine__runJavaScript__sync__click_on_element/main.py b/qt__pyqt__pyside__pyqode/QWebEngine__runJavaScript__sync__click_on_element/main.py index 09d8aa75b..a3a1287be 100644 --- a/qt__pyqt__pyside__pyqode/QWebEngine__runJavaScript__sync__click_on_element/main.py +++ b/qt__pyqt__pyside__pyqode/QWebEngine__runJavaScript__sync__click_on_element/main.py @@ -14,7 +14,7 @@ def run_js_code(page: QWebEnginePage, code: str) -> object: result_value = {"value": None} - def _on_callback(result: object): + def _on_callback(result: object) -> None: result_value["value"] = result loop.quit() @@ -38,7 +38,7 @@ def _on_callback(result: object): view.load(QUrl("https://гибдд.рф/request_main")) -def _on_load_finished(ok: bool): +def _on_load_finished(ok: bool) -> None: page = view.page() print(page.url().toString()) diff --git a/qt__pyqt__pyside__pyqode/QWidget_with_QMenuBar.py b/qt__pyqt__pyside__pyqode/QWidget_with_QMenuBar.py index 86b290e86..130249ff8 100644 --- a/qt__pyqt__pyside__pyqode/QWidget_with_QMenuBar.py +++ b/qt__pyqt__pyside__pyqode/QWidget_with_QMenuBar.py @@ -8,7 +8,7 @@ class MainWindow(Qt.QWidget): - def __init__(self, parent=None): + def __init__(self, parent=None) -> None: super().__init__(parent) menu_bar = Qt.QMenuBar() diff --git a/qt__pyqt__pyside__pyqode/RotatedButton__QGraphicsScene.py b/qt__pyqt__pyside__pyqode/RotatedButton__QGraphicsScene.py index 68f7553fb..9ecac1a74 100644 --- a/qt__pyqt__pyside__pyqode/RotatedButton__QGraphicsScene.py +++ b/qt__pyqt__pyside__pyqode/RotatedButton__QGraphicsScene.py @@ -22,7 +22,7 @@ class Window(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.scene = QGraphicsScene() diff --git a/qt__pyqt__pyside__pyqode/RunFuncThread.py b/qt__pyqt__pyside__pyqode/RunFuncThread.py index 5cbd7582d..7329a61cf 100644 --- a/qt__pyqt__pyside__pyqode/RunFuncThread.py +++ b/qt__pyqt__pyside__pyqode/RunFuncThread.py @@ -10,12 +10,12 @@ class RunFuncThread(QThread): run_finished = pyqtSignal(object) - def __init__(self, func): + def __init__(self, func) -> None: super().__init__() self.func = func - def run(self): + def run(self) -> None: self.run_finished.emit(self.func()) diff --git a/qt__pyqt__pyside__pyqode/SwitchButton__example/from_QAbstractButton/switch_button.py b/qt__pyqt__pyside__pyqode/SwitchButton__example/from_QAbstractButton/switch_button.py index 55b17bf1b..7d3cbacd3 100644 --- a/qt__pyqt__pyside__pyqode/SwitchButton__example/from_QAbstractButton/switch_button.py +++ b/qt__pyqt__pyside__pyqode/SwitchButton__example/from_QAbstractButton/switch_button.py @@ -19,7 +19,7 @@ class Switch(QAbstractButton): - def __init__(self, parent=None, track_radius=10, thumb_radius=8): + def __init__(self, parent=None, track_radius=10, thumb_radius=8) -> None: super().__init__(parent=parent) self.setCheckable(True) self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) @@ -78,7 +78,7 @@ def offset(self): return self._offset @offset.setter - def offset(self, value): + def offset(self, value) -> None: self._offset = value self.update() @@ -88,15 +88,15 @@ def sizeHint(self): # pylint: disable=invalid-name 2 * self._track_radius + 2 * self._margin, ) - def setChecked(self, checked): + def setChecked(self, checked) -> None: super().setChecked(checked) self.offset = self._end_offset[checked]() - def resizeEvent(self, event): + def resizeEvent(self, event) -> None: super().resizeEvent(event) self.offset = self._end_offset[self.isChecked()]() - def paintEvent(self, event): # pylint: disable=invalid-name, unused-argument + def paintEvent(self, event) -> None: # pylint: disable=invalid-name, unused-argument p = QPainter(self) p.setRenderHint(QPainter.Antialiasing, True) p.setPen(Qt.NoPen) @@ -147,7 +147,7 @@ def paintEvent(self, event): # pylint: disable=invalid-name, unused-argument self._thumb_text[self.isChecked()], ) - def mouseReleaseEvent(self, event): # pylint: disable=invalid-name + def mouseReleaseEvent(self, event) -> None: # pylint: disable=invalid-name super().mouseReleaseEvent(event) if event.button() == Qt.LeftButton: anim = QPropertyAnimation(self, b"offset", self) @@ -156,12 +156,12 @@ def mouseReleaseEvent(self, event): # pylint: disable=invalid-name anim.setEndValue(self._end_offset[self.isChecked()]()) anim.start() - def enterEvent(self, event): # pylint: disable=invalid-name + def enterEvent(self, event) -> None: # pylint: disable=invalid-name self.setCursor(Qt.PointingHandCursor) super().enterEvent(event) -def main(): +def main() -> None: app = QApplication([]) # Thumb size < track size (Gitlab style) diff --git a/qt__pyqt__pyside__pyqode/SwitchButton__example/from_QAbstractButton/test.py b/qt__pyqt__pyside__pyqode/SwitchButton__example/from_QAbstractButton/test.py index c70128b4f..2a9dfecad 100644 --- a/qt__pyqt__pyside__pyqode/SwitchButton__example/from_QAbstractButton/test.py +++ b/qt__pyqt__pyside__pyqode/SwitchButton__example/from_QAbstractButton/test.py @@ -9,7 +9,7 @@ class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() switch_btn1 = Switch() diff --git a/qt__pyqt__pyside__pyqode/SwitchButton__example/from_QCheckBox/switch_button.py b/qt__pyqt__pyside__pyqode/SwitchButton__example/from_QCheckBox/switch_button.py index 08f52d6a2..1db714f21 100644 --- a/qt__pyqt__pyside__pyqode/SwitchButton__example/from_QCheckBox/switch_button.py +++ b/qt__pyqt__pyside__pyqode/SwitchButton__example/from_QCheckBox/switch_button.py @@ -30,7 +30,7 @@ def __init__( circle_color="#DDD", active_color="#00BCff", animation_curve=QEasingCurve.OutBounce, - ): + ) -> None: super().__init__() self.setFixedSize(width, height) @@ -54,11 +54,11 @@ def circle_position(self) -> int: return self._circle_position @circle_position.setter - def circle_position(self, pos: int): + def circle_position(self, pos: int) -> None: self._circle_position = pos self.update() - def start_transition(self, value): + def start_transition(self, value) -> None: self.animation.setStartValue(self.circle_position) if value: self.animation.setEndValue(self.width() - self._circle_size) @@ -69,7 +69,7 @@ def start_transition(self, value): def hitButton(self, pos: QPoint) -> bool: return self.contentsRect().contains(pos) - def paintEvent(self, e): + def paintEvent(self, e) -> None: p = QPainter(self) p.setRenderHint(QPainter.Antialiasing) @@ -97,7 +97,7 @@ def paintEvent(self, e): from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Анимация кнопки переключения") diff --git a/qt__pyqt__pyside__pyqode/SwitchButton__example/from_QCheckBox/test.py b/qt__pyqt__pyside__pyqode/SwitchButton__example/from_QCheckBox/test.py index 0110f9ec7..90a7515ac 100644 --- a/qt__pyqt__pyside__pyqode/SwitchButton__example/from_QCheckBox/test.py +++ b/qt__pyqt__pyside__pyqode/SwitchButton__example/from_QCheckBox/test.py @@ -9,7 +9,7 @@ class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() switch_btn1 = ToggleButton() diff --git a/qt__pyqt__pyside__pyqode/SwitchButton__example/from_QWidget/switch_button.py b/qt__pyqt__pyside__pyqode/SwitchButton__example/from_QWidget/switch_button.py index d39c9fa68..d48da89c2 100644 --- a/qt__pyqt__pyside__pyqode/SwitchButton__example/from_QWidget/switch_button.py +++ b/qt__pyqt__pyside__pyqode/SwitchButton__example/from_QWidget/switch_button.py @@ -13,7 +13,7 @@ class SwitchButton(QtWidgets.QWidget): clicked = QtCore.pyqtSignal(bool) - def __init__(self, parent=None, w1="Yes", l1=12, w2="No", l2=33, width=60): + def __init__(self, parent=None, w1="Yes", l1=12, w2="No", l2=33, width=60) -> None: super(SwitchButton, self).__init__(parent) self.setWindowFlags(QtCore.Qt.FramelessWindowHint) self.setAttribute(QtCore.Qt.WA_TranslucentBackground) @@ -48,10 +48,10 @@ def isChecked(self) -> bool: def valueText(self) -> str: return self.__labelon.text() if self.isChecked() else self.__labeloff.text() - def setDuration(self, time): + def setDuration(self, time) -> None: self.__duration = time - def mousePressEvent(self, event): + def mousePressEvent(self, event) -> None: if not self.__enabled: return @@ -85,7 +85,7 @@ def mousePressEvent(self, event): self.clicked.emit(self.isChecked()) - def paintEvent(self, event): + def paintEvent(self, event) -> None: s = self.size() qp = QtGui.QPainter() qp.begin(self) @@ -125,12 +125,12 @@ def paintEvent(self, event): class Circle(QtWidgets.QWidget): - def __init__(self, parent=None): + def __init__(self, parent=None) -> None: super(Circle, self).__init__(parent) self.__enabled = True self.setFixedSize(20, 20) - def paintEvent(self, event): + def paintEvent(self, event) -> None: s = self.size() qp = QtGui.QPainter() qp.begin(self) @@ -168,12 +168,12 @@ def paintEvent(self, event): class Background(QtWidgets.QWidget): - def __init__(self, parent=None): + def __init__(self, parent=None) -> None: super(Background, self).__init__(parent) self.__enabled = True self.setFixedHeight(20) - def paintEvent(self, event): + def paintEvent(self, event) -> None: s = self.size() qp = QtGui.QPainter() qp.begin(self) diff --git a/qt__pyqt__pyside__pyqode/SwitchButton__example/from_QWidget/test.py b/qt__pyqt__pyside__pyqode/SwitchButton__example/from_QWidget/test.py index c36eb7f4e..33534f734 100644 --- a/qt__pyqt__pyside__pyqode/SwitchButton__example/from_QWidget/test.py +++ b/qt__pyqt__pyside__pyqode/SwitchButton__example/from_QWidget/test.py @@ -9,7 +9,7 @@ class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() switch_btn1 = SwitchButton(self, "On", 15, "Off", 31, width=60) diff --git a/qt__pyqt__pyside__pyqode/ToolBarArea/main.py b/qt__pyqt__pyside__pyqode/ToolBarArea/main.py index df9b6be32..d7f4625c3 100644 --- a/qt__pyqt__pyside__pyqode/ToolBarArea/main.py +++ b/qt__pyqt__pyside__pyqode/ToolBarArea/main.py @@ -8,7 +8,7 @@ class Widget(Qt.QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("ToolBarArea") diff --git a/qt__pyqt__pyside__pyqode/URLView__download_and_show_image_on_label/async__QNetworkAccessManager.py b/qt__pyqt__pyside__pyqode/URLView__download_and_show_image_on_label/async__QNetworkAccessManager.py index cb197b96e..3a584fbc8 100644 --- a/qt__pyqt__pyside__pyqode/URLView__download_and_show_image_on_label/async__QNetworkAccessManager.py +++ b/qt__pyqt__pyside__pyqode/URLView__download_and_show_image_on_label/async__QNetworkAccessManager.py @@ -8,7 +8,7 @@ class URLView(Qt.QWidget): - def __init__(self, parent=None): + def __init__(self, parent=None) -> None: super().__init__(parent) layout = Qt.QVBoxLayout(self) @@ -29,13 +29,13 @@ def __init__(self, parent=None): self.nam = Qt.QNetworkAccessManager() self.nam.finished.connect(self.finish_request) - def on_load(self): + def on_load(self) -> None: print("Load image") url = self.urlEdit.text() self.nam.get(Qt.QNetworkRequest(Qt.QUrl(url))) - def finish_request(self, reply): + def finish_request(self, reply) -> None: img = Qt.QPixmap() img.loadFromData(reply.readAll()) diff --git a/qt__pyqt__pyside__pyqode/URLView__download_and_show_image_on_label/async__QThread.py b/qt__pyqt__pyside__pyqode/URLView__download_and_show_image_on_label/async__QThread.py index c43226568..bf3431aad 100644 --- a/qt__pyqt__pyside__pyqode/URLView__download_and_show_image_on_label/async__QThread.py +++ b/qt__pyqt__pyside__pyqode/URLView__download_and_show_image_on_label/async__QThread.py @@ -11,7 +11,7 @@ class LoadImageThread(Qt.QThread): about_new_image = Qt.pyqtSignal(Qt.QPixmap) - def run(self): + def run(self) -> None: data = request.urlopen(self.url).read() pixmap = Qt.QPixmap() pixmap.loadFromData(data) @@ -21,7 +21,7 @@ def run(self): class URLView(Qt.QWidget): - def __init__(self, parent=None): + def __init__(self, parent=None) -> None: super().__init__(parent) layout = Qt.QVBoxLayout(self) @@ -47,7 +47,7 @@ def __init__(self, parent=None): self.thread.started.connect(lambda: self.loadButton.setEnabled(False)) self.thread.finished.connect(lambda: self.loadButton.setEnabled(True)) - def on_load(self): + def on_load(self) -> None: print("Load image") # Запускаем поток diff --git a/qt__pyqt__pyside__pyqode/URLView__download_and_show_image_on_label/sync.py b/qt__pyqt__pyside__pyqode/URLView__download_and_show_image_on_label/sync.py index 8ccc5835c..8c12217f3 100644 --- a/qt__pyqt__pyside__pyqode/URLView__download_and_show_image_on_label/sync.py +++ b/qt__pyqt__pyside__pyqode/URLView__download_and_show_image_on_label/sync.py @@ -9,7 +9,7 @@ class URLView(Qt.QWidget): - def __init__(self, parent=None): + def __init__(self, parent=None) -> None: super().__init__(parent) layout = Qt.QVBoxLayout(self) @@ -27,7 +27,7 @@ def __init__(self, parent=None): self.loadButton.clicked.connect(self.on_load) - def on_load(self): + def on_load(self) -> None: print("Load image") url = self.urlEdit.text() diff --git a/qt__pyqt__pyside__pyqode/advanced_list_widget.py b/qt__pyqt__pyside__pyqode/advanced_list_widget.py index f6b317189..4da454915 100644 --- a/qt__pyqt__pyside__pyqode/advanced_list_widget.py +++ b/qt__pyqt__pyside__pyqode/advanced_list_widget.py @@ -9,7 +9,7 @@ class AdvancedListWidget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.list_widget = QListWidget() @@ -29,7 +29,7 @@ def __init__(self): self._update_states() - def _update_states(self): + def _update_states(self) -> None: current_row: int = self.list_widget.currentRow() is_selected: bool = current_row != -1 @@ -38,39 +38,39 @@ def _update_states(self): self.action_move_up.setVisible(is_selected and current_row > 0) self.action_move_down.setVisible(is_selected and current_row < self.count() - 1) - def _append(self): + def _append(self) -> None: item = self.append("New item") self.list_widget.setCurrentItem(item) self.list_widget.editItem(item) - def _remove(self): + def _remove(self) -> None: current_row: int = self.list_widget.currentRow() if current_row == -1: return self.list_widget.takeItem(current_row) - def _move_item(self, from_row: int, to_row: int): + def _move_item(self, from_row: int, to_row: int) -> None: item = self.list_widget.takeItem(from_row) self.list_widget.insertItem(to_row, item) self.list_widget.setCurrentItem(item) - def _move_up(self): + def _move_up(self) -> None: current_row: int = self.list_widget.currentRow() if current_row < 1: return self._move_item(current_row, current_row - 1) - def _move_down(self): + def _move_down(self) -> None: current_row: int = self.list_widget.currentRow() if current_row != -1 and current_row >= self.count() - 1: return self._move_item(current_row, current_row + 1) - def set_items(self, items: list[str]): + def set_items(self, items: list[str]) -> None: self.clear() self.append_all(items) @@ -82,12 +82,12 @@ def append(self, text: str) -> QListWidgetItem: return item - def append_all(self, items: list[str]): + def append_all(self, items: list[str]) -> None: for text in items: self.append(text) - def clear(self): - return self.list_widget.clear() + def clear(self) -> None: + self.list_widget.clear() def count(self) -> int: return self.list_widget.count() diff --git a/qt__pyqt__pyside__pyqode/advanced_list_widget_pyqt6.py b/qt__pyqt__pyside__pyqode/advanced_list_widget_pyqt6.py new file mode 100644 index 000000000..75cee8a60 --- /dev/null +++ b/qt__pyqt__pyside__pyqode/advanced_list_widget_pyqt6.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +from PyQt6.QtCore import Qt +from PyQt6.QtWidgets import QListWidgetItem, QListWidget, QWidget, QVBoxLayout, QToolBar + + +class AdvancedListWidget(QWidget): + def __init__(self): + super().__init__() + + self.list_widget = QListWidget() + self.list_widget.itemSelectionChanged.connect(self._update_states) + + tool_bar = QToolBar() + self.action_append = tool_bar.addAction("➕", self._append) + self.action_remove = tool_bar.addAction("➖", self._remove) + self.action_move_up = tool_bar.addAction("🔼", self._move_up) + self.action_move_down = tool_bar.addAction("🔽", self._move_down) + + main_layout = QVBoxLayout(self) + main_layout.setContentsMargins(0, 0, 0, 0) + main_layout.setSpacing(0) + main_layout.addWidget(tool_bar) + main_layout.addWidget(self.list_widget) + + self._update_states() + + def _update_states(self): + current_row: int = self.list_widget.currentRow() + + is_selected: bool = current_row != -1 + self.action_remove.setVisible(is_selected) + + self.action_move_up.setVisible(is_selected and current_row > 0) + self.action_move_down.setVisible(is_selected and current_row < self.count() - 1) + + def _append(self): + item = self.append("New item") + + self.list_widget.setCurrentItem(item) + self.list_widget.editItem(item) + + def _remove(self): + current_row: int = self.list_widget.currentRow() + if current_row == -1: + return + + self.list_widget.takeItem(current_row) + + def _move_item(self, from_row: int, to_row: int): + item = self.list_widget.takeItem(from_row) + self.list_widget.insertItem(to_row, item) + self.list_widget.setCurrentItem(item) + + def _move_up(self): + current_row: int = self.list_widget.currentRow() + if current_row < 1: + return + + self._move_item(current_row, current_row - 1) + + def _move_down(self): + current_row: int = self.list_widget.currentRow() + if current_row != -1 and current_row >= self.count() - 1: + return + + self._move_item(current_row, current_row + 1) + + def set_items(self, items: list[str]): + self.clear() + self.append_all(items) + + def append(self, text: str) -> QListWidgetItem: + item = QListWidgetItem(text) + item.setFlags(item.flags() | Qt.ItemFlag.ItemIsEditable) + + self.list_widget.addItem(item) + + return item + + def append_all(self, items: list[str]): + for text in items: + self.append(text) + + def clear(self): + return self.list_widget.clear() + + def count(self) -> int: + return self.list_widget.count() + + def get(self, i: int) -> str: + return self.list_widget.item(i).text() + + def items(self) -> list[str]: + return [self.get(i) for i in range(self.count())] + + +if __name__ == "__main__": + from PyQt6.QtWidgets import QApplication + + app = QApplication([]) + + mw = AdvancedListWidget() + mw.set_items( + [ + "FOO", + "BAR", + "GO", + "ABC", + "123", + "!!!", + ] + ) + mw.show() + + app.exec() diff --git a/qt__pyqt__pyside__pyqode/animate_move_and_rotate_rect_draw_dynamic_QPainter_QTimer.py b/qt__pyqt__pyside__pyqode/animate_move_and_rotate_rect_draw_dynamic_QPainter_QTimer.py index cd6b52d32..dd7ca64ea 100644 --- a/qt__pyqt__pyside__pyqode/animate_move_and_rotate_rect_draw_dynamic_QPainter_QTimer.py +++ b/qt__pyqt__pyside__pyqode/animate_move_and_rotate_rect_draw_dynamic_QPainter_QTimer.py @@ -12,7 +12,7 @@ class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.angle = 0 @@ -24,7 +24,7 @@ def __init__(self): self.timer.timeout.connect(self._do_tick) self.timer.start() - def _do_tick(self): + def _do_tick(self) -> None: self.angle += 5 self.x += 5 @@ -35,7 +35,7 @@ def _do_tick(self): # Перерисование окна self.update() - def paintEvent(self, event): + def paintEvent(self, event) -> None: painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) diff --git a/qt__pyqt__pyside__pyqode/animate_move_and_rotate_triangle_QPolygonF_QPainter_QTimer.py b/qt__pyqt__pyside__pyqode/animate_move_and_rotate_triangle_QPolygonF_QPainter_QTimer.py index 0298f3439..27e1c4c38 100644 --- a/qt__pyqt__pyside__pyqode/animate_move_and_rotate_triangle_QPolygonF_QPainter_QTimer.py +++ b/qt__pyqt__pyside__pyqode/animate_move_and_rotate_triangle_QPolygonF_QPainter_QTimer.py @@ -12,7 +12,7 @@ class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.angle = 0 @@ -23,7 +23,7 @@ def __init__(self): self.timer.timeout.connect(self._do_tick) self.timer.start() - def _do_tick(self): + def _do_tick(self) -> None: self.angle += 5 self.x += 5 @@ -33,7 +33,7 @@ def _do_tick(self): # Перерисование окна self.update() - def paintEvent(self, event): + def paintEvent(self, event) -> None: painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) diff --git a/qt__pyqt__pyside__pyqode/animate_move_and_rotate_triangle_draw_dynamic_QPolygonF_QPainter_QTimer.py b/qt__pyqt__pyside__pyqode/animate_move_and_rotate_triangle_draw_dynamic_QPolygonF_QPainter_QTimer.py index d3a6cfc7f..05f066d5e 100644 --- a/qt__pyqt__pyside__pyqode/animate_move_and_rotate_triangle_draw_dynamic_QPolygonF_QPainter_QTimer.py +++ b/qt__pyqt__pyside__pyqode/animate_move_and_rotate_triangle_draw_dynamic_QPolygonF_QPainter_QTimer.py @@ -12,7 +12,7 @@ class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.angle = 0 @@ -24,7 +24,7 @@ def __init__(self): self.timer.timeout.connect(self._do_tick) self.timer.start() - def _do_tick(self): + def _do_tick(self) -> None: self.angle += 5 self.x += 5 @@ -35,7 +35,7 @@ def _do_tick(self): # Перерисование окна self.update() - def paintEvent(self, event): + def paintEvent(self, event) -> None: painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) diff --git a/qt__pyqt__pyside__pyqode/animate_rotate_triangle_QPainterPath_QPainter_QTimer.py b/qt__pyqt__pyside__pyqode/animate_rotate_triangle_QPainterPath_QPainter_QTimer.py index 0553aa149..38ad62cf4 100644 --- a/qt__pyqt__pyside__pyqode/animate_rotate_triangle_QPainterPath_QPainter_QTimer.py +++ b/qt__pyqt__pyside__pyqode/animate_rotate_triangle_QPainterPath_QPainter_QTimer.py @@ -10,7 +10,7 @@ class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.angle = 0 @@ -20,13 +20,13 @@ def __init__(self): self.timer.timeout.connect(self._do_tick) self.timer.start() - def _do_tick(self): + def _do_tick(self) -> None: self.angle += 5 # Перерисования окна self.update() - def paintEvent(self, event): + def paintEvent(self, event) -> None: painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) diff --git a/qt__pyqt__pyside__pyqode/animate_rotate_triangle_QPolygonF_QPainter_QTimer.py b/qt__pyqt__pyside__pyqode/animate_rotate_triangle_QPolygonF_QPainter_QTimer.py index 3627faf75..5749c31fc 100644 --- a/qt__pyqt__pyside__pyqode/animate_rotate_triangle_QPolygonF_QPainter_QTimer.py +++ b/qt__pyqt__pyside__pyqode/animate_rotate_triangle_QPolygonF_QPainter_QTimer.py @@ -10,7 +10,7 @@ class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.angle = 0 @@ -20,13 +20,13 @@ def __init__(self): self.timer.timeout.connect(self._do_tick) self.timer.start() - def _do_tick(self): + def _do_tick(self) -> None: self.angle += 5 # Перерисования окна self.update() - def paintEvent(self, event): + def paintEvent(self, event) -> None: painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) diff --git a/qt__pyqt__pyside__pyqode/append_custom_QStatusBar__with_icon/main.py b/qt__pyqt__pyside__pyqode/append_custom_QStatusBar__with_icon/main.py index 3a1d54418..43224f8e8 100644 --- a/qt__pyqt__pyside__pyqode/append_custom_QStatusBar__with_icon/main.py +++ b/qt__pyqt__pyside__pyqode/append_custom_QStatusBar__with_icon/main.py @@ -8,7 +8,7 @@ class Widget(Qt.QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.indicator = Qt.QLabel() @@ -35,7 +35,7 @@ def __init__(self): self.setLayout(main_layout) - def _on_text_edited(self, text): + def _on_text_edited(self, text) -> None: # Показываем сообщение на 2 секунды self.status_bar.showMessage(text, msecs=2000) diff --git a/qt__pyqt__pyside__pyqode/autowidth__QLineEdit.py b/qt__pyqt__pyside__pyqode/autowidth__QLineEdit.py index fd0268c52..cda5582f3 100644 --- a/qt__pyqt__pyside__pyqode/autowidth__QLineEdit.py +++ b/qt__pyqt__pyside__pyqode/autowidth__QLineEdit.py @@ -8,7 +8,7 @@ class Widget(Qt.QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.line_edit = Qt.QLineEdit() @@ -19,7 +19,7 @@ def __init__(self): self.setLayout(layout) - def on_text_changed(self, text): + def on_text_changed(self, text) -> None: # Рассчитываем ширину текст по шрифту width = self.line_edit.fontMetrics().width(text) self.line_edit.setMinimumWidth(width) diff --git a/qt__pyqt__pyside__pyqode/bar_chart__QtChart.py b/qt__pyqt__pyside__pyqode/bar_chart__QtChart.py index 01b20308b..064c10a6a 100644 --- a/qt__pyqt__pyside__pyqode/bar_chart__QtChart.py +++ b/qt__pyqt__pyside__pyqode/bar_chart__QtChart.py @@ -12,7 +12,7 @@ class MainWidow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() series = self.append_series() diff --git a/qt__pyqt__pyside__pyqode/buttons_setShortcut.py b/qt__pyqt__pyside__pyqode/buttons_setShortcut.py index 8bb506ea7..d2150a9cc 100644 --- a/qt__pyqt__pyside__pyqode/buttons_setShortcut.py +++ b/qt__pyqt__pyside__pyqode/buttons_setShortcut.py @@ -8,7 +8,7 @@ class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() label_result = QLabel() diff --git a/qt__pyqt__pyside__pyqode/chart_line__QtChart.py b/qt__pyqt__pyside__pyqode/chart_line__QtChart.py index 9552db54d..1035e2e11 100644 --- a/qt__pyqt__pyside__pyqode/chart_line__QtChart.py +++ b/qt__pyqt__pyside__pyqode/chart_line__QtChart.py @@ -10,7 +10,7 @@ class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() series = QLineSeries() diff --git a/qt__pyqt__pyside__pyqode/chart_line__dark_theme__QtChart.py b/qt__pyqt__pyside__pyqode/chart_line__dark_theme__QtChart.py index 32adde1e5..62e431635 100644 --- a/qt__pyqt__pyside__pyqode/chart_line__dark_theme__QtChart.py +++ b/qt__pyqt__pyside__pyqode/chart_line__dark_theme__QtChart.py @@ -10,7 +10,7 @@ class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() series = QLineSeries() diff --git a/qt__pyqt__pyside__pyqode/chart_line__datetime_axis__using_QDateTime__QtChart.py b/qt__pyqt__pyside__pyqode/chart_line__datetime_axis__using_QDateTime__QtChart.py index c8424e92b..0c5545dcd 100644 --- a/qt__pyqt__pyside__pyqode/chart_line__datetime_axis__using_QDateTime__QtChart.py +++ b/qt__pyqt__pyside__pyqode/chart_line__datetime_axis__using_QDateTime__QtChart.py @@ -24,7 +24,7 @@ class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() series = QLineSeries() diff --git a/qt__pyqt__pyside__pyqode/chart_line__datetime_axis__using_datetime__QtChart.py b/qt__pyqt__pyside__pyqode/chart_line__datetime_axis__using_datetime__QtChart.py index ea00d5468..e29a2278e 100644 --- a/qt__pyqt__pyside__pyqode/chart_line__datetime_axis__using_datetime__QtChart.py +++ b/qt__pyqt__pyside__pyqode/chart_line__datetime_axis__using_datetime__QtChart.py @@ -26,7 +26,7 @@ class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() series = QLineSeries() diff --git a/qt__pyqt__pyside__pyqode/chart_line__show_all_theme__QtChart.py b/qt__pyqt__pyside__pyqode/chart_line__show_all_theme__QtChart.py index 9535856e7..906164059 100644 --- a/qt__pyqt__pyside__pyqode/chart_line__show_all_theme__QtChart.py +++ b/qt__pyqt__pyside__pyqode/chart_line__show_all_theme__QtChart.py @@ -27,7 +27,7 @@ def get_themes() -> list[tuple[str, QChart.ChartTheme]]: class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() tab_widget = QTabWidget() diff --git a/qt__pyqt__pyside__pyqode/chart_line__show_point_marks__QtChart.py b/qt__pyqt__pyside__pyqode/chart_line__show_point_marks__QtChart.py index 9da6c983d..75a63f16a 100644 --- a/qt__pyqt__pyside__pyqode/chart_line__show_point_marks__QtChart.py +++ b/qt__pyqt__pyside__pyqode/chart_line__show_point_marks__QtChart.py @@ -10,7 +10,7 @@ class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() series = QLineSeries() diff --git a/qt__pyqt__pyside__pyqode/chart_line__show_tooltip_on_point_marks__QtChart.py b/qt__pyqt__pyside__pyqode/chart_line__show_tooltip_on_point_marks__QtChart.py index 52d9a0b3d..ed1edad19 100644 --- a/qt__pyqt__pyside__pyqode/chart_line__show_tooltip_on_point_marks__QtChart.py +++ b/qt__pyqt__pyside__pyqode/chart_line__show_tooltip_on_point_marks__QtChart.py @@ -13,7 +13,7 @@ class MainWindow(ChartViewToolTips): - def __init__(self): + def __init__(self) -> None: super().__init__() series = QLineSeries() @@ -38,7 +38,7 @@ def __init__(self): self.setChart(self._chart) - def show_series_tooltip(self, point, state: bool): + def show_series_tooltip(self, point, state: bool) -> None: if not self._tooltip: self._tooltip = Callout(self._chart) diff --git a/qt__pyqt__pyside__pyqode/chart_line__show_tooltip_on_point_marks__check_distance_by_pos__QtChart.py b/qt__pyqt__pyside__pyqode/chart_line__show_tooltip_on_point_marks__check_distance_by_pos__QtChart.py index fdb49addf..81aa59b79 100644 --- a/qt__pyqt__pyside__pyqode/chart_line__show_tooltip_on_point_marks__check_distance_by_pos__QtChart.py +++ b/qt__pyqt__pyside__pyqode/chart_line__show_tooltip_on_point_marks__check_distance_by_pos__QtChart.py @@ -13,7 +13,7 @@ class MainWindow(ChartViewToolTips): - def __init__(self): + def __init__(self) -> None: super().__init__() series = QLineSeries() @@ -38,7 +38,7 @@ def __init__(self): self.setChart(self._chart) - def show_series_tooltip(self, point, state: bool): + def show_series_tooltip(self, point, state: bool) -> None: # value -> pos point = self._chart.mapToPosition(point) diff --git a/qt__pyqt__pyside__pyqode/chart_line__show_tooltip_on_series__QtChart.py b/qt__pyqt__pyside__pyqode/chart_line__show_tooltip_on_series__QtChart.py index fcfdd6aa5..9faf17c25 100644 --- a/qt__pyqt__pyside__pyqode/chart_line__show_tooltip_on_series__QtChart.py +++ b/qt__pyqt__pyside__pyqode/chart_line__show_tooltip_on_series__QtChart.py @@ -12,7 +12,7 @@ # SOURCE: https://doc-snapshots.qt.io/qt5-5.12/qtcharts-callout-callout-h.html class Callout(QGraphicsItem): - def __init__(self, chart: QChart, parent=None): + def __init__(self, chart: QChart, parent=None) -> None: super().__init__(parent) self.hide() @@ -26,7 +26,7 @@ def __init__(self, chart: QChart, parent=None): self._anchor = QPointF() self._font = QFont() - def setText(self, text: str): + def setText(self, text: str) -> None: self._text = text metrics = QFontMetrics(self._font) self._textRect = QRectF( @@ -36,10 +36,10 @@ def setText(self, text: str): self.prepareGeometryChange() self._rect = QRectF(self._textRect.adjusted(-5, -5, 5, 5)) - def setAnchor(self, point: QPointF): + def setAnchor(self, point: QPointF) -> None: self._anchor = point - def updateGeometry(self): + def updateGeometry(self) -> None: self.prepareGeometryChange() self.setPos(self._chart.mapToPosition(self._anchor) + QPoint(10, -50)) @@ -70,7 +70,7 @@ def boundingRect(self): rect.setBottom(max(self._rect.bottom(), anchor.y())) return rect - def paint(self, painter: QPainter, option, widget=None): + def paint(self, painter: QPainter, option, widget=None) -> None: path = QPainterPath() path.addRoundedRect(self._rect, 5, 5) @@ -151,10 +151,10 @@ def paint(self, painter: QPainter, option, widget=None): painter.drawPath(path) painter.drawText(self._textRect, self._text) - def mousePressEvent(self, event: QGraphicsSceneMouseEvent): + def mousePressEvent(self, event: QGraphicsSceneMouseEvent) -> None: event.setAccepted(True) - def mouseMoveEvent(self, event: QGraphicsSceneMouseEvent): + def mouseMoveEvent(self, event: QGraphicsSceneMouseEvent) -> None: if event.buttons() & Qt.LeftButton: self.setPos( self.mapToParent(event.pos() - event.buttonDownPos(Qt.LeftButton)) @@ -165,7 +165,7 @@ def mouseMoveEvent(self, event: QGraphicsSceneMouseEvent): class ChartViewToolTips(QChartView): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setRenderHint(QPainter.Antialiasing) @@ -174,7 +174,7 @@ def __init__(self): self._callout_font_family = None self._callouts = [] - def clear_all_tooltips(self): + def clear_all_tooltips(self) -> None: if self._tooltip: self.scene().removeItem(self._tooltip) @@ -189,7 +189,7 @@ def _add_Callout(self) -> Callout: return callout - def show_series_tooltip(self, point, state: bool): + def show_series_tooltip(self, point, state: bool) -> None: if not self.chart(): return @@ -205,7 +205,7 @@ def show_series_tooltip(self, point, state: bool): else: self._tooltip.hide() - def keepCallout(self, point): + def keepCallout(self, point) -> None: if not self.chart() or not self._tooltip: return @@ -214,7 +214,7 @@ def keepCallout(self, point): self._tooltip = self._add_Callout() - def mouseReleaseEvent(self, event): + def mouseReleaseEvent(self, event) -> None: if self.chart(): pos = event.pos() point = self.chart().mapToValue(pos) @@ -222,7 +222,7 @@ def mouseReleaseEvent(self, event): super().mouseReleaseEvent(event) - def resizeEvent(self, event): + def resizeEvent(self, event) -> None: if self.scene(): size = QSizeF(event.size()) @@ -236,7 +236,7 @@ def resizeEvent(self, event): class MainWindow(ChartViewToolTips): - def __init__(self): + def __init__(self) -> None: super().__init__() series = QLineSeries() diff --git a/qt__pyqt__pyside__pyqode/check_image_on_transparents/main.py b/qt__pyqt__pyside__pyqode/check_image_on_transparents/main.py index 6510cb059..c79b07e5c 100644 --- a/qt__pyqt__pyside__pyqode/check_image_on_transparents/main.py +++ b/qt__pyqt__pyside__pyqode/check_image_on_transparents/main.py @@ -13,13 +13,13 @@ class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.img = QPixmap() self.img.load(FILE_NAME) - def paintEvent(self, event): + def paintEvent(self, event) -> None: painter = QPainter(self) painter.setBrush(Qt.darkGreen) diff --git a/qt__pyqt__pyside__pyqode/check_urls.py b/qt__pyqt__pyside__pyqode/check_urls.py index 8bccabc44..28ad3b224 100644 --- a/qt__pyqt__pyside__pyqode/check_urls.py +++ b/qt__pyqt__pyside__pyqode/check_urls.py @@ -24,7 +24,7 @@ from PyQt5.QtCore import QThread, pyqtSignal, Qt -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -45,12 +45,12 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class CheckUrlThread(QThread): about_check_url = pyqtSignal(str, str) - def __init__(self, urls: list[str] = None): + def __init__(self, urls: list[str] = None) -> None: super().__init__() self.urls = urls if urls else [] - def run(self): + def run(self) -> None: for url in self.urls: try: rs = session.get(url) @@ -66,7 +66,7 @@ def run(self): class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.urls = QPlainTextEdit() @@ -100,7 +100,7 @@ def __init__(self): self.thread.started.connect(lambda: self.pb_check.setEnabled(False)) self.thread.finished.connect(lambda: self.pb_check.setEnabled(True)) - def _on_click_check(self): + def _on_click_check(self) -> None: urls = self.urls.toPlainText().strip().splitlines() self.result_table.clearContents() @@ -116,7 +116,7 @@ def _on_click_check(self): self.thread.urls = urls self.thread.start() - def _on_about_check_url(self, url: str, code: str): + def _on_about_check_url(self, url: str, code: str) -> None: for item in self.result_table.findItems(url, Qt.MatchCaseSensitive): row = item.row() self.result_table.item(row, 1).setText(code) diff --git a/qt__pyqt__pyside__pyqode/clipboard__example.py b/qt__pyqt__pyside__pyqode/clipboard__example.py index 29ceba9b8..c4e46d003 100644 --- a/qt__pyqt__pyside__pyqode/clipboard__example.py +++ b/qt__pyqt__pyside__pyqode/clipboard__example.py @@ -18,7 +18,7 @@ from PyQt5.QtCore import Qt -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -31,7 +31,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowFlag(Qt.WindowStaysOnTopHint) diff --git a/qt__pyqt__pyside__pyqode/context_menu/qt_tray_with_simple_menu.py b/qt__pyqt__pyside__pyqode/context_menu/qt_tray_with_simple_menu.py index 0df2a6b4c..66b358a0b 100644 --- a/qt__pyqt__pyside__pyqode/context_menu/qt_tray_with_simple_menu.py +++ b/qt__pyqt__pyside__pyqode/context_menu/qt_tray_with_simple_menu.py @@ -37,7 +37,7 @@ tray.setContextMenu(menu) -def on_tray_activated(reason: QSystemTrayIcon.ActivationReason): +def on_tray_activated(reason: QSystemTrayIcon.ActivationReason) -> None: if reason == QSystemTrayIcon.ActivationReason.Context: return diff --git a/qt__pyqt__pyside__pyqode/context_menu/table.py b/qt__pyqt__pyside__pyqode/context_menu/table.py index 94b8d47b2..f64040069 100644 --- a/qt__pyqt__pyside__pyqode/context_menu/table.py +++ b/qt__pyqt__pyside__pyqode/context_menu/table.py @@ -20,7 +20,7 @@ class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() header_labels = ["NAME", "URL"] @@ -55,7 +55,7 @@ def __init__(self): self.fill_tables() - def fill_tables(self): + def fill_tables(self) -> None: self.model.appendRow( [QStandardItem("rutube"), QStandardItem("https://rutube.ru/")] ) @@ -75,7 +75,7 @@ def fill_tables(self): text = self.model.item(row, column).text() self.table_widget.setItem(row, column, QTableWidgetItem(text)) - def _custom_menu_requested(self, p: QPoint): + def _custom_menu_requested(self, p: QPoint) -> None: table = self.sender() index: QModelIndex = table.indexAt(p) diff --git a/qt__pyqt__pyside__pyqode/context_menu/table_auto_menu.py b/qt__pyqt__pyside__pyqode/context_menu/table_auto_menu.py index 751e509ae..7722d202c 100644 --- a/qt__pyqt__pyside__pyqode/context_menu/table_auto_menu.py +++ b/qt__pyqt__pyside__pyqode/context_menu/table_auto_menu.py @@ -25,7 +25,7 @@ def open_context_menu( table: QTableView, p: QPoint, get_additional_actions_func: Callable[[QTableView, int], list[QAction]] = None, -): +) -> None: index: QModelIndex = table.indexAt(p) if not index.isValid(): return @@ -57,7 +57,7 @@ def open_context_menu( class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() header_labels = ["NAME", "URL"] @@ -92,7 +92,7 @@ def __init__(self): self.fill_tables() - def fill_tables(self): + def fill_tables(self) -> None: self.model.appendRow( [QStandardItem("rutube"), QStandardItem("https://rutube.ru/")] ) @@ -112,7 +112,7 @@ def fill_tables(self): text = self.model.item(row, column).text() self.table_widget.setItem(row, column, QTableWidgetItem(text)) - def _custom_menu_requested(self, p: QPoint): + def _custom_menu_requested(self, p: QPoint) -> None: def _get_additional_actions(table: QTableView, row: int) -> list[QAction]: model = table.model() diff --git a/qt__pyqt__pyside__pyqode/create_child_window_by_center.py b/qt__pyqt__pyside__pyqode/create_child_window_by_center.py index 9a7393884..b4835f743 100644 --- a/qt__pyqt__pyside__pyqode/create_child_window_by_center.py +++ b/qt__pyqt__pyside__pyqode/create_child_window_by_center.py @@ -9,7 +9,7 @@ class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() pb_1 = QPushButton("Create [1]") @@ -33,12 +33,12 @@ def __init__(self): self.setLayout(layout) - def _create_new_window_1(self): + def _create_new_window_1(self) -> None: widget = QWidget(self, flags=Qt.Window) widget.resize(200, 100) widget.show() - def _create_new_window_2(self): + def _create_new_window_2(self) -> None: widget = QWidget(self, flags=Qt.Window) widget.resize(200, 100) @@ -47,7 +47,7 @@ def _create_new_window_2(self): widget.show() - def _create_new_window_3(self): + def _create_new_window_3(self) -> None: widget = QWidget(self, flags=Qt.Window) widget.resize(200, 100) @@ -58,7 +58,7 @@ def _create_new_window_3(self): widget.show() - def _create_new_window_4(self): + def _create_new_window_4(self) -> None: widget = QWidget(self, flags=Qt.Window) widget.resize(200, 100) diff --git a/qt__pyqt__pyside__pyqode/crypto__decrypto__xor.py b/qt__pyqt__pyside__pyqode/crypto__decrypto__xor.py index f5499f6c2..1f275d954 100644 --- a/qt__pyqt__pyside__pyqode/crypto__decrypto__xor.py +++ b/qt__pyqt__pyside__pyqode/crypto__decrypto__xor.py @@ -13,7 +13,7 @@ def crypto_xor_1(message, secret): class Window(Qt.QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("crypto / decrypto") @@ -39,7 +39,7 @@ def __init__(self): self.setLayout(layout) - def _on_convert(self): + def _on_convert(self) -> None: text = self.pte_text.toPlainText() key = self.sb_key.value() diff --git a/qt__pyqt__pyside__pyqode/darkstyle__QDarkStyleSheet__load_from_ui/main.py b/qt__pyqt__pyside__pyqode/darkstyle__QDarkStyleSheet__load_from_ui/main.py index 01192a100..b2affa7f6 100644 --- a/qt__pyqt__pyside__pyqode/darkstyle__QDarkStyleSheet__load_from_ui/main.py +++ b/qt__pyqt__pyside__pyqode/darkstyle__QDarkStyleSheet__load_from_ui/main.py @@ -12,7 +12,7 @@ class MainWindow(Qt.QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() uic.loadUi("mainwidget.ui", self) @@ -30,7 +30,7 @@ def __init__(self): self._update_pen_color() - def _choose_color(self): + def _choose_color(self) -> None: color = Qt.QColorDialog.getColor(self.pen_color) if not color.isValid(): return @@ -38,7 +38,7 @@ def _choose_color(self): self.pen_color = color self._update_pen_color() - def _update_pen_color(self): + def _update_pen_color(self) -> None: pixmap = Qt.QPixmap(self.pbPenColor.size()) pixmap.fill(self.pen_color) self.pbPenColor.setIcon(Qt.QIcon(pixmap)) diff --git a/qt__pyqt__pyside__pyqode/download_and_show_async_image_on_QGraphicsScene_QNetworkAccessManager.py b/qt__pyqt__pyside__pyqode/download_and_show_async_image_on_QGraphicsScene_QNetworkAccessManager.py index 61e06b05d..1fa1f3891 100644 --- a/qt__pyqt__pyside__pyqode/download_and_show_async_image_on_QGraphicsScene_QNetworkAccessManager.py +++ b/qt__pyqt__pyside__pyqode/download_and_show_async_image_on_QGraphicsScene_QNetworkAccessManager.py @@ -19,7 +19,7 @@ class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.scene = QGraphicsScene() @@ -39,7 +39,7 @@ def __init__(self): self.setLayout(layout) - def finish_request(self, reply): + def finish_request(self, reply) -> None: self.scene.clear() img = QPixmap() diff --git a/qt__pyqt__pyside__pyqode/download_and_show_async_image_on_QLabel_QNetworkAccessManager.py b/qt__pyqt__pyside__pyqode/download_and_show_async_image_on_QLabel_QNetworkAccessManager.py index f8741ff04..0b06c223c 100644 --- a/qt__pyqt__pyside__pyqode/download_and_show_async_image_on_QLabel_QNetworkAccessManager.py +++ b/qt__pyqt__pyside__pyqode/download_and_show_async_image_on_QLabel_QNetworkAccessManager.py @@ -11,7 +11,7 @@ class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.lbl = QLabel("loading...") @@ -28,7 +28,7 @@ def __init__(self): self.setLayout(layout) - def finish_request(self, reply): + def finish_request(self, reply) -> None: img = QPixmap() img.loadFromData(reply.readAll()) diff --git a/qt__pyqt__pyside__pyqode/download_file/complex.py b/qt__pyqt__pyside__pyqode/download_file/complex.py index 573cc60ad..fb1e0f5b8 100644 --- a/qt__pyqt__pyside__pyqode/download_file/complex.py +++ b/qt__pyqt__pyside__pyqode/download_file/complex.py @@ -24,14 +24,14 @@ class ThreadDownload(QThread): about_file_name = pyqtSignal(str) about_error = pyqtSignal(str) - def __init__(self, url: str = None, file_name: str = None): + def __init__(self, url: str = None, file_name: str = None) -> None: super().__init__() self.url = url self.file_name = file_name # SOURCE: https://github.com/gil9red/SimplePyScripts/blob/4692cbb36b5addb0f2bd5e93e69eb8c7c257bdf8/download_file/with_progress.py#L12 - def reporthook(self, blocknum, blocksize, totalsize): + def reporthook(self, blocknum, blocksize, totalsize) -> None: readsofar = blocknum * blocksize if totalsize > 0: percent = readsofar * 100.0 / totalsize @@ -51,7 +51,7 @@ def reporthook(self, blocknum, blocksize, totalsize): else: self.about_progress.emit(f"read {readsofar}") - def run(self): + def run(self) -> None: try: file_name, _ = urlretrieve( self.url, self.file_name, reporthook=self.reporthook @@ -64,7 +64,7 @@ def run(self): class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.line_edit_url = QLineEdit( @@ -92,20 +92,20 @@ def __init__(self): self.setLayout(layout) - def download(self): + def download(self) -> None: self.thread.url = self.line_edit_url.text() self.thread.file_name = self.line_edit_file_name.text() self.thread.start() - def _handle_about_progress(self, text: str): + def _handle_about_progress(self, text: str) -> None: self.setWindowTitle(text) - def _handle_about_file_name(self, text: str): + def _handle_about_file_name(self, text: str) -> None: self.text_edit_log.append( f"""

File name: {text}

""" ) - def _handle_about_error(self, text: str): + def _handle_about_error(self, text: str) -> None: self.text_edit_log.append(f"""
{text}
""") diff --git a/qt__pyqt__pyside__pyqode/download_file/simple.py b/qt__pyqt__pyside__pyqode/download_file/simple.py index 29b2426d0..9f62bc7b6 100644 --- a/qt__pyqt__pyside__pyqode/download_file/simple.py +++ b/qt__pyqt__pyside__pyqode/download_file/simple.py @@ -13,7 +13,7 @@ from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLineEdit, QFormLayout -def download_file(url: str, file_name: str): +def download_file(url: str, file_name: str) -> None: try: local_file_name, _ = urlretrieve(url, file_name) print(os.path.abspath(local_file_name)) @@ -22,7 +22,7 @@ def download_file(url: str, file_name: str): class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.line_edit_url = QLineEdit( @@ -40,7 +40,7 @@ def __init__(self): self.setLayout(layout) - def download(self): + def download(self) -> None: url = self.line_edit_url.text() file_name = self.line_edit_file_name.text() diff --git a/qt__pyqt__pyside__pyqode/draw__ellipse_board/main.py b/qt__pyqt__pyside__pyqode/draw__ellipse_board/main.py index fd341624e..e565d4012 100644 --- a/qt__pyqt__pyside__pyqode/draw__ellipse_board/main.py +++ b/qt__pyqt__pyside__pyqode/draw__ellipse_board/main.py @@ -8,12 +8,12 @@ class CellWidget(Qt.QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.ball_size = 100 - def paintEvent(self, event: Qt.QPaintEvent): + def paintEvent(self, event: Qt.QPaintEvent) -> None: painter = Qt.QPainter(self) painter.setRenderHint(Qt.QPainter.Antialiasing) painter.setPen(Qt.Qt.NoPen) @@ -30,7 +30,7 @@ def paintEvent(self, event: Qt.QPaintEvent): class Window(Qt.QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("draw__ellipse_board") @@ -60,7 +60,7 @@ def __init__(self): self.setLayout(layout) - def _set_ball_size(self, value): + def _set_ball_size(self, value) -> None: self.sl_ball_size.setValue(value) self.pb_ball_size.setValue(value) diff --git a/qt__pyqt__pyside__pyqode/draw__ellipse_board__chess_order__decrease/main.py b/qt__pyqt__pyside__pyqode/draw__ellipse_board__chess_order__decrease/main.py index fff59f2d5..15fae80ce 100644 --- a/qt__pyqt__pyside__pyqode/draw__ellipse_board__chess_order__decrease/main.py +++ b/qt__pyqt__pyside__pyqode/draw__ellipse_board__chess_order__decrease/main.py @@ -8,12 +8,12 @@ class Window(Qt.QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("draw__ellipse_board__chess_order__decrease") - def paintEvent(self, event: Qt.QPaintEvent): + def paintEvent(self, event: Qt.QPaintEvent) -> None: painter = Qt.QPainter(self) painter.setRenderHint(Qt.QPainter.Antialiasing) painter.setPen(Qt.Qt.NoPen) diff --git a/qt__pyqt__pyside__pyqode/draw__ellipse_board__decrease/main.py b/qt__pyqt__pyside__pyqode/draw__ellipse_board__decrease/main.py index 2d775ab4e..cf6110eb3 100644 --- a/qt__pyqt__pyside__pyqode/draw__ellipse_board__decrease/main.py +++ b/qt__pyqt__pyside__pyqode/draw__ellipse_board__decrease/main.py @@ -8,12 +8,12 @@ class Window(Qt.QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("draw__ellipse_board__decrease") - def paintEvent(self, event: Qt.QPaintEvent): + def paintEvent(self, event: Qt.QPaintEvent) -> None: painter = Qt.QPainter(self) painter.setRenderHint(Qt.QPainter.Antialiasing) painter.setPen(Qt.Qt.NoPen) diff --git a/qt__pyqt__pyside__pyqode/draw_frame_with_color_info/main.py b/qt__pyqt__pyside__pyqode/draw_frame_with_color_info/main.py index 96044c0cd..f077dd9d8 100644 --- a/qt__pyqt__pyside__pyqode/draw_frame_with_color_info/main.py +++ b/qt__pyqt__pyside__pyqode/draw_frame_with_color_info/main.py @@ -37,7 +37,7 @@ def get_optimal_font(family_font: str, w, h, text: str) -> QFont: return font -def draw_hex(painter: QPainter, size: int, color: QColor): +def draw_hex(painter: QPainter, size: int, color: QColor) -> None: r, g, b, _ = color.getRgb() value = "".join(f"{x:02X}" for x in [r, g, b]) @@ -56,7 +56,7 @@ def draw_hex(painter: QPainter, size: int, color: QColor): painter.restore() -def draw_rgb(painter: QPainter, size: int, color: QColor): +def draw_rgb(painter: QPainter, size: int, color: QColor) -> None: r, g, b, _ = color.getRgb() rgb = list(map(str, [r, g, b])) diff --git a/qt__pyqt__pyside__pyqode/draw_image_label__on_scroll_area/main.py b/qt__pyqt__pyside__pyqode/draw_image_label__on_scroll_area/main.py index cb77ab52e..7d29b5702 100644 --- a/qt__pyqt__pyside__pyqode/draw_image_label__on_scroll_area/main.py +++ b/qt__pyqt__pyside__pyqode/draw_image_label__on_scroll_area/main.py @@ -19,7 +19,7 @@ from PyQt5.QtCore import Qt, QEvent -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -32,7 +32,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class Example(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.flag = False @@ -77,7 +77,7 @@ def eventFilter(self, obj, e): # Стандартная обработка событий return super().eventFilter(obj, e) - def draw_ellipse(self, e): + def draw_ellipse(self, e) -> None: self.painter.drawEllipse(e.pos(), 20, 20) self.label.setPixmap(self.image) diff --git a/qt__pyqt__pyside__pyqode/draw_spiral.py b/qt__pyqt__pyside__pyqode/draw_spiral.py index d8993ee4b..38ab2b73c 100644 --- a/qt__pyqt__pyside__pyqode/draw_spiral.py +++ b/qt__pyqt__pyside__pyqode/draw_spiral.py @@ -21,7 +21,7 @@ class Helper: - def __init__(self, is_reverse_rotation: bool, is_draw_all_spiral=False): + def __init__(self, is_reverse_rotation: bool, is_draw_all_spiral=False) -> None: super().__init__() self.is_reverse_rotation = is_reverse_rotation @@ -43,7 +43,7 @@ def __init__(self, is_reverse_rotation: bool, is_draw_all_spiral=False): self.textPen: QPen = QPen(Qt.white) - def _draw_spiral(self, painter: QPainter, elapsed: int, is_reverse_rotation=False): + def _draw_spiral(self, painter: QPainter, elapsed: int, is_reverse_rotation=False) -> None: r = elapsed / 1000.0 n = 30 @@ -63,7 +63,7 @@ def _draw_spiral(self, painter: QPainter, elapsed: int, is_reverse_rotation=Fals painter.restore() - def paint(self, painter: QPainter, event: QPaintEvent, elapsed: int): + def paint(self, painter: QPainter, event: QPaintEvent, elapsed: int) -> None: painter.fillRect(event.rect(), self.background) painter.translate(100, 100) @@ -73,7 +73,7 @@ def paint(self, painter: QPainter, event: QPaintEvent, elapsed: int): class Widget(QWidget): - def __init__(self, is_reverse_rotation: bool, is_draw_all_spiral=False): + def __init__(self, is_reverse_rotation: bool, is_draw_all_spiral=False) -> None: super().__init__() self.setFixedSize(200, 200) @@ -85,11 +85,11 @@ def __init__(self, is_reverse_rotation: bool, is_draw_all_spiral=False): self.timer.timeout.connect(self.animate) self.timer.start(50) - def animate(self): + def animate(self) -> None: self.elapsed = (self.elapsed + self.timer.interval()) % 1000 self.update() - def paintEvent(self, event: QPaintEvent): + def paintEvent(self, event: QPaintEvent) -> None: painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) self.helper.paint(painter, event, self.elapsed) diff --git a/qt__pyqt__pyside__pyqode/draw_wave_SIN_and_COS.py b/qt__pyqt__pyside__pyqode/draw_wave_SIN_and_COS.py index a52c52fa1..fab8cc9d3 100644 --- a/qt__pyqt__pyside__pyqode/draw_wave_SIN_and_COS.py +++ b/qt__pyqt__pyside__pyqode/draw_wave_SIN_and_COS.py @@ -12,7 +12,7 @@ class MainWindow(QWidget): - def paintEvent(self, event): + def paintEvent(self, event) -> None: painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) diff --git a/qt__pyqt__pyside__pyqode/example_QStackedWidget/use_buttons.py b/qt__pyqt__pyside__pyqode/example_QStackedWidget/use_buttons.py index e2227877b..dae8ceada 100644 --- a/qt__pyqt__pyside__pyqode/example_QStackedWidget/use_buttons.py +++ b/qt__pyqt__pyside__pyqode/example_QStackedWidget/use_buttons.py @@ -16,7 +16,7 @@ class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.stacked_widget = QStackedWidget() diff --git a/qt__pyqt__pyside__pyqode/example_QStackedWidget/use_listwidget.py b/qt__pyqt__pyside__pyqode/example_QStackedWidget/use_listwidget.py index df42105e6..0fcdaee31 100644 --- a/qt__pyqt__pyside__pyqode/example_QStackedWidget/use_listwidget.py +++ b/qt__pyqt__pyside__pyqode/example_QStackedWidget/use_listwidget.py @@ -15,7 +15,7 @@ class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.stacked_widget = QStackedWidget() diff --git a/qt__pyqt__pyside__pyqode/filling the large list without delay Qt/async.py b/qt__pyqt__pyside__pyqode/filling the large list without delay Qt/async.py index e12d935fe..d51d5a8ff 100644 --- a/qt__pyqt__pyside__pyqode/filling the large list without delay Qt/async.py +++ b/qt__pyqt__pyside__pyqode/filling the large list without delay Qt/async.py @@ -18,7 +18,7 @@ from PyQt5.QtCore import QThread, pyqtSignal -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -31,12 +31,12 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class MyThread(QThread): about_new_value = pyqtSignal(int) - def __init__(self): + def __init__(self) -> None: super().__init__() self.executed = False - def run(self): + def run(self) -> None: print("start thread") try: @@ -65,7 +65,7 @@ def exit(self, returnCode=0): class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.lw = QListWidget() @@ -79,14 +79,14 @@ def __init__(self): self.thread = MyThread() self.thread.about_new_value.connect(lambda x: self.append_item(str(x))) - def append_item(self, item): + def append_item(self, item) -> None: self.lw.addItem(item) self.lw.scrollToBottom() - def fill(self): + def fill(self) -> None: self.thread.start() - def closeEvent(self, event): + def closeEvent(self, event) -> None: # После закрытия окна приложение не завершится пока список работает sys.exit() diff --git a/qt__pyqt__pyside__pyqode/filling the large list without delay Qt/sync.py b/qt__pyqt__pyside__pyqode/filling the large list without delay Qt/sync.py index ddee22a6c..ef922ccf3 100644 --- a/qt__pyqt__pyside__pyqode/filling the large list without delay Qt/sync.py +++ b/qt__pyqt__pyside__pyqode/filling the large list without delay Qt/sync.py @@ -16,7 +16,7 @@ from PyQt5.QtWidgets import QWidget, QListWidget, QApplication, QVBoxLayout -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -33,7 +33,7 @@ def generator_large_list(): class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.lw = QListWidget() @@ -44,12 +44,12 @@ def __init__(self): self.setLayout(layout) - def fill(self): + def fill(self) -> None: for i in generator_large_list(): self.lw.addItem(str(i)) self.lw.scrollToBottom() - def closeEvent(self, event): + def closeEvent(self, event) -> None: # После закрытия окна приложение не завершится пока список работает sys.exit() diff --git a/qt__pyqt__pyside__pyqode/full_black_screen.py b/qt__pyqt__pyside__pyqode/full_black_screen.py index 4e3af61ae..ac42ed33a 100644 --- a/qt__pyqt__pyside__pyqode/full_black_screen.py +++ b/qt__pyqt__pyside__pyqode/full_black_screen.py @@ -10,7 +10,7 @@ class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setMouseTracking(True) @@ -18,22 +18,22 @@ def __init__(self): self._enabledClose = False QTimer.singleShot(5000, self._setEnabledClose) - def _setEnabledClose(self): + def _setEnabledClose(self) -> None: self._enabledClose = True - def mouseMoveEvent(self, event): + def mouseMoveEvent(self, event) -> None: if self._enabledClose: self.close() - def mousePressEvent(self, event): + def mousePressEvent(self, event) -> None: if self._enabledClose: self.close() - def keyPressEvent(self, event): + def keyPressEvent(self, event) -> None: if self._enabledClose: self.close() - def paintEvent(self, event): + def paintEvent(self, event) -> None: color = Qt.black painter = QPainter(self) diff --git a/qt__pyqt__pyside__pyqode/full_black_screen_close_manual.py b/qt__pyqt__pyside__pyqode/full_black_screen_close_manual.py index 10f577e2a..251972571 100644 --- a/qt__pyqt__pyside__pyqode/full_black_screen_close_manual.py +++ b/qt__pyqt__pyside__pyqode/full_black_screen_close_manual.py @@ -17,7 +17,7 @@ class MainWindow(QWidget): - def __init__(self, background_color: str = "black", text_color: str = "white"): + def __init__(self, background_color: str = "black", text_color: str = "white") -> None: super().__init__() self.setStyleSheet( @@ -46,7 +46,7 @@ def __init__(self, background_color: str = "black", text_color: str = "white"): main_layout.addStretch() main_layout.addWidget(self.button_close) - def _add_animations(self): + def _add_animations(self) -> None: self.button_close.setGraphicsEffect(QGraphicsOpacityEffect()) animation_object = self.button_close.graphicsEffect() @@ -71,7 +71,7 @@ def _add_animations(self): self.animation_group.addAnimation(animation2) self.animation_group.start() - def keyPressEvent(self, event: QKeyEvent): + def keyPressEvent(self, event: QKeyEvent) -> None: if event.key() in [Qt.Key_Escape, Qt.Key_Return, Qt.Key_Enter, Qt.Key_Space]: self.close() diff --git a/qt__pyqt__pyside__pyqode/full_black_screen_close_manual_with_animations.py b/qt__pyqt__pyside__pyqode/full_black_screen_close_manual_with_animations.py index 906a6d96a..dfc1dd7cf 100644 --- a/qt__pyqt__pyside__pyqode/full_black_screen_close_manual_with_animations.py +++ b/qt__pyqt__pyside__pyqode/full_black_screen_close_manual_with_animations.py @@ -20,19 +20,19 @@ class Animation: - def __init__(self, owner: QWidget = None): + def __init__(self, owner: QWidget = None) -> None: self.owner = owner - def set_owner(self, owner: QWidget): + def set_owner(self, owner: QWidget) -> None: self.owner = owner - def prepare(self): + def prepare(self) -> None: pass - def tick(self): + def tick(self) -> None: pass - def draw(self, painter: QPainter): + def draw(self, painter: QPainter) -> None: pass @@ -42,7 +42,7 @@ class DirectionEnum(enum.IntEnum): class Ball(BaseBall): - def __init__(self, x, y, r, v_x, v_y, color): + def __init__(self, x, y, r, v_x, v_y, color) -> None: super().__init__(x, y, r, v_x, v_y, color) self.animation_alpha_direction = choice(list(DirectionEnum)) @@ -56,7 +56,7 @@ def __init__( min_ball_alpha_color: int = 35, # Минимальное значение может быть 0 max_ball_alpha_color: int = 160, # Максимальное значение может быть 255 animation_ball_alpha_color: bool = True, - ): + ) -> None: super().__init__(owner) self.balls: list[Ball] = [] @@ -65,11 +65,11 @@ def __init__( self.max_ball_alpha_color = max_ball_alpha_color self.animation_ball_alpha_color = animation_ball_alpha_color - def prepare(self): + def prepare(self) -> None: for _ in range(self.number_balls): self.append_random_ball() - def append_random_ball(self): + def append_random_ball(self) -> None: x = self.owner.width() // 2 + randint( -self.owner.width() // 3, self.owner.width() // 3 ) @@ -90,7 +90,7 @@ def append_random_ball(self): ) self.balls.append(ball) - def tick(self): + def tick(self) -> None: for ball in self.balls: ball.update() @@ -113,13 +113,13 @@ def tick(self): ball.color = ball.color[:3] + (alpha,) - def draw(self, painter: QPainter): + def draw(self, painter: QPainter) -> None: for ball in self.balls: ball.draw(painter) class MainWindow(BaseMainWindow): - def __init__(self, animations: list[Animation] = None): + def __init__(self, animations: list[Animation] = None) -> None: super().__init__() self.animations: list[Animation] = animations @@ -129,7 +129,7 @@ def __init__(self, animations: list[Animation] = None): self.timer.setInterval(1000 // 20) self.timer.timeout.connect(self.tick) - def tick(self): + def tick(self) -> None: if not self.animations: return @@ -138,7 +138,7 @@ def tick(self): self.update() - def start_animations(self): + def start_animations(self) -> None: if not self.animations: return @@ -148,7 +148,7 @@ def start_animations(self): self.timer.start() - def paintEvent(self, event: QPaintEvent): + def paintEvent(self, event: QPaintEvent) -> None: super().paintEvent(event) painter = QPainter(self) diff --git a/qt__pyqt__pyside__pyqode/get_html_from_Qt5_QWebEnginePage.py b/qt__pyqt__pyside__pyqode/get_html_from_Qt5_QWebEnginePage.py index 92b6f2c5c..b88e0790b 100644 --- a/qt__pyqt__pyside__pyqode/get_html_from_Qt5_QWebEnginePage.py +++ b/qt__pyqt__pyside__pyqode/get_html_from_Qt5_QWebEnginePage.py @@ -12,7 +12,7 @@ # Основа взята из http://stackoverflow.com/a/37755811/5909792 def get_html(url): class ExtractorHtml: - def __init__(self, url): + def __init__(self, url) -> None: _app = QApplication([]) self._page = QWebEnginePage() self._page.loadFinished.connect(self._load_finished_handler) @@ -36,10 +36,10 @@ def __init__(self, url): # Чтобы избежать падений скрипта self._page = None - def _callable(self, data): + def _callable(self, data) -> None: self.html = data - def _load_finished_handler(self, _): + def _load_finished_handler(self, _) -> None: self._counter_finished += 1 if self._counter_finished == 2: diff --git a/qt__pyqt__pyside__pyqode/get_mouse_cursor_to_pixmap__win10/gui_with_timer.py b/qt__pyqt__pyside__pyqode/get_mouse_cursor_to_pixmap__win10/gui_with_timer.py index 5a79efd34..46db7da3a 100644 --- a/qt__pyqt__pyside__pyqode/get_mouse_cursor_to_pixmap__win10/gui_with_timer.py +++ b/qt__pyqt__pyside__pyqode/get_mouse_cursor_to_pixmap__win10/gui_with_timer.py @@ -14,7 +14,7 @@ class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.DEFAULT_MOUSE_PIXMAP = QPixmap("default_mouse.png").scaledToWidth(16) @@ -29,7 +29,7 @@ def __init__(self): self.timer.setInterval(100) self.timer.start() - def _on_tick(self): + def _on_tick(self) -> None: # flags, hcursor, (x, y) = _, hcursor, _ = win32gui.GetCursorInfo() diff --git a/qt__pyqt__pyside__pyqode/highlight previous tab Qt.py b/qt__pyqt__pyside__pyqode/highlight previous tab Qt.py index 237c763a8..09e1b1718 100644 --- a/qt__pyqt__pyside__pyqode/highlight previous tab Qt.py +++ b/qt__pyqt__pyside__pyqode/highlight previous tab Qt.py @@ -14,7 +14,7 @@ class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.prev_tab_index = -1 @@ -32,7 +32,7 @@ def __init__(self): self.setCentralWidget(self.tab_widget) - def current_tab_changed(self, i): + def current_tab_changed(self, i) -> None: # Запоминание индексов предыдущей и текущей вкладки. # При переключении вкладок: # У предыдущей убирается выделение diff --git a/qt__pyqt__pyside__pyqode/hook_exceptions_in_Qt.py b/qt__pyqt__pyside__pyqode/hook_exceptions_in_Qt.py index 1d50408a4..17305c9de 100644 --- a/qt__pyqt__pyside__pyqode/hook_exceptions_in_Qt.py +++ b/qt__pyqt__pyside__pyqode/hook_exceptions_in_Qt.py @@ -11,7 +11,7 @@ # Для отлова всех исключений, которые в слотах Qt могут "затеряться" и привести к тихому падению -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) diff --git a/qt__pyqt__pyside__pyqode/image on whole cell in QTableWidget/main.py b/qt__pyqt__pyside__pyqode/image on whole cell in QTableWidget/main.py index 49cb36f6c..5a8ee92f8 100644 --- a/qt__pyqt__pyside__pyqode/image on whole cell in QTableWidget/main.py +++ b/qt__pyqt__pyside__pyqode/image on whole cell in QTableWidget/main.py @@ -17,7 +17,7 @@ # Для отлова всех исключений, которые в слотах Qt могут "затеряться" и привести к тихому падению -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -37,7 +37,7 @@ def create_item(img): class MyDelegate_1(QStyledItemDelegate): - def paint(self, painter, option, index): + def paint(self, painter, option, index) -> None: img = index.model().data(index, Qt.DecorationRole) if img is None: super().paint(painter, option, index) @@ -69,7 +69,7 @@ def paint(self, painter, option, index): class MyDelegate_2(QStyledItemDelegate): - def paint(self, painter, option, index): + def paint(self, painter, option, index) -> None: img = index.model().data(index, Qt.DecorationRole) if img is None: super().paint(painter, option, index) diff --git a/qt__pyqt__pyside__pyqode/images__QListWidget__QTableWidget_QStyledItemDelegate.py b/qt__pyqt__pyside__pyqode/images__QListWidget__QTableWidget_QStyledItemDelegate.py index 6bd603393..27ba3cf83 100644 --- a/qt__pyqt__pyside__pyqode/images__QListWidget__QTableWidget_QStyledItemDelegate.py +++ b/qt__pyqt__pyside__pyqode/images__QListWidget__QTableWidget_QStyledItemDelegate.py @@ -22,10 +22,10 @@ class ImageDelegate(QStyledItemDelegate): - def __init__(self, parent=None): + def __init__(self, parent=None) -> None: super().__init__(parent) - def paint(self, painter, option, index): + def paint(self, painter, option, index) -> None: pixmap = index.data(Qt.DecorationRole) if pixmap: # pixmap = pixmap.scaled( diff --git a/qt__pyqt__pyside__pyqode/install_translator.py b/qt__pyqt__pyside__pyqode/install_translator.py index 27f01dc36..7ac4ed192 100644 --- a/qt__pyqt__pyside__pyqode/install_translator.py +++ b/qt__pyqt__pyside__pyqode/install_translator.py @@ -8,7 +8,7 @@ from PyQt5.QtCore import QTranslator, QLibraryInfo -def question(): +def question() -> None: QMessageBox.question( None, "TITLE", diff --git a/qt__pyqt__pyside__pyqode/label_framed.py b/qt__pyqt__pyside__pyqode/label_framed.py index 25cd2034c..3f249fa00 100644 --- a/qt__pyqt__pyside__pyqode/label_framed.py +++ b/qt__pyqt__pyside__pyqode/label_framed.py @@ -8,7 +8,7 @@ class Widget(Qt.QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() layout = Qt.QVBoxLayout() diff --git a/qt__pyqt__pyside__pyqode/latin_letters_similar_to_cyrillic/main.py b/qt__pyqt__pyside__pyqode/latin_letters_similar_to_cyrillic/main.py index c6033a535..47019a532 100644 --- a/qt__pyqt__pyside__pyqode/latin_letters_similar_to_cyrillic/main.py +++ b/qt__pyqt__pyside__pyqode/latin_letters_similar_to_cyrillic/main.py @@ -14,7 +14,7 @@ class MainWindow(Qt.QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() loadUi("main.ui", self) @@ -24,7 +24,7 @@ def __init__(self): self.textEdit_text.setPlainText("СВЕТА РОЕТ РОВ, ВОВКА СЕЕТ ОВЁС") - def solve(self): + def solve(self) -> None: # Исходный текст text = self.textEdit_text.toPlainText() diff --git a/qt__pyqt__pyside__pyqode/layout_append_line__horizontal_vertical.py b/qt__pyqt__pyside__pyqode/layout_append_line__horizontal_vertical.py index c0d74c4b2..05ba470bc 100644 --- a/qt__pyqt__pyside__pyqode/layout_append_line__horizontal_vertical.py +++ b/qt__pyqt__pyside__pyqode/layout_append_line__horizontal_vertical.py @@ -8,7 +8,7 @@ class HorizontalLineWidget(QFrame): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setFrameShape(QFrame.HLine) @@ -17,7 +17,7 @@ def __init__(self): class VerticalLineWidget(QFrame): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setFrameShape(QFrame.VLine) diff --git a/qt__pyqt__pyside__pyqode/layout_column_resizer/column_resizer.py b/qt__pyqt__pyside__pyqode/layout_column_resizer/column_resizer.py index 3c5e6789a..f3a07c642 100644 --- a/qt__pyqt__pyside__pyqode/layout_column_resizer/column_resizer.py +++ b/qt__pyqt__pyside__pyqode/layout_column_resizer/column_resizer.py @@ -26,7 +26,7 @@ def __init__( widget: QWidget, formLayout: QFormLayout, itemRole: QFormLayout.ItemRole, - ): + ) -> None: super().__init__(widget) self.m_width: int = -1 @@ -54,12 +54,12 @@ def maximumSize(self) -> QSize: return size - def setWidth(self, width: int): + def setWidth(self, width: int) -> None: if width != self.m_width: self.m_width = width self.invalidate() - def setGeometry(self, _rect: QRect): + def setGeometry(self, _rect: QRect) -> None: rect: QRect = _rect width = self.widget().sizeHint().width() if ( @@ -81,7 +81,7 @@ class GridColumnInfo: class ColumnResizerPrivate: - def __init__(self, q_ptr: "ColumnResizer"): + def __init__(self, q_ptr: "ColumnResizer") -> None: self.q: ColumnResizer = q_ptr self.m_widgets: list[QWidget] = [] @@ -93,23 +93,23 @@ def __init__(self, q_ptr: "ColumnResizer"): self.m_updateTimer.setInterval(0) self.m_updateTimer.timeout.connect(self.q.updateWidth) - def scheduleWidthUpdate(self): + def scheduleWidthUpdate(self) -> None: self.m_updateTimer.start() class ColumnResizer(QObject): - def __init__(self, parent: QObject): + def __init__(self, parent: QObject) -> None: super().__init__(parent) self.d = ColumnResizerPrivate(self) - def addWidget(self, widget: QWidget): + def addWidget(self, widget: QWidget) -> None: self.d.m_widgets.append(widget) widget.installEventFilter(self) self.d.scheduleWidthUpdate() # NOTE: Here the logic is changed relative to the original - def updateWidth(self): + def updateWidth(self) -> None: width: int = 0 x: int = 0 for widget in self.d.m_widgets: @@ -131,7 +131,7 @@ def eventFilter(self, _: QObject, event: QEvent) -> bool: return False - def addWidgetsFromLayout(self, layout: QLayout, column: int): + def addWidgetsFromLayout(self, layout: QLayout, column: int) -> None: assert column >= 0 if isinstance(layout, QGridLayout): @@ -148,7 +148,7 @@ def addWidgetsFromLayout(self, layout: QLayout, column: int): else: qCritical(f"Don't know how to handle layout {layout}") - def addWidgetsFromGridLayout(self, layout: QGridLayout, column: int): + def addWidgetsFromGridLayout(self, layout: QGridLayout, column: int) -> None: for row in range(layout.rowCount()): item: QLayoutItem = layout.itemAtPosition(row, column) if not item: @@ -162,7 +162,7 @@ def addWidgetsFromGridLayout(self, layout: QGridLayout, column: int): self.d.m_gridColumnInfoList.append(GridColumnInfo(layout, column)) - def addWidgetsFromFormLayout(self, layout: QFormLayout, role: QFormLayout.ItemRole): + def addWidgetsFromFormLayout(self, layout: QFormLayout, role: QFormLayout.ItemRole) -> None: for row in range(layout.rowCount()): item: QLayoutItem = layout.itemAt(row, role) if not item: diff --git a/qt__pyqt__pyside__pyqode/layout_column_resizer/column_resizer_pyqt6.py b/qt__pyqt__pyside__pyqode/layout_column_resizer/column_resizer_pyqt6.py new file mode 100644 index 000000000..f3e1756ec --- /dev/null +++ b/qt__pyqt__pyside__pyqode/layout_column_resizer/column_resizer_pyqt6.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +# SOURCE: https://github.com/agateau/columnresizer + + +from dataclasses import dataclass + +from PyQt6.QtCore import QEvent, QTimer, QSize, QRect, Qt, QObject, qCritical +from PyQt6.QtWidgets import ( + QFormLayout, + QGridLayout, + QWidget, + QWidgetItem, + QLayout, + QLayoutItem, +) + + +class FormLayoutWidgetItem(QWidgetItem): + def __init__( + self, + widget: QWidget, + formLayout: QFormLayout, + itemRole: QFormLayout.ItemRole, + ): + super().__init__(widget) + + self.m_width: int = -1 + self.m_formLayout: QFormLayout = formLayout + self.m_itemRole: QFormLayout.ItemRole = itemRole + + def sizeHint(self) -> QSize: + size: QSize = super().sizeHint() + if self.m_width != -1: + size.setWidth(self.m_width) + + return size + + def minimumSize(self) -> QSize: + size: QSize = super().minimumSize() + if self.m_width != -1: + size.setWidth(self.m_width) + + return size + + def maximumSize(self) -> QSize: + size: QSize = super().maximumSize() + if self.m_width != -1: + size.setWidth(self.m_width) + + return size + + def setWidth(self, width: int): + if width != self.m_width: + self.m_width = width + self.invalidate() + + def setGeometry(self, _rect: QRect): + rect: QRect = _rect + width = self.widget().sizeHint().width() + if ( + self.m_itemRole == QFormLayout.ItemRole.LabelRole + and self.m_formLayout.labelAlignment() & Qt.AlignmentFlag.AlignRight + ): + rect.setLeft(rect.right() - width) + + super().setGeometry(rect) + + def formLayout(self) -> QFormLayout: + return self.m_formLayout + + +@dataclass +class GridColumnInfo: + layout: QGridLayout + column: int + + +class ColumnResizerPrivate: + def __init__(self, q_ptr: "ColumnResizer"): + self.q: ColumnResizer = q_ptr + + self.m_widgets: list[QWidget] = [] + self.m_wrWidgetItemList: list[FormLayoutWidgetItem] = [] + self.m_gridColumnInfoList: list[GridColumnInfo] = [] + + self.m_updateTimer: QTimer = QTimer(self.q) + self.m_updateTimer.setSingleShot(True) + self.m_updateTimer.setInterval(0) + self.m_updateTimer.timeout.connect(self.q.updateWidth) + + def scheduleWidthUpdate(self): + self.m_updateTimer.start() + + +class ColumnResizer(QObject): + def __init__(self, parent: QObject): + super().__init__(parent) + + self.d = ColumnResizerPrivate(self) + + def addWidget(self, widget: QWidget): + self.d.m_widgets.append(widget) + widget.installEventFilter(self) + self.d.scheduleWidthUpdate() + + # NOTE: Here the logic is changed relative to the original + def updateWidth(self): + width: int = 0 + x: int = 0 + for widget in self.d.m_widgets: + x = max(widget.pos().x(), x) + width = max(widget.sizeHint().width(), width) + + width += x + + for item in self.d.m_wrWidgetItemList: + item.setWidth(width - item.widget().pos().x()) + item.formLayout().update() + + for info in self.d.m_gridColumnInfoList: + info.layout.setColumnMinimumWidth(info.column, width) + + def eventFilter(self, _: QObject, event: QEvent) -> bool: + if event.type() == QEvent.Type.Resize: + self.d.scheduleWidthUpdate() + + return False + + def addWidgetsFromLayout(self, layout: QLayout, column: int): + assert column >= 0 + + if isinstance(layout, QGridLayout): + self.addWidgetsFromGridLayout(layout, column) + elif isinstance(layout, QFormLayout): + if column > QFormLayout.ItemRole.SpanningRole.value: + qCritical( + f"column should not be more than {QFormLayout.ItemRole.SpanningRole.value} for QFormLayout" + ) + return + + role: QFormLayout.ItemRole = QFormLayout.ItemRole(column) + self.addWidgetsFromFormLayout(layout, role) + else: + qCritical(f"Don't know how to handle layout {layout}") + + def addWidgetsFromGridLayout(self, layout: QGridLayout, column: int): + for row in range(layout.rowCount()): + item: QLayoutItem = layout.itemAtPosition(row, column) + if not item: + continue + + widget: QWidget = item.widget() + if not widget: + continue + + self.addWidget(widget) + + self.d.m_gridColumnInfoList.append(GridColumnInfo(layout, column)) + + def addWidgetsFromFormLayout(self, layout: QFormLayout, role: QFormLayout.ItemRole): + for row in range(layout.rowCount()): + item: QLayoutItem = layout.itemAt(row, role) + if not item: + continue + + widget: QWidget = item.widget() + if not widget: + continue + + layout.removeItem(item) + newItem: FormLayoutWidgetItem = FormLayoutWidgetItem(widget, layout, role) + layout.setItem(row, role, newItem) + self.addWidget(widget) + self.d.m_wrWidgetItemList.append(newItem) diff --git a/qt__pyqt__pyside__pyqode/layout_column_resizer/example.py b/qt__pyqt__pyside__pyqode/layout_column_resizer/example.py index 7461641be..f22f01688 100644 --- a/qt__pyqt__pyside__pyqode/layout_column_resizer/example.py +++ b/qt__pyqt__pyside__pyqode/layout_column_resizer/example.py @@ -30,7 +30,7 @@ class About(QDialog): - def __init__(self, title: str, use_column_resizer: bool): + def __init__(self, title: str, use_column_resizer: bool) -> None: super().__init__() self.setWindowTitle(title) diff --git a/qt__pyqt__pyside__pyqode/layout_column_resizer/example_pyqt6.py b/qt__pyqt__pyside__pyqode/layout_column_resizer/example_pyqt6.py new file mode 100644 index 000000000..7c8997c32 --- /dev/null +++ b/qt__pyqt__pyside__pyqode/layout_column_resizer/example_pyqt6.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +import sys +import platform + +from datetime import datetime +from pathlib import Path + +from PyQt6.QtWidgets import ( + QDialog, + QWidget, + QFormLayout, + QLabel, + QDialogButtonBox, + QGroupBox, + QVBoxLayout, + QScrollArea, +) + +from column_resizer_pyqt6 import ColumnResizer + + +DIR: Path = Path(__file__).resolve().parent + +PROGRAM_NAME: str = DIR.name + + +class About(QDialog): + def __init__(self, title: str, use_column_resizer: bool) -> None: + super().__init__() + + self.setWindowTitle(title) + + self._started: datetime = datetime.now() + + gb_python = QGroupBox("Python:") + gb_python_layout = QFormLayout(gb_python) + gb_python_layout.addRow( + "Version:", + QLabel(sys.version), + ) + gb_python_layout.addRow( + "Implementation:", + QLabel(platform.python_implementation()), + ) + gb_python_layout.addRow("Executable:", QLabel(sys.executable)) + + button_box = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok) + button_box.accepted.connect(self.accept) + button_box.rejected.connect(self.reject) + + fields_layout = QFormLayout() + fields_layout.addRow( + "Version:", + QLabel("1.0.0"), + ) + fields_layout.addRow( + "Directory:", + QLabel(str(DIR)), + ) + fields_layout.addRow( + "Argv:", + QLabel(" ".join(sys.argv[1:])), + ) + fields_layout.addRow(gb_python) + fields_layout.addRow( + "Platform:", + QLabel(platform.platform()), + ) + + fields_widget = QWidget() + fields_layout.setContentsMargins(0, 0, 0, 0) + fields_widget.setLayout(fields_layout) + + scroll_area = QScrollArea() + scroll_area.setWidget(fields_widget) + scroll_area.setWidgetResizable(True) + scroll_area.setFrameStyle(QScrollArea.Shape.NoFrame) + + main_layout = QVBoxLayout(self) + main_layout.addWidget(QLabel(f"

{PROGRAM_NAME}

")) + main_layout.addWidget(scroll_area) + main_layout.addWidget(button_box) + + if use_column_resizer: + resizer = ColumnResizer(self) + resizer.addWidgetsFromLayout(fields_layout, 0) + resizer.addWidgetsFromLayout(gb_python_layout, 0) + + self.resize(500, 300) + + +if __name__ == "__main__": + from PyQt6.QtWidgets import QApplication + + app = QApplication(sys.argv) + + w1 = About(f"use_column_resizer=False", use_column_resizer=False) + w1.show() + + w2 = About(f"use_column_resizer=True", use_column_resizer=True) + w2.show() + w2.move(w1.x() + w1.width(), w1.y()) + + sys.exit(app.exec()) diff --git a/qt__pyqt__pyside__pyqode/lazy__qtwidgets_itemviews_fetchmore_example__QAbstractListModel.py b/qt__pyqt__pyside__pyqode/lazy__qtwidgets_itemviews_fetchmore_example__QAbstractListModel.py index f4fb74829..3a01b50c5 100644 --- a/qt__pyqt__pyside__pyqode/lazy__qtwidgets_itemviews_fetchmore_example__QAbstractListModel.py +++ b/qt__pyqt__pyside__pyqode/lazy__qtwidgets_itemviews_fetchmore_example__QAbstractListModel.py @@ -33,7 +33,7 @@ class FileListModel(QAbstractListModel): numberPopulated = pyqtSignal(int) - def __init__(self, batch_size=50, parent=None): + def __init__(self, batch_size=50, parent=None) -> None: super().__init__(parent) self.fileList = [] @@ -65,7 +65,7 @@ def data(self, index: QModelIndex, role=Qt.DisplayRole) -> QVariant: def canFetchMore(self, parent: QModelIndex = None) -> bool: return self.fileCount < len(self.fileList) - def fetchMore(self, parent: QModelIndex = None): + def fetchMore(self, parent: QModelIndex = None) -> None: remainder = len(self.fileList) - self.fileCount itemsToFetch = min(self.batch_size, remainder) if itemsToFetch <= 0: @@ -81,7 +81,7 @@ def fetchMore(self, parent: QModelIndex = None): self.numberPopulated.emit(itemsToFetch) - def setDirPath(self, path: str): + def setDirPath(self, path: str) -> None: self.beginResetModel() # Recursive @@ -92,7 +92,7 @@ def setDirPath(self, path: str): class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Fetch More Example") @@ -126,7 +126,7 @@ def __init__(self): self.setCentralWidget(QWidget()) self.centralWidget().setLayout(layout) - def updateLog(self, number: int): + def updateLog(self, number: int) -> None: self.logViewer.append(f"{number} items added.") diff --git a/qt__pyqt__pyside__pyqode/load_url__async_thread__QNetworkAccessManager.py b/qt__pyqt__pyside__pyqode/load_url__async_thread__QNetworkAccessManager.py index 8f29a4e09..fbb1e2770 100644 --- a/qt__pyqt__pyside__pyqode/load_url__async_thread__QNetworkAccessManager.py +++ b/qt__pyqt__pyside__pyqode/load_url__async_thread__QNetworkAccessManager.py @@ -8,7 +8,7 @@ class MainWindow(Qt.QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.button = Qt.QPushButton("Load url!") @@ -19,10 +19,10 @@ def __init__(self): self.setCentralWidget(self.button) - def on_reply_finished(self, reply): + def on_reply_finished(self, reply) -> None: self.setWindowTitle(f"After load: {reply}") - def on_clicked(self): + def on_clicked(self) -> None: url = "https://github.com/gil9red/SimplePyScripts" self.setWindowTitle("Before load") diff --git a/qt__pyqt__pyside__pyqode/load_url__async_thread__QThread.py b/qt__pyqt__pyside__pyqode/load_url__async_thread__QThread.py index 530f5a991..a5b9efb71 100644 --- a/qt__pyqt__pyside__pyqode/load_url__async_thread__QThread.py +++ b/qt__pyqt__pyside__pyqode/load_url__async_thread__QThread.py @@ -11,18 +11,18 @@ class LoadUrlThread(Qt.QThread): load_finished = Qt.pyqtSignal(object) - def __init__(self, url): + def __init__(self, url) -> None: super().__init__() self.url = url - def run(self): + def run(self) -> None: rs = requests.get(self.url) self.load_finished.emit(rs) class MainWindow(Qt.QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.button = Qt.QPushButton("Load url!") @@ -30,10 +30,10 @@ def __init__(self): self.setCentralWidget(self.button) - def on_finished_load_url(self, rs): + def on_finished_load_url(self, rs) -> None: self.setWindowTitle(f"After load: {rs}") - def on_clicked(self): + def on_clicked(self) -> None: url = "https://github.com/gil9red/SimplePyScripts" self.setWindowTitle("Before load") diff --git a/qt__pyqt__pyside__pyqode/model_with_iterator__QAbstractListModel/_more_examples.py b/qt__pyqt__pyside__pyqode/model_with_iterator__QAbstractListModel/_more_examples.py index c835bc092..9535232e3 100644 --- a/qt__pyqt__pyside__pyqode/model_with_iterator__QAbstractListModel/_more_examples.py +++ b/qt__pyqt__pyside__pyqode/model_with_iterator__QAbstractListModel/_more_examples.py @@ -20,7 +20,7 @@ def get_infinity_generator(): class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() main_layout = QHBoxLayout(self) diff --git a/qt__pyqt__pyside__pyqode/model_with_iterator__QAbstractListModel/iterator_list_model.py b/qt__pyqt__pyside__pyqode/model_with_iterator__QAbstractListModel/iterator_list_model.py index bb6815932..f09e6fbc0 100644 --- a/qt__pyqt__pyside__pyqode/model_with_iterator__QAbstractListModel/iterator_list_model.py +++ b/qt__pyqt__pyside__pyqode/model_with_iterator__QAbstractListModel/iterator_list_model.py @@ -11,7 +11,7 @@ class IteratorListModel(QAbstractListModel): - def __init__(self, it: Iterator, prefetch=100, parent=None): + def __init__(self, it: Iterator, prefetch=100, parent=None) -> None: super().__init__(parent) self._at_end = False @@ -22,7 +22,7 @@ def __init__(self, it: Iterator, prefetch=100, parent=None): def canFetchMore(self, parent: QModelIndex = None) -> bool: return not self._at_end - def fetchMore(self, parent: QModelIndex = None): + def fetchMore(self, parent: QModelIndex = None) -> None: if self._at_end: return diff --git a/qt__pyqt__pyside__pyqode/multiprocessing__QApplication__create_child_process__with__Tkinter_and_Qt.py b/qt__pyqt__pyside__pyqode/multiprocessing__QApplication__create_child_process__with__Tkinter_and_Qt.py index 6388d470b..614e5b281 100644 --- a/qt__pyqt__pyside__pyqode/multiprocessing__QApplication__create_child_process__with__Tkinter_and_Qt.py +++ b/qt__pyqt__pyside__pyqode/multiprocessing__QApplication__create_child_process__with__Tkinter_and_Qt.py @@ -10,7 +10,7 @@ from PyQt5.Qt import QApplication, Qt, QLabel -def go_qt(name): +def go_qt(name) -> None: app = QApplication([]) mw = QLabel() @@ -22,7 +22,7 @@ def go_qt(name): app.exec() -def go_tk(name): +def go_tk(name) -> None: app = tk.Tk() app.minsize(150, 50) @@ -32,12 +32,12 @@ def go_tk(name): app.mainloop() -def create_qt(): +def create_qt() -> None: p = Process(target=go_qt, args=("Qt",)) p.start() -def create_tk(): +def create_tk() -> None: p = Process(target=go_tk, args=("Tk",)) p.start() diff --git a/qt__pyqt__pyside__pyqode/multiprocessing__QApplication__in_other_process.py b/qt__pyqt__pyside__pyqode/multiprocessing__QApplication__in_other_process.py index 91cec6fa4..e216d0e33 100644 --- a/qt__pyqt__pyside__pyqode/multiprocessing__QApplication__in_other_process.py +++ b/qt__pyqt__pyside__pyqode/multiprocessing__QApplication__in_other_process.py @@ -7,7 +7,7 @@ from PyQt5.Qt import QApplication, Qt, QLabel -def go(name): +def go(name) -> None: app = QApplication([]) mw = QLabel() diff --git a/qt__pyqt__pyside__pyqode/not_working__youtube_Maximum_durations_QWebView__PyQt4.py b/qt__pyqt__pyside__pyqode/not_working__youtube_Maximum_durations_QWebView__PyQt4.py index 8de39d42d..412adc556 100644 --- a/qt__pyqt__pyside__pyqode/not_working__youtube_Maximum_durations_QWebView__PyQt4.py +++ b/qt__pyqt__pyside__pyqode/not_working__youtube_Maximum_durations_QWebView__PyQt4.py @@ -48,7 +48,7 @@ def get_total_seconds(time_str): return total_seconds -def load_finished_handler(ok): +def load_finished_handler(ok) -> None: if not ok: return @@ -78,7 +78,7 @@ def get_video_link_list(): timer = QTimer() timer.setInterval(5000) - def timeout_handler(): + def timeout_handler() -> None: doc = view.page().mainFrame().documentElement() button = doc.findFirst(".load-more-button") diff --git a/qt__pyqt__pyside__pyqode/not_working__youtube_summary_durations_all_video_QWebView__PyQt4.py b/qt__pyqt__pyside__pyqode/not_working__youtube_summary_durations_all_video_QWebView__PyQt4.py index aac5e54e3..8302eb998 100644 --- a/qt__pyqt__pyside__pyqode/not_working__youtube_summary_durations_all_video_QWebView__PyQt4.py +++ b/qt__pyqt__pyside__pyqode/not_working__youtube_summary_durations_all_video_QWebView__PyQt4.py @@ -47,13 +47,13 @@ def get_total_seconds(time_str): return total_seconds -def load_finished_handler(ok): +def load_finished_handler(ok) -> None: if not ok: return doc = view.page().mainFrame().documentElement() - def update_url_video_by_time_dict(): + def update_url_video_by_time_dict() -> None: global url_video_by_time_dict html = doc.toOuterXml() @@ -72,7 +72,7 @@ def update_url_video_by_time_dict(): timer = QTimer() timer.setInterval(5000) - def timeout_handler(): + def timeout_handler() -> None: doc = view.page().mainFrame().documentElement() button = doc.findFirst(".load-more-button") diff --git a/qt__pyqt__pyside__pyqode/play_mp3__pyqt5__qmediaplayer/play.py b/qt__pyqt__pyside__pyqode/play_mp3__pyqt5__qmediaplayer/play.py index 5f7ef8616..518bc7668 100644 --- a/qt__pyqt__pyside__pyqode/play_mp3__pyqt5__qmediaplayer/play.py +++ b/qt__pyqt__pyside__pyqode/play_mp3__pyqt5__qmediaplayer/play.py @@ -7,7 +7,7 @@ from PyQt5 import Qt -def _on_media_status_changed(status): +def _on_media_status_changed(status) -> None: if status == Qt.QMediaPlayer.EndOfMedia: Qt.QCoreApplication.instance().quit() diff --git a/qt__pyqt__pyside__pyqode/pyq5__QTreeView_QFileSystemModel_and_viewer_as_QTextEdit__on_double_click.py b/qt__pyqt__pyside__pyqode/pyq5__QTreeView_QFileSystemModel_and_viewer_as_QTextEdit__on_double_click.py index 80f16a1ce..89dd73810 100644 --- a/qt__pyqt__pyside__pyqode/pyq5__QTreeView_QFileSystemModel_and_viewer_as_QTextEdit__on_double_click.py +++ b/qt__pyqt__pyside__pyqode/pyq5__QTreeView_QFileSystemModel_and_viewer_as_QTextEdit__on_double_click.py @@ -17,7 +17,7 @@ class MainWindow(QMainWindow): - def __init__(self, parent=None): + def __init__(self, parent=None) -> None: super().__init__(parent) self.setWindowTitle("Direct tree") @@ -43,7 +43,7 @@ def __init__(self, parent=None): self.setCentralWidget(splitter) - def _on_double_clicked(self, index): + def _on_double_clicked(self, index) -> None: file_name = self.model.filePath(index) with open(file_name, encoding="utf-8") as f: diff --git a/qt__pyqt__pyside__pyqode/pyq5__simple_balls__with_part_transparent_body.py b/qt__pyqt__pyside__pyqode/pyq5__simple_balls__with_part_transparent_body.py index 540969d9a..c9d857d1e 100644 --- a/qt__pyqt__pyside__pyqode/pyq5__simple_balls__with_part_transparent_body.py +++ b/qt__pyqt__pyside__pyqode/pyq5__simple_balls__with_part_transparent_body.py @@ -81,7 +81,7 @@ def get_random_color() -> tuple[int, int, int]: class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowFlags(Qt.FramelessWindowHint) @@ -105,22 +105,22 @@ def __init__(self): self.setLayout(layout) - def mousePressEvent(self, event): + def mousePressEvent(self, event) -> None: if event.button() == Qt.LeftButton: self._old_pos = event.pos() - def mouseReleaseEvent(self, event): + def mouseReleaseEvent(self, event) -> None: if event.button() == Qt.LeftButton: self._old_pos = None - def mouseMoveEvent(self, event): + def mouseMoveEvent(self, event) -> None: if not self._old_pos: return delta = event.pos() - self._old_pos self.move(self.pos() + delta) - def tick(self): + def tick(self) -> None: for ball in self.balls: ball.update() @@ -135,7 +135,7 @@ def tick(self): # Вызов перерисовки self.update() - def paintEvent(self, event): + def paintEvent(self, event) -> None: painter = QPainter(self) painter.setBrush(QColor(0, 0, 0, 1)) @@ -145,7 +145,7 @@ def paintEvent(self, event): for ball in self.balls: ball.draw(painter) - def append_random_ball(self): + def append_random_ball(self) -> None: x = self.width() // 2 + randint(-self.width() // 4, self.width() // 4) y = self.height() // 2 + randint(-self.height() // 4, self.height() // 4) r = randint(10, 20) diff --git a/qt__pyqt__pyside__pyqode/pyqt5_QToolTip_with_programmatically_timeout.py b/qt__pyqt__pyside__pyqode/pyqt5_QToolTip_with_programmatically_timeout.py index e8cd22b14..38a464657 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5_QToolTip_with_programmatically_timeout.py +++ b/qt__pyqt__pyside__pyqode/pyqt5_QToolTip_with_programmatically_timeout.py @@ -8,7 +8,7 @@ from PyQt5.QtCore import QRect, QTimer -def show_tooltip(parent, widget): +def show_tooltip(parent, widget) -> None: qtw.QToolTip.showText( parent.mapToGlobal(widget.pos()), widget.toolTip(), widget, QRect() ) diff --git a/qt__pyqt__pyside__pyqode/pyqt5_QToolTip_with_programmatically_timeout__using_QEvent.py b/qt__pyqt__pyside__pyqode/pyqt5_QToolTip_with_programmatically_timeout__using_QEvent.py index dfdfd2628..d2219b5ea 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5_QToolTip_with_programmatically_timeout__using_QEvent.py +++ b/qt__pyqt__pyside__pyqode/pyqt5_QToolTip_with_programmatically_timeout__using_QEvent.py @@ -9,7 +9,7 @@ from PyQt5.QtGui import QHelpEvent -def show_tooltip(parent, widget): +def show_tooltip(parent, widget) -> None: app.notify( widget, QHelpEvent(QHelpEvent.ToolTip, widget.pos(), parent.mapToGlobal(widget.pos())), diff --git a/qt__pyqt__pyside__pyqode/pyqt5__QComboBox.py b/qt__pyqt__pyside__pyqode/pyqt5__QComboBox.py index bb91bed54..4dc2d35f8 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__QComboBox.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__QComboBox.py @@ -8,7 +8,7 @@ class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.tb_result = QTextBrowser() @@ -24,7 +24,7 @@ def __init__(self): self.setLayout(layout) - def _on_pet_changed(self, index): + def _on_pet_changed(self, index) -> None: # print(index) # 0 # print(self.cb_pets.itemText(index)) # Собаки # print(self.cb_pets.itemData(index)) # dogs diff --git a/qt__pyqt__pyside__pyqode/pyqt5__QFileSystemModel__append_selected_files_and_dirs.py b/qt__pyqt__pyside__pyqode/pyqt5__QFileSystemModel__append_selected_files_and_dirs.py index bc546296c..4919e88a7 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__QFileSystemModel__append_selected_files_and_dirs.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__QFileSystemModel__append_selected_files_and_dirs.py @@ -18,7 +18,7 @@ class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() path = QDir.rootPath() @@ -47,11 +47,11 @@ def __init__(self): main_layout.addWidget(splitter) main_layout.addWidget(self.button_add) - def _on_selection_changed(self, selected, deselected): + def _on_selection_changed(self, selected, deselected) -> None: has = self.tree_view.selectionModel().hasSelection() self.button_add.setEnabled(has) - def _on_add(self): + def _on_add(self) -> None: for row in self.tree_view.selectionModel().selectedRows(): path = self.model.filePath(row) self.list_files.addItem(path) diff --git a/qt__pyqt__pyside__pyqode/pyqt5__QItemDelegate.py b/qt__pyqt__pyside__pyqode/pyqt5__QItemDelegate.py index a3184e042..3b269007d 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__QItemDelegate.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__QItemDelegate.py @@ -9,7 +9,7 @@ class MessagesWindow(QtWidgets.QTableView): - def __init__(self, parent=None): + def __init__(self, parent=None) -> None: super().__init__(parent) self.setModel(ModelMessages()) @@ -18,7 +18,7 @@ def __init__(self, parent=None): class ModelMessages(QtGui.QStandardItemModel): - def __init__(self, parent=None): + def __init__(self, parent=None) -> None: super().__init__(parent) self.appendRow( @@ -42,7 +42,7 @@ def __init__(self, parent=None): class ItemDateFormat(QtWidgets.QItemDelegate): - def paint(self, painter, opt: QtWidgets.QStyleOptionViewItem, index): + def paint(self, painter, opt: QtWidgets.QStyleOptionViewItem, index) -> None: self.drawBackground(painter, opt, index) self.drawFocus(painter, opt, opt.rect) try: diff --git a/qt__pyqt__pyside__pyqode/pyqt5__QSyntaxHighlighter.py b/qt__pyqt__pyside__pyqode/pyqt5__QSyntaxHighlighter.py index aa67d16a8..0d8831cda 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__QSyntaxHighlighter.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__QSyntaxHighlighter.py @@ -10,7 +10,7 @@ class MyHighlighter(QSyntaxHighlighter): - def highlightBlock(self, text): + def highlightBlock(self, text) -> None: char_format = QTextCharFormat() char_format.setFontWeight(QFont.Bold) char_format.setForeground(Qt.darkMagenta) diff --git a/qt__pyqt__pyside__pyqode/pyqt5__QSyntaxHighlighter__with_many_QTextCharFormat.py b/qt__pyqt__pyside__pyqode/pyqt5__QSyntaxHighlighter__with_many_QTextCharFormat.py index 8aedf9309..0c3db8a08 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__QSyntaxHighlighter__with_many_QTextCharFormat.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__QSyntaxHighlighter__with_many_QTextCharFormat.py @@ -8,7 +8,7 @@ class MyHighlighter(QSyntaxHighlighter): - def __init__(self, parent): + def __init__(self, parent) -> None: super().__init__(parent) self.regexp_by_format = dict() @@ -24,7 +24,7 @@ def __init__(self, parent): char_format.setForeground(Qt.darkCyan) self.regexp_by_format[r"\bcos\b"] = char_format - def highlightBlock(self, text): + def highlightBlock(self, text) -> None: for regexp, char_format in self.regexp_by_format.items(): expression = QRegularExpression(regexp) it = expression.globalMatch(text) diff --git a/qt__pyqt__pyside__pyqode/pyqt5__QTableWidget__select_all_row_and_column__by_cell_click.py b/qt__pyqt__pyside__pyqode/pyqt5__QTableWidget__select_all_row_and_column__by_cell_click.py index ec0f11a92..79cf2fd54 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__QTableWidget__select_all_row_and_column__by_cell_click.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__QTableWidget__select_all_row_and_column__by_cell_click.py @@ -9,7 +9,7 @@ class Widget(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Table") @@ -19,7 +19,7 @@ def __init__(self): self.setCentralWidget(self.table_widget) - def _on_cell_clicked(self, row, col): + def _on_cell_clicked(self, row, col) -> None: selection_model = self.table_widget.selectionModel() selection_model.clear() @@ -31,7 +31,7 @@ def _on_cell_clicked(self, row, col): selection_model.select(index, QItemSelectionModel.Select) - def fill(self): + def fill(self) -> None: self.table_widget.clear() labels = ["ID", "NAME", "PRICE"] diff --git a/qt__pyqt__pyside__pyqode/pyqt5__QTableWidget__show_dialog_on_double_click_cell.py b/qt__pyqt__pyside__pyqode/pyqt5__QTableWidget__show_dialog_on_double_click_cell.py index b63b0d877..9c67d101c 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__QTableWidget__show_dialog_on_double_click_cell.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__QTableWidget__show_dialog_on_double_click_cell.py @@ -8,7 +8,7 @@ class MainWindow(Qt.QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.table = Qt.QTableWidget() @@ -29,7 +29,7 @@ def __init__(self): self.setCentralWidget(main_widget) - def on_cell_item_clicked(self, item): + def on_cell_item_clicked(self, item) -> None: print(item) new_text, ok = Qt.QInputDialog.getText( diff --git a/qt__pyqt__pyside__pyqode/pyqt5__QThread_with_QProgressDialog_PleaseWait.py b/qt__pyqt__pyside__pyqode/pyqt5__QThread_with_QProgressDialog_PleaseWait.py index 9eb6c147f..4d8d76894 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__QThread_with_QProgressDialog_PleaseWait.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__QThread_with_QProgressDialog_PleaseWait.py @@ -11,17 +11,17 @@ class RunFuncThread(QThread): run_finished = pyqtSignal(object) - def __init__(self, func): + def __init__(self, func) -> None: super().__init__() self.func = func - def run(self): + def run(self) -> None: self.run_finished.emit(self.func()) class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.pb_go = QPushButton("Go") @@ -35,10 +35,10 @@ def __init__(self): self.setLayout(layout) - def _on_run_finished(self, value): + def _on_run_finished(self, value) -> None: self.te_log.setPlainText(str(value)) - def go(self): + def go(self) -> None: progress_dialog = QProgressDialog(self) def foo(): diff --git a/qt__pyqt__pyside__pyqode/pyqt5__QWebEnginePage__Client_async__multiprocessing__process.py b/qt__pyqt__pyside__pyqode/pyqt5__QWebEnginePage__Client_async__multiprocessing__process.py index b7c34ebdf..8013eed2f 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__QWebEnginePage__Client_async__multiprocessing__process.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__QWebEnginePage__Client_async__multiprocessing__process.py @@ -10,7 +10,7 @@ class Client(QWebEnginePage): - def __init__(self, urls): + def __init__(self, urls) -> None: self.app = QApplication([]) super().__init__() @@ -22,10 +22,10 @@ def __init__(self, urls): self.load(QUrl(url)) self.app.exec_() - def _on_load_finished(self): + def _on_load_finished(self) -> None: self.toHtml(self.callable) - def callable(self, html_str): + def callable(self, html_str) -> None: self.response_list.append(html_str) self.app.quit() diff --git a/qt__pyqt__pyside__pyqode/pyqt5__QWebEnginePage__Client_sync.py b/qt__pyqt__pyside__pyqode/pyqt5__QWebEnginePage__Client_sync.py index fa80da608..9a6d08c47 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__QWebEnginePage__Client_sync.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__QWebEnginePage__Client_sync.py @@ -10,7 +10,7 @@ class Client(QWebEnginePage): - def __init__(self, urls): + def __init__(self, urls) -> None: self.app = QApplication([]) super().__init__() @@ -22,10 +22,10 @@ def __init__(self, urls): self.load(QUrl(url)) self.app.exec_() - def _on_load_finished(self): + def _on_load_finished(self) -> None: self.toHtml(self.callable) - def callable(self, html_str): + def callable(self, html_str) -> None: self.response_list.append(html_str) self.app.quit() diff --git a/qt__pyqt__pyside__pyqode/pyqt5__QWebEngineView__get_access_token__from_append_application.py b/qt__pyqt__pyside__pyqode/pyqt5__QWebEngineView__get_access_token__from_append_application.py index b8a3b3325..5e89eeb12 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__QWebEngineView__get_access_token__from_append_application.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__QWebEngineView__get_access_token__from_append_application.py @@ -11,11 +11,11 @@ from PyQt5.QtWidgets import QApplication -def authorize(token): +def authorize(token) -> None: print(f"token: {token}") -def url_changed(url): +def url_changed(url) -> None: url = url.toString() print(f"url_changed: {url}") diff --git a/qt__pyqt__pyside__pyqode/pyqt5__WelcomeWidget.py b/qt__pyqt__pyside__pyqode/pyqt5__WelcomeWidget.py index 8f164256a..65350b21e 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__WelcomeWidget.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__WelcomeWidget.py @@ -11,7 +11,7 @@ # SOURCE: https://ru.stackoverflow.com/a/860257/201445 class WelcomeWidget(QDialog): - def __init__(self, text="Welcome my app", duration=3000): + def __init__(self, text="Welcome my app", duration=3000) -> None: super().__init__() self.setWindowFlags(Qt.FramelessWindowHint | Qt.Tool | Qt.WindowStaysOnTopHint) @@ -41,13 +41,13 @@ def __init__(self, text="Welcome my app", duration=3000): self.timer.setInterval(duration) self.timer.timeout.connect(self.close) - def exec(self): + def exec(self) -> None: self.timer.start() self.animation.start() super().exec() - def paintEvent(self, event: QPaintEvent): + def paintEvent(self, event: QPaintEvent) -> None: painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) painter.setBrush(QColor(0, 0, 0, 180)) @@ -62,7 +62,7 @@ def paintEvent(self, event: QPaintEvent): WelcomeWidget("Еще, раз! Привет!", duration=1500).exec() class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("MAIN WINDOW") diff --git a/qt__pyqt__pyside__pyqode/pyqt5__ask_before_close.py b/qt__pyqt__pyside__pyqode/pyqt5__ask_before_close.py index 3cb8c3b4f..320bd478e 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__ask_before_close.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__ask_before_close.py @@ -8,7 +8,7 @@ class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() button = QPushButton("Close") @@ -19,7 +19,7 @@ def __init__(self): self.setLayout(layout) - def closeEvent(self, event): + def closeEvent(self, event) -> None: reply = QMessageBox.question( self, "Quit", diff --git a/qt__pyqt__pyside__pyqode/pyqt5__clicked_label.py b/qt__pyqt__pyside__pyqode/pyqt5__clicked_label.py index d29e45f93..9d63666fd 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__clicked_label.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__clicked_label.py @@ -10,7 +10,7 @@ class ClickedLabel(QLabel): clicked = pyqtSignal() - def mouseReleaseEvent(self, e): + def mouseReleaseEvent(self, e) -> None: super().mouseReleaseEvent(e) self.clicked.emit() diff --git a/qt__pyqt__pyside__pyqode/pyqt5__dog_bang__mp3__qmediaplayer/main.py b/qt__pyqt__pyside__pyqode/pyqt5__dog_bang__mp3__qmediaplayer/main.py index 9eaea2bf1..363905800 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__dog_bang__mp3__qmediaplayer/main.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__dog_bang__mp3__qmediaplayer/main.py @@ -11,7 +11,7 @@ from PyQt5 import Qt -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -27,7 +27,7 @@ class Widget(Qt.QLabel): dog_sound_1 = "dog_sound_1.mp3" dog_sound_2 = "dog_sound_2.mp3" - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Dog Bang!") @@ -35,7 +35,7 @@ def __init__(self): self.setPixmap(Qt.QPixmap("dog.png")) self.player = Qt.QMediaPlayer() - def mouseReleaseEvent(self, event: Qt.QMouseEvent): + def mouseReleaseEvent(self, event: Qt.QMouseEvent) -> None: super().mouseReleaseEvent(event) file_name = self.dog_sound_1 if event.button() == Qt.Qt.LeftButton else self.dog_sound_2 diff --git a/qt__pyqt__pyside__pyqode/pyqt5__exchange_rate_and_weather__use_QThread/main.py b/qt__pyqt__pyside__pyqode/pyqt5__exchange_rate_and_weather__use_QThread/main.py index 82abc37be..f61b1d031 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__exchange_rate_and_weather__use_QThread/main.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__exchange_rate_and_weather__use_QThread/main.py @@ -13,7 +13,7 @@ from utils import exchange_rate, get_weather -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -28,12 +28,12 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class ThreadExchangeRate(Qt.QThread): about_exchange_rate = Qt.pyqtSignal(str) - def __init__(self, parent, currency): + def __init__(self, parent, currency) -> None: super().__init__(parent) self.currency = currency - def run(self): + def run(self) -> None: while True: print("Start ThreadExchangeRate.currency: " + self.currency) @@ -48,12 +48,12 @@ def run(self): class ThreadGetWeather(Qt.QThread): about_weather = Qt.pyqtSignal(str) - def __init__(self, parent, city): + def __init__(self, parent, city) -> None: super().__init__(parent) self.city = city - def run(self): + def run(self) -> None: while True: print("Start ThreadGetWeather.city: " + self.city) @@ -66,7 +66,7 @@ def run(self): class Window(Qt.QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Widget-Info: exchange rate and weather") diff --git a/qt__pyqt__pyside__pyqode/pyqt5__exchange_rate_and_weather__use_QThread/utils.py b/qt__pyqt__pyside__pyqode/pyqt5__exchange_rate_and_weather__use_QThread/utils.py index 54fdfb237..6edc92d16 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__exchange_rate_and_weather__use_QThread/utils.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__exchange_rate_and_weather__use_QThread/utils.py @@ -86,7 +86,7 @@ def exchange_rate(currency, date_req=None): } -def get_weather(city): +def get_weather(city) -> str: """ Функция возвращает описание погоды указанного населенный пункт. diff --git a/qt__pyqt__pyside__pyqode/pyqt5__move_child_on_center__parent_widget.py b/qt__pyqt__pyside__pyqode/pyqt5__move_child_on_center__parent_widget.py index b2a503b22..0c648eaec 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__move_child_on_center__parent_widget.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__move_child_on_center__parent_widget.py @@ -8,7 +8,7 @@ class MainWindow(Qt.QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.widget = Qt.QWidget() @@ -18,7 +18,7 @@ def __init__(self): self.setCentralWidget(button) - def show_and_move(self): + def show_and_move(self) -> None: self.widget.hide() self.widget.move(self.geometry().center() - self.widget.rect().center()) diff --git a/qt__pyqt__pyside__pyqode/pyqt5__one_signal_slot_for_many_buttons__QButtonGroup.py b/qt__pyqt__pyside__pyqode/pyqt5__one_signal_slot_for_many_buttons__QButtonGroup.py index 2b9103c46..74d9e9a7e 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__one_signal_slot_for_many_buttons__QButtonGroup.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__one_signal_slot_for_many_buttons__QButtonGroup.py @@ -7,7 +7,7 @@ from PyQt5.Qt import QApplication, QGroupBox, QCheckBox, QButtonGroup, QGridLayout -def _on_button_clicked(button: QCheckBox): +def _on_button_clicked(button: QCheckBox) -> None: print(button, button.text(), button.isChecked()) diff --git a/qt__pyqt__pyside__pyqode/pyqt5__one_signal_slot_for_many_buttons__findChildren.py b/qt__pyqt__pyside__pyqode/pyqt5__one_signal_slot_for_many_buttons__findChildren.py index 43bdd3f5a..c40067823 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__one_signal_slot_for_many_buttons__findChildren.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__one_signal_slot_for_many_buttons__findChildren.py @@ -7,7 +7,7 @@ from PyQt5.Qt import QApplication, QGroupBox, QCheckBox, QGridLayout, QObject -def _on_button_clicked(checked: bool): +def _on_button_clicked(checked: bool) -> None: # Небольшой костыль для получения объекта, который отправил сигнал # Костыль не нужен будет если метод будет внутри виджета -- button = self.sender() button = QObject().sender() diff --git a/qt__pyqt__pyside__pyqode/pyqt5__qtextedit_with_line_numbers.py b/qt__pyqt__pyside__pyqode/pyqt5__qtextedit_with_line_numbers.py index 030d833c0..8ff0206bc 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__qtextedit_with_line_numbers.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__qtextedit_with_line_numbers.py @@ -8,7 +8,7 @@ class LineNumberArea(Qt.QWidget): - def __init__(self, editor): + def __init__(self, editor) -> None: super().__init__(editor) self.editor = editor @@ -16,12 +16,12 @@ def __init__(self, editor): def sizeHint(self): return Qt.QSize(self.editor.line_number_area_width(), 0) - def paintEvent(self, event): + def paintEvent(self, event) -> None: self.editor.line_number_area_paint_event(event) class CodeEditor(Qt.QPlainTextEdit): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setStyleSheet( @@ -52,10 +52,10 @@ def line_number_area_width(self): space = 3 + self.fontMetrics().width("9") * digits return space - def update_line_number_area_width(self): + def update_line_number_area_width(self) -> None: self.setViewportMargins(self.line_number_area_width(), 0, 0, 0) - def update_line_number_area(self, rect, dy): + def update_line_number_area(self, rect, dy) -> None: if dy: self.line_number_area.scroll(0, dy) else: @@ -66,7 +66,7 @@ def update_line_number_area(self, rect, dy): if rect.contains(self.viewport().rect()): self.update_line_number_area_width() - def resizeEvent(self, event): + def resizeEvent(self, event) -> None: super().resizeEvent(event) cr = self.contentsRect() @@ -74,7 +74,7 @@ def resizeEvent(self, event): Qt.QRect(cr.left(), cr.top(), self.line_number_area_width(), cr.height()) ) - def line_number_area_paint_event(self, event): + def line_number_area_paint_event(self, event) -> None: painter = Qt.QPainter(self.line_number_area) painter.fillRect(event.rect(), Qt.Qt.lightGray) @@ -103,7 +103,7 @@ def line_number_area_paint_event(self, event): bottom = top + self.blockBoundingRect(block).height() block_number += 1 - def highlight_current_line(self): + def highlight_current_line(self) -> None: extra_selections = [] if not self.isReadOnly(): diff --git a/qt__pyqt__pyside__pyqode/pyqt5__reverse_color.py b/qt__pyqt__pyside__pyqode/pyqt5__reverse_color.py index f125f7c6e..a149f276c 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__reverse_color.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__reverse_color.py @@ -15,7 +15,7 @@ class MainWindow(QWidget): - def __init__(self, parent=None): + def __init__(self, parent=None) -> None: super().__init__(parent) self.button = QPushButton("Color") @@ -26,7 +26,7 @@ def __init__(self, parent=None): main_layout.addWidget(self.button) self.setLayout(main_layout) - def choose_color(self): + def choose_color(self) -> None: dialog = QColorDialog() if not dialog.exec(): return diff --git a/qt__pyqt__pyside__pyqode/pyqt5__simple_check_password__QLineEdit.py b/qt__pyqt__pyside__pyqode/pyqt5__simple_check_password__QLineEdit.py index f1f57e454..c8e860659 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__simple_check_password__QLineEdit.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__simple_check_password__QLineEdit.py @@ -8,7 +8,7 @@ class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Check password") @@ -26,7 +26,7 @@ def __init__(self): self.setLayout(main_layout) - def _on_check_password(self): + def _on_check_password(self) -> None: text = '{}' if self.le_target_password.text() == self.le_current_password.text(): diff --git a/qt__pyqt__pyside__pyqode/pyqt5__simple_check_password__with_animation_border_color__QLineEdit_QPropertyAnimation.py b/qt__pyqt__pyside__pyqode/pyqt5__simple_check_password__with_animation_border_color__QLineEdit_QPropertyAnimation.py index 13d8aa0ba..5b4600f97 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__simple_check_password__with_animation_border_color__QLineEdit_QPropertyAnimation.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__simple_check_password__with_animation_border_color__QLineEdit_QPropertyAnimation.py @@ -8,7 +8,7 @@ class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Animation check password") @@ -32,7 +32,7 @@ def __init__(self): self.animation.setStartValue(0.0) self.animation.setEndValue(1.0) - def set_border_color_password(self, value): + def set_border_color_password(self, value) -> None: color = "0, 100, 0" if self.is_correct_password() else "255, 0, 0" self.le_current_password.setStyleSheet( f"border: 3px solid rgba({color}, {value});" @@ -43,7 +43,7 @@ def set_border_color_password(self, value): def is_correct_password(self): return self.le_target_password.text() == self.le_current_password.text() - def _on_check_password(self): + def _on_check_password(self) -> None: text = '{}' if self.is_correct_password(): diff --git a/qt__pyqt__pyside__pyqode/pyqt5__simple_check_password__with_border_color__QLineEdit.py b/qt__pyqt__pyside__pyqode/pyqt5__simple_check_password__with_border_color__QLineEdit.py index 2b005b25c..2c6b53604 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__simple_check_password__with_border_color__QLineEdit.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__simple_check_password__with_border_color__QLineEdit.py @@ -8,7 +8,7 @@ class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Check password") @@ -26,7 +26,7 @@ def __init__(self): self.setLayout(main_layout) - def _on_check_password(self): + def _on_check_password(self) -> None: text = '{}' if self.le_target_password.text() == self.le_current_password.text(): diff --git a/qt__pyqt__pyside__pyqode/pyqt5__square_change_in_size__resizeEvent.py b/qt__pyqt__pyside__pyqode/pyqt5__square_change_in_size__resizeEvent.py index b3df97c10..1793301f8 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__square_change_in_size__resizeEvent.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__square_change_in_size__resizeEvent.py @@ -8,7 +8,7 @@ class Widget(Qt.QWidget): - def resizeEvent(self, event: Qt.QResizeEvent): + def resizeEvent(self, event: Qt.QResizeEvent) -> None: width, height = event.size().width(), event.size().height() width = height = max(width, height) self.resize(width, height) diff --git a/qt__pyqt__pyside__pyqode/pyqt5__translate__with__difflib__similar_words/main.py b/qt__pyqt__pyside__pyqode/pyqt5__translate__with__difflib__similar_words/main.py index 880e52650..074a8aa13 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__translate__with__difflib__similar_words/main.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__translate__with__difflib__similar_words/main.py @@ -22,7 +22,7 @@ # Для отлова исключений -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -35,7 +35,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class MainWindow(QMainWindow): - def __init__(self, parent=None): + def __init__(self, parent=None) -> None: super().__init__(parent) self.data = json.load(open("data.json", encoding="utf-8")) @@ -56,7 +56,7 @@ def __init__(self, parent=None): self.setCentralWidget(central_widget) - def _check(self): + def _check(self) -> None: word_user = self.input_word.text() output = self._retrive_definition(word_user) diff --git a/qt__pyqt__pyside__pyqode/pyqt5__very_simple_browser__QWebEngineView.py b/qt__pyqt__pyside__pyqode/pyqt5__very_simple_browser__QWebEngineView.py index bda269bd1..2c7c0a1ed 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__very_simple_browser__QWebEngineView.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__very_simple_browser__QWebEngineView.py @@ -17,7 +17,7 @@ class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("...") @@ -41,10 +41,10 @@ def __init__(self): self.setLayout(main_layout) - def _on_load_url(self): + def _on_load_url(self) -> None: self.view.load(QUrl(self.url_le.text())) - def _on_url_changed(self, url: QUrl): + def _on_url_changed(self, url: QUrl) -> None: self.url_le.setText(url.toString()) diff --git a/qt__pyqt__pyside__pyqode/pyqt5__winapi__get_color_window_frame_border.py b/qt__pyqt__pyside__pyqode/pyqt5__winapi__get_color_window_frame_border.py index 6d29b1555..286334dfe 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__winapi__get_color_window_frame_border.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__winapi__get_color_window_frame_border.py @@ -39,7 +39,7 @@ def getWindowFrameColor(): if __name__ == "__main__": app = Qt.QApplication([]) - def get_color(): + def get_color() -> None: color = getWindowFrameColor() button.setStyleSheet("background-color: " + color.name()) diff --git a/qt__pyqt__pyside__pyqode/pyqt5__winapi__get_color_window_header__use_screenshot.py b/qt__pyqt__pyside__pyqode/pyqt5__winapi__get_color_window_header__use_screenshot.py index 25f71942a..a8ea12e6a 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5__winapi__get_color_window_header__use_screenshot.py +++ b/qt__pyqt__pyside__pyqode/pyqt5__winapi__get_color_window_header__use_screenshot.py @@ -13,7 +13,7 @@ # NOTE: для отладки # label = Qt.QLabel() - def get_color(): + def get_color() -> None: rect = button.rect() indent = 5 diff --git a/qt__pyqt__pyside__pyqode/pyqt5_drag_and_drop.py b/qt__pyqt__pyside__pyqode/pyqt5_drag_and_drop.py index df4e46ddc..576e588b6 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5_drag_and_drop.py +++ b/qt__pyqt__pyside__pyqode/pyqt5_drag_and_drop.py @@ -15,7 +15,7 @@ class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Drag & Drop") @@ -38,10 +38,10 @@ def __init__(self): self._update_states() - def _update_states(self): + def _update_states(self) -> None: self.label_total_files.setText(f"Files: {self.list_files.count()}") - def dragEnterEvent(self, event): + def dragEnterEvent(self, event) -> None: # Тут выполняются проверки и дается (или нет) разрешение на Drop mime = event.mimeData() diff --git a/qt__pyqt__pyside__pyqode/pyqt5_drag_and_drop__with_QFileSystemModel.py b/qt__pyqt__pyside__pyqode/pyqt5_drag_and_drop__with_QFileSystemModel.py index a0265567c..c81193e1c 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5_drag_and_drop__with_QFileSystemModel.py +++ b/qt__pyqt__pyside__pyqode/pyqt5_drag_and_drop__with_QFileSystemModel.py @@ -18,7 +18,7 @@ class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Drag & Drop") @@ -52,10 +52,10 @@ def __init__(self): self._update_states() - def _update_states(self): + def _update_states(self) -> None: self.label_total_files.setText(f"Files: {self.list_files.count()}") - def dragEnterEvent(self, event): + def dragEnterEvent(self, event) -> None: # Тут выполняются проверки и дается (или нет) разрешение на Drop mime = event.mimeData() diff --git a/qt__pyqt__pyside__pyqode/pyqt5_paintEvent_example.py b/qt__pyqt__pyside__pyqode/pyqt5_paintEvent_example.py index 64969e208..abb263389 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5_paintEvent_example.py +++ b/qt__pyqt__pyside__pyqode/pyqt5_paintEvent_example.py @@ -12,7 +12,7 @@ from PyQt5.QtCore import Qt -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -25,29 +25,29 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.pos = None self.pos_list = [] - def mousePressEvent(self, event: QMouseEvent): + def mousePressEvent(self, event: QMouseEvent) -> None: self.pos = event.pos() self.update() - def mouseMoveEvent(self, event: QMouseEvent): + def mouseMoveEvent(self, event: QMouseEvent) -> None: self.pos = event.pos() self.update() - def mouseReleaseEvent(self, event: QMouseEvent): + def mouseReleaseEvent(self, event: QMouseEvent) -> None: self.pos_list.append(self.pos) self.pos = None self.update() - def paintEvent(self, event: QPaintEvent): + def paintEvent(self, event: QPaintEvent) -> None: if not self.pos and not self.pos_list: return diff --git a/qt__pyqt__pyside__pyqode/pyqt5_paintEvent_example_with_undo_redo__QUndoStack.py b/qt__pyqt__pyside__pyqode/pyqt5_paintEvent_example_with_undo_redo__QUndoStack.py index 64fb39941..d8eaa8acc 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5_paintEvent_example_with_undo_redo__QUndoStack.py +++ b/qt__pyqt__pyside__pyqode/pyqt5_paintEvent_example_with_undo_redo__QUndoStack.py @@ -18,7 +18,7 @@ from PyQt5.QtCore import Qt, QRectF -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -55,7 +55,7 @@ def redo(self): class Widget(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.resize(600, 400) @@ -82,16 +82,16 @@ def __init__(self): self.end_pos = None self.is_pressed = False - def can_undo_changed(self, enabled): + def can_undo_changed(self, enabled) -> None: self.actionUndo.setEnabled(enabled) - def can_redo_changed(self, enabled): + def can_redo_changed(self, enabled) -> None: self.actionRedo.setEnabled(enabled) - def make_undo_command(self): + def make_undo_command(self) -> None: self.mUndoStack.push(UndoCommand(self)) - def draw(self, canvas): + def draw(self, canvas) -> None: painter = QPainter(canvas) painter.setRenderHint(QPainter.HighQualityAntialiasing) painter.setPen(Qt.NoPen) @@ -99,23 +99,23 @@ def draw(self, canvas): painter.drawEllipse(QRectF(self.start_pos, self.end_pos)) - def paintEvent(self, event): + def paintEvent(self, event) -> None: painter = QPainter(self) painter.drawImage(self.image.rect(), self.image) if self.is_pressed: self.draw(self) - def mousePressEvent(self, event): + def mousePressEvent(self, event) -> None: self.is_pressed = True self.start_pos = event.pos() - def mouseMoveEvent(self, event): + def mouseMoveEvent(self, event) -> None: if event.buttons() & Qt.LeftButton: self.end_pos = event.pos() self.update() - def mouseReleaseEvent(self, event): + def mouseReleaseEvent(self, event) -> None: self.is_pressed = False self.end_pos = event.pos() diff --git a/qt__pyqt__pyside__pyqode/pyqt5_simple_check_password.py b/qt__pyqt__pyside__pyqode/pyqt5_simple_check_password.py index f8df632a1..221b69040 100644 --- a/qt__pyqt__pyside__pyqode/pyqt5_simple_check_password.py +++ b/qt__pyqt__pyside__pyqode/pyqt5_simple_check_password.py @@ -16,7 +16,7 @@ class Example(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Example") diff --git a/qt__pyqt__pyside__pyqode/pyqt__QGraphicsScene__draw_selection_rect.py b/qt__pyqt__pyside__pyqode/pyqt__QGraphicsScene__draw_selection_rect.py index e018bbcd5..1a41da0cd 100644 --- a/qt__pyqt__pyside__pyqode/pyqt__QGraphicsScene__draw_selection_rect.py +++ b/qt__pyqt__pyside__pyqode/pyqt__QGraphicsScene__draw_selection_rect.py @@ -16,7 +16,7 @@ class GraphicsScene(QGraphicsScene): - def __init__(self): + def __init__(self) -> None: super().__init__() self._pos = QPointF() @@ -25,7 +25,7 @@ def __init__(self): # Полупрозрачный цвет self._item_color = QColor(0, 0, 255, 128) - def mousePressEvent(self, event): + def mousePressEvent(self, event) -> None: super().mousePressEvent(event) self._pos = event.scenePos() @@ -36,14 +36,14 @@ def mousePressEvent(self, event): self.addItem(self._current_item) self._current_item.setRect(QRectF(self._pos, self._pos)) - def mouseMoveEvent(self, event): + def mouseMoveEvent(self, event) -> None: super().mouseMoveEvent(event) if self._current_item: rect = QRectF(self._pos, event.scenePos()).normalized() self._current_item.setRect(rect) - def mouseReleaseEvent(self, event): + def mouseReleaseEvent(self, event) -> None: super().mouseReleaseEvent(event) # Убираем после отпускания кнопки мыши @@ -52,7 +52,7 @@ def mouseReleaseEvent(self, event): class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() scene_rect = QRectF(0, 0, 500, 500) diff --git a/qt__pyqt__pyside__pyqode/pyqt__QListWidget__Flow.py b/qt__pyqt__pyside__pyqode/pyqt__QListWidget__Flow.py index c009d1384..deeab48ff 100644 --- a/qt__pyqt__pyside__pyqode/pyqt__QListWidget__Flow.py +++ b/qt__pyqt__pyside__pyqode/pyqt__QListWidget__Flow.py @@ -8,14 +8,14 @@ class WrapListWidget(QListWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setFlow(QListView.LeftToRight) self.setWrapping(True) self.setUniformItemSizes(True) - def resizeEvent(self, event): + def resizeEvent(self, event) -> None: super().resizeEvent(event) self.setWrapping(self.isWrapping()) diff --git a/qt__pyqt__pyside__pyqode/pyqt__QPainter__FlowWidget.py b/qt__pyqt__pyside__pyqode/pyqt__QPainter__FlowWidget.py index 3e3206a20..caa468379 100644 --- a/qt__pyqt__pyside__pyqode/pyqt__QPainter__FlowWidget.py +++ b/qt__pyqt__pyside__pyqode/pyqt__QPainter__FlowWidget.py @@ -10,7 +10,7 @@ from PyQt5.Qt import * -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -23,7 +23,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class FlowWidget(QWidget): - def __init__(self, length=25, cell_size=50, cell_font=QFont("Arial", 10)): + def __init__(self, length=25, cell_size=50, cell_font=QFont("Arial", 10)) -> None: super().__init__() self.cell_size = cell_size @@ -44,17 +44,17 @@ def minimumSizeHint(self): def minimumSize(self): return self.minimumSizeHint() - def showEvent(self, event): + def showEvent(self, event) -> None: super().showEvent(event) self.updateGeometry() - def resizeEvent(self, event): + def resizeEvent(self, event) -> None: super().resizeEvent(event) self.column_count = self.width() // self.cell_size - def paintEvent(self, event: QPaintEvent): + def paintEvent(self, event: QPaintEvent) -> None: painter = QPainter(self) painter.setPen(Qt.black) painter.setBrush(Qt.white) diff --git a/qt__pyqt__pyside__pyqode/pyqt__QPainter__draw_table.py b/qt__pyqt__pyside__pyqode/pyqt__QPainter__draw_table.py index 491bff877..ce2bc751e 100644 --- a/qt__pyqt__pyside__pyqode/pyqt__QPainter__draw_table.py +++ b/qt__pyqt__pyside__pyqode/pyqt__QPainter__draw_table.py @@ -9,7 +9,7 @@ class MatrixWidget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Widget") @@ -30,7 +30,7 @@ def __init__(self): self.setMouseTracking(True) - def resizeEvent(self, event): + def resizeEvent(self, event) -> None: super().resizeEvent(event) w, h = event.size().width(), event.size().height() @@ -38,7 +38,7 @@ def resizeEvent(self, event): self.cell_size = min_size // self.matrix_size - def mouseMoveEvent(self, event): + def mouseMoveEvent(self, event) -> None: super().mouseMoveEvent(event) pos = event.pos() @@ -48,7 +48,7 @@ def mouseMoveEvent(self, event): self.update() - def paintEvent(self, event): + def paintEvent(self, event) -> None: painter = QPainter(self) # Если индекс ячейки под курсором валидный diff --git a/qt__pyqt__pyside__pyqode/pyqt__QPainter__dynamic_draw_emoji_on_img/main.py b/qt__pyqt__pyside__pyqode/pyqt__QPainter__dynamic_draw_emoji_on_img/main.py index 7e0c0ac69..15595d1b8 100644 --- a/qt__pyqt__pyside__pyqode/pyqt__QPainter__dynamic_draw_emoji_on_img/main.py +++ b/qt__pyqt__pyside__pyqode/pyqt__QPainter__dynamic_draw_emoji_on_img/main.py @@ -25,7 +25,7 @@ # Для отлова всех исключений, которые в слотах Qt могут "затеряться" и привести к тихому падению -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -41,7 +41,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): FILE_NAME_IMAGE: str = str(DIR / "favicon.png") -def draw_text_to_bottom_right(img: QPixmap, text: str, scale_text_from_img: float = 0.5): +def draw_text_to_bottom_right(img: QPixmap, text: str, scale_text_from_img: float = 0.5) -> None: p = QPainter(img) factor = (img.width() * scale_text_from_img) / p.fontMetrics().width(text) @@ -67,7 +67,7 @@ def draw_text_to_bottom_right(img: QPixmap, text: str, scale_text_from_img: floa class Window(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.img_view = QLabel() @@ -89,11 +89,11 @@ def __init__(self): main_layout.addWidget(self.img_view) main_layout.addLayout(buttons_layout) - def _update_img_view(self, img: QPixmap): + def _update_img_view(self, img: QPixmap) -> None: self.img_view.setPixmap(img) self.img_view.setMinimumSize(img.size() * 1.1) - def _on_button_clicked(self, button: QAbstractButton): + def _on_button_clicked(self, button: QAbstractButton) -> None: text = button.text() img = QPixmap(FILE_NAME_IMAGE) draw_text_to_bottom_right(img, text) diff --git a/qt__pyqt__pyside__pyqode/pyqt__UpdaterMessageExample__QThread.py b/qt__pyqt__pyside__pyqode/pyqt__UpdaterMessageExample__QThread.py index 4752b7f3f..6197622df 100644 --- a/qt__pyqt__pyside__pyqode/pyqt__UpdaterMessageExample__QThread.py +++ b/qt__pyqt__pyside__pyqode/pyqt__UpdaterMessageExample__QThread.py @@ -19,7 +19,7 @@ class AboutUpdateThread(QThread): about_update = pyqtSignal(str) - def run(self): + def run(self) -> None: while True: # Делаем какие-то действия и проверки, и вызываем сигнал about_update, # чтобы сообщить о новой версии @@ -33,7 +33,7 @@ def run(self): class Window(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.log = QPlainTextEdit() @@ -48,10 +48,10 @@ def __init__(self): self.thread.about_update.connect(self.on_about_update) self.thread.start() - def add_log(self, text): + def add_log(self, text) -> None: self.log.appendPlainText(text) - def on_about_update(self, text): + def on_about_update(self, text) -> None: self.add_log(f"Пришло обновление '{text}'") mb = QMessageBox() diff --git a/qt__pyqt__pyside__pyqode/pyqt__animation_framework__hello_world.py b/qt__pyqt__pyside__pyqode/pyqt__animation_framework__hello_world.py index 3513e98c7..c3432d640 100644 --- a/qt__pyqt__pyside__pyqode/pyqt__animation_framework__hello_world.py +++ b/qt__pyqt__pyside__pyqode/pyqt__animation_framework__hello_world.py @@ -11,7 +11,7 @@ class MainWindow(Qt.QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.label = Qt.QLabel("Animated label", parent=self) @@ -24,7 +24,7 @@ def __init__(self): self.animation.setStartValue(Qt.QRect(0, 0, 100, 30)) self.animation.setEndValue(Qt.QRect(250, 250, 100, 30)) - def _on_click(self): + def _on_click(self) -> None: self.animation.start() diff --git a/qt__pyqt__pyside__pyqode/pyqt__custom_title_bar__FramelessWindow/FramelessWindow.py b/qt__pyqt__pyside__pyqode/pyqt__custom_title_bar__FramelessWindow/FramelessWindow.py index f311eabae..e1c2d494e 100644 --- a/qt__pyqt__pyside__pyqode/pyqt__custom_title_bar__FramelessWindow/FramelessWindow.py +++ b/qt__pyqt__pyside__pyqode/pyqt__custom_title_bar__FramelessWindow/FramelessWindow.py @@ -48,12 +48,12 @@ # SOURCE: https://github.com/gil9red/SimplePyScripts/blob/29b1f87e4381c398d906261b98c2ecf8c9933646/qt__pyqt__pyside__pyqode/ElidedLabel.py class ElidedLabel(QLabel): - def __init__(self, *args, **kwargs): + def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self.setMinimumWidth(50) - def paintEvent(self, event): + def paintEvent(self, event) -> None: painter = QPainter(self) metrics = QFontMetrics(self.font()) @@ -139,7 +139,7 @@ class TitleBar(QWidget): # Сигнал перемещения окна aboutWindowMovedDelta = pyqtSignal(QPoint) - def __init__(self, *args, **kwargs): + def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) # Поддержка настройки фона qss @@ -237,12 +237,12 @@ def addWidget( widget: QWidget, width: int = Default.TITLE_HEIGHT, height: int = Default.TITLE_HEIGHT, - ): + ) -> None: self.layout_custom_widget.addWidget(widget) widget.setFixedSize(width, height) - def showMaximized(self): + def showMaximized(self) -> None: if self.button_maximum.text() == TitleBarButtonEnum.MAXIMUM.value: # Максимизировать self.button_maximum.setText(TitleBarButtonEnum.NORMAL.value) @@ -251,7 +251,7 @@ def showMaximized(self): self.button_maximum.setText(TitleBarButtonEnum.MAXIMUM.value) self.aboutWindowNormalized.emit() - def setHeight(self, height: int = Default.TITLE_HEIGHT): + def setHeight(self, height: int = Default.TITLE_HEIGHT) -> None: """Установка высоты строки заголовка""" self.setFixedHeight(height) @@ -259,40 +259,40 @@ def setHeight(self, height: int = Default.TITLE_HEIGHT): for button in self.findChildren(QAbstractButton): button.setFixedSize(height, height) - def setTitle(self, title: str): + def setTitle(self, title: str) -> None: """Установить заголовок""" self.titleLabel.setText(title) - def setIcon(self, icon: QIcon): + def setIcon(self, icon: QIcon) -> None: """Настройки значкa""" self.iconLabel.setPixmap(icon.pixmap(self.iconSize, self.iconSize)) - def setIconSize(self, size: int): + def setIconSize(self, size: int) -> None: """Установить размер значка""" self.iconSize = size - def enterEvent(self, _): + def enterEvent(self, _) -> None: self.setCursor(Qt.ArrowCursor) - def mouseDoubleClickEvent(self, _): + def mouseDoubleClickEvent(self, _) -> None: self.showMaximized() - def mousePressEvent(self, event: QMouseEvent): + def mousePressEvent(self, event: QMouseEvent) -> None: """Событие клика мыши""" if event.button() == Qt.LeftButton: self._old_pos = event.pos() event.accept() - def mouseReleaseEvent(self, event: QMouseEvent): + def mouseReleaseEvent(self, event: QMouseEvent) -> None: """Событие отказов мыши""" self._old_pos = None event.accept() - def mouseMoveEvent(self, event: QMouseEvent): + def mouseMoveEvent(self, event: QMouseEvent) -> None: if event.buttons() == Qt.LeftButton and self._old_pos: self.aboutWindowMovedDelta.emit(event.pos() - self._old_pos) @@ -313,7 +313,7 @@ class DirectionEnum(Enum): class FramelessWindow(QWidget): - def __init__(self, *args, **kwargs): + def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self.setStyleSheet(STYLE_SHEET) @@ -360,17 +360,17 @@ def __init__(self, *args, **kwargs): self.windowTitleChanged.connect(self.titleBar.setTitle) self.windowIconChanged.connect(self.titleBar.setIcon) - def setTitleBarHeight(self, height: int = Default.TITLE_HEIGHT): + def setTitleBarHeight(self, height: int = Default.TITLE_HEIGHT) -> None: """Установка высоты строки заголовка""" self.titleBar.setHeight(height) - def setIconSize(self, size: int): + def setIconSize(self, size: int) -> None: """Установка размера значка""" self.titleBar.setIconSize(size) - def setWidget(self, widget: QWidget): + def setWidget(self, widget: QWidget) -> None: """Настройте свои собственные элементы управления""" self._widget = widget @@ -383,11 +383,11 @@ def setWidget(self, widget: QWidget): self._widget.installEventFilter(self) self.layout().addWidget(self._widget) - def set_pinned(self, flag: bool): + def set_pinned(self, flag: bool) -> None: self.setWindowFlag(Qt.WindowStaysOnTopHint, flag) self.show() - def delta_move(self, delta_pos: QPoint): + def delta_move(self, delta_pos: QPoint) -> None: if ( self.windowState() == Qt.WindowMaximized or self.windowState() == Qt.WindowFullScreen @@ -398,7 +398,7 @@ def delta_move(self, delta_pos: QPoint): # Для перемещения окна self.move(self.pos() + delta_pos) - def showMaximized(self): + def showMaximized(self) -> None: """ Чтобы максимизировать, удалите верхнюю, нижнюю, левую и правую границы. Если вы не удалите его, в пограничной области будут пробелы. @@ -408,7 +408,7 @@ def showMaximized(self): self.layout().setContentsMargins(0, 0, 0, 0) - def showNormal(self): + def showNormal(self) -> None: """ Восстановить, сохранить верхнюю и нижнюю левую и правую границы, иначе нет границы, которую нельзя отрегулировать @@ -434,7 +434,7 @@ def eventFilter(self, obj: QObject, event: QEvent): return super().eventFilter(obj, event) - def paintEvent(self, event: QPaintEvent): + def paintEvent(self, event: QPaintEvent) -> None: """ Поскольку это полностью прозрачное фоновое окно, жесткая для поиска граница с прозрачностью 1 рисуется в событии перерисовывания, чтобы отрегулировать размер окна. @@ -452,7 +452,7 @@ def paintEvent(self, event: QPaintEvent): ) painter.drawRect(self.rect()) - def mousePressEvent(self, event: QMouseEvent): + def mousePressEvent(self, event: QMouseEvent) -> None: """Событие клика мыши""" super().mousePressEvent(event) @@ -460,7 +460,7 @@ def mousePressEvent(self, event: QMouseEvent): if event.button() == Qt.LeftButton: self._old_pos = event.pos() - def mouseReleaseEvent(self, event: QMouseEvent): + def mouseReleaseEvent(self, event: QMouseEvent) -> None: """Событие отказов мыши""" super().mouseReleaseEvent(event) @@ -468,7 +468,7 @@ def mouseReleaseEvent(self, event: QMouseEvent): self._old_pos = None self._direction = None - def mouseMoveEvent(self, event: QMouseEvent): + def mouseMoveEvent(self, event: QMouseEvent) -> None: """Событие перемещения мыши""" super().mouseMoveEvent(event) @@ -533,7 +533,7 @@ def mouseMoveEvent(self, event: QMouseEvent): # Курсор по умолчанию self.setCursor(Qt.ArrowCursor) - def _resizeWidget(self, pos: QPoint): + def _resizeWidget(self, pos: QPoint) -> None: """Отрегулируйте размер окна""" if self._direction is None: @@ -617,7 +617,7 @@ def _resizeWidget(self, pos: QPoint): from PyQt5.QtWidgets import QApplication, QTextEdit, QMessageBox - def log_uncaught_exceptions(ex_cls, ex, tb): + def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) diff --git a/qt__pyqt__pyside__pyqode/pyqt__design_patterns__composite__draw.py b/qt__pyqt__pyside__pyqode/pyqt__design_patterns__composite__draw.py index 0dc87ea03..759dbec22 100644 --- a/qt__pyqt__pyside__pyqode/pyqt__design_patterns__composite__draw.py +++ b/qt__pyqt__pyside__pyqode/pyqt__design_patterns__composite__draw.py @@ -16,7 +16,7 @@ from PyQt5.Qt import * -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -35,77 +35,77 @@ def draw(self, painter: QPainter): class CompositeGraphic(Graphic): - def __init__(self): + def __init__(self) -> None: self.__child_graphics: list[Graphic] = [] - def draw(self, painter: QPainter): + def draw(self, painter: QPainter) -> None: for graphic in self.__child_graphics: graphic.draw(painter) # Adds the graphic to the composition - def add(self, graphic: Graphic): + def add(self, graphic: Graphic) -> None: if graphic in self.__child_graphics: return self.__child_graphics.append(graphic) # Removes the graphic from the composition - def remove(self, graphic: Graphic): + def remove(self, graphic: Graphic) -> None: self.__child_graphics.remove(graphic) class Ellipse(Graphic): - def __init__(self, x, y, rx, ry): + def __init__(self, x, y, rx, ry) -> None: self.x = x self.y = y self.rx = rx self.ry = ry - def draw(self, painter: QPainter): + def draw(self, painter: QPainter) -> None: painter.drawEllipse(self.x, self.y, self.rx, self.ry) class Point(Graphic): - def __init__(self, x, y): + def __init__(self, x, y) -> None: self.x = x self.y = y - def draw(self, painter: QPainter): + def draw(self, painter: QPainter) -> None: painter.drawPoint(self.x, self.y) class Rect(Graphic): - def __init__(self, x, y, w, h): + def __init__(self, x, y, w, h) -> None: self.x = x self.y = y self.w = w self.h = h - def draw(self, painter: QPainter): + def draw(self, painter: QPainter) -> None: painter.drawRect(self.x, self.y, self.w, self.h) class Line(Graphic): - def __init__(self, x1, y1, x2, y2): + def __init__(self, x1, y1, x2, y2) -> None: self.x1 = x1 self.y1 = y1 self.x2 = x2 self.y2 = y2 - def draw(self, painter: QPainter): + def draw(self, painter: QPainter) -> None: painter.drawLine(self.x1, self.y1, self.x2, self.y2) class CanvasWidget(QWidget): - def __init__(self, graphic: Graphic): + def __init__(self, graphic: Graphic) -> None: super().__init__() self.setWindowTitle("Canvas") self.graphic = graphic - def paintEvent(self, event): + def paintEvent(self, event) -> None: painter = QPainter(self) painter.setBrush(Qt.green) diff --git a/qt__pyqt__pyside__pyqode/pyqt__frameless__window_as_glass__win10__using_SetWindowCompositionAttribute.py b/qt__pyqt__pyside__pyqode/pyqt__frameless__window_as_glass__win10__using_SetWindowCompositionAttribute.py index 849783fc8..b5b53b791 100644 --- a/qt__pyqt__pyside__pyqode/pyqt__frameless__window_as_glass__win10__using_SetWindowCompositionAttribute.py +++ b/qt__pyqt__pyside__pyqode/pyqt__frameless__window_as_glass__win10__using_SetWindowCompositionAttribute.py @@ -41,7 +41,7 @@ class WINCOMPATTRDATA(Structure): class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowFlags(Qt.FramelessWindowHint) @@ -73,15 +73,15 @@ def __init__(self): self.setLayout(layout) - def mousePressEvent(self, event): + def mousePressEvent(self, event) -> None: if event.button() == Qt.LeftButton: self._old_pos = event.pos() - def mouseReleaseEvent(self, event): + def mouseReleaseEvent(self, event) -> None: if event.button() == Qt.LeftButton: self._old_pos = None - def mouseMoveEvent(self, event): + def mouseMoveEvent(self, event) -> None: if not self._old_pos: return diff --git a/qt__pyqt__pyside__pyqode/pyqt__frameless__window_as_glass__win7__using_DwmEnableBlurBehindWindow.py b/qt__pyqt__pyside__pyqode/pyqt__frameless__window_as_glass__win7__using_DwmEnableBlurBehindWindow.py index 83e4b160c..e31ec9696 100644 --- a/qt__pyqt__pyside__pyqode/pyqt__frameless__window_as_glass__win7__using_DwmEnableBlurBehindWindow.py +++ b/qt__pyqt__pyside__pyqode/pyqt__frameless__window_as_glass__win7__using_DwmEnableBlurBehindWindow.py @@ -55,7 +55,7 @@ def DWM_enable_blur_behind_window(widget): class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowFlags(Qt.FramelessWindowHint) @@ -71,15 +71,15 @@ def __init__(self): self.setLayout(layout) - def mousePressEvent(self, event): + def mousePressEvent(self, event) -> None: if event.button() == Qt.LeftButton: self._old_pos = event.pos() - def mouseReleaseEvent(self, event): + def mouseReleaseEvent(self, event) -> None: if event.button() == Qt.LeftButton: self._old_pos = None - def mouseMoveEvent(self, event): + def mouseMoveEvent(self, event) -> None: if not self._old_pos: return diff --git a/qt__pyqt__pyside__pyqode/pyqt__frameless__window_as_glass__with_custom_frame_color__win7__using_DwmEnableBlurBehindWindow.py b/qt__pyqt__pyside__pyqode/pyqt__frameless__window_as_glass__with_custom_frame_color__win7__using_DwmEnableBlurBehindWindow.py index 8b6883832..3aad22167 100644 --- a/qt__pyqt__pyside__pyqode/pyqt__frameless__window_as_glass__with_custom_frame_color__win7__using_DwmEnableBlurBehindWindow.py +++ b/qt__pyqt__pyside__pyqode/pyqt__frameless__window_as_glass__with_custom_frame_color__win7__using_DwmEnableBlurBehindWindow.py @@ -57,7 +57,7 @@ def DWM_enable_blur_behind_window(widget): class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowFlags(Qt.FramelessWindowHint) @@ -73,22 +73,22 @@ def __init__(self): self.setLayout(layout) - def mousePressEvent(self, event): + def mousePressEvent(self, event) -> None: if event.button() == Qt.LeftButton: self._old_pos = event.pos() - def mouseReleaseEvent(self, event): + def mouseReleaseEvent(self, event) -> None: if event.button() == Qt.LeftButton: self._old_pos = None - def mouseMoveEvent(self, event): + def mouseMoveEvent(self, event) -> None: if not self._old_pos: return delta = event.pos() - self._old_pos self.move(self.pos() + delta) - def paintEvent(self, event): + def paintEvent(self, event) -> None: painter = QPainter(self) painter.setBrush(Qt.transparent) diff --git a/qt__pyqt__pyside__pyqode/pyqt__frameless__window_as_glass__with_custom_frame_color__win7__using_DwmEnableBlurBehindWindow__with_custom_resizable.py b/qt__pyqt__pyside__pyqode/pyqt__frameless__window_as_glass__with_custom_frame_color__win7__using_DwmEnableBlurBehindWindow__with_custom_resizable.py index 8450b6c97..cfd74002f 100644 --- a/qt__pyqt__pyside__pyqode/pyqt__frameless__window_as_glass__with_custom_frame_color__win7__using_DwmEnableBlurBehindWindow__with_custom_resizable.py +++ b/qt__pyqt__pyside__pyqode/pyqt__frameless__window_as_glass__with_custom_frame_color__win7__using_DwmEnableBlurBehindWindow__with_custom_resizable.py @@ -61,7 +61,7 @@ def DWM_enable_blur_behind_window(widget): class Widget(ResizableFramelessWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() DWM_enable_blur_behind_window(self) @@ -74,7 +74,7 @@ def __init__(self): self.setLayout(layout) - def paintEvent(self, event): + def paintEvent(self, event) -> None: painter = QPainter(self) painter.setBrush(Qt.transparent) diff --git a/qt__pyqt__pyside__pyqode/pyqt__frameless_transparent_window_with_custom_mouse_move.py b/qt__pyqt__pyside__pyqode/pyqt__frameless_transparent_window_with_custom_mouse_move.py index 6930d77aa..4c7e14eda 100644 --- a/qt__pyqt__pyside__pyqode/pyqt__frameless_transparent_window_with_custom_mouse_move.py +++ b/qt__pyqt__pyside__pyqode/pyqt__frameless_transparent_window_with_custom_mouse_move.py @@ -10,7 +10,7 @@ class Example(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Example") @@ -21,22 +21,22 @@ def __init__(self): self._press = False self._old_pos = None - def mousePressEvent(self, event): + def mousePressEvent(self, event) -> None: if event.button() == Qt.LeftButton: self._old_pos = event.pos() - def mouseReleaseEvent(self, event): + def mouseReleaseEvent(self, event) -> None: if event.button() == Qt.LeftButton: self._old_pos = None - def mouseMoveEvent(self, event): + def mouseMoveEvent(self, event) -> None: if not self._old_pos: return delta = event.pos() - self._old_pos self.move(self.pos() + delta) - def paintEvent(self, event: QtGui.QPaintEvent): + def paintEvent(self, event: QtGui.QPaintEvent) -> None: painter = QtGui.QPainter(self) painter.setPen(QtGui.QPen(Qt.black, 50)) painter.drawRect(self.rect()) diff --git a/qt__pyqt__pyside__pyqode/pyqt__frameless_window_with_custom_frame_color.py b/qt__pyqt__pyside__pyqode/pyqt__frameless_window_with_custom_frame_color.py index e0a6f0b78..614714199 100644 --- a/qt__pyqt__pyside__pyqode/pyqt__frameless_window_with_custom_frame_color.py +++ b/qt__pyqt__pyside__pyqode/pyqt__frameless_window_with_custom_frame_color.py @@ -10,7 +10,7 @@ class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowFlags(Qt.FramelessWindowHint) @@ -29,22 +29,22 @@ def __init__(self): self.setLayout(layout) - def mousePressEvent(self, event): + def mousePressEvent(self, event) -> None: if event.button() == Qt.LeftButton: self._old_pos = event.pos() - def mouseReleaseEvent(self, event): + def mouseReleaseEvent(self, event) -> None: if event.button() == Qt.LeftButton: self._old_pos = None - def mouseMoveEvent(self, event): + def mouseMoveEvent(self, event) -> None: if not self._old_pos: return delta = event.pos() - self._old_pos self.move(self.pos() + delta) - def paintEvent(self, event): + def paintEvent(self, event) -> None: painter = QPainter(self) painter.setBrush(Qt.white) diff --git a/qt__pyqt__pyside__pyqode/pyqt__frameless_window_with_custom_frame_color__change_color_on__mouse_enter_leave.py b/qt__pyqt__pyside__pyqode/pyqt__frameless_window_with_custom_frame_color__change_color_on__mouse_enter_leave.py index adbbb64f7..177674372 100644 --- a/qt__pyqt__pyside__pyqode/pyqt__frameless_window_with_custom_frame_color__change_color_on__mouse_enter_leave.py +++ b/qt__pyqt__pyside__pyqode/pyqt__frameless_window_with_custom_frame_color__change_color_on__mouse_enter_leave.py @@ -10,7 +10,7 @@ class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowFlags(Qt.FramelessWindowHint) @@ -27,32 +27,32 @@ def __init__(self): self.setLayout(layout) - def mousePressEvent(self, event): + def mousePressEvent(self, event) -> None: if event.button() == Qt.LeftButton: self._old_pos = event.pos() - def mouseReleaseEvent(self, event): + def mouseReleaseEvent(self, event) -> None: if event.button() == Qt.LeftButton: self._old_pos = None - def mouseMoveEvent(self, event): + def mouseMoveEvent(self, event) -> None: if not self._old_pos: return delta = event.pos() - self._old_pos self.move(self.pos() + delta) - def enterEvent(self, event): + def enterEvent(self, event) -> None: self.frame_color = Qt.darkCyan self.update() - def leaveEvent(self, event): + def leaveEvent(self, event) -> None: self.frame_color = Qt.darkGreen self.update() - def paintEvent(self, event): + def paintEvent(self, event) -> None: painter = QPainter(self) painter.setBrush(Qt.white) diff --git a/qt__pyqt__pyside__pyqode/pyqt__frameless_window_with_part_transparent_body.py b/qt__pyqt__pyside__pyqode/pyqt__frameless_window_with_part_transparent_body.py index 37051277a..bbfebf3d7 100644 --- a/qt__pyqt__pyside__pyqode/pyqt__frameless_window_with_part_transparent_body.py +++ b/qt__pyqt__pyside__pyqode/pyqt__frameless_window_with_part_transparent_body.py @@ -10,7 +10,7 @@ class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowFlags(Qt.FramelessWindowHint) @@ -25,22 +25,22 @@ def __init__(self): self.setLayout(layout) - def mousePressEvent(self, event): + def mousePressEvent(self, event) -> None: if event.button() == Qt.LeftButton: self._old_pos = event.pos() - def mouseReleaseEvent(self, event): + def mouseReleaseEvent(self, event) -> None: if event.button() == Qt.LeftButton: self._old_pos = None - def mouseMoveEvent(self, event): + def mouseMoveEvent(self, event) -> None: if not self._old_pos: return delta = event.pos() - self._old_pos self.move(self.pos() + delta) - def paintEvent(self, event): + def paintEvent(self, event) -> None: painter = QPainter(self) painter.setBrush(QColor(0, 0, 0, 200)) diff --git a/qt__pyqt__pyside__pyqode/pyqt__loading_gif/main__QMovie__QLabel.py b/qt__pyqt__pyside__pyqode/pyqt__loading_gif/main__QMovie__QLabel.py index e7f196080..4c0646303 100644 --- a/qt__pyqt__pyside__pyqode/pyqt__loading_gif/main__QMovie__QLabel.py +++ b/qt__pyqt__pyside__pyqode/pyqt__loading_gif/main__QMovie__QLabel.py @@ -10,7 +10,7 @@ class Window(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("loading_gif") diff --git a/qt__pyqt__pyside__pyqode/pyqt__loading_gif/main__QMovie__QLabel__QGraphicsScene.py b/qt__pyqt__pyside__pyqode/pyqt__loading_gif/main__QMovie__QLabel__QGraphicsScene.py index 98f86a2ca..553172511 100644 --- a/qt__pyqt__pyside__pyqode/pyqt__loading_gif/main__QMovie__QLabel__QGraphicsScene.py +++ b/qt__pyqt__pyside__pyqode/pyqt__loading_gif/main__QMovie__QLabel__QGraphicsScene.py @@ -18,7 +18,7 @@ class Window(QGraphicsView): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("loading_gif") diff --git a/qt__pyqt__pyside__pyqode/pyqt__mouse_manual_move__FramelessWindowHint.py b/qt__pyqt__pyside__pyqode/pyqt__mouse_manual_move__FramelessWindowHint.py index 1877b28a9..842217910 100644 --- a/qt__pyqt__pyside__pyqode/pyqt__mouse_manual_move__FramelessWindowHint.py +++ b/qt__pyqt__pyside__pyqode/pyqt__mouse_manual_move__FramelessWindowHint.py @@ -9,7 +9,7 @@ class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowFlags(Qt.FramelessWindowHint) @@ -22,15 +22,15 @@ def __init__(self): self.setLayout(layout) - def mousePressEvent(self, event): + def mousePressEvent(self, event) -> None: if event.button() == Qt.LeftButton: self._old_pos = event.pos() - def mouseReleaseEvent(self, event): + def mouseReleaseEvent(self, event) -> None: if event.button() == Qt.LeftButton: self._old_pos = None - def mouseMoveEvent(self, event): + def mouseMoveEvent(self, event) -> None: if not self._old_pos: return diff --git a/qt__pyqt__pyside__pyqode/pyqt__mouse_manual_move__FramelessWindowHint__with_custom_resizable.py b/qt__pyqt__pyside__pyqode/pyqt__mouse_manual_move__FramelessWindowHint__with_custom_resizable.py index 43c651431..a288bb7e6 100644 --- a/qt__pyqt__pyside__pyqode/pyqt__mouse_manual_move__FramelessWindowHint__with_custom_resizable.py +++ b/qt__pyqt__pyside__pyqode/pyqt__mouse_manual_move__FramelessWindowHint__with_custom_resizable.py @@ -13,7 +13,7 @@ from PyQt5.QtCore import Qt -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -43,7 +43,7 @@ class ResizableFramelessWidget(QWidget): # Четыре периметра MARGINS = 10 - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowFlags(Qt.FramelessWindowHint) @@ -94,7 +94,7 @@ def _is_bottom(self, pos): wm, hm = self.width() - self.MARGINS, self.height() - self.MARGINS return self.MARGINS <= x_pos <= wm and hm <= y_pos <= self.height() - def mousePressEvent(self, event): + def mousePressEvent(self, event) -> None: """Событие клика мыши""" super().mousePressEvent(event) @@ -116,7 +116,7 @@ def mousePressEvent(self, event): self._is_margin_press = True break - def mouseReleaseEvent(self, event): + def mouseReleaseEvent(self, event) -> None: """Событие отказов мыши""" super().mouseReleaseEvent(event) @@ -124,7 +124,7 @@ def mouseReleaseEvent(self, event): self._is_margin_press = False self._direction = None - def mouseMoveEvent(self, event): + def mouseMoveEvent(self, event) -> None: """Событие перемещения мыши""" super().mouseMoveEvent(event) @@ -190,7 +190,7 @@ def mouseMoveEvent(self, event): # Курсор по умолчанию self.setCursor(Qt.ArrowCursor) - def _resizeWidget(self, pos): + def _resizeWidget(self, pos) -> None: """Отрегулируйте размер окна""" if self._direction is None: return diff --git a/qt__pyqt__pyside__pyqode/pyqt__mouse_manual_move__FramelessWindowHint__with_custom_resizable__with_custom_frame_color.py.py b/qt__pyqt__pyside__pyqode/pyqt__mouse_manual_move__FramelessWindowHint__with_custom_resizable__with_custom_frame_color.py.py index 6147d7f4f..e3282a1f2 100644 --- a/qt__pyqt__pyside__pyqode/pyqt__mouse_manual_move__FramelessWindowHint__with_custom_resizable__with_custom_frame_color.py.py +++ b/qt__pyqt__pyside__pyqode/pyqt__mouse_manual_move__FramelessWindowHint__with_custom_resizable__with_custom_frame_color.py.py @@ -14,7 +14,7 @@ class Widget(ResizableFramelessWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setAttribute(Qt.WA_TranslucentBackground) @@ -29,7 +29,7 @@ def __init__(self): self.setLayout(layout) - def paintEvent(self, event): + def paintEvent(self, event) -> None: painter = QPainter(self) painter.setBrush(Qt.white) diff --git a/qt__pyqt__pyside__pyqode/pyqt__redirect_print_stream_to_qtextedit.py b/qt__pyqt__pyside__pyqode/pyqt__redirect_print_stream_to_qtextedit.py index f20e972cd..d362b6a6d 100644 --- a/qt__pyqt__pyside__pyqode/pyqt__redirect_print_stream_to_qtextedit.py +++ b/qt__pyqt__pyside__pyqode/pyqt__redirect_print_stream_to_qtextedit.py @@ -17,17 +17,17 @@ class Severity: DEBUG = 0 ERROR = 1 - def __init__(self, io_stream, severity): + def __init__(self, io_stream, severity) -> None: super().__init__() self.io_stream = io_stream self.severity = severity - def write(self, text): + def write(self, text) -> None: self.io_stream.write(text) self.emit_write.emit(text, self.severity) - def flush(self): + def flush(self) -> None: self.io_stream.flush() @@ -39,7 +39,7 @@ def flush(self): class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.text_edit = QTextEdit() @@ -55,7 +55,7 @@ def __init__(self): self.setCentralWidget(self.text_edit) - def append_log(self, text: str, severity: OutputLogger.Severity): + def append_log(self, text: str, severity: OutputLogger.Severity) -> None: text = repr(text) if severity == OutputLogger.Severity.ERROR: diff --git a/qt__pyqt__pyside__pyqode/qt-gui-python-console.py b/qt__pyqt__pyside__pyqode/qt-gui-python-console.py index 04d037772..5a02b3ac8 100644 --- a/qt__pyqt__pyside__pyqode/qt-gui-python-console.py +++ b/qt__pyqt__pyside__pyqode/qt-gui-python-console.py @@ -40,11 +40,11 @@ class _QPythonConsoleInterpreter(_InteractiveConsole): """InteractiveConsole subclass that sends all output to the GUI.""" - def __init__(self, ui, locals=None): + def __init__(self, ui, locals=None) -> None: _InteractiveConsole.__init__(self, locals) self.ui = ui - def write(self, data): + def write(self, data) -> None: if data: if data[-1] == "\n": data = data[:-1] @@ -68,7 +68,7 @@ def runsource(self, source, filename="", symbol="single"): class _QPythonConsoleUI(object): """UI layout container for QPythonConsole.""" - def __init__(self, parent): + def __init__(self, parent) -> None: if parent.layout() is None: parent.setLayout(QHBoxLayout()) layout = QVBoxLayout() @@ -105,7 +105,7 @@ class QPythonConsole(QWidget): passing a dict as the "locals" argument. """ - def __init__(self, parent=None, locals=None): + def __init__(self, parent=None, locals=None) -> None: super(QPythonConsole, self).__init__(parent) self.ui = _QPythonConsoleUI(self) self.interpreter = _QPythonConsoleInterpreter(self.ui, locals) @@ -114,7 +114,7 @@ def __init__(self, parent=None, locals=None): self.history = [] self.history_pos = 0 - def _on_enter_line(self): + def _on_enter_line(self) -> None: line = self.ui.input.text() self.ui.input.setText("") self.interpreter.write(self.ui.prompt.text() + line) @@ -130,7 +130,7 @@ def _on_enter_line(self): else: self.ui.prompt.setText(">>> ") - def eventFilter(self, obj, event): + def eventFilter(self, obj, event) -> bool: if event.type() == QEvent.KeyPress: if event.key() == Qt.Key_Up: self.go_history(-1) @@ -138,7 +138,7 @@ def eventFilter(self, obj, event): self.go_history(1) return False - def go_history(self, offset): + def go_history(self, offset) -> None: if offset < 0: self.history_pos = max(0, self.history_pos + offset) elif offset > 0: diff --git a/qt__pyqt__pyside__pyqode/qt__class_tree__parse_and_print__recursively__from__doc_qt_io/console.py b/qt__pyqt__pyside__pyqode/qt__class_tree__parse_and_print__recursively__from__doc_qt_io/console.py index 68d290402..bb6da7de8 100644 --- a/qt__pyqt__pyside__pyqode/qt__class_tree__parse_and_print__recursively__from__doc_qt_io/console.py +++ b/qt__pyqt__pyside__pyqode/qt__class_tree__parse_and_print__recursively__from__doc_qt_io/console.py @@ -27,7 +27,7 @@ def get_inherited_children(url, root): return [(a.text.strip(), urljoin(url, a["href"])) for a in td_list] -def print_children(url, total_class_list, global_number=-1, indent_level=0): +def print_children(url, total_class_list, global_number=-1, indent_level=0) -> None: if global_number > 0 and len(total_class_list) >= global_number: # print('GLOBAL_NUMBER!') return diff --git a/qt__pyqt__pyside__pyqode/qt__class_tree__parse_and_print__recursively__from__doc_qt_io/gui.py b/qt__pyqt__pyside__pyqode/qt__class_tree__parse_and_print__recursively__from__doc_qt_io/gui.py index f6a8835e8..b0fff3092 100644 --- a/qt__pyqt__pyside__pyqode/qt__class_tree__parse_and_print__recursively__from__doc_qt_io/gui.py +++ b/qt__pyqt__pyside__pyqode/qt__class_tree__parse_and_print__recursively__from__doc_qt_io/gui.py @@ -19,7 +19,7 @@ class MainWindow(qtw.QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle( @@ -36,7 +36,7 @@ def __init__(self): def _fill_root( self, node: qtw.QTreeWidgetItem, url: str, global_number: int, indent_level=0 - ): + ) -> None: if global_number > 0 and self.number_total_class >= global_number: return @@ -70,7 +70,7 @@ def _fill_root( for name, url in inherited_children: self._fill_root(item, url, global_number, indent_level + 1) - def fill_tree(self, global_number=-1): + def fill_tree(self, global_number=-1) -> None: self.number_total_class = 0 self.tree.clear() @@ -84,7 +84,7 @@ def fill_tree(self, global_number=-1): f"Items: {self.number_total_class}.\nElapsed: {time.perf_counter() - t:.3f} sec", ) - def closeEvent(self, e): + def closeEvent(self, e) -> None: sys.exit() diff --git a/qt__pyqt__pyside__pyqode/qt__qtablewidget_fill_from_thread__with_api.py b/qt__pyqt__pyside__pyqode/qt__qtablewidget_fill_from_thread__with_api.py index 0478dedf9..ee8d76a52 100644 --- a/qt__pyqt__pyside__pyqode/qt__qtablewidget_fill_from_thread__with_api.py +++ b/qt__pyqt__pyside__pyqode/qt__qtablewidget_fill_from_thread__with_api.py @@ -25,7 +25,7 @@ class CheckNewData(QThread): about_new_data = Signal(dict) - def run(self): + def run(self) -> None: while True: # API - start rs = requests.get( @@ -41,7 +41,7 @@ def run(self): class Sheet(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setMinimumSize(QSize(600, 300)) @@ -70,7 +70,7 @@ def __init__(self): central_widget.setLayout(grid_layout) self.setCentralWidget(central_widget) - def update_table(self, data): + def update_table(self, data) -> None: print("update_table:", data) k = data["result"][0]["Last"] diff --git a/qt__pyqt__pyside__pyqode/qt_dummy_calculator_window__with_autodown_button_on_key_press.py b/qt__pyqt__pyside__pyqode/qt_dummy_calculator_window__with_autodown_button_on_key_press.py index a67990c2c..0403abd01 100644 --- a/qt__pyqt__pyside__pyqode/qt_dummy_calculator_window__with_autodown_button_on_key_press.py +++ b/qt__pyqt__pyside__pyqode/qt_dummy_calculator_window__with_autodown_button_on_key_press.py @@ -10,7 +10,7 @@ from PyQt5.QtWidgets import * -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -23,7 +23,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("dummy_calculator_window") @@ -47,7 +47,7 @@ def __init__(self): self.setLayout(layout) - def keyPressEvent(self, event): + def keyPressEvent(self, event) -> None: try: key = chr(event.key()) @@ -59,7 +59,7 @@ def keyPressEvent(self, event): super().keyPressEvent(event) - def keyReleaseEvent(self, event): + def keyReleaseEvent(self, event) -> None: try: key = chr(event.key()) diff --git a/qt__pyqt__pyside__pyqode/qt_fill_QTableWidget_from_SQL/main.py b/qt__pyqt__pyside__pyqode/qt_fill_QTableWidget_from_SQL/main.py index 99b6e952d..fa2c5bbab 100644 --- a/qt__pyqt__pyside__pyqode/qt_fill_QTableWidget_from_SQL/main.py +++ b/qt__pyqt__pyside__pyqode/qt_fill_QTableWidget_from_SQL/main.py @@ -17,7 +17,7 @@ class Widget(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Table") @@ -25,7 +25,7 @@ def __init__(self): self.table_widget = QTableWidget() self.setCentralWidget(self.table_widget) - def fill(self): + def fill(self) -> None: self.table_widget.clear() labels = ["ID", "NAME", "PRICE"] diff --git a/qt__pyqt__pyside__pyqode/qt_log_uncaught_exceptions.py b/qt__pyqt__pyside__pyqode/qt_log_uncaught_exceptions.py index b1310d235..bea0decfb 100644 --- a/qt__pyqt__pyside__pyqode/qt_log_uncaught_exceptions.py +++ b/qt__pyqt__pyside__pyqode/qt_log_uncaught_exceptions.py @@ -10,7 +10,7 @@ from PyQt5.QtWidgets import QMessageBox -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) diff --git a/qt__pyqt__pyside__pyqode/qt_pixel_draw_image/main.py b/qt__pyqt__pyside__pyqode/qt_pixel_draw_image/main.py index fbf24ad56..476a489e9 100644 --- a/qt__pyqt__pyside__pyqode/qt_pixel_draw_image/main.py +++ b/qt__pyqt__pyside__pyqode/qt_pixel_draw_image/main.py @@ -13,7 +13,7 @@ from PyQt5.QtCore import Qt, QTimer -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -29,7 +29,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("qt_pixel_draw_image") @@ -58,7 +58,7 @@ def __init__(self): self.timer.timeout.connect(self._draw_pixel) self.timer.start(1) # 1 ms - def _draw_pixel(self): + def _draw_pixel(self) -> None: # Если список пустой if not self.pixel_list: self.timer.stop() @@ -73,7 +73,7 @@ def _draw_pixel(self): # Перерисование виджета self.update() - def paintEvent(self, event): + def paintEvent(self, event) -> None: painter = QPainter(self) # Рисуем старую картинку diff --git a/qt__pyqt__pyside__pyqode/qt_pixel_draw_image/main_with_fast_draw.py b/qt__pyqt__pyside__pyqode/qt_pixel_draw_image/main_with_fast_draw.py index c94861685..f31882a4b 100644 --- a/qt__pyqt__pyside__pyqode/qt_pixel_draw_image/main_with_fast_draw.py +++ b/qt__pyqt__pyside__pyqode/qt_pixel_draw_image/main_with_fast_draw.py @@ -13,7 +13,7 @@ from PyQt5.QtCore import Qt, QTimer -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -29,7 +29,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("qt_pixel_draw_image") @@ -64,7 +64,7 @@ def __init__(self): self.timer.timeout.connect(self._draw_pixel) self.timer.start(1) # 1 ms - def _draw_pixel(self): + def _draw_pixel(self) -> None: # Количество пикселей за один шаг pixels_by_step = 15 @@ -84,7 +84,7 @@ def _draw_pixel(self): # Перерисование виджета self.update() - def paintEvent(self, event): + def paintEvent(self, event) -> None: painter = QPainter(self) # Рисуем старую картинку diff --git a/qt__pyqt__pyside__pyqode/qt_sorting_pixel_draw_image/main.py b/qt__pyqt__pyside__pyqode/qt_sorting_pixel_draw_image/main.py index 12db711ed..3e3406a87 100644 --- a/qt__pyqt__pyside__pyqode/qt_sorting_pixel_draw_image/main.py +++ b/qt__pyqt__pyside__pyqode/qt_sorting_pixel_draw_image/main.py @@ -14,7 +14,7 @@ from PyQt5.QtCore import QTimer -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -31,7 +31,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle(DIR.name) @@ -65,7 +65,7 @@ def __init__(self): self.timer.timeout.connect(self._draw_pixel) self.timer.start(15) # ms - def _draw_pixel(self): + def _draw_pixel(self) -> None: if not self.pixel_matrix: self.timer.stop() return @@ -80,7 +80,7 @@ def _draw_pixel(self): # Перерисование виджета self.update() - def paintEvent(self, event): + def paintEvent(self, event) -> None: painter = QPainter(self) # Рисуем старую картинку diff --git a/qt__pyqt__pyside__pyqode/qt_tree_model_xml/main.py b/qt__pyqt__pyside__pyqode/qt_tree_model_xml/main.py index 0d8336a64..b8e54aa09 100644 --- a/qt__pyqt__pyside__pyqode/qt_tree_model_xml/main.py +++ b/qt__pyqt__pyside__pyqode/qt_tree_model_xml/main.py @@ -15,7 +15,7 @@ class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("tree_model") @@ -76,11 +76,11 @@ def __init__(self): self.view.expandAll() - def add(self): + def add(self) -> None: item = QStandardItem("animals") self.model.appendRow(item) - def add_child(self): + def add_child(self) -> None: child = QStandardItem("dog") index = self.view.currentIndex() @@ -90,12 +90,12 @@ def add_child(self): self.view.setExpanded(item.index(), True) - def remove(self): + def remove(self) -> None: index = self.view.currentIndex() if index is not None and index.isValid(): self.model.removeRow(index.row(), index.parent()) - def create_xml(self, root_item, root_xml, doc): + def create_xml(self, root_item, root_xml, doc) -> None: # Перебор детей элемента for row in range(root_item.rowCount()): child = root_item.child(row) @@ -106,7 +106,7 @@ def create_xml(self, root_item, root_xml, doc): self.create_xml(child, tag, doc) - def save_tree(self): + def save_tree(self) -> None: # Рекурсивный перебор дерева root = self.model.invisibleRootItem() @@ -124,7 +124,7 @@ def save_tree(self): file.close() - def create_item_model(self, item_root, xml_root): + def create_item_model(self, item_root, xml_root) -> None: children = xml_root.childNodes() for i in range(children.count()): xml_child = children.item(i) @@ -136,7 +136,7 @@ def create_item_model(self, item_root, xml_root): if xml_child.hasChildNodes(): self.create_item_model(item_child, xml_child) - def restore_tree(self): + def restore_tree(self) -> None: self.model.clear() self.model.setHorizontalHeaderLabels(["Animals"]) diff --git a/qt__pyqt__pyside__pyqode/random_text_progress.py b/qt__pyqt__pyside__pyqode/random_text_progress.py index 044e5718d..e138d8709 100644 --- a/qt__pyqt__pyside__pyqode/random_text_progress.py +++ b/qt__pyqt__pyside__pyqode/random_text_progress.py @@ -28,7 +28,7 @@ def get_random_text_progress(text: str) -> list[str]: class RandomTextProgress(QLabel): - def __init__(self, text: str, msec: int = 300): + def __init__(self, text: str, msec: int = 300) -> None: super().__init__() self._text = text @@ -40,7 +40,7 @@ def __init__(self, text: str, msec: int = 300): self._on_tick() - def _on_tick(self): + def _on_tick(self) -> None: if not self._seq_text: self._seq_text = get_random_text_progress(self._text) @@ -48,7 +48,7 @@ def _on_tick(self): class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() font = self.font() diff --git a/qt__pyqt__pyside__pyqode/remote_controller__widget_with_webserver/base_camera.py b/qt__pyqt__pyside__pyqode/remote_controller__widget_with_webserver/base_camera.py index 81d8846e5..7c746d3fd 100644 --- a/qt__pyqt__pyside__pyqode/remote_controller__widget_with_webserver/base_camera.py +++ b/qt__pyqt__pyside__pyqode/remote_controller__widget_with_webserver/base_camera.py @@ -24,7 +24,7 @@ class CameraEvent(object): available. """ - def __init__(self): + def __init__(self) -> None: self.events = {} def wait(self): @@ -37,7 +37,7 @@ def wait(self): self.events[ident] = [threading.Event(), time.time()] return self.events[ident][0].wait() - def set(self): + def set(self) -> None: """Invoked by the camera thread when a new frame is available.""" now = time.time() remove = None @@ -57,7 +57,7 @@ def set(self): if remove: del self.events[remove] - def clear(self): + def clear(self) -> None: """Invoked from each client's thread after a frame was processed.""" self.events[get_ident()][0].clear() @@ -70,7 +70,7 @@ class BaseCamera(object): STOPPING_IF_IDLE = True - def __init__(self): + def __init__(self) -> None: """Start the background camera thread if it isn't running yet.""" if BaseCamera.thread is None: BaseCamera.last_access = time.time() @@ -99,7 +99,7 @@ def frames(): raise RuntimeError("Must be implemented by subclasses.") @classmethod - def _thread(cls): + def _thread(cls) -> None: """Camera background thread.""" print("Starting camera thread.") diff --git a/qt__pyqt__pyside__pyqode/remote_controller__widget_with_webserver/frameless_widget_with_webserver.py b/qt__pyqt__pyside__pyqode/remote_controller__widget_with_webserver/frameless_widget_with_webserver.py index f5d60cbc9..fb87c2a18 100644 --- a/qt__pyqt__pyside__pyqode/remote_controller__widget_with_webserver/frameless_widget_with_webserver.py +++ b/qt__pyqt__pyside__pyqode/remote_controller__widget_with_webserver/frameless_widget_with_webserver.py @@ -36,7 +36,7 @@ from config import PORT, PATH_DEFAULT_MOUSE -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: # Если было запрошено прерывание if isinstance(ex, KeyboardInterrupt): sys.exit() @@ -55,7 +55,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class CommandServerThread(QThread): about_command = pyqtSignal(str) - def __init__(self, parent=None, port=PORT): + def __init__(self, parent=None, port=PORT) -> None: super().__init__(parent) self.port = port @@ -72,15 +72,15 @@ def command(command: str): return jsonify({"status": True}) - def set_pixmap(self, pixmap_data: bytes): + def set_pixmap(self, pixmap_data: bytes) -> None: self.pixmap_data = pixmap_data - def run(self): + def run(self) -> None: self.app.run(port=self.port) class MainWindow(QWidget): - def __init__(self, port=PORT, mouse_permeability=True): + def __init__(self, port=PORT, mouse_permeability=True) -> None: super().__init__() self.setWindowTitle(Path(__file__).name) @@ -119,10 +119,10 @@ def __init__(self, port=PORT, mouse_permeability=True): self.timer.timeout.connect(self._on_tick) self.timer.start(30) - def _on_stats_query(self): + def _on_stats_query(self) -> None: self.thread_screenshot.set_stats(self.geometry(), self.isVisible()) - def _on_tick(self): + def _on_tick(self) -> None: if self.isHidden(): return @@ -158,34 +158,34 @@ def _on_tick(self): self.thread_command.set_pixmap(bytes(data)) - def mousePressEvent(self, event: QMouseEvent): + def mousePressEvent(self, event: QMouseEvent) -> None: if event.button() == Qt.LeftButton: self._old_pos = event.pos() - def mouseReleaseEvent(self, event: QMouseEvent): + def mouseReleaseEvent(self, event: QMouseEvent) -> None: if event.button() == Qt.LeftButton: self._old_pos = None - def mouseMoveEvent(self, event: QMouseEvent): + def mouseMoveEvent(self, event: QMouseEvent) -> None: if not self._old_pos: return delta = event.pos() - self._old_pos self.move(self.pos() + delta) - def move_left(self): + def move_left(self) -> None: self.move(self.pos() + QPoint(-10, 0)) - def move_right(self): + def move_right(self) -> None: self.move(self.pos() + QPoint(10, 0)) - def move_up(self): + def move_up(self) -> None: self.move(self.pos() + QPoint(0, -10)) - def move_down(self): + def move_down(self) -> None: self.move(self.pos() + QPoint(0, 10)) - def process_command(self, command: str): + def process_command(self, command: str) -> None: command = command.upper() if command == "LEFT": @@ -205,7 +205,7 @@ def process_command(self, command: str): rect.moveCenter(QCursor.pos()) self.setGeometry(rect) - def keyReleaseEvent(self, event: QKeyEvent): + def keyReleaseEvent(self, event: QKeyEvent) -> None: if event.key() == Qt.Key_Left: self.move_left() elif event.key() == Qt.Key_Right: @@ -215,7 +215,7 @@ def keyReleaseEvent(self, event: QKeyEvent): elif event.key() == Qt.Key_Down: self.move_down() - def paintEvent(self, event: QPaintEvent): + def paintEvent(self, event: QPaintEvent) -> None: painter = QPainter(self) painter.setBrush(QColor(0, 0, 0, 0 if self.mouse_permeability else 1)) @@ -224,7 +224,7 @@ def paintEvent(self, event: QPaintEvent): painter.drawRect(self.rect()) -def main(port=PORT, is_visible=True, width=800, height=600, mouse_permeability=True): +def main(port=PORT, is_visible=True, width=800, height=600, mouse_permeability=True) -> None: app = QApplication([]) w = MainWindow(port, mouse_permeability) diff --git a/qt__pyqt__pyside__pyqode/remote_controller__widget_with_webserver/remote_controller_widget.py b/qt__pyqt__pyside__pyqode/remote_controller__widget_with_webserver/remote_controller_widget.py index 975f8df4a..c9ecaf6f9 100644 --- a/qt__pyqt__pyside__pyqode/remote_controller__widget_with_webserver/remote_controller_widget.py +++ b/qt__pyqt__pyside__pyqode/remote_controller__widget_with_webserver/remote_controller_widget.py @@ -27,7 +27,7 @@ class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle(Path(__file__).name) @@ -70,7 +70,7 @@ def _create_button(self, data: str, expanding=True) -> QPushButton: return button - def _send_command(self, data: str): + def _send_command(self, data: str) -> None: try: rs = requests.post(URL.format(data)) rs.raise_for_status() @@ -85,10 +85,10 @@ def _send_command(self, data: str): except: pass - def _on_click(self, data: str): + def _on_click(self, data: str) -> None: Thread(target=self._send_command, args=[data]).start() - def _on_tick(self): + def _on_tick(self) -> None: Thread(target=self._send_command, args=["SCREENSHOT"]).start() diff --git a/qt__pyqt__pyside__pyqode/remote_controller__widget_with_webserver/widget_with_webserver.py b/qt__pyqt__pyside__pyqode/remote_controller__widget_with_webserver/widget_with_webserver.py index 5e2ade375..ad6a67bc3 100644 --- a/qt__pyqt__pyside__pyqode/remote_controller__widget_with_webserver/widget_with_webserver.py +++ b/qt__pyqt__pyside__pyqode/remote_controller__widget_with_webserver/widget_with_webserver.py @@ -15,7 +15,7 @@ class CommandServerThread(QThread): about_command = pyqtSignal(str) - def __init__(self, parent=None, port=20000): + def __init__(self, parent=None, port=20000) -> None: super().__init__(parent) self.port = port @@ -28,12 +28,12 @@ def command(command: str): return jsonify({"status": True}) - def run(self): + def run(self) -> None: self.app.run(port=self.port) class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("MainWindow + CommandServerThread") diff --git a/qt__pyqt__pyside__pyqode/ru_stackoverflow_exception_questions/gatherer.py b/qt__pyqt__pyside__pyqode/ru_stackoverflow_exception_questions/gatherer.py index 8d94f8149..ae0fc9601 100644 --- a/qt__pyqt__pyside__pyqode/ru_stackoverflow_exception_questions/gatherer.py +++ b/qt__pyqt__pyside__pyqode/ru_stackoverflow_exception_questions/gatherer.py @@ -28,12 +28,12 @@ class Question: - def __init__(self, id): + def __init__(self, id) -> None: self.id = id self.editable = False self.editable_date = None - def __repr__(self): + def __repr__(self) -> str: return f"" @property diff --git a/qt__pyqt__pyside__pyqode/ru_stackoverflow_exception_questions/web_tag_editor.py b/qt__pyqt__pyside__pyqode/ru_stackoverflow_exception_questions/web_tag_editor.py index 3f1e61947..d32417b19 100644 --- a/qt__pyqt__pyside__pyqode/ru_stackoverflow_exception_questions/web_tag_editor.py +++ b/qt__pyqt__pyside__pyqode/ru_stackoverflow_exception_questions/web_tag_editor.py @@ -41,7 +41,7 @@ def get_logger(name, file="log.txt", encoding="utf8"): class WebPage(QWebPage): - def userAgentForUrl(self, url): + def userAgentForUrl(self, url) -> str: return ( "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0" ) @@ -54,7 +54,7 @@ def userAgentForUrl(self, url): class WebTagEditor(QWebView): - def __init__(self, login, password, question_url): + def __init__(self, login, password, question_url) -> None: super().__init__() self.login = login @@ -74,7 +74,7 @@ def __init__(self, login, password, question_url): self.setPage(WebPage()) - def go(self): + def go(self) -> None: self.load("https://ru.stackoverflow.com/users/login") self.doc.findFirst("#email").setAttribute("value", self.login) self.doc.findFirst("#password").setAttribute("value", self.password) @@ -159,7 +159,7 @@ def go(self): self.loadFinished.connect(loop.quit) loop.exec_() - def load(self, url): + def load(self, url) -> None: logger.debug("Начата загрузка url: %s.", url) super().load(url) @@ -174,13 +174,13 @@ def load(self, url): def doc(self): return self.page().mainFrame().documentElement() - def evaluate_java_script(self, js): + def evaluate_java_script(self, js) -> None: logger.debug('Исполнение js-кода:\n"%s".', js) self.doc.evaluateJavaScript(js) # result = self.doc.evaluateJavaScript(js) # logger.debug('Результат:\n"%s".', str(result).encode()) - def add_tag(self, name): + def add_tag(self, name) -> None: logger.debug('Добавление тэга: "%s".', name) js = f""" diff --git a/qt__pyqt__pyside__pyqode/run_cmd_in_new_window.py b/qt__pyqt__pyside__pyqode/run_cmd_in_new_window.py index c83a45f73..79ad182cc 100644 --- a/qt__pyqt__pyside__pyqode/run_cmd_in_new_window.py +++ b/qt__pyqt__pyside__pyqode/run_cmd_in_new_window.py @@ -12,7 +12,7 @@ from PyQt5.QtWidgets import QWidget, QPushButton, QApplication, QVBoxLayout, QMessageBox -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -25,7 +25,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.cmd_command = "start cmd.exe @cmd /k ipconfig" @@ -42,10 +42,10 @@ def __init__(self): self.setLayout(layout) - def btn_clicked_subprocess(self): + def btn_clicked_subprocess(self) -> None: subprocess.run(self.cmd_command.split(), shell=True) - def btn_clicked_os_system(self): + def btn_clicked_os_system(self) -> None: os.system(self.cmd_command) diff --git a/qt__pyqt__pyside__pyqode/run_js.py b/qt__pyqt__pyside__pyqode/run_js.py index c98ff79eb..b9f6590b6 100644 --- a/qt__pyqt__pyside__pyqode/run_js.py +++ b/qt__pyqt__pyside__pyqode/run_js.py @@ -20,7 +20,7 @@ def run_js(code: str) -> Any: result: Any = None callback_finished = False - def _callback(v): + def _callback(v) -> None: nonlocal result, callback_finished result = v callback_finished = True diff --git a/qt__pyqt__pyside__pyqode/save_text_as_image/main.py b/qt__pyqt__pyside__pyqode/save_text_as_image/main.py index 796752158..5218d5adb 100644 --- a/qt__pyqt__pyside__pyqode/save_text_as_image/main.py +++ b/qt__pyqt__pyside__pyqode/save_text_as_image/main.py @@ -29,7 +29,7 @@ DIR = Path(__file__).parent -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -42,7 +42,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle(DIR.name) @@ -76,7 +76,7 @@ def __init__(self): self.setLayout(form_layout) - def _on_save_as(self): + def _on_save_as(self) -> None: # Список строк с поддерживаемыми форматами изображений formats = [str(x, encoding="utf-8") for x in QImageWriter.supportedImageFormats()] @@ -89,7 +89,7 @@ def _on_save_as(self): if file_name: self.result_label.pixmap().save(file_name) - def render_image(self): + def render_image(self) -> None: font = self.cb_font.currentFont() need_width = self.sb_width.value() text = self.text_edit.text() diff --git a/qt__pyqt__pyside__pyqode/schedule_and_QThread.py b/qt__pyqt__pyside__pyqode/schedule_and_QThread.py index 1f3da91a6..42746bcd8 100644 --- a/qt__pyqt__pyside__pyqode/schedule_and_QThread.py +++ b/qt__pyqt__pyside__pyqode/schedule_and_QThread.py @@ -19,7 +19,7 @@ class Ui_MainWindow(object): - def setupUi(self, MainWindow): + def setupUi(self, MainWindow) -> None: MainWindow.setObjectName("MainWindow") MainWindow.resize(449, 208) self.centralwidget = QtWidgets.QWidget(MainWindow) @@ -48,7 +48,7 @@ def setupUi(self, MainWindow): self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) - def retranslateUi(self, MainWindow): + def retranslateUi(self, MainWindow) -> None: _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) self.label.setText(_translate("MainWindow", "Когда вывести сообщение:")) @@ -58,17 +58,17 @@ def retranslateUi(self, MainWindow): class ScheduleThread(QThread): about_time = pyqtSignal(str) - def add_time(self, time: str): + def add_time(self, time: str) -> None: schedule.every().day.at(time).do(self.about_time.emit, time) - def run(self): + def run(self) -> None: while True: schedule.run_pending() time.sleep(1) class Example(QMainWindow, Ui_MainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setupUi(self) @@ -81,10 +81,10 @@ def __init__(self): self.thread.about_time.connect(self.write) self.thread.start() - def write(self, time: str): + def write(self, time: str) -> None: print("красафчик", time) - def go(self): + def go(self) -> None: try: t = self.lineEdit.text() datetime_object = datetime.strptime(t, "%H:%M") diff --git a/qt__pyqt__pyside__pyqode/send_QKeyEvent/send_key.py b/qt__pyqt__pyside__pyqode/send_QKeyEvent/send_key.py index facba9f26..8f4d76d9a 100644 --- a/qt__pyqt__pyside__pyqode/send_QKeyEvent/send_key.py +++ b/qt__pyqt__pyside__pyqode/send_QKeyEvent/send_key.py @@ -8,7 +8,7 @@ from PySide.QtCore import Qt -def key_press_release(widget, key, modifier=Qt.NoModifier): +def key_press_release(widget, key, modifier=Qt.NoModifier) -> None: """ Функция для отправления события нажатия кнопки. @@ -53,7 +53,7 @@ def key_press_release(widget, key, modifier=Qt.NoModifier): view.loadFinished.connect(loop.quit) loop.exec_() - def random_click(): + def random_click() -> None: """Функция для случайного клика на WASD.""" key = random.choice([Qt.Key_W, Qt.Key_S, Qt.Key_A, Qt.Key_D]) diff --git a/qt__pyqt__pyside__pyqode/send_QKeyEvent__auto_click_button.py b/qt__pyqt__pyside__pyqode/send_QKeyEvent__auto_click_button.py index 3eea73644..cf5e3aa99 100644 --- a/qt__pyqt__pyside__pyqode/send_QKeyEvent__auto_click_button.py +++ b/qt__pyqt__pyside__pyqode/send_QKeyEvent__auto_click_button.py @@ -7,7 +7,7 @@ from PyQt5.Qt import Qt, QKeyEvent, QApplication, QPushButton, QTimer -def key_press_release(widget, key, modifier=Qt.NoModifier): +def key_press_release(widget, key, modifier=Qt.NoModifier) -> None: """ Функция для отправления события нажатия кнопки. # Имитация нажатия на пробел: diff --git a/qt__pyqt__pyside__pyqode/show_QSplashScreen/_test_widget.py b/qt__pyqt__pyside__pyqode/show_QSplashScreen/_test_widget.py index f7d83faf7..e21b08a52 100644 --- a/qt__pyqt__pyside__pyqode/show_QSplashScreen/_test_widget.py +++ b/qt__pyqt__pyside__pyqode/show_QSplashScreen/_test_widget.py @@ -9,7 +9,7 @@ class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Main Form") @@ -24,10 +24,10 @@ def __init__(self): self._my_sleep(1500) - def do_load(self): + def do_load(self) -> None: self._my_sleep(3000) - def _my_sleep(self, ms: int): + def _my_sleep(self, ms: int) -> None: # NOTE: Для симуляции ожидания прогрузок loop = QEventLoop() QTimer.singleShot(ms, loop.quit) diff --git a/qt__pyqt__pyside__pyqode/show_QSplashScreen/main_animation__with_gif.py b/qt__pyqt__pyside__pyqode/show_QSplashScreen/main_animation__with_gif.py index 1c008dc37..ea2b5e034 100644 --- a/qt__pyqt__pyside__pyqode/show_QSplashScreen/main_animation__with_gif.py +++ b/qt__pyqt__pyside__pyqode/show_QSplashScreen/main_animation__with_gif.py @@ -9,22 +9,22 @@ class GifSplashScreen(QSplashScreen): - def __init__(self, file_name: str, *args, **kwargs): + def __init__(self, file_name: str, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self.movie = QMovie(file_name, parent=self) self.movie.frameChanged.connect(self._on_frame_changed) self.movie.start() - def _on_frame_changed(self, _): + def _on_frame_changed(self, _) -> None: self.setPixmap(self.movie.currentPixmap()) - def finish(self, widget): + def finish(self, widget) -> None: super().finish(widget) self.movie.stop() - def mousePressEvent(self, event: QMouseEvent): + def mousePressEvent(self, event: QMouseEvent) -> None: # Ignoring "hide" on click # https://code.woboq.org/qt5/qtbase/src/widgets/widgets/qsplashscreen.cpp.html#_ZN13QSplashScreen15mousePressEventEP11QMouseEvent pass diff --git a/qt__pyqt__pyside__pyqode/show_all_standard_qt_icon__from_StandardPixmap.py b/qt__pyqt__pyside__pyqode/show_all_standard_qt_icon__from_StandardPixmap.py index 844c3f034..24df2ed8e 100644 --- a/qt__pyqt__pyside__pyqode/show_all_standard_qt_icon__from_StandardPixmap.py +++ b/qt__pyqt__pyside__pyqode/show_all_standard_qt_icon__from_StandardPixmap.py @@ -21,7 +21,7 @@ # Для отлова всех исключений, которые в слотах Qt могут "затеряться" и привести к тихому падению -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) diff --git a/qt__pyqt__pyside__pyqode/show_current_process_memory_info.py b/qt__pyqt__pyside__pyqode/show_current_process_memory_info.py index 4971e53d5..c69d8997f 100644 --- a/qt__pyqt__pyside__pyqode/show_current_process_memory_info.py +++ b/qt__pyqt__pyside__pyqode/show_current_process_memory_info.py @@ -13,7 +13,7 @@ class MainWidget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self._label_info = QLabel() @@ -31,7 +31,7 @@ def __init__(self): self.update_memory_info() - def update_memory_info(self): + def update_memory_info(self) -> None: memory_bytes = self._process.memory_info().rss self._label_info.setText( diff --git a/qt__pyqt__pyside__pyqode/show_current_process_memory_info__with__button_for_append_new_objects.py b/qt__pyqt__pyside__pyqode/show_current_process_memory_info__with__button_for_append_new_objects.py index f89c0a226..01cc91e5d 100644 --- a/qt__pyqt__pyside__pyqode/show_current_process_memory_info__with__button_for_append_new_objects.py +++ b/qt__pyqt__pyside__pyqode/show_current_process_memory_info__with__button_for_append_new_objects.py @@ -22,7 +22,7 @@ class MainWidget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self._label_info = QLabel() @@ -55,11 +55,11 @@ def __init__(self): self.update_memory_info() - def _on_append_clicked(self): + def _on_append_clicked(self) -> None: row = [0 for _ in range(self._spin_box_numbers.value())] self._items.append(row) - def update_memory_info(self): + def update_memory_info(self) -> None: memory_bytes = self._process.memory_info().rss self._label_info.setText( diff --git a/qt__pyqt__pyside__pyqode/show_hide_tabs__QTabWidget.py b/qt__pyqt__pyside__pyqode/show_hide_tabs__QTabWidget.py index 453f3910f..b6cd25977 100644 --- a/qt__pyqt__pyside__pyqode/show_hide_tabs__QTabWidget.py +++ b/qt__pyqt__pyside__pyqode/show_hide_tabs__QTabWidget.py @@ -11,7 +11,7 @@ class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.tab_widget = QTabWidget() diff --git a/qt__pyqt__pyside__pyqode/show_images_and_append_their_to_json/main.py b/qt__pyqt__pyside__pyqode/show_images_and_append_their_to_json/main.py index 844c472e1..9b024afab 100644 --- a/qt__pyqt__pyside__pyqode/show_images_and_append_their_to_json/main.py +++ b/qt__pyqt__pyside__pyqode/show_images_and_append_their_to_json/main.py @@ -24,7 +24,7 @@ class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self._current_index_image = 0 @@ -79,21 +79,21 @@ def __init__(self): def get_current_image_file_name(self): return self._images[self._current_index_image] - def load_prev_image(self): + def load_prev_image(self) -> None: self._current_index_image -= 1 if self._current_index_image < 0: self._current_index_image = 0 self.load_current_image() - def load_next_image(self): + def load_next_image(self) -> None: self._current_index_image += 1 if self._current_index_image >= len(self._images): self._current_index_image = len(self._images) - 1 self.load_current_image() - def load_current_image(self): + def load_current_image(self) -> None: self.update_states() file_name = self.get_current_image_file_name() @@ -102,7 +102,7 @@ def load_current_image(self): pixmap.load(file_name) self.label_image.setPixmap(pixmap) - def _on_add_file_name(self): + def _on_add_file_name(self) -> None: key = self.line_edit_key.text() file_name = self.get_current_image_file_name() @@ -116,7 +116,7 @@ def _on_add_file_name(self): json.dumps(self._data, indent=4, ensure_ascii=False) ) - def update_states(self): + def update_states(self) -> None: file_name = self.get_current_image_file_name() self.setWindowTitle( f"{self._current_index_image + 1} / {len(self._images)} : {file_name}" diff --git a/qt__pyqt__pyside__pyqode/show_new_process_handler__using__psutil.py b/qt__pyqt__pyside__pyqode/show_new_process_handler__using__psutil.py index c7e2cc4fe..6208125d2 100644 --- a/qt__pyqt__pyside__pyqode/show_new_process_handler__using__psutil.py +++ b/qt__pyqt__pyside__pyqode/show_new_process_handler__using__psutil.py @@ -16,22 +16,22 @@ class OnNewProcessHandler(Thread): - def __init__(self, timeout_secs=1.0, daemon=None): + def __init__(self, timeout_secs=1.0, daemon=None) -> None: super().__init__(daemon=daemon) self._process = dict() self._listeners: list[ListenerFunc] = [] self._timeout_secs = timeout_secs - def add_listener(self, listener: ListenerFunc): + def add_listener(self, listener: ListenerFunc) -> None: if listener not in self._listeners: self._listeners.append(listener) - def remove_listener(self, listener: ListenerFunc): + def remove_listener(self, listener: ListenerFunc) -> None: if listener in self._listeners: self._listeners.remove(listener) - def remove_all_listener(self): + def remove_all_listener(self) -> None: self._listeners.clear() @staticmethod @@ -48,7 +48,7 @@ def get_process() -> dict: return items - def run(self): + def run(self) -> None: while True: current_process = self.get_process() @@ -71,7 +71,7 @@ def run(self): if __name__ == "__main__": - def print_listener(process_list): + def print_listener(process_list) -> None: result = [] for p in process_list: result.append(f"{p['name']} (pid={p['pid']})") @@ -91,7 +91,7 @@ def print_listener(process_list): mw = QPlainTextEdit() - def print_listener2(process_list): + def print_listener2(process_list) -> None: result = [] for p in process_list: result.append(f"{p['name']} (pid={p['pid']})") diff --git a/qt__pyqt__pyside__pyqode/show_target_icon__behind_cursor/main.py b/qt__pyqt__pyside__pyqode/show_target_icon__behind_cursor/main.py index 5f6af6685..4297b8dfd 100644 --- a/qt__pyqt__pyside__pyqode/show_target_icon__behind_cursor/main.py +++ b/qt__pyqt__pyside__pyqode/show_target_icon__behind_cursor/main.py @@ -14,7 +14,7 @@ FILE_NAME = str(Path(__file__).resolve().parent / "target.png") -def move_window_to_cursor(widget: QWidget): +def move_window_to_cursor(widget: QWidget) -> None: width, height = widget.width(), widget.height() pos = QCursor.pos() pos.setX(int(pos.x() - width / 2)) diff --git a/qt__pyqt__pyside__pyqode/show_user_grouple_rss__qt.py b/qt__pyqt__pyside__pyqode/show_user_grouple_rss__qt.py index 98faa4a2e..c3a9c836e 100644 --- a/qt__pyqt__pyside__pyqode/show_user_grouple_rss__qt.py +++ b/qt__pyqt__pyside__pyqode/show_user_grouple_rss__qt.py @@ -15,7 +15,7 @@ from PyQt5.QtCore import * -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -39,7 +39,7 @@ def get_feeds_by_manga_chapters(url_rss: str) -> list: class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("show_user_grouple_rss__qt") @@ -85,17 +85,17 @@ def __init__(self): # Set default url self.line_edit_url_user.setText("https://grouple.co/user/315828") - def _on_line_edit_url_user_text_changed(self, text): + def _on_line_edit_url_user_text_changed(self, text) -> None: id_user = text.replace(" ", "").split("/")[-1] self.line_edit_id_user.setText(id_user) - def _on_line_edit_id_user_text_changed(self, text): + def _on_line_edit_id_user_text_changed(self, text) -> None: id_user = text.strip() self.line_edit_rss_user.setText( f"https://grouple.co/user/rss/{id_user}?filter=" ) - def _start(self): + def _start(self) -> None: self.list_widget_feeds.clear() url_rss = self.line_edit_rss_user.text() @@ -108,7 +108,7 @@ def _start(self): self.list_widget_feeds.addItem(item) @staticmethod - def _on_item_double_clicked(item): + def _on_item_double_clicked(item) -> None: url = item.data(Qt.UserRole) webbrowser.open_new_tab(url) diff --git a/qt__pyqt__pyside__pyqode/simple_TreeModel.py b/qt__pyqt__pyside__pyqode/simple_TreeModel.py index 61b6dd95e..13369b4a8 100644 --- a/qt__pyqt__pyside__pyqode/simple_TreeModel.py +++ b/qt__pyqt__pyside__pyqode/simple_TreeModel.py @@ -13,7 +13,7 @@ from PyQt5.QtCore import Qt, QAbstractItemModel, QModelIndex -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -26,7 +26,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class TreeItem: - def __init__(self, *args): + def __init__(self, *args) -> None: self._childItems: list[TreeItem] = [] self._itemData = args self._parentItem: TreeItem = None @@ -50,11 +50,11 @@ def appendChild(self, child: Union["TreeItem", str]) -> "TreeItem": return child - def appendChilds(self, childs: list["TreeItem"]): + def appendChilds(self, childs: list["TreeItem"]) -> None: for x in childs: self.appendChild(x) - def clearChilren(self): + def clearChilren(self) -> None: if self._model: self._model.beginRemoveRows(self.index(), 0, self.childCount()) @@ -86,7 +86,7 @@ def row(self) -> int: def parentItem(self) -> Optional["TreeItem"]: return self._parentItem - def setModel(self, model: QAbstractItemModel): + def setModel(self, model: QAbstractItemModel) -> None: self._model = model def model(self) -> QAbstractItemModel: @@ -102,7 +102,7 @@ def index(self, column=0) -> QModelIndex: class TreeModel(QAbstractItemModel): column_names = ["File name"] - def __init__(self): + def __init__(self) -> None: super().__init__() self._root_item = TreeItem("") @@ -111,7 +111,7 @@ def __init__(self): def rootItem(self) -> TreeItem: return self._root_item - def setModelData(self, items: list[TreeItem]): + def setModelData(self, items: list[TreeItem]) -> None: self.beginResetModel() self._root_item.clearChilren() diff --git a/qt__pyqt__pyside__pyqode/simple_editor__save_as.py b/qt__pyqt__pyside__pyqode/simple_editor__save_as.py index d30663e8a..527c26c7e 100644 --- a/qt__pyqt__pyside__pyqode/simple_editor__save_as.py +++ b/qt__pyqt__pyside__pyqode/simple_editor__save_as.py @@ -8,7 +8,7 @@ class Example(Qt.QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Hi") @@ -20,7 +20,7 @@ def __init__(self): save_file_action = menu.addAction("Save As ...") save_file_action.triggered.connect(self.save_as) - def save_as(self): + def save_as(self) -> None: file_name, ok = Qt.QFileDialog.getSaveFileName(self) if not ok: return diff --git a/qt__pyqt__pyside__pyqode/simple_key_press_handler__keyPressEvent.py b/qt__pyqt__pyside__pyqode/simple_key_press_handler__keyPressEvent.py index bba957ad8..ffaef95d4 100644 --- a/qt__pyqt__pyside__pyqode/simple_key_press_handler__keyPressEvent.py +++ b/qt__pyqt__pyside__pyqode/simple_key_press_handler__keyPressEvent.py @@ -10,7 +10,7 @@ class MainWindow(QLabel): - def keyPressEvent(self, event: QKeyEvent): + def keyPressEvent(self, event: QKeyEvent) -> None: super().keyPressEvent(event) text = f"{event.key()} : {event.text()!r}" diff --git a/qt__pyqt__pyside__pyqode/site_screenshot__QWebEngineView.py b/qt__pyqt__pyside__pyqode/site_screenshot__QWebEngineView.py index dbcfa8144..81c903638 100644 --- a/qt__pyqt__pyside__pyqode/site_screenshot__QWebEngineView.py +++ b/qt__pyqt__pyside__pyqode/site_screenshot__QWebEngineView.py @@ -15,12 +15,12 @@ class Screenshot(QWebEngineView): - def __init__(self, app: QApplication): + def __init__(self, app: QApplication) -> None: super().__init__() self.app = app - def capture(self, url: str, output_file: str): + def capture(self, url: str, output_file: str) -> None: self.output_file = output_file self.load(QUrl(url)) self.loadFinished.connect(self.on_loaded) @@ -31,13 +31,13 @@ def capture(self, url: str, output_file: str): self.show() - def on_loaded(self): + def on_loaded(self) -> None: size = self.page().contentsSize().toSize() self.resize(size) # Wait for resize QTimer.singleShot(1000, self.take_screenshot) - def take_screenshot(self): + def take_screenshot(self) -> None: self.grab().save(self.output_file, "PNG") self.app.quit() diff --git a/qt__pyqt__pyside__pyqode/slide_show/main.py b/qt__pyqt__pyside__pyqode/slide_show/main.py index a69238e6a..2d2ab3ef8 100644 --- a/qt__pyqt__pyside__pyqode/slide_show/main.py +++ b/qt__pyqt__pyside__pyqode/slide_show/main.py @@ -48,7 +48,7 @@ class SlideShowWidget(QWidget): - def __init__(self, image_list: list[str]): + def __init__(self, image_list: list[str]) -> None: super().__init__() self.setWindowTitle("SlideShowWidget") @@ -66,11 +66,11 @@ def __init__(self, image_list: list[str]): self.resize(200, 200) - def set_timeout(self, timeout): + def set_timeout(self, timeout) -> None: self.timer.setInterval(timeout * 1000) self.timer.start() - def next(self): + def next(self) -> None: if not self.image_list: return @@ -82,7 +82,7 @@ def next(self): if self.current_index >= len(self.image_list): self.current_index = 0 - def resizeEvent(self, event): + def resizeEvent(self, event) -> None: super().resizeEvent(event) if self.source_image: @@ -91,7 +91,7 @@ def resizeEvent(self, event): Qt.KeepAspectRatio, ) - def paintEvent(self, event): + def paintEvent(self, event) -> None: if self.source_image is None: super().paintEvent(event) return diff --git a/qt__pyqt__pyside__pyqode/speech_recognition__microphone__google/main.py b/qt__pyqt__pyside__pyqode/speech_recognition__microphone__google/main.py index 5bd89d206..ee89ab6db 100644 --- a/qt__pyqt__pyside__pyqode/speech_recognition__microphone__google/main.py +++ b/qt__pyqt__pyside__pyqode/speech_recognition__microphone__google/main.py @@ -19,7 +19,7 @@ from PyQt5 import Qt -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -36,7 +36,7 @@ class SpeechRecognitionThread(Qt.QThread): language = "en-US" - def run(self): + def run(self) -> None: try: r = sr.Recognizer() @@ -65,7 +65,7 @@ def run(self): class Window(Qt.QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("speech_recognition__microphone__google") @@ -102,14 +102,14 @@ def __init__(self): # Start speech recognition self.pb_microphone.clicked.connect(self._speech_recognition_start) - def _speech_recognition_start(self): + def _speech_recognition_start(self) -> None: self.pb_microphone.setEnabled(False) self.pte_result.clear() self.thread.language = self.cb_lang.currentText() self.thread.start() - def _speech_recognition_finish(self): + def _speech_recognition_finish(self) -> None: self.pb_microphone.setEnabled(True) self.progress_bar.hide() diff --git a/qt__pyqt__pyside__pyqode/standart_qt_icon_to_base64.py b/qt__pyqt__pyside__pyqode/standart_qt_icon_to_base64.py index 2335c6dfb..7eb9b6cc0 100644 --- a/qt__pyqt__pyside__pyqode/standart_qt_icon_to_base64.py +++ b/qt__pyqt__pyside__pyqode/standart_qt_icon_to_base64.py @@ -21,7 +21,7 @@ # Для отлова всех исключений, которые в слотах Qt могут "затеряться" и привести к тихому падению -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) diff --git a/qt__pyqt__pyside__pyqode/students/add_student_dialog.py b/qt__pyqt__pyside__pyqode/students/add_student_dialog.py index 6c4df3f40..2feeec5ac 100644 --- a/qt__pyqt__pyside__pyqode/students/add_student_dialog.py +++ b/qt__pyqt__pyside__pyqode/students/add_student_dialog.py @@ -25,7 +25,7 @@ class AddStudentDialog(QDialog): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Add student dialog") @@ -49,7 +49,7 @@ def __init__(self): self.student = None - def accept(self): + def accept(self) -> None: super().accept() self.student = Student(self.name.text(), self.group.text()) diff --git a/qt__pyqt__pyside__pyqode/students/main_window.py b/qt__pyqt__pyside__pyqode/students/main_window.py index c00f2ea50..76c9a388e 100644 --- a/qt__pyqt__pyside__pyqode/students/main_window.py +++ b/qt__pyqt__pyside__pyqode/students/main_window.py @@ -11,7 +11,7 @@ class MyWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Students") @@ -48,7 +48,7 @@ def add(self): self.table.setItem(row, 0, QTableWidgetItem(student.name)) self.table.setItem(row, 1, QTableWidgetItem(student.group)) - def remove(self): + def remove(self) -> None: row = self.table.currentRow() if row != -1: self.table.removeRow(row) diff --git a/qt__pyqt__pyside__pyqode/students/student.py b/qt__pyqt__pyside__pyqode/students/student.py index b16bf218f..e662fd7b2 100644 --- a/qt__pyqt__pyside__pyqode/students/student.py +++ b/qt__pyqt__pyside__pyqode/students/student.py @@ -5,6 +5,6 @@ class Student: - def __init__(self, name, group): + def __init__(self, name, group) -> None: self.name = name self.group = group diff --git a/qt__pyqt__pyside__pyqode/tab_widget__QTabWidget__qt.py b/qt__pyqt__pyside__pyqode/tab_widget__QTabWidget__qt.py index bab934522..3273eb205 100644 --- a/qt__pyqt__pyside__pyqode/tab_widget__QTabWidget__qt.py +++ b/qt__pyqt__pyside__pyqode/tab_widget__QTabWidget__qt.py @@ -8,7 +8,7 @@ class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.tab_widget = QTabWidget() @@ -26,21 +26,21 @@ def __init__(self): self.update_states() - def update_states(self): + def update_states(self) -> None: self.action_add_tab.setEnabled(self.tab_widget.count() < 3) self.action_remove_tab.setEnabled(self.tab_widget.count() > 0) - def add_tab(self): + def add_tab(self) -> None: tab = QTextEdit() self.tab_widget.addTab(tab, str(self.tab_widget.count() + 1)) self.update_states() - def remove_tab(self): + def remove_tab(self) -> None: index = self.tab_widget.currentIndex() self._on_close_tab(index) - def _on_close_tab(self, index): + def _on_close_tab(self, index) -> None: if index == -1: return diff --git a/qt__pyqt__pyside__pyqode/table__cell__gif__setCellWidget/main.py b/qt__pyqt__pyside__pyqode/table__cell__gif__setCellWidget/main.py index e5b0f00d0..47a1fc4b9 100644 --- a/qt__pyqt__pyside__pyqode/table__cell__gif__setCellWidget/main.py +++ b/qt__pyqt__pyside__pyqode/table__cell__gif__setCellWidget/main.py @@ -8,7 +8,7 @@ class Window(Qt.QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.table = Qt.QTableWidget() diff --git a/qt__pyqt__pyside__pyqode/table__cell__icon_image/main.py b/qt__pyqt__pyside__pyqode/table__cell__icon_image/main.py index b897eb833..92108be5f 100644 --- a/qt__pyqt__pyside__pyqode/table__cell__icon_image/main.py +++ b/qt__pyqt__pyside__pyqode/table__cell__icon_image/main.py @@ -8,7 +8,7 @@ class Window(Qt.QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.table = Qt.QTableWidget() diff --git a/qt__pyqt__pyside__pyqode/test_sql_fetchMore__QSqlTableModel_QSqlQueryModel/main__QSqlQueryModel.py b/qt__pyqt__pyside__pyqode/test_sql_fetchMore__QSqlTableModel_QSqlQueryModel/main__QSqlQueryModel.py index 8b8bad9f9..b00be87fd 100644 --- a/qt__pyqt__pyside__pyqode/test_sql_fetchMore__QSqlTableModel_QSqlQueryModel/main__QSqlQueryModel.py +++ b/qt__pyqt__pyside__pyqode/test_sql_fetchMore__QSqlTableModel_QSqlQueryModel/main__QSqlQueryModel.py @@ -20,7 +20,7 @@ TABLE_ROW_COUNT = query.value(0) -def update_window_title(): +def update_window_title() -> None: mw.setWindowTitle(f"{model.rowCount()} / {TABLE_ROW_COUNT}") diff --git a/qt__pyqt__pyside__pyqode/test_sql_fetchMore__QSqlTableModel_QSqlQueryModel/main__QSqlTableModel.py b/qt__pyqt__pyside__pyqode/test_sql_fetchMore__QSqlTableModel_QSqlQueryModel/main__QSqlTableModel.py index 30043e79a..406b72d97 100644 --- a/qt__pyqt__pyside__pyqode/test_sql_fetchMore__QSqlTableModel_QSqlQueryModel/main__QSqlTableModel.py +++ b/qt__pyqt__pyside__pyqode/test_sql_fetchMore__QSqlTableModel_QSqlQueryModel/main__QSqlTableModel.py @@ -20,7 +20,7 @@ TABLE_ROW_COUNT = query.value(0) -def update_window_title(): +def update_window_title() -> None: mw.setWindowTitle(f"{model.rowCount()} / {TABLE_ROW_COUNT}") diff --git a/qt__pyqt__pyside__pyqode/window_as_glass__win7__using_DwmExtendFrameIntoClientArea.py b/qt__pyqt__pyside__pyqode/window_as_glass__win7__using_DwmExtendFrameIntoClientArea.py index bd3b4d768..8741b4b47 100644 --- a/qt__pyqt__pyside__pyqode/window_as_glass__win7__using_DwmExtendFrameIntoClientArea.py +++ b/qt__pyqt__pyside__pyqode/window_as_glass__win7__using_DwmExtendFrameIntoClientArea.py @@ -11,7 +11,7 @@ class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setAttribute(Qt.WA_TranslucentBackground) diff --git a/qt__pyqt__pyside__pyqode/xeyes_like/eyes/common.py b/qt__pyqt__pyside__pyqode/xeyes_like/eyes/common.py index fe120b7bd..c6340463d 100644 --- a/qt__pyqt__pyside__pyqode/xeyes_like/eyes/common.py +++ b/qt__pyqt__pyside__pyqode/xeyes_like/eyes/common.py @@ -136,7 +136,7 @@ def percent_number(number: float, percent: int) -> float: return number if percent < 0 else (number / 100) * percent -def set_top_of_all_windows(widget: QWidget, top: bool): +def set_top_of_all_windows(widget: QWidget, top: bool) -> None: old_pos: QPoint = widget.pos() if top: diff --git a/qt__pyqt__pyside__pyqode/xeyes_like/eyes/eye.py b/qt__pyqt__pyside__pyqode/xeyes_like/eyes/eye.py index eac0d61b7..033b89b1e 100644 --- a/qt__pyqt__pyside__pyqode/xeyes_like/eyes/eye.py +++ b/qt__pyqt__pyside__pyqode/xeyes_like/eyes/eye.py @@ -48,19 +48,19 @@ class Eye(EllipseObject): visible_iris: bool = True visible_pupil: bool = True - def draw(self, painter: QPainter): + def draw(self, painter: QPainter) -> None: self.draw_eye(painter) self.draw_iris(painter) self.draw_pupil(painter) - def draw_eye(self, painter: QPainter): + def draw_eye(self, painter: QPainter) -> None: painter.save() painter.setBrush(self.brush) painter.setPen(self.pen) painter.drawEllipse(self.center, self.radiusX, self.radiusY) painter.restore() - def draw_iris(self, painter: QPainter): + def draw_iris(self, painter: QPainter) -> None: if not self.visible_iris: return @@ -126,7 +126,7 @@ def draw_iris(self, painter: QPainter): painter.restore() - def draw_pupil(self, painter: QPainter): + def draw_pupil(self, painter: QPainter) -> None: if not self.visible_pupil: return diff --git a/qt__pyqt__pyside__pyqode/xeyes_like/eyes/eye_widget.py b/qt__pyqt__pyside__pyqode/xeyes_like/eyes/eye_widget.py index 29238e78a..44a0401d4 100644 --- a/qt__pyqt__pyside__pyqode/xeyes_like/eyes/eye_widget.py +++ b/qt__pyqt__pyside__pyqode/xeyes_like/eyes/eye_widget.py @@ -37,21 +37,21 @@ class EyeWidget(QWidget): position_look: QPoint = QPoint(0, 0) - def __init__(self, parent: QWidget = None): + def __init__(self, parent: QWidget = None) -> None: super().__init__(parent) self.set_diameter(MINIMAL_SIZE_EYE) - def set_diameter(self, diameter: int): + def set_diameter(self, diameter: int) -> None: diameter = max(diameter, MINIMAL_SIZE_EYE) self.setFixedSize(diameter, diameter) - def look_there(self, position: QPoint): + def look_there(self, position: QPoint) -> None: self.position_look = self.mapFromGlobal(position) self.update() - def paintEvent(self, event: QPaintEvent): + def paintEvent(self, event: QPaintEvent) -> None: painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) diff --git a/qt__pyqt__pyside__pyqode/xeyes_like/eyes/eyes_widget.py b/qt__pyqt__pyside__pyqode/xeyes_like/eyes/eyes_widget.py index 4faa37ee3..52dd700ea 100644 --- a/qt__pyqt__pyside__pyqode/xeyes_like/eyes/eyes_widget.py +++ b/qt__pyqt__pyside__pyqode/xeyes_like/eyes/eyes_widget.py @@ -19,7 +19,7 @@ class EyesWidget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.eyes: list[EyeWidget] = [EyeWidget(self) for _ in range(2)] @@ -28,14 +28,14 @@ def __init__(self): self.timer_cursor_pos.timeout.connect(self.refresh_look_there) self.timer_cursor_pos.start(30) - def refresh_look_there(self): + def refresh_look_there(self) -> None: self.update() position: QPoint = QCursor.pos() for eye in self.eyes: eye.look_there(position) - def update_minimum_size(self): + def update_minimum_size(self) -> None: if not self.eyes: return @@ -54,11 +54,11 @@ def update_minimum_size(self): min_height + D_INDENT_TOP + D_INDENT_BOTTOM, ) - def update_size(self): + def update_size(self) -> None: self.update_minimum_size() QApplication.instance().postEvent(self, QResizeEvent(self.size(), self.size())) - def resizeEvent(self, event: QResizeEvent): + def resizeEvent(self, event: QResizeEvent) -> None: super().resizeEvent(event) if not self.eyes: diff --git a/qt__pyqt__pyside__pyqode/xeyes_like/main.py b/qt__pyqt__pyside__pyqode/xeyes_like/main.py index 6b7e2007c..116b67526 100644 --- a/qt__pyqt__pyside__pyqode/xeyes_like/main.py +++ b/qt__pyqt__pyside__pyqode/xeyes_like/main.py @@ -14,7 +14,7 @@ # from support import set_top_of_all_windows -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) diff --git a/regexp_examples/sub__with_callback_on_match.py b/regexp_examples/sub__with_callback_on_match.py index a8ac2fc46..eeb487cea 100644 --- a/regexp_examples/sub__with_callback_on_match.py +++ b/regexp_examples/sub__with_callback_on_match.py @@ -37,7 +37,7 @@ counter = 3000 - 1 -def on_sub(_): +def on_sub(_) -> str: global counter counter += 1 diff --git a/remove_all_py__author__.py b/remove_all_py__author__.py index 76e5e555b..3589455ad 100644 --- a/remove_all_py__author__.py +++ b/remove_all_py__author__.py @@ -13,7 +13,7 @@ TEMPLATE_DIR = "No __author__ in {path}" -def process_file(file_name: Path): +def process_file(file_name: Path) -> None: text = file_name.read_text("utf-8") text = re.sub(r"__author__ = .+", "", text) text = re.sub(r"\n{4,}", "\n\n\n", text) diff --git a/remove_comments_from_python_code/clear_code.py b/remove_comments_from_python_code/clear_code.py index 0ad291ac1..ad016f2ea 100644 --- a/remove_comments_from_python_code/clear_code.py +++ b/remove_comments_from_python_code/clear_code.py @@ -47,7 +47,7 @@ def clear_code( return astunparse.unparse(tree) -def clear_file(file_name: str, new_file_name: str = None, encoding="utf-8"): +def clear_file(file_name: str, new_file_name: str = None, encoding="utf-8") -> None: if new_file_name is None: new_file_name = file_name @@ -58,7 +58,7 @@ def clear_file(file_name: str, new_file_name: str = None, encoding="utf-8"): f.write(text) -def clear_directory(dir_path: str): +def clear_directory(dir_path: str) -> None: new_dir_path = Path(dir_path + "_copy_clear") shutil.rmtree(new_dir_path, ignore_errors=True) diff --git a/requests__examples/pastebin3_requests.py b/requests__examples/pastebin3_requests.py index d02c07d1e..e79272506 100644 --- a/requests__examples/pastebin3_requests.py +++ b/requests__examples/pastebin3_requests.py @@ -145,7 +145,7 @@ def paste( return rs.text -def delete_paste(dev_key, user_key, paste_key): +def delete_paste(dev_key, user_key, paste_key) -> bool: """Deleting A Paste Created By A User :param dev_key: diff --git a/requests__examples/prodobavki.com_dobavki__print_info.py b/requests__examples/prodobavki.com_dobavki__print_info.py index 51097af64..ea06599ee 100644 --- a/requests__examples/prodobavki.com_dobavki__print_info.py +++ b/requests__examples/prodobavki.com_dobavki__print_info.py @@ -10,7 +10,7 @@ from bs4 import BeautifulSoup -def print_info(url): +def print_info(url) -> None: rs = requests.get(url) root = BeautifulSoup(rs.content, "lxml") diff --git a/requests__examples/timeout/manual.py b/requests__examples/timeout/manual.py new file mode 100644 index 000000000..aad110b7b --- /dev/null +++ b/requests__examples/timeout/manual.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +import requests + +TIMEOUT: float = 60 + +session = requests.Session() + +rs = session.get("https://httpbin.org/delay/1", timeout=TIMEOUT) +print(rs) + +rs = session.get("https://httpbin.org/delay/2", timeout=TIMEOUT) +print(rs) + +rs = session.get("https://httpbin.org/delay/3", timeout=TIMEOUT) +print(rs) diff --git a/requests__examples/timeout/manual_function.py b/requests__examples/timeout/manual_function.py new file mode 100644 index 000000000..60106ae6b --- /dev/null +++ b/requests__examples/timeout/manual_function.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +import requests +from requests.exceptions import RequestException + + +TIMEOUT: float = 60 + +session = requests.Session() + + +def do_get(url: str, **kwargs) -> requests.Response | None: + timeout: float | None = kwargs.get("timeout") + if timeout is None: + kwargs["timeout"] = TIMEOUT + + exc: Exception | None = None + for _ in range(5): + try: + return session.get(url, **kwargs) + except RequestException as e: # NOTE: Были ошибки сети + exc = e + + if exc: + raise exc + + +rs = do_get("https://httpbin.org/delay/1") +print(rs) + +rs = do_get("https://httpbin.org/delay/2") +print(rs) + +rs = do_get("https://httpbin.org/delay/3") +print(rs) diff --git a/requests__examples/timeout/patched_requests_send.py b/requests__examples/timeout/patched_requests_send.py new file mode 100644 index 000000000..d55f1a310 --- /dev/null +++ b/requests__examples/timeout/patched_requests_send.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +import requests + +TIMEOUT: float = 60 + + +if not hasattr(requests.Session.send, "_is_patched"): + original_requests_send = requests.Session.send + + def patched_requests_send(self, request, **kwargs): + if kwargs.get("timeout") is None: + kwargs["timeout"] = TIMEOUT + return original_requests_send(self, request, **kwargs) + + patched_requests_send._is_patched = True + requests.Session.send = patched_requests_send + + +session = requests.session() + +rs = session.get("https://httpbin.org/delay/1") +print(rs) + +rs = session.get("https://httpbin.org/delay/2") +print(rs) + +rs = session.get("https://httpbin.org/delay/3") +print(rs) diff --git a/requests__examples/timeout/timeout_http_adapter.py b/requests__examples/timeout/timeout_http_adapter.py new file mode 100644 index 000000000..6c7ba7be1 --- /dev/null +++ b/requests__examples/timeout/timeout_http_adapter.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +import requests +from requests.adapters import HTTPAdapter + +TIMEOUT: float = 60 + + +class TimeoutHttpAdapter(HTTPAdapter): + def __init__(self, timeout, *args, **kwargs) -> None: + self._timeout = timeout + super().__init__(*args, **kwargs) + + def send(self, request, timeout=None, **kwargs): + if timeout is None: + timeout = self._timeout + return super().send(request, timeout=timeout, **kwargs) + + +adapter = TimeoutHttpAdapter(timeout=TIMEOUT) + +session = requests.session() +session.mount("http://", adapter) +session.mount("https://", adapter) + + +rs = session.get("https://httpbin.org/delay/1") +print(rs) + +rs = session.get("https://httpbin.org/delay/2") +print(rs) + +rs = session.get("https://httpbin.org/delay/3") +print(rs) diff --git a/requests__examples/timeout/timeout_session.py b/requests__examples/timeout/timeout_session.py new file mode 100644 index 000000000..a02c0b348 --- /dev/null +++ b/requests__examples/timeout/timeout_session.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +import requests + +TIMEOUT: float = 60 + + +class TimeoutSession(requests.Session): + def request(self, *args, **kwargs): + kwargs.setdefault("timeout", TIMEOUT) + return super().request(*args, **kwargs) + + +session = TimeoutSession() + +rs = session.get("https://httpbin.org/delay/1") +print(rs) + +rs = session.get("https://httpbin.org/delay/2") +print(rs) + +rs = session.get("https://httpbin.org/delay/3") +print(rs) diff --git a/requests_multiprocessing_adapter.py b/requests_multiprocessing_adapter.py index 98f8753a3..01cd80567 100644 --- a/requests_multiprocessing_adapter.py +++ b/requests_multiprocessing_adapter.py @@ -64,12 +64,12 @@ class RunFuncThread(QThread): run_finished = pyqtSignal(object) about_error = pyqtSignal(Exception) - def __init__(self, func: Callable[[], Any]): + def __init__(self, func: Callable[[], Any]) -> None: super().__init__() self.func: Callable[[], Any] = func - def run(self): + def run(self) -> None: try: self.run_finished.emit(self.func()) except Exception as e: @@ -83,7 +83,7 @@ def do_get(url: str) -> str: class Addon(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.progress_bar = QProgressBar() @@ -113,16 +113,16 @@ def __init__(self): def get_data(self) -> Any: raise NotImplementedError() - def refresh(self): + def refresh(self) -> None: self.thread_run.start() - def _started(self): + def _started(self) -> None: self.progress_bar.show() self.n += 1 self.log.appendPlainText(f"[{self.n}] Started") - def _finished(self): + def _finished(self) -> None: self.progress_bar.hide() self.log.appendPlainText("Finished\n") @@ -149,7 +149,7 @@ def get_data(self) -> Any: class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() main_layout = QGridLayout(self) @@ -170,7 +170,7 @@ def __init__(self): self.timer.timeout.connect(self.refresh) self.timer.start() - def refresh(self): + def refresh(self) -> None: print("\n[REFRESH]") for addon in self.addons: diff --git a/rumble (vibration) a xbox 360 controller/gui.py b/rumble (vibration) a xbox 360 controller/gui.py index d5ec806b6..6f2e22289 100644 --- a/rumble (vibration) a xbox 360 controller/gui.py +++ b/rumble (vibration) a xbox 360 controller/gui.py @@ -11,7 +11,7 @@ class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Rumble (vibration) a xbox 360 controller") @@ -68,14 +68,14 @@ def __init__(self): central_widget.setLayout(layout) self.setCentralWidget(central_widget) - def _enable_vibration(self, enable): + def _enable_vibration(self, enable) -> None: if enable: self.timer.start() else: self.timer.stop() set_vibration(0, 0) - def _timeout(self): + def _timeout(self) -> None: set_vibration(self.left_motor.value(), self.right_motor.value()) diff --git a/rumble (vibration) a xbox 360 controller/rumble.py b/rumble (vibration) a xbox 360 controller/rumble.py index 7f1c6f5bf..2497e6ff7 100644 --- a/rumble (vibration) a xbox 360 controller/rumble.py +++ b/rumble (vibration) a xbox 360 controller/rumble.py @@ -28,7 +28,7 @@ class XINPUT_VIBRATION(ctypes.Structure): XInputSetState.restype = ctypes.c_uint -def set_vibration(left_motor, right_motor, controller=0): +def set_vibration(left_motor, right_motor, controller=0) -> None: if type(left_motor) == float: left_motor_value = int(left_motor * 65535) else: @@ -43,7 +43,7 @@ def set_vibration(left_motor, right_motor, controller=0): XInputSetState(controller, ctypes.byref(vibration)) -def set_vibration_with_duration(left_motor, right_motor, controller=0, duration=1.0): +def set_vibration_with_duration(left_motor, right_motor, controller=0, duration=1.0) -> None: t = time.time() while True: diff --git a/rumble (vibration) a xbox 360 controller/web/main.py b/rumble (vibration) a xbox 360 controller/web/main.py index 32c049696..3af36236b 100644 --- a/rumble (vibration) a xbox 360 controller/web/main.py +++ b/rumble (vibration) a xbox 360 controller/web/main.py @@ -210,7 +210,7 @@ def get_status(): return jsonify(data) -def vibration_tick(): +def vibration_tick() -> None: while True: if DEBUG: print( diff --git a/run_processes_with_output_in_web/common.py b/run_processes_with_output_in_web/common.py index 7a9e2ceca..09a5cec5c 100644 --- a/run_processes_with_output_in_web/common.py +++ b/run_processes_with_output_in_web/common.py @@ -37,14 +37,14 @@ class Task: process_return_code: int = None __need_stop: bool = field(init=False, repr=False, default=False) - def run(self, threaded: bool = False): + def run(self, threaded: bool = False) -> None: self.status = TaskStatusEnum.Running - def process_callback(process: Popen): + def process_callback(process: Popen) -> None: self.process = process self.process_id = self.process.pid - def on_exit(): + def on_exit() -> None: self.status = TaskStatusEnum.Stopped if self.__need_stop else TaskStatusEnum.Finished self.process_return_code = self.process.returncode @@ -64,16 +64,16 @@ def stop_on() -> bool: stop_on=stop_on, ) - def stop(self): + def stop(self) -> None: self.__need_stop = True if __name__ == "__main__": - def process_stdout(text): + def process_stdout(text) -> None: print("process_stdout:", repr(text)) - def process_stderr(text): + def process_stderr(text) -> None: print("process_stderr:", repr(text)) task = Task( diff --git a/run_processes_with_output_in_web/main.py b/run_processes_with_output_in_web/main.py index c636fd55f..94bab0193 100644 --- a/run_processes_with_output_in_web/main.py +++ b/run_processes_with_output_in_web/main.py @@ -47,8 +47,8 @@ def index(): @socketio.on("run") -def run(message): - def send_update_task(stdout: str = None, stderr: str = None): +def run(message) -> None: + def send_update_task(stdout: str = None, stderr: str = None) -> None: data = dict( id=task.id, command=task.command, @@ -61,10 +61,10 @@ def send_update_task(stdout: str = None, stderr: str = None): print("send_update_task", data) emit("update_task", data) - def process_stdout(text: str): + def process_stdout(text: str) -> None: send_update_task(stdout=text) - def process_stderr(text: str): + def process_stderr(text: str) -> None: send_update_task(stderr=text) task = Task( diff --git a/scapy__examples/sniff__gui__pyqt5/main.py b/scapy__examples/sniff__gui__pyqt5/main.py index 8703fb543..1cfe1f473 100644 --- a/scapy__examples/sniff__gui__pyqt5/main.py +++ b/scapy__examples/sniff__gui__pyqt5/main.py @@ -15,7 +15,7 @@ from scapy.all import sniff -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -30,18 +30,18 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class SniffThread(Qt.QThread): about_new_data = Qt.pyqtSignal(str) - def _packethandler(self, pkt): + def _packethandler(self, pkt) -> None: data = pkt.summary() print(data) self.about_new_data.emit(data) - def run(self): + def run(self) -> None: sniff(filter="tcp", prn=self._packethandler) class MainWindow(Qt.QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Sniff with scapy") @@ -74,7 +74,7 @@ def __init__(self): self.thread.about_new_data.connect(self._append_new_item) self.thread.start() - def _append_new_item(self, data): + def _append_new_item(self, data) -> None: # Если флаг не стоит if not self.cb_log.isChecked(): return diff --git a/scapy__examples/sniff_tcp.py b/scapy__examples/sniff_tcp.py index 6d3c28627..a8466001f 100644 --- a/scapy__examples/sniff_tcp.py +++ b/scapy__examples/sniff_tcp.py @@ -9,7 +9,7 @@ from scapy.all import sniff -def _packethandler(pkt): +def _packethandler(pkt) -> None: data = pkt.summary() print(data) diff --git a/schedule_examples/make_dir_every_day_at_06.00.py b/schedule_examples/make_dir_every_day_at_06.00.py index 126ea5b0c..d6a6d04c0 100644 --- a/schedule_examples/make_dir_every_day_at_06.00.py +++ b/schedule_examples/make_dir_every_day_at_06.00.py @@ -10,7 +10,7 @@ from datetime import date -def job(): +def job() -> None: print(date.today()) try: diff --git a/schedule_examples/you_need_to_rest.py b/schedule_examples/you_need_to_rest.py index 02616b5a4..a7a2aef19 100644 --- a/schedule_examples/you_need_to_rest.py +++ b/schedule_examples/you_need_to_rest.py @@ -15,7 +15,7 @@ # 60 * 1000 * 10 -- 10 minutes -def show_message(text, timeout=60 * 1000 * 10): +def show_message(text, timeout=60 * 1000 * 10) -> None: print(f"show_message: {text!r}") msg = QMessageBox() diff --git a/schedule_examples/you_need_to_rest_with_tray/main.py b/schedule_examples/you_need_to_rest_with_tray/main.py index 7b2d4f570..7a0712502 100644 --- a/schedule_examples/you_need_to_rest_with_tray/main.py +++ b/schedule_examples/you_need_to_rest_with_tray/main.py @@ -19,7 +19,7 @@ from PyQt5.QtCore import * -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -42,7 +42,7 @@ class RunSchedulerThread(QThread): about_show_message = pyqtSignal(str) about_description = pyqtSignal(str) - def run(self): + def run(self) -> None: schedule.every().day.at("11:00").do(self.about_show_message.emit, "Пора в столовку") schedule.every().day.at("13:00").do(self.about_show_message.emit, "Иди прогуляйся") schedule.every().day.at("15:00").do(self.about_show_message.emit, "Иди прогуляйся") diff --git a/search_and_delete_of_empty_folders/delete.py b/search_and_delete_of_empty_folders/delete.py index ab64a7415..6020dbf30 100644 --- a/search_and_delete_of_empty_folders/delete.py +++ b/search_and_delete_of_empty_folders/delete.py @@ -9,7 +9,7 @@ from search import search_of_empty_folders -def delete_of_empty_folders(dir, empty_folders=None): +def delete_of_empty_folders(dir, empty_folders=None) -> None: if empty_folders is None: empty_folders = search_of_empty_folders(dir) diff --git a/search_for_similar_images__perceptual_hash__phash/db.py b/search_for_similar_images__perceptual_hash__phash/db.py index 8b005582b..ae3520b7e 100644 --- a/search_for_similar_images__perceptual_hash__phash/db.py +++ b/search_for_similar_images__perceptual_hash__phash/db.py @@ -25,7 +25,7 @@ def create_connect() -> sqlite3.Connection: return sqlite3.connect(DB_FILE_NAME) -def init_db(): +def init_db() -> None: # Создание базы и таблицы with create_connect() as connect: connect.execute( @@ -118,7 +118,7 @@ def db_get_all() -> list[dict]: return connect.execute("SELECT * FROM ImageHash").fetchall() -def db_create_backup(backup_dir="backup"): +def db_create_backup(backup_dir="backup") -> None: file_name = str(datetime.today().date()) + ".sqlite" os.makedirs(backup_dir, exist_ok=True) diff --git a/search_for_similar_images__perceptual_hash__phash/main.py b/search_for_similar_images__perceptual_hash__phash/main.py index c3e306cfc..5f4ab678d 100644 --- a/search_for_similar_images__perceptual_hash__phash/main.py +++ b/search_for_similar_images__perceptual_hash__phash/main.py @@ -57,7 +57,7 @@ from ui.CrossSearchSimilarImagesDialog import CrossSearchSimilarImagesDialog -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -73,7 +73,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle(str(Path(__file__).parent.name)) @@ -84,7 +84,7 @@ def __init__(self): self._update_states() - def _fill_menus(self): + def _fill_menus(self) -> None: self.menu_file = self.menuBar().addMenu("File") action_exit = self.menu_file.addAction("Exit") action_exit.triggered.connect(self.close) @@ -99,7 +99,7 @@ def _fill_menus(self): action_about = self.menu_help.addAction("About") action_about.triggered.connect(lambda: AboutDialog(self).exec()) - def _fill_toolbars(self): + def _fill_toolbars(self) -> None: # tool_bar_general self.tool_bar_general = self.addToolBar("General") @@ -203,7 +203,7 @@ def _fill_toolbars(self): ) # tool_bar_similar_image_control - def _fill_dockwidgets(self): + def _fill_dockwidgets(self) -> None: self.indexing_settings = IndexingSettingsWidget() indexing_settings_widget_dock_widget = QDockWidget( self.indexing_settings.windowTitle() @@ -222,7 +222,7 @@ def _fill_dockwidgets(self): Qt.RightDockWidgetArea, search_for_similar_settings_dock_widget ) - def _fill_ui(self): + def _fill_ui(self) -> None: self._fill_menus() self._fill_toolbars() self._fill_dockwidgets() @@ -312,7 +312,7 @@ def _fill_ui(self): self.setCentralWidget(splitter) - def _update_states(self): + def _update_states(self) -> None: file_name_indexed = self.list_indexed_images_widget.currentFileName() has_index_list_images_widget = bool(file_name_indexed) @@ -369,7 +369,7 @@ def _update_states(self): self.model_similar_images.fileCount ) - def fill_images_db(self): + def fill_images_db(self) -> None: self.image_by_hashes.clear() for row in db_get_all(): @@ -432,7 +432,7 @@ def _get_files(self, path_dir: Path, suffixes: list) -> list: return file_names - def start_indexing(self): + def start_indexing(self) -> None: path_dir = self.indexing_settings.dir_box.getValue() path_dir = Path(path_dir).resolve() if not path_dir.is_dir(): @@ -515,7 +515,7 @@ def start_indexing(self): print(f"\nTotal: {default_timer() - time_start:.2f} secs. Added: {number}") - def start_search_for_similar(self): + def start_search_for_similar(self) -> None: file_name = self.list_indexed_images_widget.currentFileName() if not file_name: return @@ -603,7 +603,7 @@ def start_search_for_similar(self): self.model_similar_images.set_file_list(results) - def cross_search_similar_images(self): + def cross_search_similar_images(self) -> None: hash_algo = self.search_for_similar_settings.cb_algo.currentText() max_score = self.search_for_similar_settings.sb_max_score.value() @@ -625,41 +625,41 @@ def cross_search_similar_images(self): # self.list_images_widget_similar.setCurrentIndex(index) # self.list_images_widget_similar.scrollTo(index) - def select_indexed_image(self): + def select_indexed_image(self) -> None: file_name = self.list_indexed_images_widget.currentFileName() explore(file_name) - def open_indexed_image_directory(self): + def open_indexed_image_directory(self) -> None: file_name = self.list_indexed_images_widget.currentFileName() explore(Path(file_name).parent, select=False) - def run_indexed_image(self): + def run_indexed_image(self) -> None: file_name = self.list_indexed_images_widget.currentFileName() explore(file_name, select=False) - def view_details_indexed_image(self): + def view_details_indexed_image(self) -> None: file_name = self.list_indexed_images_widget.currentFileName() data = self.image_by_hashes[file_name] ImageHashDetailsDialog(file_name, data, parent=self).show() - def select_similar_image(self): + def select_similar_image(self) -> None: file_name = self.list_images_widget_similar.currentFileName() explore(file_name) - def open_similar_image_directory(self): + def open_similar_image_directory(self) -> None: file_name = self.list_images_widget_similar.currentFileName() explore(Path(file_name).parent, select=False) - def run_similar_image(self): + def run_similar_image(self) -> None: file_name = self.list_images_widget_similar.currentFileName() explore(file_name, select=False) - def view_details_similar_image(self): + def view_details_similar_image(self) -> None: file_name = self.list_images_widget_similar.currentFileName() data = self.image_by_hashes[file_name] ImageHashDetailsDialog(file_name, data, parent=self).show() - def read_settings(self): + def read_settings(self) -> None: ini = QSettings(SETTINGS_FILE_NAME, QSettings.IniFormat) state = ini.value("MainWindow_State") @@ -673,7 +673,7 @@ def read_settings(self): self.indexing_settings.read_settings(ini) self.search_for_similar_settings.read_settings(ini) - def write_settings(self): + def write_settings(self) -> None: ini = QSettings(SETTINGS_FILE_NAME, QSettings.IniFormat) ini.setValue("MainWindow_State", self.saveState()) ini.setValue("MainWindow_Geometry", self.saveGeometry()) @@ -681,7 +681,7 @@ def write_settings(self): self.indexing_settings.write_settings(ini) self.search_for_similar_settings.write_settings(ini) - def closeEvent(self, event): + def closeEvent(self, event) -> None: self.write_settings() QApplication.closeAllWindows() diff --git a/search_for_similar_images__perceptual_hash__phash/ui/AboutDialog.py b/search_for_similar_images__perceptual_hash__phash/ui/AboutDialog.py index ad6575db3..2a7f1e008 100644 --- a/search_for_similar_images__perceptual_hash__phash/ui/AboutDialog.py +++ b/search_for_similar_images__perceptual_hash__phash/ui/AboutDialog.py @@ -8,7 +8,7 @@ class AboutDialog(QDialog): - def __init__(self, parent=None): + def __init__(self, parent=None) -> None: super().__init__(parent) self.setWindowTitle("About") diff --git a/search_for_similar_images__perceptual_hash__phash/ui/CrossSearchSimilarImagesDialog.py b/search_for_similar_images__perceptual_hash__phash/ui/CrossSearchSimilarImagesDialog.py index 83cb3d211..f846360be 100644 --- a/search_for_similar_images__perceptual_hash__phash/ui/CrossSearchSimilarImagesDialog.py +++ b/search_for_similar_images__perceptual_hash__phash/ui/CrossSearchSimilarImagesDialog.py @@ -25,7 +25,7 @@ class CrossSearchSimilarImagesThread(QThread): def __init__( self, image_by_hashes: dict = None, hash_algo: str = None, max_score: int = None - ): + ) -> None: super().__init__() self.image_by_hashes = image_by_hashes @@ -73,7 +73,7 @@ class CrossSearchSimilarImagesDialog(QDialog): window_title = "Cross search similar images" - def __init__(self, parent=None): + def __init__(self, parent=None) -> None: super().__init__(parent) self.setWindowTitle(self.window_title) @@ -106,7 +106,7 @@ def __init__(self, parent=None): layout.addWidget(self.tree_widget) self.setLayout(layout) - def _on_about_found_similars(self, file_name: str, similars: list[str]): + def _on_about_found_similars(self, file_name: str, similars: list[str]) -> None: item = QTreeWidgetItem([f"{file_name} ({len(similars)})"]) item.setData(0, Qt.UserRole, file_name) @@ -117,7 +117,7 @@ def _on_about_found_similars(self, file_name: str, similars: list[str]): child.setData(0, Qt.UserRole, x) item.addChild(child) - def start(self, image_by_hashes: dict, hash_algo: str, max_score: int): + def start(self, image_by_hashes: dict, hash_algo: str, max_score: int) -> None: self.setWindowTitle( f"{self.window_title}. hash_algo={hash_algo} max_score={max_score}" ) diff --git a/search_for_similar_images__perceptual_hash__phash/ui/FieldsProgressDialog.py b/search_for_similar_images__perceptual_hash__phash/ui/FieldsProgressDialog.py index 3c1a6e0da..88c45f0f7 100644 --- a/search_for_similar_images__perceptual_hash__phash/ui/FieldsProgressDialog.py +++ b/search_for_similar_images__perceptual_hash__phash/ui/FieldsProgressDialog.py @@ -18,7 +18,7 @@ def __init__( window_title, label_text="Operation in progress...", parent=None, - ): + ) -> None: super().__init__(parent) self.setWindowModality(Qt.WindowModal) @@ -30,7 +30,7 @@ def __init__( self.setLabelText(label_text) - def setFields(self, fields: dict): + def setFields(self, fields: dict) -> None: self._label.setFields(fields) # NOTE: Для вызова внутреннего ensureSizeIsAtLeastSizeHint, без которого не будет diff --git a/search_for_similar_images__perceptual_hash__phash/ui/FlatProgressBar.py b/search_for_similar_images__perceptual_hash__phash/ui/FlatProgressBar.py index 585fac9fd..888cb3c5d 100644 --- a/search_for_similar_images__perceptual_hash__phash/ui/FlatProgressBar.py +++ b/search_for_similar_images__perceptual_hash__phash/ui/FlatProgressBar.py @@ -8,7 +8,7 @@ class FlatProgressBar(QProgressBar): - def __init__(self, *args): + def __init__(self, *args) -> None: super().__init__(*args) self.setTextVisible(False) @@ -28,7 +28,7 @@ def __init__(self, *args): """ ) - def setValue(self, value: int): + def setValue(self, value: int) -> None: super().setValue(value) self.setToolTip( diff --git a/search_for_similar_images__perceptual_hash__phash/ui/ImageHashDetailsDialog.py b/search_for_similar_images__perceptual_hash__phash/ui/ImageHashDetailsDialog.py index d11a94d8d..b32ae3b5c 100644 --- a/search_for_similar_images__perceptual_hash__phash/ui/ImageHashDetailsDialog.py +++ b/search_for_similar_images__perceptual_hash__phash/ui/ImageHashDetailsDialog.py @@ -11,7 +11,7 @@ class ImageHashDetailsDialog(QDialog): - def __init__(self, file_name: str, data: dict, parent=None): + def __init__(self, file_name: str, data: dict, parent=None) -> None: super().__init__(parent) self.setWindowTitle("ImageHash Details") diff --git a/search_for_similar_images__perceptual_hash__phash/ui/IndexingSettingsWidget.py b/search_for_similar_images__perceptual_hash__phash/ui/IndexingSettingsWidget.py index c11988e3c..88108f4d3 100644 --- a/search_for_similar_images__perceptual_hash__phash/ui/IndexingSettingsWidget.py +++ b/search_for_similar_images__perceptual_hash__phash/ui/IndexingSettingsWidget.py @@ -13,7 +13,7 @@ class IndexingSettingsWidget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Indexing") @@ -27,7 +27,7 @@ def __init__(self): self.setLayout(layout) - def read_settings(self, ini: QSettings): + def read_settings(self, ini: QSettings) -> None: ini.beginGroup(self.__class__.__name__) self.dir_box.setValue(ini.value("dir_box", USER_PICTURES_DIR)) @@ -35,7 +35,7 @@ def read_settings(self, ini: QSettings): ini.endGroup() - def write_settings(self, ini: QSettings): + def write_settings(self, ini: QSettings) -> None: ini.beginGroup(self.__class__.__name__) ini.setValue("dir_box", self.dir_box.getValue()) diff --git a/search_for_similar_images__perceptual_hash__phash/ui/KeyValueLabel.py b/search_for_similar_images__perceptual_hash__phash/ui/KeyValueLabel.py index f36349310..21829472c 100644 --- a/search_for_similar_images__perceptual_hash__phash/ui/KeyValueLabel.py +++ b/search_for_similar_images__perceptual_hash__phash/ui/KeyValueLabel.py @@ -8,7 +8,7 @@ class KeyValueLabel(QLabel): - def __init__(self, parent=None): + def __init__(self, parent=None) -> None: super().__init__(parent) self._field_by_row = dict() @@ -17,7 +17,7 @@ def __init__(self, parent=None): self.setMinimumSize(200, 150) - def setFields(self, fields: dict): + def setFields(self, fields: dict) -> None: while not self._layout.isEmpty(): self._layout.takeAt(0) diff --git a/search_for_similar_images__perceptual_hash__phash/ui/ListImagesWidget.py b/search_for_similar_images__perceptual_hash__phash/ui/ListImagesWidget.py index a466fdb20..6440c3dcd 100644 --- a/search_for_similar_images__perceptual_hash__phash/ui/ListImagesWidget.py +++ b/search_for_similar_images__perceptual_hash__phash/ui/ListImagesWidget.py @@ -11,7 +11,7 @@ class ListImagesWidget(QListView): - def __init__(self, icon_width, icon_height, image_cache, file_name_index): + def __init__(self, icon_width, icon_height, image_cache, file_name_index) -> None: super().__init__() self.setMovement(QListView.Static) diff --git a/search_for_similar_images__perceptual_hash__phash/ui/SearchForSimilarSettingsWidget.py b/search_for_similar_images__perceptual_hash__phash/ui/SearchForSimilarSettingsWidget.py index 4f9c1d689..3dee00e31 100644 --- a/search_for_similar_images__perceptual_hash__phash/ui/SearchForSimilarSettingsWidget.py +++ b/search_for_similar_images__perceptual_hash__phash/ui/SearchForSimilarSettingsWidget.py @@ -17,7 +17,7 @@ class SearchForSimilarSettingsWidget(QWidget): about_mark_matching = pyqtSignal(bool) - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Search for similar") @@ -37,7 +37,7 @@ def __init__(self): self.setLayout(layout) - def read_settings(self, ini: QSettings): + def read_settings(self, ini: QSettings) -> None: ini.beginGroup(self.__class__.__name__) self.cb_algo.setCurrentText(ini.value("algo", DEFAULT_IMAGE_HASH_ALGO)) @@ -48,7 +48,7 @@ def read_settings(self, ini: QSettings): ini.endGroup() - def write_settings(self, ini: QSettings): + def write_settings(self, ini: QSettings) -> None: ini.beginGroup(self.__class__.__name__) ini.setValue("algo", self.cb_algo.currentText()) diff --git a/search_for_similar_images__perceptual_hash__phash/ui/SelectDirBox.py b/search_for_similar_images__perceptual_hash__phash/ui/SelectDirBox.py index 627707bab..7fcd8e81e 100644 --- a/search_for_similar_images__perceptual_hash__phash/ui/SelectDirBox.py +++ b/search_for_similar_images__perceptual_hash__phash/ui/SelectDirBox.py @@ -25,7 +25,7 @@ class SelectDirBox(QWidget): valueChanged = pyqtSignal(str) valueEdited = pyqtSignal(str) - def __init__(self, value="", visible_label=True): + def __init__(self, value="", visible_label=True) -> None: super().__init__() self._label = QLabel("Directory:") @@ -58,26 +58,26 @@ def __init__(self, value="", visible_label=True): self.setLayout(layout) - def setValue(self, value: str): + def setValue(self, value: str) -> None: self._value.setText(value) self._value.setToolTip(value) def getValue(self) -> str: return self._value.text() - def _on_select_path(self): + def _on_select_path(self) -> None: path = QFileDialog.getExistingDirectory(self, None, self._value.text()) if not path: return self.setValue(path) - def _on_open_dir(self): + def _on_open_dir(self) -> None: path = self._value.text() if os.path.isdir(path): os.startfile(path) - def resizeEvent(self, event): + def resizeEvent(self, event) -> None: super().resizeEvent(event) self._button_select_path.setFixedHeight(self._value.height()) diff --git a/search_for_similar_images__perceptual_hash__phash/ui/ThumbnailDelegate.py b/search_for_similar_images__perceptual_hash__phash/ui/ThumbnailDelegate.py index aa3b9d0d3..0a788084b 100644 --- a/search_for_similar_images__perceptual_hash__phash/ui/ThumbnailDelegate.py +++ b/search_for_similar_images__perceptual_hash__phash/ui/ThumbnailDelegate.py @@ -42,7 +42,7 @@ def __init__( height, image_cache: dict, file_name_index=0, - ): + ) -> None: super().__init__() self.width = width @@ -53,11 +53,11 @@ def __init__( self.image_cache = image_cache self.file_name_index = file_name_index - def _on_about_image(self, file_name: str, image: QImage, index: QModelIndex): + def _on_about_image(self, file_name: str, image: QImage, index: QModelIndex) -> None: self.image_cache[file_name] = image self.view.update(index) - def paint(self, painter: QPainter, opt: QStyleOptionViewItem, index: QModelIndex): + def paint(self, painter: QPainter, opt: QStyleOptionViewItem, index: QModelIndex) -> None: rect = opt.rect self.initStyleOption(opt, index) diff --git a/search_of_empty_folders_in_all_disk__multithreading_multiprocessing/gui.py b/search_of_empty_folders_in_all_disk__multithreading_multiprocessing/gui.py index a83f10a2a..5c841c767 100644 --- a/search_of_empty_folders_in_all_disk__multithreading_multiprocessing/gui.py +++ b/search_of_empty_folders_in_all_disk__multithreading_multiprocessing/gui.py @@ -30,7 +30,7 @@ from main import sizeof_fmt -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -46,7 +46,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class SearchThread(QThread): about_new_text = pyqtSignal(str) - def run(self): + def run(self) -> None: # "-u : unbuffered binary stdout and stderr." Иначе, при запуске питона, пока н завершится скрипт # данные с stdout и stderr не будут получены command = [sys.executable, "-u", "main.py"] @@ -62,7 +62,7 @@ def run(self): class EmptyFoldersTab(QWidget): about_new_text = pyqtSignal(str) - def __init__(self): + def __init__(self) -> None: super().__init__() self.line_list = None @@ -99,7 +99,7 @@ def __init__(self): layout.addWidget(self.view) self.setLayout(layout) - def _on_show_in_explorer(self, index=None): + def _on_show_in_explorer(self, index=None) -> None: if not index: index = self.view.currentIndex() if index is None: @@ -112,7 +112,7 @@ def _on_show_in_explorer(self, index=None): os.system(cmd) - def _on_remove_folder(self): + def _on_remove_folder(self) -> None: index = self.view.currentIndex() if index is None: return @@ -143,7 +143,7 @@ def _on_remove_folder(self): except PermissionError as e: QMessageBox.critical(None, "PermissionError", str(e)) - def _reread_list(self): + def _reread_list(self) -> None: if not self.line_list: return @@ -161,7 +161,7 @@ def _reread_list(self): if new_line_list: self.view.setCurrentIndex(self.model.index(0)) - def fill(self, file_name): + def fill(self, file_name) -> None: self.about_new_text.emit("Start fill: " + file_name) t = time.clock() @@ -185,7 +185,7 @@ def fill(self, file_name): class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle(f"search_of_empty_folders [{sys.executable}]") @@ -214,11 +214,11 @@ def __init__(self): self.setCentralWidget(self.tab_widget) - def append_log(self, text): + def append_log(self, text) -> None: time_str = datetime.today().strftime("%H:%M:%S") self.text_edit_log.append(time_str + ": " + text) - def _start_search(self): + def _start_search(self) -> None: t = time.clock() self.append_log("Start search") diff --git a/search_of_empty_folders_in_all_disk__multithreading_multiprocessing/main.py b/search_of_empty_folders_in_all_disk__multithreading_multiprocessing/main.py index a65ef0a85..05b2f1e39 100644 --- a/search_of_empty_folders_in_all_disk__multithreading_multiprocessing/main.py +++ b/search_of_empty_folders_in_all_disk__multithreading_multiprocessing/main.py @@ -20,7 +20,7 @@ from humanize import naturalsize as sizeof_fmt -def search_empty_folders(disk): +def search_empty_folders(disk) -> None: disk_letter = disk[0] file_name = f"log of {disk_letter}.txt" diff --git a/selenium__examples/PyQt5_with_selenium.py b/selenium__examples/PyQt5_with_selenium.py index a27010003..3cf6e0471 100644 --- a/selenium__examples/PyQt5_with_selenium.py +++ b/selenium__examples/PyQt5_with_selenium.py @@ -33,7 +33,7 @@ class StackOverFlowBotThread(QThread): about_search_result = pyqtSignal(str, str) about_change_title = pyqtSignal(str) - def __init__(self): + def __init__(self) -> None: super().__init__() self.is_running = False @@ -46,10 +46,10 @@ def __init__(self): self._search = None - def search(self, text: str): + def search(self, text: str) -> None: self._search = text - def run(self): + def run(self) -> None: self.is_running = True self.driver.get(URL) @@ -85,7 +85,7 @@ def run(self): finally: self.driver.quit() - def quit(self): + def quit(self) -> None: self.driver.quit() self.is_running = False @@ -93,7 +93,7 @@ def quit(self): class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.search = QLineEdit("gil9red") @@ -122,16 +122,16 @@ def __init__(self): central_widget.setLayout(main_layout) self.setCentralWidget(central_widget) - def on_search(self): + def on_search(self) -> None: self.result.clear() text = self.search.text() self.bot_thread.search(text) - def on_search_result(self, title, url): + def on_search_result(self, title, url) -> None: self.result.append(f'{title}') - def closeEvent(self, event): + def closeEvent(self, event) -> None: self.bot_thread.quit() diff --git a/selenium__examples/music_yandex_ru/get_all_tracks_playlist/common.py b/selenium__examples/music_yandex_ru/get_all_tracks_playlist/common.py index 4857eafbb..7255f2c37 100644 --- a/selenium__examples/music_yandex_ru/get_all_tracks_playlist/common.py +++ b/selenium__examples/music_yandex_ru/get_all_tracks_playlist/common.py @@ -72,7 +72,7 @@ def get_track(track_el) -> Track: return Track(title, artists, length, available) -def print_statistic(tracks: list[Track]): +def print_statistic(tracks: list[Track]) -> None: print_fmt = "{:%s}. {}" % len(str(len(tracks))) unavailable_tracks = [] @@ -93,7 +93,7 @@ def print_statistic(tracks: list[Track]): print(print_fmt.format(i, track.get_full_title())) -def dump(tracks: list[Track], file_name: str | Path): +def dump(tracks: list[Track], file_name: str | Path) -> None: json.dump( tracks, open(file_name, "w", encoding="utf-8"), diff --git a/selenium__examples/ru_stackoverflow_counting_negative_reputation/main.py b/selenium__examples/ru_stackoverflow_counting_negative_reputation/main.py index c74284944..f72193100 100644 --- a/selenium__examples/ru_stackoverflow_counting_negative_reputation/main.py +++ b/selenium__examples/ru_stackoverflow_counting_negative_reputation/main.py @@ -19,7 +19,7 @@ def get_int(element) -> int: return int(value) -def scroll_and_click(element, sleep: float = None): +def scroll_and_click(element, sleep: float = None) -> None: driver.execute_script("arguments[0].scrollIntoView()", element) element.click() diff --git a/show_console_triangle.py b/show_console_triangle.py index c7df79f02..40b990099 100644 --- a/show_console_triangle.py +++ b/show_console_triangle.py @@ -4,7 +4,7 @@ __author__ = "ipetrash" -def print_triangle(n): +def print_triangle(n) -> None: """ n = 5 diff --git a/shutdown.py b/shutdown.py index f25ea0244..5a5b0743b 100644 --- a/shutdown.py +++ b/shutdown.py @@ -9,7 +9,7 @@ import os -def shutdown(off_pc=19): +def shutdown(off_pc=19) -> None: while time.localtime().tm_hour != off_pc: time.sleep(60) # Ожидание 1 минута diff --git a/simple_console_progress_bar.py b/simple_console_progress_bar.py index 73c610637..bf621efec 100644 --- a/simple_console_progress_bar.py +++ b/simple_console_progress_bar.py @@ -8,7 +8,7 @@ import time -def loop(): +def loop() -> None: for c in itertools.cycle("|/-\\"): print(c + "\b", flush=True, end="") diff --git a/simplecrypt__example/encrypt_with_zip_compress.py b/simplecrypt__example/encrypt_with_zip_compress.py index e1bb4ca74..2a2cc1722 100644 --- a/simplecrypt__example/encrypt_with_zip_compress.py +++ b/simplecrypt__example/encrypt_with_zip_compress.py @@ -67,7 +67,7 @@ def get_logger(name): log = get_logger("encrypt_with_zip_compress") -def run_crypt_decrypt(message, password, use_zip=False, show_hex=False): +def run_crypt_decrypt(message, password, use_zip=False, show_hex=False) -> None: start_time = time.time() text_hex = binascii.hexlify(message) diff --git a/simplecrypt__example/encrypt_with_zlib_compress.py b/simplecrypt__example/encrypt_with_zlib_compress.py index 8abd73a21..6feccec42 100644 --- a/simplecrypt__example/encrypt_with_zlib_compress.py +++ b/simplecrypt__example/encrypt_with_zlib_compress.py @@ -55,7 +55,7 @@ def get_logger(name): log = get_logger("encrypt_with_zlib_compress") -def crypt_decrypt_test(message, password, use_zlib=False, show_hex=False): +def crypt_decrypt_test(message, password, use_zlib=False, show_hex=False) -> None: start_time = time.time() text_hex = binascii.hexlify(message) diff --git a/simpleeval__examples__calc/basic/creating_an_evaluator_class.py b/simpleeval__examples__calc/basic/creating_an_evaluator_class.py index 726f5bdf4..90e87fb0a 100644 --- a/simpleeval__examples__calc/basic/creating_an_evaluator_class.py +++ b/simpleeval__examples__calc/basic/creating_an_evaluator_class.py @@ -18,7 +18,7 @@ # Append functions -def boo(): +def boo() -> str: return "Boo!" diff --git a/simpleeval__examples__calc/basic/extending__EvalNoMethods__disable_object_methods.py b/simpleeval__examples__calc/basic/extending__EvalNoMethods__disable_object_methods.py index ded2b9502..bebd4c76f 100644 --- a/simpleeval__examples__calc/basic/extending__EvalNoMethods__disable_object_methods.py +++ b/simpleeval__examples__calc/basic/extending__EvalNoMethods__disable_object_methods.py @@ -25,7 +25,7 @@ def _eval_call(self, node): class Foo: @classmethod - def get(cls): + def get(cls) -> int: return 1 my_eval = simpleeval.SimpleEval() diff --git a/simpleeval__examples__calc/simple_eval__hashlib__fill_functions.py b/simpleeval__examples__calc/simple_eval__hashlib__fill_functions.py index 0c0fa20f6..1b901ccf9 100644 --- a/simpleeval__examples__calc/simple_eval__hashlib__fill_functions.py +++ b/simpleeval__examples__calc/simple_eval__hashlib__fill_functions.py @@ -16,7 +16,7 @@ def hashlib_func(value, algo_name): class SimpleHashlibEval(SimpleEval): - def __init__(self): + def __init__(self) -> None: functions = dict() for algo_name in hashlib.algorithms_guaranteed: diff --git a/simpleeval__examples__calc/simple_eval__math.py b/simpleeval__examples__calc/simple_eval__math.py index e23b48c1b..9592f4acb 100644 --- a/simpleeval__examples__calc/simple_eval__math.py +++ b/simpleeval__examples__calc/simple_eval__math.py @@ -19,7 +19,7 @@ def get_name_by_func(obj: object) -> dict: class SimpleMathEval(SimpleEval): - def __init__(self): + def __init__(self) -> None: names = { "e": math.e, "inf": math.inf, diff --git a/single instance program/use_filelock.py b/single instance program/use_filelock.py index 8c22b550d..4bc918f34 100644 --- a/single instance program/use_filelock.py +++ b/single instance program/use_filelock.py @@ -36,7 +36,7 @@ def run_with_lock( if __name__ == "__main__": - def main(): + def main() -> None: print("Start") time.sleep(20) print("Finish") diff --git a/sirena_parser/main.py b/sirena_parser/main.py index e4f8e1bd8..a8dd4cce2 100644 --- a/sirena_parser/main.py +++ b/sirena_parser/main.py @@ -8,7 +8,7 @@ class SirenaRecord: - def __init__(self, line: str): + def __init__(self, line: str) -> None: self.values: list[str] = [] self.type = line[0] @@ -48,7 +48,7 @@ def __init__(self, line: str): class SirenaMessage: - def __init__(self, queue_lines: list[str]): + def __init__(self, queue_lines: list[str]) -> None: self.lines: list[str] = [] self.records: list[SirenaRecord] = [] @@ -71,7 +71,7 @@ def __init__(self, queue_lines: list[str]): class SirenaFile: - def __init__(self, file_name: str): + def __init__(self, file_name: str) -> None: self.lines: list[str] = [] self.queue_lines: list[str] = [] self.messages: list[SirenaMessage] = [] diff --git a/socket__tcp__examples/common.py b/socket__tcp__examples/common.py index 1211c9e5d..079423f35 100644 --- a/socket__tcp__examples/common.py +++ b/socket__tcp__examples/common.py @@ -15,7 +15,7 @@ def crc32_from_bytes(data: bytes) -> int: return zlib.crc32(data) & 0xFFFFFFFF -def send_msg__with_crc32(sock, msg): +def send_msg__with_crc32(sock, msg) -> None: # Prefix each message with a 12-byte (network byte order) length: 8-byte data length and 4-byte crc32 data crc32 = crc32_from_bytes(msg) msg = struct.pack(">QI", len(msg), crc32) + msg @@ -47,7 +47,7 @@ def recv_msg__with_crc32(sock) -> bytes | None: return msg -def send_msg(sock, msg, msg_len_format: str = ">Q"): +def send_msg(sock, msg, msg_len_format: str = ">Q") -> None: # Prefix each message with a 8-byte (>Q) length (network byte order) msg = struct.pack(msg_len_format, len(msg)) + msg sock.sendall(msg) diff --git a/socket__tcp__examples/hello_world__using_socketserver/server.py b/socket__tcp__examples/hello_world__using_socketserver/server.py index 21b7f3760..56455b9ca 100644 --- a/socket__tcp__examples/hello_world__using_socketserver/server.py +++ b/socket__tcp__examples/hello_world__using_socketserver/server.py @@ -26,7 +26,7 @@ class MyTCPHandler(socketserver.BaseRequestHandler): client. """ - def handle(self): + def handle(self) -> None: print("Connected:", self.client_address) data = recv_msg(self.request) diff --git a/socket__tcp__examples/hello_world__with_RSA_AES__commands_in_JSON__client=private_and_server=public/server.py b/socket__tcp__examples/hello_world__with_RSA_AES__commands_in_JSON__client=private_and_server=public/server.py index 15de87f36..cd4a61162 100644 --- a/socket__tcp__examples/hello_world__with_RSA_AES__commands_in_JSON__client=private_and_server=public/server.py +++ b/socket__tcp__examples/hello_world__with_RSA_AES__commands_in_JSON__client=private_and_server=public/server.py @@ -64,7 +64,7 @@ def process_command(data: bytes, conn, addr) -> bytes: return json.dumps(rq, ensure_ascii=False).encode("utf-8") -def process_connect(conn, addr): +def process_connect(conn, addr) -> None: print(f"[+] New connection from {addr}") try: diff --git a/socket__tcp__examples/hello_world__with_RSA_AES__commands_in_JSON__client=public_and_server=private/server.py b/socket__tcp__examples/hello_world__with_RSA_AES__commands_in_JSON__client=public_and_server=private/server.py index d6370f5b5..11cd96fcb 100644 --- a/socket__tcp__examples/hello_world__with_RSA_AES__commands_in_JSON__client=public_and_server=private/server.py +++ b/socket__tcp__examples/hello_world__with_RSA_AES__commands_in_JSON__client=public_and_server=private/server.py @@ -51,7 +51,7 @@ def process_command(data: bytes, conn, addr) -> bytes: return json.dumps(rq, ensure_ascii=False).encode("utf-8") -def process_connect(conn, addr): +def process_connect(conn, addr) -> None: print(f"[+] New connection from {addr}") try: diff --git a/socket__tcp__examples/http_server.py b/socket__tcp__examples/http_server.py index 664077539..fcb1c7aa9 100644 --- a/socket__tcp__examples/http_server.py +++ b/socket__tcp__examples/http_server.py @@ -10,7 +10,7 @@ import socket -def send_answer(conn, status="200 OK", typ="text/plain; charset=utf-8", data=""): +def send_answer(conn, status="200 OK", typ="text/plain; charset=utf-8", data="") -> None: data = data.encode("utf-8") conn.send(b"GET HTTP/1.1 " + status.encode("utf-8") + b"\r\n") @@ -22,7 +22,7 @@ def send_answer(conn, status="200 OK", typ="text/plain; charset=utf-8", data="") conn.send(data) -def parse(conn): # Обработка соединения в отдельной функции +def parse(conn) -> None: # Обработка соединения в отдельной функции data = b"" while b"\r\n" not in data: # Ждём первую строку diff --git a/socket__tcp__examples/http_server__threading.py b/socket__tcp__examples/http_server__threading.py index 0a19dbd30..c48b20248 100644 --- a/socket__tcp__examples/http_server__threading.py +++ b/socket__tcp__examples/http_server__threading.py @@ -13,7 +13,7 @@ from threading import Thread -def send_answer(conn, status="200 OK", typ="text/plain; charset=utf-8", data=""): +def send_answer(conn, status="200 OK", typ="text/plain; charset=utf-8", data="") -> None: data = data.encode("utf-8") conn.send(b"GET HTTP/1.1 " + status.encode("utf-8") + b"\r\n") @@ -25,7 +25,7 @@ def send_answer(conn, status="200 OK", typ="text/plain; charset=utf-8", data="") conn.send(data) -def parse(conn): # Обработка соединения в отдельной функции +def parse(conn) -> None: # Обработка соединения в отдельной функции try: data = b"" diff --git a/socket__tcp__examples/http_server_deflate.py b/socket__tcp__examples/http_server_deflate.py index 6879bfccb..217ca1a8f 100644 --- a/socket__tcp__examples/http_server_deflate.py +++ b/socket__tcp__examples/http_server_deflate.py @@ -11,7 +11,7 @@ PORT = 8080 -def send_answer(conn, status="200 OK", typ="text/plain; charset=utf-8", data=b""): +def send_answer(conn, status="200 OK", typ="text/plain; charset=utf-8", data=b"") -> None: conn.send(b"GET HTTP/1.1 " + status.encode("utf-8") + b"\r\n") conn.send(b"Server: simplehttp\r\n") conn.send(b"Connection: close\r\n") diff --git a/socket__tcp__examples/redirect_stdout/client.py b/socket__tcp__examples/redirect_stdout/client.py index ffb62e29c..eba26b335 100644 --- a/socket__tcp__examples/redirect_stdout/client.py +++ b/socket__tcp__examples/redirect_stdout/client.py @@ -16,10 +16,10 @@ class SocketIO: - def __init__(self, socket: socket.socket): + def __init__(self, socket: socket.socket) -> None: self.socket = socket - def write(self, text: str): + def write(self, text: str) -> None: data = text.encode("utf-8") print(f"Sending ({len(data)}): {data!r}", file=sys.stderr) diff --git a/socket__tcp__examples/send_and_receive_at_the_same_time/client.py b/socket__tcp__examples/send_and_receive_at_the_same_time/client.py index 9cb5642c0..4d4295e10 100644 --- a/socket__tcp__examples/send_and_receive_at_the_same_time/client.py +++ b/socket__tcp__examples/send_and_receive_at_the_same_time/client.py @@ -21,7 +21,7 @@ sock.connect((HOST, PORT)) -def read_from(): +def read_from() -> None: while True: response_data = recv_msg(sock) if response_data: diff --git a/socket__tcp__examples/send_and_receive_at_the_same_time/server.py b/socket__tcp__examples/send_and_receive_at_the_same_time/server.py index dde3bd02b..f7c1e8957 100644 --- a/socket__tcp__examples/send_and_receive_at_the_same_time/server.py +++ b/socket__tcp__examples/send_and_receive_at_the_same_time/server.py @@ -20,7 +20,7 @@ rqs: list[bytes] = [] -def write_to(): +def write_to() -> None: while True: if rqs: idx = random.randrange(len(rqs)) diff --git a/socket__tcp__examples/send_and_receive_at_the_same_time_iso8583_client_only/client.py b/socket__tcp__examples/send_and_receive_at_the_same_time_iso8583_client_only/client.py index c7fd084bf..daa455a3f 100644 --- a/socket__tcp__examples/send_and_receive_at_the_same_time_iso8583_client_only/client.py +++ b/socket__tcp__examples/send_and_receive_at_the_same_time_iso8583_client_only/client.py @@ -26,7 +26,7 @@ MSG_LEN_FORMAT = ">H" -def read_from(): +def read_from() -> None: while True: response_data: bytes = recv_msg(sock, MSG_LEN_FORMAT) if response_data: diff --git a/sort__alphanumeric__natural_sort.py b/sort__alphanumeric__natural_sort.py index f506bd581..6d8a6f84f 100644 --- a/sort__alphanumeric__natural_sort.py +++ b/sort__alphanumeric__natural_sort.py @@ -12,7 +12,7 @@ def natural_sorted(items: list) -> list: return sorted(items, key=get_num) -def natural_sort(items: list): +def natural_sort(items: list) -> None: items.sort(key=get_num) diff --git a/speak__[does_not_work]/play_mp3/play.py b/speak__[does_not_work]/play_mp3/play.py index 0ff39910d..61f6a86c1 100644 --- a/speak__[does_not_work]/play_mp3/play.py +++ b/speak__[does_not_work]/play_mp3/play.py @@ -4,7 +4,7 @@ __author__ = 'ipetrash' -def play(file_name): +def play(file_name) -> None: import pyglet import os dll_file_name = os.path.join(os.path.dirname(__file__), 'avbin') @@ -16,7 +16,7 @@ def play(file_name): player.play() - def update(dt): + def update(dt) -> None: if not player.playing: # Отпишем функцию, иначе при повторном вызове, иначе # будет двойной вызов при следующем воспроизведении diff --git a/sqlalchemy_examples/sqlite_video_table_example/main.py b/sqlalchemy_examples/sqlite_video_table_example/main.py index c6cbb3073..bf03310cb 100644 --- a/sqlalchemy_examples/sqlite_video_table_example/main.py +++ b/sqlalchemy_examples/sqlite_video_table_example/main.py @@ -45,7 +45,7 @@ class Serial(Base): # TODO: для удаления связанных сериалов: http://docs.sqlalchemy.org/en/latest/orm/cascades.html#unitofwork-cascades Videos = relationship("SerialVideo", backref="Serial", order_by="SerialVideo.Id") - def __repr__(self): + def __repr__(self) -> str: return f'' @@ -65,7 +65,7 @@ class SerialVideo(Base): Title = Column(String) Duration = Column(Integer) - def __repr__(self): + def __repr__(self) -> str: return f'' diff --git a/sqlite3__examples/backup__examples/common.py b/sqlite3__examples/backup__examples/common.py index 704cbc548..e39a116eb 100644 --- a/sqlite3__examples/backup__examples/common.py +++ b/sqlite3__examples/backup__examples/common.py @@ -16,7 +16,7 @@ def create_zip_for_file( file_name_zip: str | Path, file_name: Path, delete_file_name: bool = True, -): +) -> None: with zipfile.ZipFile( file_name_zip, mode="w", compression=zipfile.ZIP_DEFLATED ) as f: @@ -26,7 +26,7 @@ def create_zip_for_file( file_name.unlink() -def _process_test(connect: sqlite3.Connection): +def _process_test(connect: sqlite3.Connection) -> None: connect.executescript( """ create table if not exists stocks ( @@ -52,7 +52,7 @@ def run_test( dir_db_backup: Path, use_zip: bool = True, delete_file_name_after_zip: bool = True, -): +) -> None: with sqlite3.connect(":memory:") as connect: print("MEMORY") _process_test(connect) diff --git a/sqlite3__examples/custom_func__redefine_upper__check_speed.py b/sqlite3__examples/custom_func__redefine_upper__check_speed.py index 88520cb31..249181a85 100644 --- a/sqlite3__examples/custom_func__redefine_upper__check_speed.py +++ b/sqlite3__examples/custom_func__redefine_upper__check_speed.py @@ -50,7 +50,7 @@ print() - def run_test(): + def run_test() -> None: sql = "SELECT COUNT(*) FROM stocks WHERE UPPER(trans) LIKE UPPER('%SELL%')" elapsed = timeit( stmt="c.execute(sql).fetchone()", diff --git a/sqlite3__examples/select_lazy__fetchmany__offset_limit.py b/sqlite3__examples/select_lazy__fetchmany__offset_limit.py index 3069d07dc..2aa22ffa2 100644 --- a/sqlite3__examples/select_lazy__fetchmany__offset_limit.py +++ b/sqlite3__examples/select_lazy__fetchmany__offset_limit.py @@ -10,7 +10,7 @@ import sqlite3 -def _print_1(c: sqlite3.Cursor): +def _print_1(c: sqlite3.Cursor) -> None: i = 1 while True: batch = c.fetchmany(BATCH_SIZE) @@ -21,12 +21,12 @@ def _print_1(c: sqlite3.Cursor): i += 1 -def _print_2(c: sqlite3.Cursor): +def _print_2(c: sqlite3.Cursor) -> None: for i, batch in enumerate(iter(lambda: c.fetchmany(BATCH_SIZE), []), 1): print(f"{i:3}. {len(batch):3}: {batch}") -def _print_3(c: sqlite3.Cursor, sql: str): +def _print_3(c: sqlite3.Cursor, sql: str) -> None: i = 1 offset = 0 while True: diff --git a/sqlite3__examples/view_many_images__lazy__delegates__async_load_images/db.py b/sqlite3__examples/view_many_images__lazy__delegates__async_load_images/db.py index d2ef0f3e9..9a3723603 100644 --- a/sqlite3__examples/view_many_images__lazy__delegates__async_load_images/db.py +++ b/sqlite3__examples/view_many_images__lazy__delegates__async_load_images/db.py @@ -15,7 +15,7 @@ def create_connect() -> sqlite3.Connection: return sqlite3.connect(DB_FILE_NAME) -def init_db(): +def init_db() -> None: # Создание базы и таблицы with create_connect() as connect: connect.execute( diff --git a/sqlite3__examples/view_many_images__lazy__delegates__async_load_images/main.py b/sqlite3__examples/view_many_images__lazy__delegates__async_load_images/main.py index 8e7fd6335..c092dccac 100644 --- a/sqlite3__examples/view_many_images__lazy__delegates__async_load_images/main.py +++ b/sqlite3__examples/view_many_images__lazy__delegates__async_load_images/main.py @@ -26,7 +26,7 @@ def data(self, index: QModelIndex, role: int = Qt.DisplayRole) -> object: class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() query = QSqlQuery("SELECT COUNT(*) FROM File") @@ -69,7 +69,7 @@ def __init__(self): self.setLayout(layout) - def _on_added_new_items(self): + def _on_added_new_items(self) -> None: self.setWindowTitle( f"Items. " f"SQL: {self.model_sql.rowCount()} / {self.total_rows_sql} ({self.model_sql.rowCount() / self.total_rows_sql:.1%}) | " diff --git a/sqlite3__examples/view_many_images__lazy__delegates__async_load_images/utils/ListImagesWidget.py b/sqlite3__examples/view_many_images__lazy__delegates__async_load_images/utils/ListImagesWidget.py index c7557c4f9..e70937f9b 100644 --- a/sqlite3__examples/view_many_images__lazy__delegates__async_load_images/utils/ListImagesWidget.py +++ b/sqlite3__examples/view_many_images__lazy__delegates__async_load_images/utils/ListImagesWidget.py @@ -10,7 +10,7 @@ class ListImagesWidget(QListView): - def __init__(self, icon_width, icon_height, image_cache, file_name_index): + def __init__(self, icon_width, icon_height, image_cache, file_name_index) -> None: super().__init__() self.setMovement(QListView.Static) diff --git a/sqlite3__examples/view_many_images__lazy__delegates__async_load_images/utils/ThumbnailDelegate.py b/sqlite3__examples/view_many_images__lazy__delegates__async_load_images/utils/ThumbnailDelegate.py index d83412e5d..c232ef689 100644 --- a/sqlite3__examples/view_many_images__lazy__delegates__async_load_images/utils/ThumbnailDelegate.py +++ b/sqlite3__examples/view_many_images__lazy__delegates__async_load_images/utils/ThumbnailDelegate.py @@ -36,7 +36,7 @@ def __init__( height, image_cache: dict, file_name_index=0, - ): + ) -> None: super().__init__() self.width = width @@ -47,11 +47,11 @@ def __init__( self.image_cache = image_cache self.file_name_index = file_name_index - def _on_about_image(self, file_name: str, image: QImage, index: QModelIndex): + def _on_about_image(self, file_name: str, image: QImage, index: QModelIndex) -> None: self.image_cache[file_name] = image self.view.update(index) - def paint(self, painter: QPainter, opt: QStyleOptionViewItem, index: QModelIndex): + def paint(self, painter: QPainter, opt: QStyleOptionViewItem, index: QModelIndex) -> None: rect = opt.rect self.initStyleOption(opt, index) diff --git a/sqlite3__examples/view_many_images__lazy__delegates__async_load_images/utils/ThumbnailWorker.py b/sqlite3__examples/view_many_images__lazy__delegates__async_load_images/utils/ThumbnailWorker.py index 063c2de1e..08402af25 100644 --- a/sqlite3__examples/view_many_images__lazy__delegates__async_load_images/utils/ThumbnailWorker.py +++ b/sqlite3__examples/view_many_images__lazy__delegates__async_load_images/utils/ThumbnailWorker.py @@ -13,7 +13,7 @@ class Signals(QObject): class ThumbnailWorker(QRunnable): - def __init__(self, file_name: str, width, height): + def __init__(self, file_name: str, width, height) -> None: super().__init__() self.file_name = file_name @@ -21,7 +21,7 @@ def __init__(self, file_name: str, width, height): self.height = height self.signals = Signals() - def run(self): + def run(self) -> None: img = QImage(self.file_name) if img.isNull(): return diff --git a/sqlite3__examples/view_many_rows_lazy__QSqlQueryModel.py b/sqlite3__examples/view_many_rows_lazy__QSqlQueryModel.py index b93b94f74..9ce79b4aa 100644 --- a/sqlite3__examples/view_many_rows_lazy__QSqlQueryModel.py +++ b/sqlite3__examples/view_many_rows_lazy__QSqlQueryModel.py @@ -23,7 +23,7 @@ class ListViewDelegate(QStyledItemDelegate): def paint( self, painter: QPainter, option: QStyleOptionViewItem, index: QModelIndex - ): + ) -> None: opt = option self.initStyleOption(opt, index) diff --git a/stack_and_queue/main.py b/stack_and_queue/main.py index 7c7dfa0ae..906c0123c 100644 --- a/stack_and_queue/main.py +++ b/stack_and_queue/main.py @@ -8,7 +8,7 @@ class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("Stack and Queue") @@ -64,7 +64,7 @@ def __init__(self): self.setLayout(main_layout) - def _on_push(self): + def _on_push(self) -> None: number = str(self.spinbox_number.value()) if self.radio_button_stack.isChecked(): @@ -74,7 +74,7 @@ def _on_push(self): self.spinbox_number.setValue(self.spinbox_number.value() + 1) - def _on_pop(self): + def _on_pop(self) -> None: if self.radio_button_stack.isChecked(): self.list_widget_stack.takeItem(0) else: diff --git a/stackoverflow_people_reached__tracking/db.py b/stackoverflow_people_reached__tracking/db.py index 318c849a0..3d31d99ea 100644 --- a/stackoverflow_people_reached__tracking/db.py +++ b/stackoverflow_people_reached__tracking/db.py @@ -17,7 +17,7 @@ DB_FILE_NAME = str(pathlib.Path(__file__).resolve().parent / "db.sqlite") -def db_create_backup(backup_dir="backup"): +def db_create_backup(backup_dir="backup") -> None: os.makedirs(backup_dir, exist_ok=True) file_name = str(dt.datetime.today().date()) + ".sqlite" @@ -68,7 +68,7 @@ def append(url: str, value_human: str) -> "PeopleReached": url=url, value_human=value_human, value=value )[0] - def __str__(self): + def __str__(self) -> str: return ( f"PeopleReached(id={self.id}, url={repr(self.url)}, date={self.date}, " f"value_human={repr(self.value_human)}, value={self.value})" diff --git a/stackoverflow_site__parsing/preparation_description_tag_stackoverflow__qt_gui/mainwindow.py b/stackoverflow_site__parsing/preparation_description_tag_stackoverflow__qt_gui/mainwindow.py index 5f52c4ecc..e33a4ec49 100644 --- a/stackoverflow_site__parsing/preparation_description_tag_stackoverflow__qt_gui/mainwindow.py +++ b/stackoverflow_site__parsing/preparation_description_tag_stackoverflow__qt_gui/mainwindow.py @@ -24,7 +24,7 @@ class MainWindow(QMainWindow): - def __init__(self, parent=None): + def __init__(self, parent=None) -> None: super().__init__(parent) self.ui = Ui_MainWindow() @@ -75,7 +75,7 @@ def __init__(self, parent=None): self.update_states() - def update_states(self): + def update_states(self) -> None: self.ui.action_save.setEnabled(False) self.ui.action_save_all.setEnabled(len(self.modified_tags) > 0) @@ -87,7 +87,7 @@ def update_states(self): if tag_id is not None: self.ui.action_save.setEnabled(tag_id in self.modified_tags) - def filter_list_tag_only_empty(self, has_filter=None): + def filter_list_tag_only_empty(self, has_filter=None) -> None: if has_filter is None: has_filter = self.ui.check_box_only_empty.isChecked() @@ -105,7 +105,7 @@ def filter_list_tag_only_empty(self, has_filter=None): self._fill_tag_list(tags) - def list_view_tag_list_clicked(self, index): + def list_view_tag_list_clicked(self, index) -> None: item = self.tag_list_model.itemFromIndex(index) if item is not None: tag_id = item.data() @@ -113,7 +113,7 @@ def list_view_tag_list_clicked(self, index): else: logger.warn('Item from index; "%s" not found.', index) - def list_view_modified_tags_clicked(self, index): + def list_view_modified_tags_clicked(self, index) -> None: item = self.modified_tags_model.itemFromIndex(index) if item is not None: tag_id = item.data() @@ -125,10 +125,10 @@ def list_view_modified_tags_clicked(self, index): logger.warn('Item from index; "%s" not found.', index) @staticmethod - def tag_title(tag): + def tag_title(tag) -> str: return f'#{tag["id"]}: {", ".join(tag["name"])}' - def fill_tag_list(self): + def fill_tag_list(self) -> None: self.tags_dict.clear() tag_file_list = [ @@ -153,7 +153,7 @@ def fill_tag_list(self): self.update_states() - def _fill_tag_list(self, tags_dict): + def _fill_tag_list(self, tags_dict) -> None: self.tag_list_model.clear() self.ui.list_view_tag_list.blockSignals(True) @@ -192,7 +192,7 @@ def hash_tag(tag): md5.update(text.encode()) return md5.hexdigest() - def check_modified_tag(self, tag_id): + def check_modified_tag(self, tag_id) -> None: tag = self.tags_dict[tag_id] new_hash = self.hash_tag(tag) @@ -214,7 +214,7 @@ def check_modified_tag(self, tag_id): font.setBold(tag_id in self.modified_tags) item.setFont(font) - def fill_list_modified_tags(self): + def fill_list_modified_tags(self) -> None: # Обновление списка измененных тегов self.modified_tags_model.clear() @@ -235,7 +235,7 @@ def tag_id_from_index(self, index): else: logger.warn('Index: "%s" is not valid.', index) - def ref_guide_text_changed(self): + def ref_guide_text_changed(self) -> None: index = self.ui.list_view_tag_list.currentIndex() if not index.isValid(): logger.warn('Index "%s" is not valid!', index) @@ -248,7 +248,7 @@ def ref_guide_text_changed(self): self.check_modified_tag(tag_id) self.update_states() - def description_text_changed(self): + def description_text_changed(self) -> None: index = self.ui.list_view_tag_list.currentIndex() tag_id = self.tag_id_from_index(index) tag = self.tags_dict[tag_id] @@ -257,7 +257,7 @@ def description_text_changed(self): self.check_modified_tag(tag_id) self.update_states() - def fill_tag_info_from_id(self, tag_id): + def fill_tag_info_from_id(self, tag_id) -> None: if tag_id not in self.tags_dict: logger.warn('Tag id: "%s" not found!', tag_id) return @@ -292,11 +292,11 @@ def fill_tag_info_from_id(self, tag_id): self.update_states() - def fill_tag_info_from_index(self, index): + def fill_tag_info_from_index(self, index) -> None: tag_id = self.tag_id_from_index(index) self.fill_tag_info_from_id(tag_id) - def save_tag(self, tag_id): + def save_tag(self, tag_id) -> None: if tag_id not in self.tags_dict: logger.warn('Tag with id "%s" not found.', tag_id) return @@ -343,16 +343,16 @@ def save_tag(self, tag_id): self.update_states() - def save(self): + def save(self) -> None: index = self.ui.list_view_tag_list.currentIndex() tag_id = self.tag_id_from_index(index) self.save_tag(tag_id) - def save_all(self): + def save_all(self) -> None: while self.modified_tags: self.save_tag(self.modified_tags[0]) - def read_settings(self): + def read_settings(self) -> None: # NOTE: при сложных настройках, лучше перейти на json или yaml config = QSettings(CONFIG_FILE, QSettings.IniFormat) self.restoreState(config.value("MainWindow_State")) @@ -362,7 +362,7 @@ def read_settings(self): bool(config.value("Check_box_only_empty", False)) ) - def write_settings(self): + def write_settings(self) -> None: config = QSettings(CONFIG_FILE, QSettings.IniFormat) config.setValue("MainWindow_State", self.saveState()) config.setValue("MainWindow_Geometry", self.saveGeometry()) @@ -371,6 +371,6 @@ def write_settings(self): "Check_box_only_empty", self.ui.check_box_only_empty.isChecked() ) - def closeEvent(self, event): + def closeEvent(self, event) -> None: self.write_settings() sys.exit() diff --git a/stepik_lesson/course_512/24460_step_9/stepik_lesson_24460_step_9.py b/stepik_lesson/course_512/24460_step_9/stepik_lesson_24460_step_9.py index 786304373..fc9369c09 100644 --- a/stepik_lesson/course_512/24460_step_9/stepik_lesson_24460_step_9.py +++ b/stepik_lesson/course_512/24460_step_9/stepik_lesson_24460_step_9.py @@ -107,7 +107,7 @@ def bar(): class Namespace: - def __init__(self, name, parent=None): + def __init__(self, name, parent=None) -> None: self.name = name self.parent = parent @@ -122,7 +122,7 @@ def get_ns_value(self, var): return None - def __repr__(self): + def __repr__(self) -> str: return f'' diff --git a/stepik_lesson/course_512/24461_step_9/stepik_lesson_24461_step_9.py b/stepik_lesson/course_512/24461_step_9/stepik_lesson_24461_step_9.py index effe2a777..c6c408536 100644 --- a/stepik_lesson/course_512/24461_step_9/stepik_lesson_24461_step_9.py +++ b/stepik_lesson/course_512/24461_step_9/stepik_lesson_24461_step_9.py @@ -48,11 +48,11 @@ def get_current_part(self): class Buffer: - def __init__(self, part_size=5): + def __init__(self, part_size=5) -> None: self._nums = list() self._part_size = part_size - def add(self, *a): + def add(self, *a) -> None: # добавить следующую часть последовательности self._nums += a diff --git a/stepik_lesson/course_512/24462_step_7/stepik_lesson_24462_step_7.py b/stepik_lesson/course_512/24462_step_7/stepik_lesson_24462_step_7.py index 0d55e372b..312877f88 100644 --- a/stepik_lesson/course_512/24462_step_7/stepik_lesson_24462_step_7.py +++ b/stepik_lesson/course_512/24462_step_7/stepik_lesson_24462_step_7.py @@ -107,11 +107,11 @@ class C(B): # поэтому можно этот класс заменить словарем вида { 'name': '...', 'parents': [...] } # И, соответственно, функцию has_parent вынести из класса и поменять, чтобы она работала с словарем. class Class: - def __init__(self, name): + def __init__(self, name) -> None: self.name = name self.list_parent_class = list() - def has_parent(self, name): + def has_parent(self, name) -> bool: # Поиск предка в текущем классе for parent in self.list_parent_class: if parent.name == name: @@ -124,12 +124,12 @@ def has_parent(self, name): return False - def __str__(self): + def __str__(self) -> str: return ( f'Class <"{self.name}": {[cls.name for cls in self.list_parent_class]}>' ) - def __repr__(self): + def __repr__(self) -> str: return self.__str__() from collections import OrderedDict, defaultdict diff --git a/stepik_lesson/course_512/24462_step_8/stepik_lesson_24462_step_8.py b/stepik_lesson/course_512/24462_step_8/stepik_lesson_24462_step_8.py index 35d4a7137..5cf57c905 100644 --- a/stepik_lesson/course_512/24462_step_8/stepik_lesson_24462_step_8.py +++ b/stepik_lesson/course_512/24462_step_8/stepik_lesson_24462_step_8.py @@ -38,19 +38,19 @@ def div(self): class ExtendedStack(list): - def sum(self): + def sum(self) -> None: # операция сложения self.append(self.pop() + self.pop()) - def sub(self): + def sub(self) -> None: # операция вычитания self.append(self.pop() - self.pop()) - def mul(self): + def mul(self) -> None: # операция умножения self.append(self.pop() * self.pop()) - def div(self): + def div(self) -> None: # операция целочисленного деления self.append(self.pop() // self.pop()) diff --git a/stepik_lesson/course_512/24462_step_9/stepik_lesson_24462_step_9.py b/stepik_lesson/course_512/24462_step_9/stepik_lesson_24462_step_9.py index 56e2ed1a0..8b7395ce6 100644 --- a/stepik_lesson/course_512/24462_step_9/stepik_lesson_24462_step_9.py +++ b/stepik_lesson/course_512/24462_step_9/stepik_lesson_24462_step_9.py @@ -31,12 +31,12 @@ def log(self, msg): class Loggable: - def log(self, msg): + def log(self, msg) -> None: print(str(time.ctime()) + ": " + str(msg)) class LoggableList(list, Loggable): - def append(self, x): + def append(self, x) -> None: self.log(x) super().append(x) diff --git a/stepik_lesson/course_512/24463_step_7/24463_step_7.py b/stepik_lesson/course_512/24463_step_7/24463_step_7.py index 622886381..cfe198afa 100644 --- a/stepik_lesson/course_512/24463_step_7/24463_step_7.py +++ b/stepik_lesson/course_512/24463_step_7/24463_step_7.py @@ -112,11 +112,11 @@ class Error1(Error2, Error3 ... ErrorK): # поэтому можно этот класс заменить словарем вида { 'name': '...', 'parents': [...] } # И, соответственно, функцию has_parent вынести из класса и поменять, чтобы она работала с словарем. class Class: - def __init__(self, name): + def __init__(self, name) -> None: self.name = name self.list_parent_class = list() - def has_parent(self, name): + def has_parent(self, name) -> bool: # Поиск предка в текущем классе for parent in self.list_parent_class: if parent.name == name: @@ -129,12 +129,12 @@ def has_parent(self, name): return False - def __str__(self): + def __str__(self) -> str: return ( f'Class <"{self.name}": {[cls.name for cls in self.list_parent_class]}>' ) - def __repr__(self): + def __repr__(self) -> str: return self.__str__() from collections import OrderedDict, defaultdict diff --git a/stepik_lesson/course_512/24464_step_4/main.py b/stepik_lesson/course_512/24464_step_4/main.py index 6a1e3c0f4..03444e881 100644 --- a/stepik_lesson/course_512/24464_step_4/main.py +++ b/stepik_lesson/course_512/24464_step_4/main.py @@ -104,7 +104,7 @@ def judge_all(pos, neg): # допускает элемент, если его допускают все функции (neg == 0) return neg == 0 - def __init__(self, iterable, *funcs, judge=judge_any): + def __init__(self, iterable, *funcs, judge=judge_any) -> None: # iterable - исходная последовательность # funcs - допускающие функции # judge - решающая функция diff --git a/stepik_lesson/course_512/24469_step_6/main.py b/stepik_lesson/course_512/24469_step_6/main.py index d48ea0934..d6792588f 100644 --- a/stepik_lesson/course_512/24469_step_6/main.py +++ b/stepik_lesson/course_512/24469_step_6/main.py @@ -60,7 +60,7 @@ import time -def work(s, a, b): +def work(s, a, b) -> None: t = time.clock() count = 0 diff --git a/stepik_lesson/course_512/24473_step_4/main.py b/stepik_lesson/course_512/24473_step_4/main.py index 0a3a25ad8..ef71fa13a 100644 --- a/stepik_lesson/course_512/24473_step_4/main.py +++ b/stepik_lesson/course_512/24473_step_4/main.py @@ -47,7 +47,7 @@ class C(A): class_list = json.loads(class_list) class Class: - def __init__(self, name): + def __init__(self, name) -> None: self.name = name self.children = list() @@ -61,10 +61,10 @@ def all_children(self, children=None): return children - def __str__(self): + def __str__(self) -> str: return f'' - def __repr__(self): + def __repr__(self) -> str: return self.__str__() dict_class_by_name_dict = {cls["name"]: cls for cls in class_list} diff --git a/stepik_lesson/course_512/24474_step_4/main.py b/stepik_lesson/course_512/24474_step_4/main.py index 10b5dc6c7..da352119c 100644 --- a/stepik_lesson/course_512/24474_step_4/main.py +++ b/stepik_lesson/course_512/24474_step_4/main.py @@ -43,7 +43,7 @@ # Ключом является цвет, значением -- сумма ценности color_by_price_dict = defaultdict(int) - def work(element, level=1): + def work(element, level=1) -> None: """Рекурсивная функция для перебора всех элементов и подсчета их ценности.""" # Плюсуем ценность diff --git a/string_formatting/string_formatting.py b/string_formatting/string_formatting.py index 0cd9ebda5..b16c3bdcc 100644 --- a/string_formatting/string_formatting.py +++ b/string_formatting/string_formatting.py @@ -5,7 +5,7 @@ class Foo: - def __init__(self, a, b): + def __init__(self, a, b) -> None: self.a = a self.b = b diff --git a/struct__examples__parse_binary_files/read_BMP_header/main.py b/struct__examples__parse_binary_files/read_BMP_header/main.py index a5b062a55..adb945881 100644 --- a/struct__examples__parse_binary_files/read_BMP_header/main.py +++ b/struct__examples__parse_binary_files/read_BMP_header/main.py @@ -25,7 +25,7 @@ } -def print_info(file_name: str): +def print_info(file_name: str) -> None: with open(file_name, "rb") as f: # Bitmap file header # BITMAPFILEHEADER diff --git a/struct__examples__parse_binary_files/read_JPEG_header/main.py b/struct__examples__parse_binary_files/read_JPEG_header/main.py index eba7100c2..a1c6a0846 100644 --- a/struct__examples__parse_binary_files/read_JPEG_header/main.py +++ b/struct__examples__parse_binary_files/read_JPEG_header/main.py @@ -12,7 +12,7 @@ import struct -def print_info(file_name: str): +def print_info(file_name: str) -> None: print(file_name) with open(file_name, "rb") as f: diff --git a/struct__examples__parse_binary_files/read_PNG_header/main.py b/struct__examples__parse_binary_files/read_PNG_header/main.py index 89a80308e..f92de4900 100644 --- a/struct__examples__parse_binary_files/read_PNG_header/main.py +++ b/struct__examples__parse_binary_files/read_PNG_header/main.py @@ -17,7 +17,7 @@ def crc32_from_bytes(data: bytes) -> int: return zlib.crc32(data) & 0xFFFFFFFF -def print_info(file_name: str): +def print_info(file_name: str) -> None: print(file_name) def read_chunk(f) -> (int, bytes, bytes, int): diff --git a/submitting_water_meter_readings/db.py b/submitting_water_meter_readings/db.py index ef49280f0..47d6cded4 100644 --- a/submitting_water_meter_readings/db.py +++ b/submitting_water_meter_readings/db.py @@ -22,7 +22,7 @@ def create_connect() -> sqlite3.Connection: return sqlite3.connect(DB_FILE_NAME) -def init_db(): +def init_db() -> None: # Создание базы и таблицы with create_connect() as connect: connect.execute( @@ -37,7 +37,7 @@ def init_db(): ) -def db_create_backup(backup_dir="backup"): +def db_create_backup(backup_dir="backup") -> None: file_name = str(dt.datetime.today().date()) + ".sqlite" if not os.path.exists(backup_dir): @@ -61,7 +61,7 @@ def get_last(date: dt.date = None) -> int: return -1 if result is None else result[0] -def delete_last(): +def delete_last() -> None: with create_connect() as connect: last_id = get_last() connect.execute("DELETE FROM Water WHERE id = ?", [last_id]) diff --git a/submitting_water_meter_readings/old/send_mail__utils.py b/submitting_water_meter_readings/old/send_mail__utils.py index 427fb1973..fce63ade8 100644 --- a/submitting_water_meter_readings/old/send_mail__utils.py +++ b/submitting_water_meter_readings/old/send_mail__utils.py @@ -87,10 +87,10 @@ def open_web_page_mail(value_cold: int, value_hot: int) -> (bool, str): return True, '' -def run_auto_ping_logon(): +def run_auto_ping_logon() -> None: prefix = run_auto_ping_logon.__name__ - def run(): + def run() -> None: while True: try: driver = get_driver(headless=True) diff --git a/submitting_water_meter_readings/utils.py b/submitting_water_meter_readings/utils.py index fb0748b6b..565620ed7 100644 --- a/submitting_water_meter_readings/utils.py +++ b/submitting_water_meter_readings/utils.py @@ -93,10 +93,10 @@ def open_web_page_water_meter(value_cold: int, value_hot: int) -> tuple[bool, st return True, "" -def run_auto_ping_logon(): +def run_auto_ping_logon() -> None: prefix = run_auto_ping_logon.__name__ - def run(): + def run() -> None: while True: try: driver = get_driver(headless=True) diff --git a/submitting_water_meter_readings/web.py b/submitting_water_meter_readings/web.py index 22ed279f9..5a5bbc610 100644 --- a/submitting_water_meter_readings/web.py +++ b/submitting_water_meter_readings/web.py @@ -90,7 +90,7 @@ def parse_POST(self): return postvars - def do_GET(self): + def do_GET(self) -> None: o = urlsplit(self.path) # Only index and ALLOW_LIST @@ -135,7 +135,7 @@ def do_GET(self): self.wfile.write(text.encode("utf-8")) - def do_POST(self): + def do_POST(self) -> None: o = urlsplit(self.path) # Only index @@ -199,7 +199,7 @@ def do_POST(self): def run( server_class=HTTPServer, handler_class=HttpProcessor, host="127.0.0.1", port=8080 -): +) -> None: log.info( f"HTTP server running on http://{'127.0.0.1' if host == '0.0.0.0' else host}:{port}" ) diff --git a/svgwrite__examples/fill_background.py b/svgwrite__examples/fill_background.py index 5cf8595c9..4e0b2342c 100644 --- a/svgwrite__examples/fill_background.py +++ b/svgwrite__examples/fill_background.py @@ -8,7 +8,7 @@ import svgwrite -def create_svg(name): +def create_svg(name) -> None: svg_size_width = 200 svg_size_height = 200 diff --git a/svgwrite__examples/from_examples/basic_shapes.py b/svgwrite__examples/from_examples/basic_shapes.py index 24b58521b..cf96ae4e9 100644 --- a/svgwrite__examples/from_examples/basic_shapes.py +++ b/svgwrite__examples/from_examples/basic_shapes.py @@ -12,7 +12,7 @@ from svgwrite import cm, mm -def basic_shapes(name): +def basic_shapes(name) -> None: dwg = svgwrite.Drawing(filename=name, debug=True) hlines = dwg.add(dwg.g(id="hlines", stroke="green")) diff --git a/svgwrite__examples/from_examples/bezier.py b/svgwrite__examples/from_examples/bezier.py index bb2775327..e0dd18c5d 100644 --- a/svgwrite__examples/from_examples/bezier.py +++ b/svgwrite__examples/from_examples/bezier.py @@ -19,7 +19,7 @@ def nfrange(fstart, fstop, n): return [fstart + delta * i for i in range(n)] -def create_svg(name): +def create_svg(name) -> None: svg_size = 900 font_size = 20 title = "Example of Bezier curves" diff --git a/svgwrite__examples/from_examples/checkerboard.py b/svgwrite__examples/from_examples/checkerboard.py index dbfb2b695..aba9ab937 100644 --- a/svgwrite__examples/from_examples/checkerboard.py +++ b/svgwrite__examples/from_examples/checkerboard.py @@ -28,7 +28,7 @@ """ -def draw_board(dwg): +def draw_board(dwg) -> None: def group(classname): return dwg.add(dwg.g(class_=classname)) diff --git a/svgwrite__examples/from_examples/circle_blur.py b/svgwrite__examples/from_examples/circle_blur.py index 453cdd80a..278cab904 100644 --- a/svgwrite__examples/from_examples/circle_blur.py +++ b/svgwrite__examples/from_examples/circle_blur.py @@ -11,7 +11,7 @@ import svgwrite -def create_svg(name): +def create_svg(name) -> None: SVG_SIZE = 900 FONT_SIZE = 20 diff --git a/svgwrite__examples/from_examples/color_names.py b/svgwrite__examples/from_examples/color_names.py index ab60c0c14..3d6f39903 100644 --- a/svgwrite__examples/from_examples/color_names.py +++ b/svgwrite__examples/from_examples/color_names.py @@ -17,7 +17,7 @@ # -def create_svg(name): +def create_svg(name) -> None: svg_size_width = 900 svg_size_height = 4500 font_size = 20 diff --git a/svgwrite__examples/from_examples/color_triangles_function.py b/svgwrite__examples/from_examples/color_triangles_function.py index 3fcd8c5fb..efc225d49 100644 --- a/svgwrite__examples/from_examples/color_triangles_function.py +++ b/svgwrite__examples/from_examples/color_triangles_function.py @@ -14,7 +14,7 @@ from svgwrite import rgb -def create_svg(name): +def create_svg(name) -> None: width = 900 height = 900 font_size = 20 @@ -31,7 +31,7 @@ def create_svg(name): tri_color = ((20, 128, 30), (10, 0, 50), (0, 0, 128)) dwg = svgwrite.Drawing(name, (width, height), debug=True) - def draw_triangle(insert, size, fill, rotate=None): + def draw_triangle(insert, size, fill, rotate=None) -> None: x, y = insert points = [insert, (x + size, y), ((x + size / 2.0), (y + size * tri_height))] triangle = dwg.add(dwg.polygon(points, fill=fill, stroke="none")) diff --git a/svgwrite__examples/from_examples/defs_test.py b/svgwrite__examples/from_examples/defs_test.py index 6d0d1a19c..47b8ef0c7 100644 --- a/svgwrite__examples/from_examples/defs_test.py +++ b/svgwrite__examples/from_examples/defs_test.py @@ -19,7 +19,7 @@ """ -def create_svg(name): +def create_svg(name) -> None: svg_size_width = 900 svg_size_height = 900 font_size = 20 diff --git a/svgwrite__examples/from_examples/fractal__L_system.py b/svgwrite__examples/from_examples/fractal__L_system.py index 53eea9b50..94451b658 100644 --- a/svgwrite__examples/from_examples/fractal__L_system.py +++ b/svgwrite__examples/from_examples/fractal__L_system.py @@ -109,7 +109,7 @@ # SOURCE: http://code.activestate.com/recipes/577159/ -def LSystem(name, formula=LevyCurve): +def LSystem(name, formula=LevyCurve) -> None: # L-System Fractals print("Creating: " + name) diff --git a/svgwrite__examples/from_examples/fractal__koch_snowflake.py b/svgwrite__examples/from_examples/fractal__koch_snowflake.py index b6dc46874..2bb1b2c0f 100644 --- a/svgwrite__examples/from_examples/fractal__koch_snowflake.py +++ b/svgwrite__examples/from_examples/fractal__koch_snowflake.py @@ -13,13 +13,13 @@ import math -def create_svg(name): +def create_svg(name) -> None: # Koch Snowflake and Sierpinski Triangle combination fractal using recursion # ActiveState Recipe 577156 # Created by FB36 on Sat, 27 Mar 2010 (MIT) # http://code.activestate.com/recipes/577156-koch-snowflake-and-sierpinski-triangle-combination/ - def tf(x0, y0, x1, y1, x2, y2): + def tf(x0, y0, x1, y1, x2, y2) -> None: a = math.sqrt((x1 - x0) ** 2 + (y1 - y0) ** 2) b = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2) c = math.sqrt((x0 - x2) ** 2 + (y0 - y2) ** 2) @@ -42,7 +42,7 @@ def tf(x0, y0, x1, y1, x2, y2): tf(x3, y3, x1, y1, x4, y4) tf(x5, y5, x4, y4, x2, y2) - def sf(ax, ay, bx, by): + def sf(ax, ay, bx, by) -> None: f = math.sqrt((bx - ax) ** 2 + (by - ay) ** 2) if f < 1.0: diff --git a/svgwrite__examples/from_examples/fractal__mandelbrot.py b/svgwrite__examples/from_examples/fractal__mandelbrot.py index 722d4ea72..fe469bb1a 100644 --- a/svgwrite__examples/from_examples/fractal__mandelbrot.py +++ b/svgwrite__examples/from_examples/fractal__mandelbrot.py @@ -13,11 +13,11 @@ # SOURCE: http://code.activestate.com/recipes/577111/ -def create_svg(name): +def create_svg(name) -> None: # Mandelbrot fractal # FB - 201003254 - def put_pixel(pos, color): + def put_pixel(pos, color) -> None: mandelbrot_group.add(dwg.circle(center=pos, r=0.5, fill=color)) # Image size diff --git a/svgwrite__examples/from_examples/hyperlink.py b/svgwrite__examples/from_examples/hyperlink.py index 75490f6fd..89979d794 100644 --- a/svgwrite__examples/from_examples/hyperlink.py +++ b/svgwrite__examples/from_examples/hyperlink.py @@ -11,7 +11,7 @@ import svgwrite -def hyperlink(name): +def hyperlink(name) -> None: dwg = svgwrite.Drawing(name, (200, 200), debug=True) # use the hyperlink element diff --git a/svgwrite__examples/from_examples/length_units.py b/svgwrite__examples/from_examples/length_units.py index 5a2d039fb..f93d795fb 100644 --- a/svgwrite__examples/from_examples/length_units.py +++ b/svgwrite__examples/from_examples/length_units.py @@ -11,7 +11,7 @@ import svgwrite -def create_svg(name): +def create_svg(name) -> None: svg_size = 900 font_size = 20 title1 = "Example of units of length" diff --git a/svgwrite__examples/from_examples/line_cap_join.py b/svgwrite__examples/from_examples/line_cap_join.py index a41887759..8b073bf1d 100644 --- a/svgwrite__examples/from_examples/line_cap_join.py +++ b/svgwrite__examples/from_examples/line_cap_join.py @@ -11,7 +11,7 @@ import svgwrite -def create_svg(name): +def create_svg(name) -> None: svg_size = 900 font_size = 20 title = "Example of stroke_linecap, stroke_linejoin" diff --git a/svgwrite__examples/from_examples/marker.py b/svgwrite__examples/from_examples/marker.py index 61f4482ea..a91d733d2 100644 --- a/svgwrite__examples/from_examples/marker.py +++ b/svgwrite__examples/from_examples/marker.py @@ -11,7 +11,7 @@ import svgwrite -def create_svg(name): +def create_svg(name) -> None: # Shows how to use the element. # W3C reference: http://www.w3.org/TR/SVG11/painting.html#MarkerElement # diff --git a/svgwrite__examples/from_examples/pattern.py b/svgwrite__examples/from_examples/pattern.py index 4cf712710..7cebab5fe 100644 --- a/svgwrite__examples/from_examples/pattern.py +++ b/svgwrite__examples/from_examples/pattern.py @@ -11,7 +11,7 @@ import svgwrite -def create_svg(name): +def create_svg(name) -> None: dwg = svgwrite.Drawing(name, size=("20cm", "15cm"), profile="full", debug=True) # Set user coordinate space diff --git a/svgwrite__examples/from_examples/radial_gradient.py b/svgwrite__examples/from_examples/radial_gradient.py index 9c158fe90..072238f8c 100644 --- a/svgwrite__examples/from_examples/radial_gradient.py +++ b/svgwrite__examples/from_examples/radial_gradient.py @@ -11,7 +11,7 @@ import svgwrite -def create_svg(name): +def create_svg(name) -> None: dwg = svgwrite.Drawing(name, size=("20cm", "15cm"), profile="full", debug=True) # Ыet user coordinate space diff --git a/svgwrite__examples/from_examples/simple_text.py b/svgwrite__examples/from_examples/simple_text.py index 062e03a33..fbfbed8c0 100644 --- a/svgwrite__examples/from_examples/simple_text.py +++ b/svgwrite__examples/from_examples/simple_text.py @@ -11,7 +11,7 @@ import svgwrite -def simple_text(name): +def simple_text(name) -> None: dwg = svgwrite.Drawing(name, (200, 200), debug=True) paragraph = dwg.add(dwg.g(font_size=14)) diff --git a/svgwrite__examples/from_examples/solidcolor.py b/svgwrite__examples/from_examples/solidcolor.py index 3803d155b..4bb956320 100644 --- a/svgwrite__examples/from_examples/solidcolor.py +++ b/svgwrite__examples/from_examples/solidcolor.py @@ -11,7 +11,7 @@ import svgwrite -def solid_color(name): +def solid_color(name) -> None: dwg = svgwrite.Drawing(name, size=("20cm", "15cm"), profile="tiny", debug=True) # set user coordinate space diff --git a/svgwrite__examples/from_examples/tag_element__use.py b/svgwrite__examples/from_examples/tag_element__use.py index f0cdca134..89649eb2f 100644 --- a/svgwrite__examples/from_examples/tag_element__use.py +++ b/svgwrite__examples/from_examples/tag_element__use.py @@ -12,7 +12,7 @@ from svgwrite import rgb -def create_svg(name): +def create_svg(name) -> None: """Shows how to use the 'use' element.""" w, h = "100%", "100%" diff --git a/svgwrite__examples/from_examples/tenticles.py b/svgwrite__examples/from_examples/tenticles.py index 36f899e9c..e119bc9d6 100644 --- a/svgwrite__examples/from_examples/tenticles.py +++ b/svgwrite__examples/from_examples/tenticles.py @@ -61,7 +61,7 @@ def __init__( p_ecolour, p_can_branch, dwg, - ): + ) -> None: """tendrile class instance for each arm""" self.x = p_x self.y = p_y @@ -95,12 +95,12 @@ def __init__( # of the old tendrile. self.group = self.dwg.g(id="branch" + str(next(UNIQUE_NUM))) - def angle_set(self, p_val): + def angle_set(self, p_val) -> None: # limit the angle to range -2*math.pi to 2*math.pi which is +- full circle. # Use math.fmod because % returns with the sign of the second number. self.angle = math.fmod(p_val, (2 * math.pi)) - def create(self): + def create(self) -> None: for i in range(self.n): if i != 0: if random.randint(1, 100) == 1 and self.can_branch: @@ -181,11 +181,11 @@ def create(self): ) ) - def draw(self): + def draw(self) -> None: self.dwg.add(self.group) -def create_svg(name): +def create_svg(name) -> None: """ Create many circles in a curling tentril fashion. """ diff --git a/svgwrite__examples/from_examples/text_font_generic_family.py b/svgwrite__examples/from_examples/text_font_generic_family.py index 685551ff2..e2b819f04 100644 --- a/svgwrite__examples/from_examples/text_font_generic_family.py +++ b/svgwrite__examples/from_examples/text_font_generic_family.py @@ -14,7 +14,7 @@ # 'serif', 'sans-serif', 'cursive', 'fantasy', and 'monospace' from the CSS specification -def create_svg(name): +def create_svg(name) -> None: font_size = 20 title = name + ": Example of text using generic family fonts" diff --git a/svgwrite__examples/from_examples/text_font_size.py b/svgwrite__examples/from_examples/text_font_size.py index 4e7edad2f..c44d5781c 100644 --- a/svgwrite__examples/from_examples/text_font_size.py +++ b/svgwrite__examples/from_examples/text_font_size.py @@ -14,7 +14,7 @@ # http://www.w3.org/TR/2008/REC-CSS2-20080411/fonts.html#font-size-props -def create_svg(name): +def create_svg(name) -> None: svg_size = 900 font_size = 20 title = name + ": Example of text font_sizes" diff --git a/svgwrite__examples/from_examples/text_justify.py b/svgwrite__examples/from_examples/text_justify.py index a92ab63e1..f809b0882 100644 --- a/svgwrite__examples/from_examples/text_justify.py +++ b/svgwrite__examples/from_examples/text_justify.py @@ -11,7 +11,7 @@ import svgwrite -def create_svg(name): +def create_svg(name) -> None: svg_size = 900 font_size = 20 title = "Example of text_anchor (justified) text" diff --git a/svgwrite__examples/pretty_xml_in_svg.py b/svgwrite__examples/pretty_xml_in_svg.py index 32650f0bc..6bb9c687c 100644 --- a/svgwrite__examples/pretty_xml_in_svg.py +++ b/svgwrite__examples/pretty_xml_in_svg.py @@ -11,7 +11,7 @@ import svgwrite -def hyperlink(name, pretty): +def hyperlink(name, pretty) -> None: dwg = svgwrite.Drawing(name, (200, 200), debug=True) # use the hyperlink element diff --git a/telegram__telethon__examples/auto_answer.py b/telegram__telethon__examples/auto_answer.py index 355441d89..be4ca4ddf 100644 --- a/telegram__telethon__examples/auto_answer.py +++ b/telegram__telethon__examples/auto_answer.py @@ -17,7 +17,7 @@ with TelegramClient("my", API_ID, API_HASH) as client: @client.on(events.NewMessage(from_users=[321346650, 257199860])) - async def handler(event): + async def handler(event) -> None: print(event) await event.reply("Сейчас не могу ответить 😔") diff --git a/telegram__telethon__examples/hello_world.py b/telegram__telethon__examples/hello_world.py index 5c80364a2..b441d5378 100644 --- a/telegram__telethon__examples/hello_world.py +++ b/telegram__telethon__examples/hello_world.py @@ -20,7 +20,7 @@ print("Picture small:", client.download_profile_photo("me", download_big=False)) @client.on(events.NewMessage(pattern="(?i).*Hello")) - async def handler(event): + async def handler(event) -> None: print(event.stringify()) await event.reply("Hey!") diff --git "a/telegram__telethon__examples/\321\207\321\203\320\262\320\260\320\272__wazzup/\321\207\321\203\320\262\320\260\320\272__wazzup.py" "b/telegram__telethon__examples/\321\207\321\203\320\262\320\260\320\272__wazzup/\321\207\321\203\320\262\320\260\320\272__wazzup.py" index 75fad8247..78b439939 100644 --- "a/telegram__telethon__examples/\321\207\321\203\320\262\320\260\320\272__wazzup/\321\207\321\203\320\262\320\260\320\272__wazzup.py" +++ "b/telegram__telethon__examples/\321\207\321\203\320\262\320\260\320\272__wazzup/\321\207\321\203\320\262\320\260\320\272__wazzup.py" @@ -27,7 +27,7 @@ me_id = client.get_me().id @client.on(events.NewMessage(pattern="(?i).*чу+ва+к|wa+zz+u+p")) - async def handler(event): + async def handler(event) -> None: print(event.stringify()) if event.chat_id == me_id or event.message.from_id == me_id: diff --git a/telegram_bot__telethon__examples/register_next_step_handler.py b/telegram_bot__telethon__examples/register_next_step_handler.py index 5c3b6fb95..8ecf6c008 100644 --- a/telegram_bot__telethon__examples/register_next_step_handler.py +++ b/telegram_bot__telethon__examples/register_next_step_handler.py @@ -20,14 +20,14 @@ # SOURCE: https://ru.stackoverflow.com/questions/1264757 -def func(message): +def func(message) -> None: text = message.text result = data_year.get(text, "В этот день праздников нет. Иди работать!") bot.send_message(message.from_user.id, result) @bot.message_handler(content_types=["text"]) -def get_text_messages(message): +def get_text_messages(message) -> None: data = bot.send_message( message.from_user.id, "Введите дату в формате Д.ММ и нажмите ENTER" ) diff --git a/telegram_bot__telethon__examples/restriction_on_frequent_sending_of_messages__using_dict.py b/telegram_bot__telethon__examples/restriction_on_frequent_sending_of_messages__using_dict.py index e6882ec07..68b3b18c0 100644 --- a/telegram_bot__telethon__examples/restriction_on_frequent_sending_of_messages__using_dict.py +++ b/telegram_bot__telethon__examples/restriction_on_frequent_sending_of_messages__using_dict.py @@ -19,12 +19,12 @@ @bot.message_handler(commands=["help", "start"]) -def on_start(message: telebot.types.Message): +def on_start(message: telebot.types.Message) -> None: bot.send_message(message.chat.id, "Write something") @bot.message_handler(func=lambda message: True) -def on_request(message: telebot.types.Message): +def on_request(message: telebot.types.Message) -> None: text = "Получено!" need_seconds = 50 current_time = dt.datetime.now() diff --git a/telegram_bot__telethon__examples/step_example.py b/telegram_bot__telethon__examples/step_example.py index 6a64235fa..fd82eac96 100644 --- a/telegram_bot__telethon__examples/step_example.py +++ b/telegram_bot__telethon__examples/step_example.py @@ -19,7 +19,7 @@ class User: - def __init__(self, name): + def __init__(self, name) -> None: self.name = name self.age = None self.sex = None @@ -27,7 +27,7 @@ def __init__(self, name): # Handle '/start' and '/help' @bot.message_handler(commands=["help", "start"]) -def send_welcome(message): +def send_welcome(message) -> None: msg = bot.reply_to( message, """\ @@ -38,7 +38,7 @@ def send_welcome(message): bot.register_next_step_handler(msg, process_name_step) -def process_name_step(message): +def process_name_step(message) -> None: try: chat_id = message.chat.id name = message.text @@ -50,7 +50,7 @@ def process_name_step(message): bot.reply_to(message, "oooops") -def process_age_step(message): +def process_age_step(message) -> None: try: chat_id = message.chat.id age = message.text diff --git a/telegram_bot_examples/alban.py b/telegram_bot_examples/alban.py index c481a90d1..2082deff5 100644 --- a/telegram_bot_examples/alban.py +++ b/telegram_bot_examples/alban.py @@ -20,18 +20,18 @@ @log_func(log) -def on_start(update: Update, _: CallbackContext): +def on_start(update: Update, _: CallbackContext) -> None: update.effective_message.reply_text("Write something") @log_func(log) -def on_request(update: Update, _: CallbackContext): +def on_request(update: Update, _: CallbackContext) -> None: message = update.effective_message message.reply_text(get_alban(message.text)) -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_start), MessageHandler(Filters.text, on_request), diff --git a/telegram_bot_examples/auto_in_progress_message/core.py b/telegram_bot_examples/auto_in_progress_message/core.py index 88d30b43c..7dfff8108 100644 --- a/telegram_bot_examples/auto_in_progress_message/core.py +++ b/telegram_bot_examples/auto_in_progress_message/core.py @@ -10,7 +10,8 @@ import time from itertools import cycle -from typing import Sequence +from typing import Sequence, Optional, Type +from types import TracebackType # pip install python-telegram-bot from telegram import Update, ReplyMarkup, Message, ParseMode @@ -46,9 +47,7 @@ class ProgressValue(enum.Enum): RECTS_SMALL = "□□□□□", "■□□□□", "■■□□□", "■■■□□", "■■■■□", "■■■■■" PARALLELOGRAMS = "▱▱▱▱▱", "▰▱▱▱▱", "▰▰▱▱▱", "▰▰▰▱▱", "▰▰▰▰▱", "▰▰▰▰▰" CIRCLES = "⚪⚪⚪⚪⚪", "⚫⚪⚪⚪⚪", "⚫⚫⚪⚪⚪", "⚫⚫⚫⚪⚪", "⚫⚫⚫⚫⚪", "⚫⚫⚫⚫⚫" - CHICKENS = get_seqs_with_sub_animation( - items=["🥚", "🐣", "🐥", "🐔", "🍗"] - ) + CHICKENS = get_seqs_with_sub_animation(items=["🥚", "🐣", "🐥", "🐔", "🍗"]) FACES = get_seqs_with_sub_animation( items=["😶", "☹️", "🙁", "😕", "😐", "🙂", "😊", "😀", "😄", "😁"] ) @@ -82,7 +81,7 @@ def __init__( init_seconds: int = 0, *args, **kwargs, - ): + ) -> None: super().__init__(*args, **kwargs) self.daemon = True @@ -101,7 +100,7 @@ def __init__( self._seconds: int = init_seconds self.init_seconds: int = init_seconds - def run(self): + def run(self) -> None: self._seconds = self.init_seconds while True: @@ -126,7 +125,7 @@ def run(self): except BadRequest: pass - def stop(self): + def stop(self) -> None: self._stop.set() def is_stopped(self) -> bool: @@ -144,7 +143,7 @@ def __init__( quote: bool = True, progress_value: ProgressValue = None, **kwargs, - ): + ) -> None: self.text = text self.update = update self.context = context @@ -182,7 +181,12 @@ def __enter__(self): return self - def __exit__(self, exc_type, exc_value, traceback): + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_value: Optional[BaseException], + traceback: Optional[TracebackType], + ) -> None: if self.thread_progress: self.thread_progress.stop() @@ -237,7 +241,7 @@ def run( progress_value: ProgressValue, text_fmt: str = "Please, wait {value} (elapsed {seconds} seconds)", number: int = 10, - ): + ) -> None: _progress_bar = cycle(progress_value.value) _seconds = 0 for _ in range(number): diff --git a/telegram_bot_examples/auto_in_progress_message/main.py b/telegram_bot_examples/auto_in_progress_message/main.py index 003a4aa70..ae5f14ca6 100644 --- a/telegram_bot_examples/auto_in_progress_message/main.py +++ b/telegram_bot_examples/auto_in_progress_message/main.py @@ -39,18 +39,18 @@ ALL_COMMANDS = [] -def run_command(message: Message, sleep_seconds: int = 10): +def run_command(message: Message, sleep_seconds: int = 10) -> None: time.sleep(sleep_seconds) message.reply_text("Hello World!") @log_func(log) -def on_start(update: Update, _: CallbackContext): +def on_start(update: Update, _: CallbackContext) -> None: update.effective_message.reply_text("Write something") @log_func(log) -def on_request(update: Update, _: CallbackContext): +def on_request(update: Update, _: CallbackContext) -> None: message = update.effective_message text = "Commands:\n" + "\n".join(f" /{x}" for x in ALL_COMMANDS) @@ -58,21 +58,21 @@ def on_request(update: Update, _: CallbackContext): @log_func(log) -def on_simple(update: Update, _: CallbackContext): +def on_simple(update: Update, _: CallbackContext) -> None: message = update.effective_message run_command(message) @log_func(log) @show_temp_message_decorator() -def on_in_progress(update: Update, _: CallbackContext): +def on_in_progress(update: Update, _: CallbackContext) -> None: message = update.effective_message run_command(message) @log_func(log) @show_temp_message_decorator(text="Пожалуйста, подождите...") -def on_custom_in_progress(update: Update, _: CallbackContext): +def on_custom_in_progress(update: Update, _: CallbackContext) -> None: message = update.effective_message run_command(message) @@ -89,7 +89,7 @@ def on_custom_in_progress(update: Update, _: CallbackContext): ) ), ) -def on_custom_all_in_progress(update: Update, _: CallbackContext): +def on_custom_all_in_progress(update: Update, _: CallbackContext) -> None: message = update.effective_message run_command(message) @@ -99,7 +99,7 @@ def on_custom_all_in_progress(update: Update, _: CallbackContext): text="Выполняется работа {value}", progress_value=ProgressValue.LINES, ) -def on_animation_lines(update: Update, _: CallbackContext): +def on_animation_lines(update: Update, _: CallbackContext) -> None: message = update.effective_message run_command(message) @@ -109,7 +109,7 @@ def on_animation_lines(update: Update, _: CallbackContext): text="Выполняется работа {value}", progress_value=ProgressValue.SPINNER, ) -def on_animation_spinner(update: Update, _: CallbackContext): +def on_animation_spinner(update: Update, _: CallbackContext) -> None: message = update.effective_message run_command(message) @@ -119,7 +119,7 @@ def on_animation_spinner(update: Update, _: CallbackContext): text="Please, wait {value}", progress_value=ProgressValue.POINTS, ) -def on_animation_points(update: Update, _: CallbackContext): +def on_animation_points(update: Update, _: CallbackContext) -> None: message = update.effective_message run_command(message) @@ -130,7 +130,7 @@ def on_animation_points(update: Update, _: CallbackContext): parse_mode=ParseMode.HTML, progress_value=ProgressValue.MOON_PHASES_1, ) -def on_animation_moon_phases1(update: Update, _: CallbackContext): +def on_animation_moon_phases1(update: Update, _: CallbackContext) -> None: message = update.effective_message run_command(message) @@ -141,7 +141,7 @@ def on_animation_moon_phases1(update: Update, _: CallbackContext): parse_mode=ParseMode.HTML, progress_value=ProgressValue.MOON_PHASES_2, ) -def on_animation_moon_phases2(update: Update, _: CallbackContext): +def on_animation_moon_phases2(update: Update, _: CallbackContext) -> None: message = update.effective_message run_command(message) @@ -151,7 +151,7 @@ def on_animation_moon_phases2(update: Update, _: CallbackContext): text="Loading {value}", progress_value=ProgressValue.BLOCKS, ) -def on_animation_blocks(update: Update, _: CallbackContext): +def on_animation_blocks(update: Update, _: CallbackContext) -> None: message = update.effective_message run_command(message) @@ -161,7 +161,7 @@ def on_animation_blocks(update: Update, _: CallbackContext): text="Loading {value}", progress_value=ProgressValue.RECTS_LARGE, ) -def on_animation_rects_large(update: Update, _: CallbackContext): +def on_animation_rects_large(update: Update, _: CallbackContext) -> None: message = update.effective_message run_command(message) @@ -171,7 +171,7 @@ def on_animation_rects_large(update: Update, _: CallbackContext): text="Loading {value}", progress_value=ProgressValue.RECTS_SMALL, ) -def on_animation_rects_small(update: Update, _: CallbackContext): +def on_animation_rects_small(update: Update, _: CallbackContext) -> None: message = update.effective_message run_command(message) @@ -181,7 +181,7 @@ def on_animation_rects_small(update: Update, _: CallbackContext): text="Loading {value}", progress_value=ProgressValue.PARALLELOGRAMS, ) -def on_animation_parallelograms(update: Update, _: CallbackContext): +def on_animation_parallelograms(update: Update, _: CallbackContext) -> None: message = update.effective_message run_command(message) @@ -191,7 +191,7 @@ def on_animation_parallelograms(update: Update, _: CallbackContext): text="Loading {value}", progress_value=ProgressValue.CIRCLES, ) -def on_animation_circles(update: Update, _: CallbackContext): +def on_animation_circles(update: Update, _: CallbackContext) -> None: message = update.effective_message run_command(message) @@ -212,7 +212,7 @@ def on_animation_circles(update: Update, _: CallbackContext): ) ), ) -def on_custom_all_animation(update: Update, _: CallbackContext): +def on_custom_all_animation(update: Update, _: CallbackContext) -> None: message = update.effective_message run_command(message) @@ -222,7 +222,7 @@ def on_custom_all_animation(update: Update, _: CallbackContext): text="{value} x {value}", progress_value=ProgressValue.RECTS_SMALL, ) -def on_custom_no_text_animation(update: Update, _: CallbackContext): +def on_custom_no_text_animation(update: Update, _: CallbackContext) -> None: message = update.effective_message run_command(message) @@ -232,7 +232,7 @@ def on_custom_no_text_animation(update: Update, _: CallbackContext): text="KFC {value}", progress_value=ProgressValue.CHICKENS, ) -def on_sub_animation_chickens(update: Update, _: CallbackContext): +def on_sub_animation_chickens(update: Update, _: CallbackContext) -> None: message = update.effective_message run_command(message, sleep_seconds=30) @@ -242,12 +242,12 @@ def on_sub_animation_chickens(update: Update, _: CallbackContext): text="Faces {value}", progress_value=ProgressValue.FACES, ) -def on_sub_animation_faces(update: Update, _: CallbackContext): +def on_sub_animation_faces(update: Update, _: CallbackContext) -> None: message = update.effective_message run_command(message, sleep_seconds=30) -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_start), CommandHandler("simple", on_simple), @@ -271,7 +271,7 @@ def main(): MessageHandler(Filters.text, on_request), ] - def before_start_func(updater: Updater): + def before_start_func(updater: Updater) -> None: for commands in updater.dispatcher.handlers.values(): for command in commands: if isinstance(command, CommandHandler): diff --git a/telegram_bot_examples/calendar_example/main.py b/telegram_bot_examples/calendar_example/main.py index bf4b53569..32f61402e 100644 --- a/telegram_bot_examples/calendar_example/main.py +++ b/telegram_bot_examples/calendar_example/main.py @@ -27,21 +27,21 @@ @log_func(log) -def on_request(update: Update, _: CallbackContext): +def on_request(update: Update, _: CallbackContext) -> None: message = update.effective_message message.reply_text("Use: /calendar") @log_func(log) -def on_calendar(update: Update, _: CallbackContext): +def on_calendar(update: Update, _: CallbackContext) -> None: update.effective_message.reply_text( "Please select a date: ", reply_markup=telegramcalendar.create_calendar() ) @log_func(log) -def on_callback_query(update: Update, context: CallbackContext): +def on_callback_query(update: Update, context: CallbackContext) -> None: query = update.callback_query query.answer() @@ -55,7 +55,7 @@ def on_callback_query(update: Update, context: CallbackContext): ) -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_request), CommandHandler("calendar", on_calendar), diff --git a/telegram_bot_examples/calendar_example/main__mini.py b/telegram_bot_examples/calendar_example/main__mini.py index 8b870e3df..f72423938 100644 --- a/telegram_bot_examples/calendar_example/main__mini.py +++ b/telegram_bot_examples/calendar_example/main__mini.py @@ -17,13 +17,13 @@ import config -def on_calendar(update: Update, _: CallbackContext): +def on_calendar(update: Update, _: CallbackContext) -> None: update.effective_message.reply_text( "Please select a date: ", reply_markup=telegramcalendar.create_calendar() ) -def on_callback_query(update: Update, context: CallbackContext): +def on_callback_query(update: Update, context: CallbackContext) -> None: query = update.callback_query query.answer() @@ -37,7 +37,7 @@ def on_callback_query(update: Update, context: CallbackContext): ) -def main(): +def main() -> None: # Create the EventHandler and pass it your bot's token. updater = Updater(config.TOKEN, use_context=True) diff --git a/telegram_bot_examples/coin_flip/main.py b/telegram_bot_examples/coin_flip/main.py index a2fc45ec8..68f7d0670 100644 --- a/telegram_bot_examples/coin_flip/main.py +++ b/telegram_bot_examples/coin_flip/main.py @@ -41,7 +41,7 @@ @log_func(log) -def on_start(update: Update, _: CallbackContext): +def on_start(update: Update, _: CallbackContext) -> None: reply_markup = ReplyKeyboardMarkup.from_button( "Подкинуть монетку", resize_keyboard=True ) @@ -53,7 +53,7 @@ def on_start(update: Update, _: CallbackContext): @log_func(log) -def on_request(update: Update, _: CallbackContext): +def on_request(update: Update, _: CallbackContext) -> None: message = update.effective_message reply_markup = InlineKeyboardMarkup.from_button( @@ -69,7 +69,7 @@ def on_request(update: Update, _: CallbackContext): @log_func(log) -def on_callback_coin_flip(update: Update, _: CallbackContext): +def on_callback_coin_flip(update: Update, _: CallbackContext) -> None: message = update.effective_message query = update.callback_query @@ -101,14 +101,14 @@ def on_callback_coin_flip(update: Update, _: CallbackContext): @log_func(log) -def on_callback_hide_coin_flip(update: Update, _: CallbackContext): +def on_callback_hide_coin_flip(update: Update, _: CallbackContext) -> None: query = update.callback_query query.answer() query.message.delete() -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_start), MessageHandler(Filters.text, on_request), diff --git a/telegram_bot_examples/commands.py b/telegram_bot_examples/commands.py index 1d4387e0f..d7412bb05 100644 --- a/telegram_bot_examples/commands.py +++ b/telegram_bot_examples/commands.py @@ -23,12 +23,12 @@ @log_func(log) -def on_start(update: Update, _: CallbackContext): +def on_start(update: Update, _: CallbackContext) -> None: update.effective_message.reply_text("Write something") @log_func(log) -def on_request(update: Update, _: CallbackContext): +def on_request(update: Update, _: CallbackContext) -> None: message = update.effective_message text = "Commands:\n" + "\n".join(f" /{x}" for x in ALL_COMMANDS) @@ -36,7 +36,7 @@ def on_request(update: Update, _: CallbackContext): @log_func(log) -def on_say_hello(update: Update, context: CallbackContext): +def on_say_hello(update: Update, context: CallbackContext) -> None: message = update.effective_message args = context.args @@ -49,18 +49,18 @@ def on_say_hello(update: Update, context: CallbackContext): @log_func(log) -def on_say_hello_world(update: Update, _: CallbackContext): +def on_say_hello_world(update: Update, _: CallbackContext) -> None: message = update.effective_message message.reply_text("Hello World!") @log_func(log) -def on_cmd(update: Update, context: CallbackContext): +def on_cmd(update: Update, context: CallbackContext) -> None: message = update.effective_message message.reply_text(f"Args: {context.args}") -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_start), CommandHandler("say_hello", on_say_hello), @@ -69,7 +69,7 @@ def main(): MessageHandler(Filters.text, on_request), ] - def before_start_func(updater: Updater): + def before_start_func(updater: Updater) -> None: for commands in updater.dispatcher.handlers.values(): for command in commands: if isinstance(command, CommandHandler): diff --git a/telegram_bot_examples/common.py b/telegram_bot_examples/common.py index b5af25f45..784351bb9 100644 --- a/telegram_bot_examples/common.py +++ b/telegram_bot_examples/common.py @@ -92,7 +92,7 @@ def wrapper(update: Update, context: CallbackContext): return actual_decorator -def reply_error(log: logging.Logger, update: Update, context: CallbackContext): +def reply_error(log: logging.Logger, update: Update, context: CallbackContext) -> None: log.error("Error: %s\nUpdate: %s", context.error, update, exc_info=context.error) if update: update.effective_message.reply_text(config.ERROR_TEXT) @@ -109,7 +109,7 @@ def start_bot( handlers: list[Handler], before_start_func: Callable[[Updater], None] = None, **updater_kwargs, -): +) -> None: log.debug("Start") cpu_count = os.cpu_count() @@ -149,7 +149,7 @@ def start_bot( log.debug("Finish") -def run_main(main_func: Callable, log: logging.Logger, timeout=15): +def run_main(main_func: Callable, log: logging.Logger, timeout=15) -> None: while True: try: main_func() diff --git a/telegram_bot_examples/counter_in__InlineKeyboardButton__cache_dict.py b/telegram_bot_examples/counter_in__InlineKeyboardButton__cache_dict.py index 1b288eebc..24ffd26a4 100644 --- a/telegram_bot_examples/counter_in__InlineKeyboardButton__cache_dict.py +++ b/telegram_bot_examples/counter_in__InlineKeyboardButton__cache_dict.py @@ -44,12 +44,12 @@ def get_reply_markup(data: dict[str, int]) -> InlineKeyboardMarkup: @log_func(log) -def on_start(update: Update, _: CallbackContext): +def on_start(update: Update, _: CallbackContext) -> None: update.effective_message.reply_text("Write something") @log_func(log) -def on_request(update: Update, _: CallbackContext): +def on_request(update: Update, _: CallbackContext) -> None: chat_id = update.effective_chat.id message_id = update.effective_message.message_id @@ -64,7 +64,7 @@ def on_request(update: Update, _: CallbackContext): @log_func(log) -def on_callback_query(update: Update, _: CallbackContext): +def on_callback_query(update: Update, _: CallbackContext) -> None: query = update.callback_query query.answer() @@ -91,7 +91,7 @@ def on_callback_query(update: Update, _: CallbackContext): query.message.edit_reply_markup(reply_markup=get_reply_markup(data)) -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_start), MessageHandler(Filters.text, on_request), diff --git a/telegram_bot_examples/counter_in__InlineKeyboardButton__telegram_context.py b/telegram_bot_examples/counter_in__InlineKeyboardButton__telegram_context.py index 8919f74b9..f9efda6d6 100644 --- a/telegram_bot_examples/counter_in__InlineKeyboardButton__telegram_context.py +++ b/telegram_bot_examples/counter_in__InlineKeyboardButton__telegram_context.py @@ -28,12 +28,12 @@ @log_func(log) -def on_start(update: Update, _: CallbackContext): +def on_start(update: Update, _: CallbackContext) -> None: update.effective_message.reply_text("Write something") @log_func(log) -def on_request(update: Update, _: CallbackContext): +def on_request(update: Update, _: CallbackContext) -> None: keyboard = [ [ InlineKeyboardButton(str(value), callback_data=data) @@ -46,7 +46,7 @@ def on_request(update: Update, _: CallbackContext): @log_func(log) -def on_callback_query(update: Update, _: CallbackContext): +def on_callback_query(update: Update, _: CallbackContext) -> None: query = update.callback_query query.answer() @@ -62,7 +62,7 @@ def on_callback_query(update: Update, _: CallbackContext): query.message.edit_reply_markup(reply_markup=reply_markup) -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_start), MessageHandler(Filters.text, on_request), diff --git a/telegram_bot_examples/deep_linking__start_argument.py b/telegram_bot_examples/deep_linking__start_argument.py index 00b80b1d7..75cd0dce1 100644 --- a/telegram_bot_examples/deep_linking__start_argument.py +++ b/telegram_bot_examples/deep_linking__start_argument.py @@ -19,7 +19,7 @@ @log_func(log) -def on_start(update: Update, context: CallbackContext): +def on_start(update: Update, context: CallbackContext) -> None: start_argument = "" if context.args: # https://t.me/?start= @@ -29,13 +29,13 @@ def on_start(update: Update, context: CallbackContext): @log_func(log) -def on_request(update: Update, _: CallbackContext): +def on_request(update: Update, _: CallbackContext) -> None: message = update.effective_message message.reply_text(message.text) -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_start), MessageHandler(Filters.text, on_request), diff --git a/telegram_bot_examples/dice.py b/telegram_bot_examples/dice.py index 556ec2a43..183917e6d 100644 --- a/telegram_bot_examples/dice.py +++ b/telegram_bot_examples/dice.py @@ -24,12 +24,12 @@ @log_func(log) -def on_start(update: Update, _: CallbackContext): +def on_start(update: Update, _: CallbackContext) -> None: update.effective_message.reply_text("Select dice:", reply_markup=REPLY_MARKUP) @log_func(log) -def on_callback_query_dice(update: Update, _: CallbackContext): +def on_callback_query_dice(update: Update, _: CallbackContext) -> None: query = update.callback_query query.answer() @@ -39,7 +39,7 @@ def on_callback_query_dice(update: Update, _: CallbackContext): query.message.reply_text(f"dice={rs_message.dice.value}") -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_start), CallbackQueryHandler(on_callback_query_dice, pattern=PATTERN_DICE), diff --git a/telegram_bot_examples/echo__check_user_language.py b/telegram_bot_examples/echo__check_user_language.py index 5a0cca9ff..ac9923551 100644 --- a/telegram_bot_examples/echo__check_user_language.py +++ b/telegram_bot_examples/echo__check_user_language.py @@ -15,18 +15,18 @@ @log_func(log) -def on_start(update: Update, _: CallbackContext): +def on_start(update: Update, _: CallbackContext) -> None: update.effective_message.reply_text("Write something") @log_func(log) -def on_request(update: Update, _: CallbackContext): +def on_request(update: Update, _: CallbackContext) -> None: message = update.effective_message message.reply_text(f"Language code: {update.effective_user.language_code}") -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_start), MessageHandler(Filters.text, on_request), diff --git a/telegram_bot_examples/funs_tests__speak_pict_youtube/speak_pict_youtube.py b/telegram_bot_examples/funs_tests__speak_pict_youtube/speak_pict_youtube.py index 836f9e7fe..f8bbd19fd 100644 --- a/telegram_bot_examples/funs_tests__speak_pict_youtube/speak_pict_youtube.py +++ b/telegram_bot_examples/funs_tests__speak_pict_youtube/speak_pict_youtube.py @@ -36,21 +36,21 @@ # Define a few command handlers. These usually take the two arguments bot and # update. Error handlers also receive the raised TelegramError object in error. -def start(update: Update, context: CallbackContext): +def start(update: Update, context: CallbackContext) -> None: update.effective_message.reply_text(text="Hi!") -def help(update: Update, context: CallbackContext): +def help(update: Update, context: CallbackContext) -> None: text = "Commands:\n" + "\n".join(f" /{x}" for x in ALL_COMMANDS) update.effective_message.reply_text(text) -def echo(update: Update, context: CallbackContext): +def echo(update: Update, context: CallbackContext) -> None: message = update.effective_message message.reply_text(text=f"Echo: {message.text}") -def on_exchange_rates(update: Update, _: CallbackContext): +def on_exchange_rates(update: Update, _: CallbackContext) -> None: text = "Курс:" for code in ["USD", "EUR"]: text += f"\n {code}: {exchange_rate(code)[0]}" @@ -59,20 +59,20 @@ def on_exchange_rates(update: Update, _: CallbackContext): update.effective_message.reply_text(text=text) -def pict(update: Update, _: CallbackContext): +def pict(update: Update, _: CallbackContext) -> None: update.effective_message.reply_photo( "https://t8.mangas.rocks/auto/07/48/88/Onepunchman_t1_gl1_18.png" ) -def pict2(update: Update, _: CallbackContext): +def pict2(update: Update, _: CallbackContext) -> None: message = update.effective_message with open("files/Onepunchman_t1_gl1_18.png", "rb") as f: message.reply_photo(f) -def pict3(update: Update, _: CallbackContext): +def pict3(update: Update, _: CallbackContext) -> None: message = update.effective_message max_parts = 10 @@ -91,7 +91,7 @@ def pict3(update: Update, _: CallbackContext): # Поиск на YouTube -def on_video(update: Update, context: CallbackContext): +def on_video(update: Update, context: CallbackContext) -> None: message = update.effective_message args = context.args @@ -203,11 +203,11 @@ def on_video(update: Update, context: CallbackContext): # message.reply_text(text='Speak gender изменена: {} -> {}.'.format(last_gender, gender)) -def on_error(update: Update, context: CallbackContext): +def on_error(update: Update, context: CallbackContext) -> None: reply_error(log, update, context) -def main(): +def main() -> None: cpu_count = os.cpu_count() workers = cpu_count log.debug("System: CPU_COUNT=%s, WORKERS=%s", cpu_count, workers) diff --git a/telegram_bot_examples/get_user_info.py b/telegram_bot_examples/get_user_info.py index ddc1eb6e0..ef5dde738 100644 --- a/telegram_bot_examples/get_user_info.py +++ b/telegram_bot_examples/get_user_info.py @@ -15,18 +15,18 @@ @log_func(log) -def on_start(update: Update, _: CallbackContext): +def on_start(update: Update, _: CallbackContext) -> None: update.effective_message.reply_text("Write something") @log_func(log) -def on_request(update: Update, _: CallbackContext): +def on_request(update: Update, _: CallbackContext) -> None: message = update.effective_message message.reply_text(str(update.effective_user)) -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_start), MessageHandler(Filters.text, on_request), diff --git a/telegram_bot_examples/get_user_profile_photos.py b/telegram_bot_examples/get_user_profile_photos.py index 97be34462..4c13ca4f3 100644 --- a/telegram_bot_examples/get_user_profile_photos.py +++ b/telegram_bot_examples/get_user_profile_photos.py @@ -19,12 +19,12 @@ @log_func(log) -def on_start(update: Update, _: CallbackContext): +def on_start(update: Update, _: CallbackContext) -> None: update.effective_message.reply_text("Write something") @log_func(log) -def on_request(update: Update, context: CallbackContext): +def on_request(update: Update, context: CallbackContext) -> None: message = update.effective_message user_id = update.effective_user.id @@ -41,7 +41,7 @@ def on_request(update: Update, context: CallbackContext): message.reply_photo(file_id, caption=file_id) -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_start), MessageHandler(Filters.text, on_request), diff --git a/telegram_bot_examples/giphy_send_gif/main.py b/telegram_bot_examples/giphy_send_gif/main.py index 50c61e41d..cf24ff415 100644 --- a/telegram_bot_examples/giphy_send_gif/main.py +++ b/telegram_bot_examples/giphy_send_gif/main.py @@ -50,18 +50,18 @@ def get_random_gif_url(query: str) -> str | None: @log_func(log) -def on_start(update: Update, _: CallbackContext): +def on_start(update: Update, _: CallbackContext) -> None: update.effective_message.reply_text("Write something or /get_local_file_gif") @log_func(log) -def on_get_local_file_gif(update: Update, _: CallbackContext): +def on_get_local_file_gif(update: Update, _: CallbackContext) -> None: message = update.effective_message message.reply_document(document=open(SAMPLE_GIF_FILE_NAME, "rb"), quote=True) @log_func(log) -def on_request(update: Update, _: CallbackContext): +def on_request(update: Update, _: CallbackContext) -> None: message = update.effective_message url = get_random_gif_url(message.text) @@ -74,7 +74,7 @@ def on_request(update: Update, _: CallbackContext): message.reply_text(text="Not found!", quote=True) -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_start), CommandHandler("get_local_file_gif", on_get_local_file_gif), diff --git a/telegram_bot_examples/handle_errors.py b/telegram_bot_examples/handle_errors.py index b1ba52de4..0815a0c14 100644 --- a/telegram_bot_examples/handle_errors.py +++ b/telegram_bot_examples/handle_errors.py @@ -47,7 +47,7 @@ class ErrorHandlingMode(enum.Enum): log = get_logger(__file__) -def reply_error(log: logging.Logger, update: Update, context: CallbackContext): +def reply_error(log: logging.Logger, update: Update, context: CallbackContext) -> None: log.error("Error: %s\nUpdate: %s", context.error, update, exc_info=context.error) # traceback.format_exception returns the usual python message about an exception, but as a @@ -92,7 +92,7 @@ def reply_error(log: logging.Logger, update: Update, context: CallbackContext): @log_func(log) -def on_request(update: Update, _: CallbackContext): +def on_request(update: Update, _: CallbackContext) -> None: message = update.effective_message user = update.effective_user chat = update.effective_chat @@ -107,7 +107,7 @@ def on_request(update: Update, _: CallbackContext): @log_func(log) -def on_reply_command(update: Update, _: CallbackContext): +def on_reply_command(update: Update, _: CallbackContext) -> None: message = update.effective_message DATA["MODE"] = ErrorHandlingMode[message.text] @@ -120,7 +120,7 @@ def on_reply_command(update: Update, _: CallbackContext): 1 / 0 -def main(): +def main() -> None: updater = Updater( config.TOKEN, defaults=Defaults(run_async=True), diff --git a/telegram_bot_examples/handle_reply_command.py b/telegram_bot_examples/handle_reply_command.py index 617d16c77..3005e08d2 100644 --- a/telegram_bot_examples/handle_reply_command.py +++ b/telegram_bot_examples/handle_reply_command.py @@ -18,19 +18,19 @@ @log_func(log) -def on_start(update: Update, _: CallbackContext): +def on_start(update: Update, _: CallbackContext) -> None: update.effective_message.reply_text("Write something") @log_func(log) -def on_request(update: Update, _: CallbackContext): +def on_request(update: Update, _: CallbackContext) -> None: message = update.effective_message message.reply_text("Echo: " + message.text, reply_markup=REPLY_KEYBOARD_MARKUP) @log_func(log) -def on_reply_command(update: Update, _: CallbackContext): +def on_reply_command(update: Update, _: CallbackContext) -> None: message = update.effective_message message.reply_text( @@ -38,7 +38,7 @@ def on_reply_command(update: Update, _: CallbackContext): ) -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_start), MessageHandler(Filters.text(COMMANDS), on_reply_command), diff --git a/telegram_bot_examples/handle_reply_command__max_buttons.py b/telegram_bot_examples/handle_reply_command__max_buttons.py index f3edb8848..986c63b44 100644 --- a/telegram_bot_examples/handle_reply_command__max_buttons.py +++ b/telegram_bot_examples/handle_reply_command__max_buttons.py @@ -21,18 +21,18 @@ @log_func(log) -def on_start(update: Update, _: CallbackContext): +def on_start(update: Update, _: CallbackContext) -> None: update.effective_message.reply_text("Write something") @log_func(log) -def on_request(update: Update, _: CallbackContext): +def on_request(update: Update, _: CallbackContext) -> None: message = update.effective_message message.reply_text("Echo: " + message.text, reply_markup=REPLY_KEYBOARD_MARKUP) -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_start), MessageHandler(Filters.text, on_request), diff --git a/telegram_bot_examples/hello_world__echo.py b/telegram_bot_examples/hello_world__echo.py index 10a5847d3..59f6f4454 100644 --- a/telegram_bot_examples/hello_world__echo.py +++ b/telegram_bot_examples/hello_world__echo.py @@ -15,18 +15,18 @@ @log_func(log) -def on_start(update: Update, _: CallbackContext): +def on_start(update: Update, _: CallbackContext) -> None: update.effective_message.reply_text("Write something") @log_func(log) -def on_request(update: Update, _: CallbackContext): +def on_request(update: Update, _: CallbackContext) -> None: message = update.effective_message message.reply_text("Echo: " + message.text) -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_start), MessageHandler(Filters.text, on_request), diff --git a/telegram_bot_examples/hello_world__echo_with_reply.py b/telegram_bot_examples/hello_world__echo_with_reply.py index 1067ad0cb..83d6ce052 100644 --- a/telegram_bot_examples/hello_world__echo_with_reply.py +++ b/telegram_bot_examples/hello_world__echo_with_reply.py @@ -15,18 +15,18 @@ @log_func(log) -def on_start(update: Update, _: CallbackContext): +def on_start(update: Update, _: CallbackContext) -> None: update.effective_message.reply_text("Write something") @log_func(log) -def on_request(update: Update, _: CallbackContext): +def on_request(update: Update, _: CallbackContext) -> None: message = update.effective_message message.reply_text(message.text, quote=True) -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_start), MessageHandler(Filters.text, on_request), diff --git a/telegram_bot_examples/massage_ConversationHandler.py b/telegram_bot_examples/massage_ConversationHandler.py index 9762039ef..9d143faed 100644 --- a/telegram_bot_examples/massage_ConversationHandler.py +++ b/telegram_bot_examples/massage_ConversationHandler.py @@ -55,7 +55,7 @@ def facts_to_str(user_data: dict) -> str: @log_func(log) -def on_main_menu(update: Update, _: CallbackContext): +def on_main_menu(update: Update, _: CallbackContext) -> None: # Если функция вызвана из CallbackQueryHandler query = update.callback_query if query: @@ -349,12 +349,12 @@ def on_recording(update: Update, context: CallbackContext): return on_sing_up(update, context) -def on_error(update, context): +def on_error(update, context) -> None: """Log Errors caused by Updates.""" log.warning('Update "%s" caused error "%s"', update, context.error) -def main(): +def main() -> None: updater = Updater( token=TOKEN, defaults=Defaults(run_async=True), diff --git a/telegram_bot_examples/pagination/example_as_images.py b/telegram_bot_examples/pagination/example_as_images.py index b8915be39..4cd2ae4c7 100644 --- a/telegram_bot_examples/pagination/example_as_images.py +++ b/telegram_bot_examples/pagination/example_as_images.py @@ -30,7 +30,7 @@ @log_func(log) -def on_request(update: Update, _: CallbackContext): +def on_request(update: Update, _: CallbackContext) -> None: message = update.effective_message paginator = InlineKeyboardPaginator( @@ -48,7 +48,7 @@ def on_request(update: Update, _: CallbackContext): @log_func(log) -def on_callback_query(update: Update, _: CallbackContext): +def on_callback_query(update: Update, _: CallbackContext) -> None: query = update.callback_query query.answer() @@ -77,7 +77,7 @@ def on_callback_query(update: Update, _: CallbackContext): ) -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_request), MessageHandler(Filters.text, on_request), diff --git a/telegram_bot_examples/pagination/example_as_images_with_text.py b/telegram_bot_examples/pagination/example_as_images_with_text.py index 51a42635e..b18c36bfc 100644 --- a/telegram_bot_examples/pagination/example_as_images_with_text.py +++ b/telegram_bot_examples/pagination/example_as_images_with_text.py @@ -30,7 +30,7 @@ @log_func(log) -def on_request(update: Update, _: CallbackContext): +def on_request(update: Update, _: CallbackContext) -> None: message = update.effective_message paginator = InlineKeyboardPaginator( @@ -48,7 +48,7 @@ def on_request(update: Update, _: CallbackContext): @log_func(log) -def on_callback_query(update: Update, _: CallbackContext): +def on_callback_query(update: Update, _: CallbackContext) -> None: query = update.callback_query query.answer() @@ -77,7 +77,7 @@ def on_callback_query(update: Update, _: CallbackContext): ) -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_request), MessageHandler(Filters.text, on_request), diff --git a/telegram_bot_examples/pagination/example_as_text.py b/telegram_bot_examples/pagination/example_as_text.py index 09909d242..567b82a68 100644 --- a/telegram_bot_examples/pagination/example_as_text.py +++ b/telegram_bot_examples/pagination/example_as_text.py @@ -30,7 +30,7 @@ @log_func(log) -def on_request(update: Update, _: CallbackContext): +def on_request(update: Update, _: CallbackContext) -> None: message = update.effective_message paginator = InlineKeyboardPaginator( @@ -49,7 +49,7 @@ def on_request(update: Update, _: CallbackContext): @log_func(log) -def on_callback_query(update: Update, _: CallbackContext): +def on_callback_query(update: Update, _: CallbackContext) -> None: query = update.callback_query query.answer() @@ -75,7 +75,7 @@ def on_callback_query(update: Update, _: CallbackContext): ) -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_request), MessageHandler(Filters.text, on_request), diff --git a/telegram_bot_examples/qrcode_bot.py b/telegram_bot_examples/qrcode_bot.py index 446ff4cb2..b821cec1b 100644 --- a/telegram_bot_examples/qrcode_bot.py +++ b/telegram_bot_examples/qrcode_bot.py @@ -20,12 +20,12 @@ @log_func(log) -def on_start(update: Update, _: CallbackContext): +def on_start(update: Update, _: CallbackContext) -> None: update.effective_message.reply_text("Write something") @log_func(log) -def on_request(update: Update, _: CallbackContext): +def on_request(update: Update, _: CallbackContext) -> None: message = update.effective_message bytes_io = BytesIO() @@ -40,7 +40,7 @@ def on_request(update: Update, _: CallbackContext): message.reply_photo(photo=bytes_io, quote=True) -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_start), MessageHandler(Filters.text, on_request), diff --git a/telegram_bot_examples/questionnaire__anketa__ConversationHandler.py b/telegram_bot_examples/questionnaire__anketa__ConversationHandler.py index 19dc5b6d5..340a91ffe 100644 --- a/telegram_bot_examples/questionnaire__anketa__ConversationHandler.py +++ b/telegram_bot_examples/questionnaire__anketa__ConversationHandler.py @@ -43,7 +43,7 @@ @log_func(log) -def on_start(update: Update, _: CallbackContext): +def on_start(update: Update, _: CallbackContext) -> None: update.effective_message.reply_text( "Введите что-нибудь", reply_markup=REPLY_KEYBOARD_MARKUP ) @@ -121,7 +121,7 @@ def on_anketa_exit_comment(update: Update, context: CallbackContext): @log_func(log) -def on_anketa_invalid_set_rating(update: Update, _: CallbackContext): +def on_anketa_invalid_set_rating(update: Update, _: CallbackContext) -> None: update.effective_message.reply_text( "Я вас не понимаю, выберите оценку на клавиатуре!", reply_markup=REPLY_KEYBOARD_MARKUP_SET_RATING, @@ -129,13 +129,13 @@ def on_anketa_invalid_set_rating(update: Update, _: CallbackContext): @log_func(log) -def on_request(update: Update, _: CallbackContext): +def on_request(update: Update, _: CallbackContext) -> None: message = update.effective_message message.reply_text("Echo: " + message.text, reply_markup=REPLY_KEYBOARD_MARKUP) -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_start), ConversationHandler( diff --git a/telegram_bot_examples/questionnaire__anketa__user_data.py b/telegram_bot_examples/questionnaire__anketa__user_data.py index 0fbbbce91..f2ca6ba6e 100644 --- a/telegram_bot_examples/questionnaire__anketa__user_data.py +++ b/telegram_bot_examples/questionnaire__anketa__user_data.py @@ -39,14 +39,14 @@ @log_func(log) -def on_start(update: Update, _: CallbackContext): +def on_start(update: Update, _: CallbackContext) -> None: update.effective_message.reply_text( "Введите что-нибудь", reply_markup=REPLY_KEYBOARD_MARKUP ) @log_func(log) -def on_request(update: Update, context: CallbackContext): +def on_request(update: Update, context: CallbackContext) -> None: message = update.effective_message state = context.user_data.get("state") @@ -103,7 +103,7 @@ def on_request(update: Update, context: CallbackContext): message.reply_text("Спасибо!", reply_markup=REPLY_KEYBOARD_MARKUP) -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_start), MessageHandler(Filters.text, on_request), diff --git a/telegram_bot_examples/reminder/db.py b/telegram_bot_examples/reminder/db.py index 9c1a26353..cd6e4a2de 100644 --- a/telegram_bot_examples/reminder/db.py +++ b/telegram_bot_examples/reminder/db.py @@ -30,7 +30,7 @@ DB_DIR_NAME.mkdir(parents=True, exist_ok=True) -def db_create_backup(backup_dir="backup", date_fmt="%Y-%m-%d"): +def db_create_backup(backup_dir="backup", date_fmt="%Y-%m-%d") -> None: backup_path = Path(backup_dir) backup_path.mkdir(parents=True, exist_ok=True) @@ -65,7 +65,7 @@ def get_inherited_models(cls) -> list[Type["BaseModel"]]: return sorted(cls.__subclasses__(), key=lambda x: x.__name__) @classmethod - def print_count_of_tables(cls): + def print_count_of_tables(cls) -> None: items = [] for sub_cls in cls.get_inherited_models(): name = sub_cls.__name__ @@ -74,7 +74,7 @@ def print_count_of_tables(cls): print(", ".join(items)) - def __str__(self): + def __str__(self) -> str: fields = [] for k, field in self._meta.fields.items(): v = getattr(self, k) @@ -101,7 +101,7 @@ class User(BaseModel): language_code = TextField(null=True) last_activity = DateTimeField(default=datetime.now) - def update_last_activity(self): + def update_last_activity(self) -> None: self.last_activity = datetime.now() self.save() @@ -132,7 +132,7 @@ class Chat(BaseModel): description = TextField(null=True) last_activity = DateTimeField(default=datetime.now) - def update_last_activity(self): + def update_last_activity(self) -> None: self.last_activity = datetime.now() self.save() diff --git a/telegram_bot_examples/reminder/main.py b/telegram_bot_examples/reminder/main.py index bdfb32821..6c824a60e 100644 --- a/telegram_bot_examples/reminder/main.py +++ b/telegram_bot_examples/reminder/main.py @@ -28,7 +28,7 @@ from utils import parse_command, get_pretty_datetime -def do_checking_reminders(log: Logger, bot: Bot): +def do_checking_reminders(log: Logger, bot: Bot) -> None: while True: try: expected_time = dt.datetime.now() - dt.timedelta(seconds=1) @@ -64,7 +64,7 @@ def do_checking_reminders(log: Logger, bot: Bot): @log_func(log) -def on_start(update: Update, _: CallbackContext): +def on_start(update: Update, _: CallbackContext) -> None: update.effective_message.reply_text( 'Введите что-нибудь, например: "напомни через 1 час".\n' 'Для получения списка напоминаний, напишите: "список"' @@ -72,7 +72,7 @@ def on_start(update: Update, _: CallbackContext): @log_func(log) -def on_request(update: Update, _: CallbackContext): +def on_request(update: Update, _: CallbackContext) -> None: message = update.effective_message command = message.text @@ -95,7 +95,7 @@ def on_request(update: Update, _: CallbackContext): @log_func(log) -def on_get_reminders(update: Update, _: CallbackContext): +def on_get_reminders(update: Update, _: CallbackContext) -> None: message = update.effective_message chat = update.effective_chat user = update.effective_user @@ -122,14 +122,14 @@ def on_get_reminders(update: Update, _: CallbackContext): message.reply_text(text) -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_start), MessageHandler(Filters.regex("(?i)^Список$"), on_get_reminders), MessageHandler(Filters.text, on_request), ] - def before_start_func(updater: Updater): + def before_start_func(updater: Updater) -> None: # TODO: When the bot crashes, it is possible to create duplicate thread # Need using global variable for getting bot thread = Thread(target=do_checking_reminders, args=[log, updater.bot]) diff --git a/telegram_bot_examples/restriction_on_frequent_sending_of_messages__using_dict.py b/telegram_bot_examples/restriction_on_frequent_sending_of_messages__using_dict.py index a1ad0beb3..84b1f4c80 100644 --- a/telegram_bot_examples/restriction_on_frequent_sending_of_messages__using_dict.py +++ b/telegram_bot_examples/restriction_on_frequent_sending_of_messages__using_dict.py @@ -20,12 +20,12 @@ @log_func(log) -def on_start(update: Update, _: CallbackContext): +def on_start(update: Update, _: CallbackContext) -> None: update.effective_message.reply_text("Write something") @log_func(log) -def on_request(update: Update, _: CallbackContext): +def on_request(update: Update, _: CallbackContext) -> None: message = update.effective_message text = "Получено!" @@ -52,7 +52,7 @@ def on_request(update: Update, _: CallbackContext): message.reply_text(text, quote=True) -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_start), MessageHandler(Filters.text, on_request), diff --git a/telegram_bot_examples/send_contact_or_location.py b/telegram_bot_examples/send_contact_or_location.py index 19bed6e0e..57ccb2b84 100644 --- a/telegram_bot_examples/send_contact_or_location.py +++ b/telegram_bot_examples/send_contact_or_location.py @@ -21,21 +21,21 @@ @log_func(log) -def on_start(update: Update, _: CallbackContext): +def on_start(update: Update, _: CallbackContext) -> None: update.effective_message.reply_text( "Write something", reply_markup=REPLY_KEYBOARD_MARKUP ) @log_func(log) -def on_request(update: Update, _: CallbackContext): +def on_request(update: Update, _: CallbackContext) -> None: message = update.effective_message message.reply_text("Echo: " + message.text, reply_markup=REPLY_KEYBOARD_MARKUP) @log_func(log) -def on_contact_or_location(update: Update, _: CallbackContext): +def on_contact_or_location(update: Update, _: CallbackContext) -> None: message = update.effective_message text = "" @@ -48,7 +48,7 @@ def on_contact_or_location(update: Update, _: CallbackContext): message.reply_text(text, reply_markup=REPLY_KEYBOARD_MARKUP) -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_start), MessageHandler(Filters.text, on_request), diff --git a/telegram_bot_examples/send_photo_using_file_id.py b/telegram_bot_examples/send_photo_using_file_id.py index 4dce314df..3db0853b3 100644 --- a/telegram_bot_examples/send_photo_using_file_id.py +++ b/telegram_bot_examples/send_photo_using_file_id.py @@ -20,7 +20,7 @@ @log_func(log) -def on_start(update: Update, _: CallbackContext): +def on_start(update: Update, _: CallbackContext) -> None: update.effective_message.reply_text( "Отправка картинки боту вернет её с file_id\n" "Отправка текстом file_id вернет картинку" @@ -40,7 +40,7 @@ def on_request(update: Update, _: CallbackContext): @log_func(log) -def on_photo(update: Update, _: CallbackContext): +def on_photo(update: Update, _: CallbackContext) -> None: message = update.effective_message photo_large = max(message.photo, key=lambda x: (x.width, x.height)) @@ -49,7 +49,7 @@ def on_photo(update: Update, _: CallbackContext): message.reply_photo(file_id, caption=f"file_id: {file_id}", quote=True) -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_start), MessageHandler(Filters.text, on_request), diff --git a/telegram_bot_examples/set_run_async=True_for_all_handlers__using_defaults__simple.py b/telegram_bot_examples/set_run_async=True_for_all_handlers__using_defaults__simple.py index 4e5f59b10..0a762771b 100644 --- a/telegram_bot_examples/set_run_async=True_for_all_handlers__using_defaults__simple.py +++ b/telegram_bot_examples/set_run_async=True_for_all_handlers__using_defaults__simple.py @@ -13,13 +13,13 @@ import config -def on_request(update: Update, _: CallbackContext): +def on_request(update: Update, _: CallbackContext) -> None: message = update.effective_message message.reply_text(f"Thread: {threading.current_thread()}") -def main(): +def main() -> None: updater = Updater( config.TOKEN, defaults=Defaults(run_async=True), diff --git a/telegram_bot_examples/settings_inline_menu.py b/telegram_bot_examples/settings_inline_menu.py index c959cb647..aa1e7af07 100644 --- a/telegram_bot_examples/settings_inline_menu.py +++ b/telegram_bot_examples/settings_inline_menu.py @@ -69,7 +69,7 @@ def get_pattern_full(self) -> re.Pattern: ) -def _on_reply_debug(update: Update, context: CallbackContext): +def _on_reply_debug(update: Update, context: CallbackContext) -> None: query = update.callback_query settings = SettingState.DEBUG @@ -103,7 +103,7 @@ def _on_reply_debug(update: Update, context: CallbackContext): query.edit_message_text(text, reply_markup=reply_markup) -def _on_reply_year(update: Update, context: CallbackContext): +def _on_reply_year(update: Update, context: CallbackContext) -> None: query = update.callback_query settings = SettingState.YEAR @@ -153,7 +153,7 @@ def _on_reply_year(update: Update, context: CallbackContext): query.edit_message_text(text, reply_markup=reply_markup) -def _on_reply_sex(update: Update, context: CallbackContext): +def _on_reply_sex(update: Update, context: CallbackContext) -> None: query = update.callback_query settings = SettingState.SEX @@ -191,12 +191,12 @@ def _on_reply_sex(update: Update, context: CallbackContext): @log_func(log) -def on_start(update: Update, context: CallbackContext): +def on_start(update: Update, context: CallbackContext) -> None: update.effective_message.reply_text("Enter /settings") @log_func(log) -def on_settings(update: Update, context: CallbackContext): +def on_settings(update: Update, context: CallbackContext) -> None: # Если функция вызвана из CallbackQueryHandler query = update.callback_query if query: @@ -221,7 +221,7 @@ def on_settings(update: Update, context: CallbackContext): @log_func(log) -def on_debug(update: Update, context: CallbackContext): +def on_debug(update: Update, context: CallbackContext) -> None: query = update.callback_query query.answer() @@ -229,7 +229,7 @@ def on_debug(update: Update, context: CallbackContext): @log_func(log) -def on_year(update: Update, context: CallbackContext): +def on_year(update: Update, context: CallbackContext) -> None: query = update.callback_query query.answer() @@ -237,14 +237,14 @@ def on_year(update: Update, context: CallbackContext): @log_func(log) -def on_sex(update: Update, context: CallbackContext): +def on_sex(update: Update, context: CallbackContext) -> None: query = update.callback_query query.answer() _on_reply_sex(update, context) -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_start), diff --git a/telegram_bot_examples/show_alert.py b/telegram_bot_examples/show_alert.py index bba3007f0..457ae786b 100644 --- a/telegram_bot_examples/show_alert.py +++ b/telegram_bot_examples/show_alert.py @@ -21,7 +21,7 @@ @log_func(log) -def on_start(update: Update, _: CallbackContext): +def on_start(update: Update, _: CallbackContext) -> None: message = update.effective_message reply_markup = InlineKeyboardMarkup( @@ -38,7 +38,7 @@ def on_start(update: Update, _: CallbackContext): @log_func(log) -def on_select(update: Update, _: CallbackContext): +def on_select(update: Update, _: CallbackContext) -> None: query = update.callback_query if query.data == "cat": @@ -49,7 +49,7 @@ def on_select(update: Update, _: CallbackContext): query.answer("Nothing") -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_start), MessageHandler(Filters.text, on_start), diff --git a/telegram_bot_examples/user_data__PicklePersistence/main.py b/telegram_bot_examples/user_data__PicklePersistence/main.py index d4ffde3db..04e262c0f 100644 --- a/telegram_bot_examples/user_data__PicklePersistence/main.py +++ b/telegram_bot_examples/user_data__PicklePersistence/main.py @@ -24,12 +24,12 @@ @log_func(log) -def on_start(update: Update, _: CallbackContext): +def on_start(update: Update, _: CallbackContext) -> None: update.effective_message.reply_text("Commands: set and get.") @log_func(log) -def on_set(update: Update, context: CallbackContext): +def on_set(update: Update, context: CallbackContext) -> None: message = update.effective_message end = context.match.span()[1] @@ -41,7 +41,7 @@ def on_set(update: Update, context: CallbackContext): @log_func(log) -def on_get(update: Update, context: CallbackContext): +def on_get(update: Update, context: CallbackContext) -> None: message = update.effective_message text = context.user_data.get("text", "") @@ -50,13 +50,13 @@ def on_get(update: Update, context: CallbackContext): @log_func(log) -def on_request(update: Update, _: CallbackContext): +def on_request(update: Update, _: CallbackContext) -> None: message = update.effective_message message.reply_text("Echo: " + message.text) -def main(): +def main() -> None: handlers = [ CommandHandler("start", on_start), MessageHandler(Filters.regex(r"(?i)^(set)\b"), on_set), diff --git a/tensorflow__deep_dream/common.py b/tensorflow__deep_dream/common.py index 0d16dad0a..fdaf6e24e 100644 --- a/tensorflow__deep_dream/common.py +++ b/tensorflow__deep_dream/common.py @@ -26,7 +26,7 @@ # TODO: перенести сюда вспомогательные методы из основного скрипта -def download_tensorflow_model(data_dir="data/"): +def download_tensorflow_model(data_dir="data/") -> None: if not os.path.exists(data_dir): os.mkdir(data_dir) @@ -53,13 +53,13 @@ def download_tensorflow_model(data_dir="data/"): print("Finish extract") -def showarray(a): +def showarray(a) -> None: a = np.uint8(np.clip(a, 0, 1) * 255) plt.imshow(a) plt.show() -def savearray(a, file_name: io.BytesIO | str): +def savearray(a, file_name: io.BytesIO | str) -> None: print("Saving to:", file_name) a = np.uint8(np.clip(a, 0, 1) * 255) diff --git a/tensorflow__deep_dream/main.py b/tensorflow__deep_dream/main.py index a28643693..d42aafa60 100644 --- a/tensorflow__deep_dream/main.py +++ b/tensorflow__deep_dream/main.py @@ -382,7 +382,7 @@ def render_deepdream_from_layer_by_unit( return name -def main(): +def main() -> None: # # # PRINT: layer by units # t_obj_layers = [x.split('/')[1] for x in layers] diff --git a/test_system__envelope.py b/test_system__envelope.py index fda6c4c14..a189b4f11 100644 --- a/test_system__envelope.py +++ b/test_system__envelope.py @@ -29,7 +29,7 @@ ] -def check_1(x, y): +def check_1(x, y) -> None: if envelop_x > x and envelop_y > y: print("ДА") elif envelop_y > x and envelop_x > y: @@ -83,7 +83,7 @@ def check_1(x, y): ] -def check_2(x, y, z): +def check_2(x, y, z) -> None: if hole_x > x and hole_y > y: print("ДА") elif hole_x > y and hole_y > x: diff --git a/textwrap__examples/dedent_examples.py b/textwrap__examples/dedent_examples.py index 8664607ae..9fbee109b 100644 --- a/textwrap__examples/dedent_examples.py +++ b/textwrap__examples/dedent_examples.py @@ -17,7 +17,7 @@ print() -def foo(): +def foo() -> None: """ Съешь ещё этих мягких французских булок, да выпей же чаю diff --git a/time_intervals__call_center.py b/time_intervals__call_center.py index f66c55b6f..6a98890b3 100644 --- a/time_intervals__call_center.py +++ b/time_intervals__call_center.py @@ -22,7 +22,7 @@ class Interval: start: datetime end: datetime - def __init__(self, start_time: str, duration: int): + def __init__(self, start_time: str, duration: int) -> None: self.start = datetime.strptime(start_time, "%H:%M:%S") self.end = self.start + timedelta(seconds=duration) diff --git a/time_this_using_with.py b/time_this_using_with.py index 328756c40..1d99735a3 100644 --- a/time_this_using_with.py +++ b/time_this_using_with.py @@ -5,10 +5,12 @@ from timeit import default_timer +from types import TracebackType +from typing import Optional, Type class TimeThis: - def __init__(self, title="TimeThis"): + def __init__(self, title="TimeThis") -> None: self.title = title self.start_time = None @@ -16,10 +18,13 @@ def __enter__(self): self.start_time = default_timer() return self - def __exit__(self, exc_type, exc_value, exc_traceback): - print( - f"[{self.title}] total time: {default_timer() - self.start_time} sec" - ) + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_value: Optional[BaseException], + exc_traceback: Optional[TracebackType], + ) -> None: + print(f"[{self.title}] total time: {default_timer() - self.start_time} sec") if __name__ == "__main__": diff --git a/timeout_block/kthread.py b/timeout_block/kthread.py index 17a40e4da..bbff52ff7 100644 --- a/timeout_block/kthread.py +++ b/timeout_block/kthread.py @@ -14,17 +14,17 @@ class Kill(Exception): class KThread(Thread): - def __init__(self, *args, **keywords): + def __init__(self, *args, **keywords) -> None: Thread.__init__(self, *args, **keywords) self.killed = False - def start(self): + def start(self) -> None: """Start the thread.""" self.__run_backup = self.run self.run = self.__run # Force the Thread to install our trace. Thread.start(self) - def __run(self): + def __run(self) -> None: """Hacked run function, which installs the trace.""" sys.settrace(self.globaltrace) @@ -47,14 +47,14 @@ def localtrace(self, frame, why, arg): raise Kill() return self.localtrace - def kill(self): + def kill(self) -> None: self.killed = True if __name__ == "__main__": import time - def unlimited_wait(): + def unlimited_wait() -> None: i = 0 while True: diff --git a/timeout_block/main.py b/timeout_block/main.py index 827def87f..b15ad7ad5 100644 --- a/timeout_block/main.py +++ b/timeout_block/main.py @@ -27,7 +27,7 @@ def the_wrapper_around_the_original_function(*args, **kwargs): @timeout(seconds=3) -def unlimited_wait(): +def unlimited_wait() -> None: i = 0 while True: @@ -37,7 +37,7 @@ def unlimited_wait(): @timeout(seconds=3, raise_timeout=True) -def unlimited_wait2(): +def unlimited_wait2() -> None: i = 0 while True: diff --git a/tkinter_examples/Entry_Button__on_click.py b/tkinter_examples/Entry_Button__on_click.py index a6449a344..863aaad06 100644 --- a/tkinter_examples/Entry_Button__on_click.py +++ b/tkinter_examples/Entry_Button__on_click.py @@ -8,7 +8,7 @@ from tkinter import messagebox -def on_button_clicked(): +def on_button_clicked() -> None: try: w = int(weight.get()) h = int(height.get()) diff --git a/tkinter_examples/build_example/main.py b/tkinter_examples/build_example/main.py index 35092ab47..a6f64ded4 100644 --- a/tkinter_examples/build_example/main.py +++ b/tkinter_examples/build_example/main.py @@ -26,7 +26,7 @@ log.pack(side="top", fill="both", expand="true") -def loopproc(): +def loopproc() -> None: print("Hello " + name.get() + "!") tk.after(1000, loopproc) diff --git a/tkinter_examples/button__change_button_icon_on_click/main.py b/tkinter_examples/button__change_button_icon_on_click/main.py index 1966cfdd2..58cb6a159 100644 --- a/tkinter_examples/button__change_button_icon_on_click/main.py +++ b/tkinter_examples/button__change_button_icon_on_click/main.py @@ -7,7 +7,7 @@ import tkinter as tk -def _on_button_click(button): +def _on_button_click(button) -> None: global PHOTO_COUNTER PHOTO_COUNTER += 1 if len(photo_list) <= PHOTO_COUNTER: diff --git a/tkinter_examples/button__change_button_icon_on_click/main__next_image_generator.py b/tkinter_examples/button__change_button_icon_on_click/main__next_image_generator.py index 83cea0eb1..e56b46e32 100644 --- a/tkinter_examples/button__change_button_icon_on_click/main__next_image_generator.py +++ b/tkinter_examples/button__change_button_icon_on_click/main__next_image_generator.py @@ -7,7 +7,7 @@ import tkinter as tk -def _on_button_click(button): +def _on_button_click(button) -> None: button.config(image=get_next_image()) diff --git a/tkinter_examples/button__change_button_icon_on_click/main__next_image_generator__using__itertools_cycle.py b/tkinter_examples/button__change_button_icon_on_click/main__next_image_generator__using__itertools_cycle.py index 87a93a7b7..1d8b4175f 100644 --- a/tkinter_examples/button__change_button_icon_on_click/main__next_image_generator__using__itertools_cycle.py +++ b/tkinter_examples/button__change_button_icon_on_click/main__next_image_generator__using__itertools_cycle.py @@ -25,7 +25,7 @@ def get_next_image() -> tk.PhotoImage: return next(CYCLED_IMAGES) -def _on_button_click(): +def _on_button_click() -> None: panel.config(image=get_next_image()) diff --git a/tkinter_examples/button_entry_label.py b/tkinter_examples/button_entry_label.py index b4ec3b72d..32ef77402 100644 --- a/tkinter_examples/button_entry_label.py +++ b/tkinter_examples/button_entry_label.py @@ -7,7 +7,7 @@ import tkinter as tk -def on_button_perevod_clicked(): +def on_button_perevod_clicked() -> None: your_text = text1.get() a = your_text.encode("cp1251") b = list(map(int, a)) diff --git a/tkinter_examples/center_window.py b/tkinter_examples/center_window.py index c09e13d44..42b5935c4 100644 --- a/tkinter_examples/center_window.py +++ b/tkinter_examples/center_window.py @@ -4,7 +4,7 @@ __author__ = "ipetrash" -def center_window(root, width=300, height=200): +def center_window(root, width=300, height=200) -> None: # get screen width and height screen_width = root.winfo_screenwidth() screen_height = root.winfo_screenheight() diff --git a/tkinter_examples/class_Example_with_Frame_Listbox.py b/tkinter_examples/class_Example_with_Frame_Listbox.py index accb8eb38..afc4219f2 100644 --- a/tkinter_examples/class_Example_with_Frame_Listbox.py +++ b/tkinter_examples/class_Example_with_Frame_Listbox.py @@ -8,13 +8,13 @@ class Example(tk.Frame): - def __init__(self, parent): + def __init__(self, parent) -> None: super().__init__(parent) self.parent = parent self.init_ui() - def init_ui(self): + def init_ui(self) -> None: self.pack(fill=tk.BOTH, expand=1) acts = ["Scarlett Johansson", "Rachel Weiss", "Natalie Portman", "Jessica Alba"] @@ -31,7 +31,7 @@ def init_ui(self): self.pack() - def on_select(self, val): + def on_select(self, val) -> None: sender = val.widget idx = sender.curselection() value = sender.get(idx) diff --git a/tkinter_examples/class_Example_with_Frame_Tab_Notebook.py b/tkinter_examples/class_Example_with_Frame_Tab_Notebook.py index d6d6958f5..fc2e6bc5f 100644 --- a/tkinter_examples/class_Example_with_Frame_Tab_Notebook.py +++ b/tkinter_examples/class_Example_with_Frame_Tab_Notebook.py @@ -8,13 +8,13 @@ class Example(Frame): - def __init__(self, parent): + def __init__(self, parent) -> None: super().__init__(parent) self.parent = parent self.init_ui() - def init_ui(self): + def init_ui(self) -> None: self.notebook = ttk.Notebook(self, width=1000, height=700) a_tab = ttk.Frame(self.notebook) diff --git a/tkinter_examples/class_Example_with_Frame_Text.py b/tkinter_examples/class_Example_with_Frame_Text.py index aa34d3c8d..a836ac006 100644 --- a/tkinter_examples/class_Example_with_Frame_Text.py +++ b/tkinter_examples/class_Example_with_Frame_Text.py @@ -8,13 +8,13 @@ class Example(tk.Frame): - def __init__(self, parent): + def __init__(self, parent) -> None: super().__init__(parent) self.parent = parent self.init_ui() - def init_ui(self): + def init_ui(self) -> None: self.text = tk.Text(self, width=20, height=10) self.text.pack() self.text.insert(1.0, "Hello World!\nFoo\nBar\n\n123\n") @@ -24,7 +24,7 @@ def init_ui(self): self.pack() - def on_append(self): + def on_append(self) -> None: self.text.insert(tk.END, "Go-go-go!\n") diff --git a/tkinter_examples/create_new_window__on_click_button.py b/tkinter_examples/create_new_window__on_click_button.py index a7954a690..1ca5c8a9b 100644 --- a/tkinter_examples/create_new_window__on_click_button.py +++ b/tkinter_examples/create_new_window__on_click_button.py @@ -7,7 +7,7 @@ import tkinter as tk -def create_window(): +def create_window() -> None: window = tk.Toplevel(root) button_new = tk.Button(window, text="Create new+ window", command=create_window) diff --git a/tkinter_examples/create_new_window__on_click_button__v2.py b/tkinter_examples/create_new_window__on_click_button__v2.py index 8cabf245c..13e884bb9 100644 --- a/tkinter_examples/create_new_window__on_click_button__v2.py +++ b/tkinter_examples/create_new_window__on_click_button__v2.py @@ -8,7 +8,7 @@ class MainApp(Tk): - def __init__(self, *arg, **kwarg): + def __init__(self, *arg, **kwarg) -> None: super().__init__(*arg, **kwarg) label = Label(self, text="First Window") @@ -17,12 +17,12 @@ def __init__(self, *arg, **kwarg): label.pack() button.pack() - def new_window(self): + def new_window(self) -> None: Window().mainloop() class Window(Tk): - def __init__(self, *arg, **kwarg): + def __init__(self, *arg, **kwarg) -> None: super().__init__(*arg, **kwarg) label = Label(self, text="Second Window") diff --git a/tkinter_examples/draw_chess_board_with_figures.py b/tkinter_examples/draw_chess_board_with_figures.py index be1b3951f..9e294f911 100644 --- a/tkinter_examples/draw_chess_board_with_figures.py +++ b/tkinter_examples/draw_chess_board_with_figures.py @@ -14,7 +14,7 @@ canvas.pack() -def square(): +def square() -> None: y = 0 while y < 700: x = 0 @@ -25,7 +25,7 @@ def square(): y += 88 -def board(): +def board() -> None: fill = "#FECD72" outline = "#825100" for i in range(0, 8): @@ -38,7 +38,7 @@ def board(): fill, outline = outline, fill -def checkers(): +def checkers() -> None: board = [ [0, 2, 0, 2, 0, 2, 0, 2], [2, 0, 2, 0, 2, 0, 2, 0], diff --git a/tkinter_examples/draw_with_sin_cos__global_t.py b/tkinter_examples/draw_with_sin_cos__global_t.py index 47fe58c41..1c7cccea0 100644 --- a/tkinter_examples/draw_with_sin_cos__global_t.py +++ b/tkinter_examples/draw_with_sin_cos__global_t.py @@ -22,7 +22,7 @@ t = 0.0 -def but(event): +def but(event) -> None: global t for _ in range(100): diff --git a/tkinter_examples/draw_with_sin_cos__make_counter_adder.py b/tkinter_examples/draw_with_sin_cos__make_counter_adder.py index 162d94de0..7ed22f200 100644 --- a/tkinter_examples/draw_with_sin_cos__make_counter_adder.py +++ b/tkinter_examples/draw_with_sin_cos__make_counter_adder.py @@ -36,7 +36,7 @@ def counter(step=0): # counter() is a closure inc = make_counter_adder(0.0) -def but(event): +def but(event) -> None: for _ in range(100): t = inc() diff --git a/tkinter_examples/entry_echo.py b/tkinter_examples/entry_echo.py index 74f67eded..7ac28e672 100644 --- a/tkinter_examples/entry_echo.py +++ b/tkinter_examples/entry_echo.py @@ -13,7 +13,7 @@ center_window(app) -def _on_key_press(event): +def _on_key_press(event) -> None: text = entry.get() label_1["text"] = text diff --git a/tkinter_examples/excepthook__report_callback_exception__log_uncaught_exceptions.py b/tkinter_examples/excepthook__report_callback_exception__log_uncaught_exceptions.py index a00540cba..68f0b0df9 100644 --- a/tkinter_examples/excepthook__report_callback_exception__log_uncaught_exceptions.py +++ b/tkinter_examples/excepthook__report_callback_exception__log_uncaught_exceptions.py @@ -10,7 +10,7 @@ from tkinter import Tk, messagebox -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) print(text) @@ -29,7 +29,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): root.report_callback_exception = log_uncaught_exceptions -def m_geometry(win): +def m_geometry(win) -> None: # NOTE: this error -> root.report_callback_exception # x = (win.winfo_screenwidth() / 2) - (295 / 2) y = (win.winfo_screenheight() / 2) - (395 / 2) diff --git a/tkinter_examples/fill_widgets_as_cell_table__using_loops.py b/tkinter_examples/fill_widgets_as_cell_table__using_loops.py index 9569b225a..ea576319b 100644 --- a/tkinter_examples/fill_widgets_as_cell_table__using_loops.py +++ b/tkinter_examples/fill_widgets_as_cell_table__using_loops.py @@ -13,15 +13,15 @@ alphabet = "abcdefghijklmnopqrstuvwxyz" -def on_selecting_file(): +def on_selecting_file() -> None: pass -def on_change_symbols(): +def on_change_symbols() -> None: pass -def on_window_deleted(): +def on_window_deleted() -> None: print("Window closed") root.quit() diff --git a/tkinter_examples/hello_world.py b/tkinter_examples/hello_world.py index 7ec83b5a8..b957deb18 100644 --- a/tkinter_examples/hello_world.py +++ b/tkinter_examples/hello_world.py @@ -11,12 +11,12 @@ class Application(tk.Frame): - def __init__(self, parent=None): + def __init__(self, parent=None) -> None: super().__init__(parent) self.init_ui() - def init_ui(self): + def init_ui(self) -> None: self.hi_there = tk.Button(self) self.hi_there["text"] = "Hello World\n(click me)" self.hi_there["command"] = self.say_hi @@ -27,7 +27,7 @@ def init_ui(self): self.pack() - def say_hi(self): + def say_hi(self) -> None: print("hi there, everyone!") diff --git a/tkinter_examples/super_hello_world.py b/tkinter_examples/super_hello_world.py index c3baf1e7b..732f7a835 100644 --- a/tkinter_examples/super_hello_world.py +++ b/tkinter_examples/super_hello_world.py @@ -11,7 +11,7 @@ from tkinter import messagebox -def center_window(root, width=300, height=200): +def center_window(root, width=300, height=200) -> None: # get screen width and height screen_width = root.winfo_screenwidth() screen_height = root.winfo_screenheight() @@ -22,11 +22,11 @@ def center_window(root, width=300, height=200): root.geometry("%dx%d+%d+%d" % (width, height, x, y)) -def on_btn_1(): +def on_btn_1() -> None: print("Hello World!") -def on_btn_2(): +def on_btn_2() -> None: text = "Hello World!" messagebox.showerror("Error", text) diff --git a/tkinter_examples/tab_Notebook__with_widgets_as_modules/main.py b/tkinter_examples/tab_Notebook__with_widgets_as_modules/main.py index 0a314e604..2a546c51c 100644 --- a/tkinter_examples/tab_Notebook__with_widgets_as_modules/main.py +++ b/tkinter_examples/tab_Notebook__with_widgets_as_modules/main.py @@ -12,7 +12,7 @@ class MainWindow(Frame): - def __init__(self, parent): + def __init__(self, parent) -> None: super().__init__(parent) self.parent = parent @@ -20,7 +20,7 @@ def __init__(self, parent): self.init_ui() - def init_ui(self): + def init_ui(self) -> None: self.parent["padx"] = 10 self.parent["pady"] = 10 diff --git a/tkinter_examples/tab_Notebook__with_widgets_as_modules/main_v2.py b/tkinter_examples/tab_Notebook__with_widgets_as_modules/main_v2.py index 23844cb31..aefb36a22 100644 --- a/tkinter_examples/tab_Notebook__with_widgets_as_modules/main_v2.py +++ b/tkinter_examples/tab_Notebook__with_widgets_as_modules/main_v2.py @@ -12,13 +12,13 @@ class MainInterface: - def __init__(self): + def __init__(self) -> None: self.window = Tk() self.window.title("version") self.window.geometry("300x250") self.create_widgets() - def create_widgets(self): + def create_widgets(self) -> None: self.window["padx"] = 10 self.window["pady"] = 10 diff --git a/tkinter_examples/tab_Notebook__with_widgets_as_modules/tab_a.py b/tkinter_examples/tab_Notebook__with_widgets_as_modules/tab_a.py index accb8eb38..afc4219f2 100644 --- a/tkinter_examples/tab_Notebook__with_widgets_as_modules/tab_a.py +++ b/tkinter_examples/tab_Notebook__with_widgets_as_modules/tab_a.py @@ -8,13 +8,13 @@ class Example(tk.Frame): - def __init__(self, parent): + def __init__(self, parent) -> None: super().__init__(parent) self.parent = parent self.init_ui() - def init_ui(self): + def init_ui(self) -> None: self.pack(fill=tk.BOTH, expand=1) acts = ["Scarlett Johansson", "Rachel Weiss", "Natalie Portman", "Jessica Alba"] @@ -31,7 +31,7 @@ def init_ui(self): self.pack() - def on_select(self, val): + def on_select(self, val) -> None: sender = val.widget idx = sender.curselection() value = sender.get(idx) diff --git a/tkinter_examples/tab_Notebook__with_widgets_as_modules/tab_b.py b/tkinter_examples/tab_Notebook__with_widgets_as_modules/tab_b.py index aa34d3c8d..a836ac006 100644 --- a/tkinter_examples/tab_Notebook__with_widgets_as_modules/tab_b.py +++ b/tkinter_examples/tab_Notebook__with_widgets_as_modules/tab_b.py @@ -8,13 +8,13 @@ class Example(tk.Frame): - def __init__(self, parent): + def __init__(self, parent) -> None: super().__init__(parent) self.parent = parent self.init_ui() - def init_ui(self): + def init_ui(self) -> None: self.text = tk.Text(self, width=20, height=10) self.text.pack() self.text.insert(1.0, "Hello World!\nFoo\nBar\n\n123\n") @@ -24,7 +24,7 @@ def init_ui(self): self.pack() - def on_append(self): + def on_append(self) -> None: self.text.insert(tk.END, "Go-go-go!\n") diff --git a/tkinter_examples/tab_Notebook__with_widgets_as_modules/tab_c.py b/tkinter_examples/tab_Notebook__with_widgets_as_modules/tab_c.py index 642cb1f80..5436ee422 100644 --- a/tkinter_examples/tab_Notebook__with_widgets_as_modules/tab_c.py +++ b/tkinter_examples/tab_Notebook__with_widgets_as_modules/tab_c.py @@ -8,19 +8,19 @@ class Example(tk.Frame): - def __init__(self, parent): + def __init__(self, parent) -> None: super().__init__(parent) self.parent = parent self.init_ui() - def init_ui(self): + def init_ui(self) -> None: self.button = tk.Button(self, text="Append", command=self.on_click) self.button.pack() self.pack() - def on_click(self): + def on_click(self) -> None: print("Hello World!") diff --git a/tkinter_examples/table__label__on_click_cell_handler.py b/tkinter_examples/table__label__on_click_cell_handler.py index 998fc1af4..8a6a252d1 100644 --- a/tkinter_examples/table__label__on_click_cell_handler.py +++ b/tkinter_examples/table__label__on_click_cell_handler.py @@ -7,7 +7,7 @@ from tkinter import Tk, Label -def turn(event): +def turn(event) -> None: value = event.widget["text"] value = 1 if value == "." else int(value) + 1 diff --git a/tkinter_examples/weather_example.py b/tkinter_examples/weather_example.py index 661581985..966df4614 100644 --- a/tkinter_examples/weather_example.py +++ b/tkinter_examples/weather_example.py @@ -34,7 +34,7 @@ def get_weather_info(api_key, place): label2.grid() -def update_clock(): +def update_clock() -> None: temperature, status = get_weather_info(api_key=API_KEY, place="Donetsk") print(temperature, status) diff --git a/translate_text_screenshot_by_hotkey/main.py b/translate_text_screenshot_by_hotkey/main.py index 3c0de3cc9..cea5f0763 100644 --- a/translate_text_screenshot_by_hotkey/main.py +++ b/translate_text_screenshot_by_hotkey/main.py @@ -29,13 +29,13 @@ pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe" -def error_sound(): +def error_sound() -> None: duration = 300 # milliseconds freq = 1000 # Hz winsound.Beep(freq, duration) -def run(): +def run() -> None: try: file_name = f"screenshot_{dt.datetime.now():%Y-%m-%d_%H%M%S}.html" print(file_name) diff --git a/ttl_cache.py b/ttl_cache.py index f9bcf397e..0ebdcde99 100644 --- a/ttl_cache.py +++ b/ttl_cache.py @@ -41,7 +41,7 @@ def wrapper(*args, **kwargs): if __name__ == "__main__": # Example usage: @ttl_cache(ttl_seconds=5) - def get_data(item_id): + def get_data(item_id) -> str: print(f"Fetching data for item_id: {item_id} (expensive operation)...") time.sleep(1) # Simulate a slow operation return f"Data for {item_id} at {time.time()}" diff --git a/unistream_examples/utils.py b/unistream_examples/utils.py index 38b74b791..3446dc54e 100644 --- a/unistream_examples/utils.py +++ b/unistream_examples/utils.py @@ -9,14 +9,14 @@ import hashlib import logging -from datetime import datetime +from datetime import datetime, timezone from urllib.parse import urlsplit from babel.dates import format_datetime def get_today_RFC1123_date(): - now = datetime.utcnow() + now = datetime.now(timezone.utc) format = "EEE, dd LLL yyyy hh:mm:ss" return format_datetime(now, format, locale="en") + " GMT" @@ -26,7 +26,7 @@ def hmac_sha256(key, msg): return base64.b64encode(signature).decode() -def get_authorization_header(application_id, secret, today_date, url, headers): +def get_authorization_header(application_id, secret, today_date, url, headers) -> str: logging.debug("Url:\n%s", url) url_parts = urlsplit(url) diff --git a/update_task_and_jobs_from_gist/ConEmu_start_task/3. modify_ConEmu_settings_tasks.py b/update_task_and_jobs_from_gist/ConEmu_start_task/3. modify_ConEmu_settings_tasks.py index b7074e64a..a3ce08047 100644 --- a/update_task_and_jobs_from_gist/ConEmu_start_task/3. modify_ConEmu_settings_tasks.py +++ b/update_task_and_jobs_from_gist/ConEmu_start_task/3. modify_ConEmu_settings_tasks.py @@ -24,7 +24,7 @@ def get_current_datetime() -> str: return dt.datetime.now().strftime("%Y-%m-%d %H:%M:%S") -def update_tasks(tasks_el: ET.Element): +def update_tasks(tasks_el: ET.Element) -> None: tasks_el.attrib["modified"] = get_current_datetime() tasks = tasks_el.findall("key") @@ -38,7 +38,7 @@ def update_tasks(tasks_el: ET.Element): task_el.attrib["build"] = tasks_el.attrib["build"] -def create_task(tasks_el: ET.Element, name: str, commands: list[str]): +def create_task(tasks_el: ET.Element, name: str, commands: list[str]) -> None: task_el = ET.SubElement(tasks_el, "key") ET.SubElement(task_el, "value", name="Name", type="string", data="{%s}" % name) diff --git a/update_task_and_jobs_from_gist/ConEmu_start_task/move ConEmu to second desktop.py b/update_task_and_jobs_from_gist/ConEmu_start_task/move ConEmu to second desktop.py index ab7bf136d..2e788a51e 100644 --- a/update_task_and_jobs_from_gist/ConEmu_start_task/move ConEmu to second desktop.py +++ b/update_task_and_jobs_from_gist/ConEmu_start_task/move ConEmu to second desktop.py @@ -21,7 +21,7 @@ def get_hwnd_for_pid(pid: int): - def callback(hwnd: int, hwnds: list): + def callback(hwnd: int, hwnds: list) -> bool: if win32gui.IsWindowVisible(hwnd) and win32gui.IsWindowEnabled(hwnd): _, found_pid = win32process.GetWindowThreadProcessId(hwnd) if found_pid == pid: diff --git a/update_task_and_jobs_from_gist/Jenkins_jobs/run_jobs.py b/update_task_and_jobs_from_gist/Jenkins_jobs/run_jobs.py index bdb2a33db..afb8b3dd2 100644 --- a/update_task_and_jobs_from_gist/Jenkins_jobs/run_jobs.py +++ b/update_task_and_jobs_from_gist/Jenkins_jobs/run_jobs.py @@ -7,12 +7,12 @@ from common import get_jobs_for_run, client -def run_job(job): +def run_job(job) -> None: print(f"Run {job.full_name!r}") job.build() -def run_in_view(view_name: str): +def run_in_view(view_name: str) -> None: for job in client.views.get(view_name): run_job(job) diff --git a/upper_print.py b/upper_print.py index de25d549d..395388797 100644 --- a/upper_print.py +++ b/upper_print.py @@ -5,7 +5,7 @@ def upper_print(f): - def wrapper(*args, **kwargs): + def wrapper(*args, **kwargs) -> None: f(*[i.upper() if hasattr(i, "upper") else i for i in args], **kwargs) return wrapper diff --git a/url2image/url2image.py b/url2image/url2image.py index 295e9a1e5..03cf51844 100644 --- a/url2image/url2image.py +++ b/url2image/url2image.py @@ -22,7 +22,7 @@ class WebPage(QWebPage): - def userAgentForUrl(self, url): + def userAgentForUrl(self, url) -> str: return ( "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0" ) diff --git a/using_proxy/proxy_requests__upgraded.py b/using_proxy/proxy_requests__upgraded.py index a65d1eace..73bb1f146 100644 --- a/using_proxy/proxy_requests__upgraded.py +++ b/using_proxy/proxy_requests__upgraded.py @@ -26,14 +26,14 @@ class ProxyRequests: ] EMPTY_WARN = "Proxy Pool has been emptied" - def __init__(self, url: str, timeout=5): + def __init__(self, url: str, timeout=5) -> None: self.url = url self.proxies = [] self.used_proxy = None self.timeout = timeout self._acquire_sockets() - def _acquire_sockets(self): + def _acquire_sockets(self) -> None: rs = requests.get("https://www.sslproxies.org/") matches = findall(r"\d+\.\d+\.\d+\.\d+\d+", rs.text) revised = [m.replace("", "") for m in matches] diff --git a/html_parsing/jut_su/anime.py b/video_parsers/jut_su/anime.py similarity index 100% rename from html_parsing/jut_su/anime.py rename to video_parsers/jut_su/anime.py diff --git a/html_parsing/jut_su/anime_get_video_list.py b/video_parsers/jut_su/anime_get_video_list.py similarity index 100% rename from html_parsing/jut_su/anime_get_video_list.py rename to video_parsers/jut_su/anime_get_video_list.py diff --git a/html_parsing/jut_su/anime_search.py b/video_parsers/jut_su/anime_search.py similarity index 100% rename from html_parsing/jut_su/anime_search.py rename to video_parsers/jut_su/anime_search.py diff --git a/html_parsing/jut_su/common.py b/video_parsers/jut_su/common.py similarity index 100% rename from html_parsing/jut_su/common.py rename to video_parsers/jut_su/common.py diff --git a/html_parsing/jut_su/download_video.py b/video_parsers/jut_su/download_video.py similarity index 100% rename from html_parsing/jut_su/download_video.py rename to video_parsers/jut_su/download_video.py diff --git a/html_parsing/jut_su/get_possible_achievements_from_video.py b/video_parsers/jut_su/get_possible_achievements_from_video.py similarity index 100% rename from html_parsing/jut_su/get_possible_achievements_from_video.py rename to video_parsers/jut_su/get_possible_achievements_from_video.py diff --git a/html_parsing/jut_su/get_user_achievements.py b/video_parsers/jut_su/get_user_achievements.py similarity index 100% rename from html_parsing/jut_su/get_user_achievements.py rename to video_parsers/jut_su/get_user_achievements.py diff --git a/html_parsing/jut_su/test.py b/video_parsers/jut_su/test.py similarity index 94% rename from html_parsing/jut_su/test.py rename to video_parsers/jut_su/test.py index 4f1b278bc..71e636f75 100644 --- a/html_parsing/jut_su/test.py +++ b/video_parsers/jut_su/test.py @@ -36,7 +36,7 @@ class GetPossibleAchievementsTestCase(unittest.TestCase): "hash": "dc3acd1d8af21525", } - def test_parse_raw_anime_achievement(self): + def test_parse_raw_anime_achievement(self) -> None: text = """ category: "events", time_start: 704, @@ -49,7 +49,7 @@ def test_parse_raw_anime_achievement(self): actual = get_possible_achievements_from_video.parse_raw_anime_achievement(text) self.assertEqual(actual, self.EXPECTED_704) - def test_parse_raw_anime_achievements(self): + def test_parse_raw_anime_achievements(self) -> None: text = """ var this_anime_achievements = []; this_anime_achievements.push({ @@ -78,7 +78,7 @@ def test_parse_raw_anime_achievements(self): ] self.assertEqual(actual, expected) - def test_get_raw_achievements(self): + def test_get_raw_achievements(self) -> None: actual = get_possible_achievements_from_video.get_raw_achievements( "https://jut.su/bleeach/episode-193.html" ) @@ -96,14 +96,14 @@ def test_get_raw_achievements(self): self.assertEqual(actual, expected) - def test_get_anime_achievement(self): + def test_get_anime_achievement(self) -> None: expected = self.EXPECTED_704 actual = get_possible_achievements_from_video.get_anime_achievement(expected) actual = dataclasses.asdict(actual) self.assertEqual(actual, expected) - def test_get_achievements(self): + def test_get_achievements(self) -> None: actual = get_possible_achievements_from_video.get_achievements( "https://jut.su/bleeach/episode-193.html" ) @@ -124,7 +124,7 @@ def test_get_achievements(self): class GetUserAchievementsTestCase(unittest.TestCase): - def test_get_achievements(self): + def test_get_achievements(self) -> None: url = "https://jut.su/user/gil9red/achievements/" get_achievements = get_user_achievements.get_achievements @@ -181,7 +181,7 @@ def test_get_achievements(self): class SearchTestCase(unittest.TestCase): - def test_search(self): + def test_search(self) -> None: self.assertFalse(search(text="21331231ваываыва")) self.assertTrue(search(text="bleach")) diff --git a/html_parsing/rutube/common.py b/video_parsers/rutube/common.py similarity index 100% rename from html_parsing/rutube/common.py rename to video_parsers/rutube/common.py diff --git a/html_parsing/rutube/get_videos_from_channel.py b/video_parsers/rutube/get_videos_from_channel.py similarity index 100% rename from html_parsing/rutube/get_videos_from_channel.py rename to video_parsers/rutube/get_videos_from_channel.py diff --git a/html_parsing/rutube/get_videos_from_playlist.py b/video_parsers/rutube/get_videos_from_playlist.py similarity index 100% rename from html_parsing/rutube/get_videos_from_playlist.py rename to video_parsers/rutube/get_videos_from_playlist.py diff --git a/video_parsers/vkvideo/get_videos.py b/video_parsers/vkvideo/get_videos.py new file mode 100644 index 000000000..78b442a28 --- /dev/null +++ b/video_parsers/vkvideo/get_videos.py @@ -0,0 +1,308 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +import time + +from dataclasses import dataclass +from datetime import datetime +from typing import Any, Self, Generator + +# NOTE: https://playwright.dev/python/docs/library#pip +# pip install playwright==1.50.0 +# playwright install firefox +from playwright.sync_api import Response, TimeoutError, sync_playwright + +import requests + +DEFAULT_TIMEOUT_MS: int = 30_000 +MAX_VIDEOS_SAFETY_LIMIT: int = 100 + + +@dataclass(frozen=True) +class VideoInfo: + id: int + owner_id: int + title: str + direct_url: str | None + share_url: str | None + date: datetime + description: str | None + duration: int + + @classmethod + def from_dict(cls, data: dict[str, Any]) -> Self: + return cls( + id=data["id"], + owner_id=data["owner_id"], + title=data["title"], + direct_url=data.get("direct_url"), + share_url=data.get("share_url"), + date=datetime.fromtimestamp(data["date"]), + description=data.get("description"), + duration=data["duration"], + ) + + +@dataclass +class ApiInfo: + url: str + rq_headers: dict[str, str] + rq_data: dict[str, str] + rs_data: dict[str, Any] + + +def get_api_info(url: str) -> ApiInfo: + with sync_playwright() as p: + browser = p.firefox.launch() + + page = browser.new_page() + page.set_default_timeout(DEFAULT_TIMEOUT_MS) + + page.goto(url, wait_until="commit") + + def is_api(rs: Response) -> bool: + url: str = rs.url + return ( + "api" in url + and rs.request.method == "POST" + and rs.status == 200 + # NOTE: Уточнение с "?" в конце для исключения ссылки вида catalog.getVideoShowcase + and ("/video.getFromAlbum?" in url or "/catalog.getVideo?" in url) + and "json" in str(rs.headers) + ) + + with page.expect_response(is_api) as response_info: + rs = response_info.value + return ApiInfo( + url=rs.url, + rq_headers=rs.request.headers, + rq_data=rs.request.post_data_json, + rs_data=rs.json(), + ) + + +def parse_videos(rs: dict[str, Any]) -> list[VideoInfo]: + videos: list[dict[str, Any]] + if "videos" in rs: # На странице канала + videos = rs["videos"] + else: # На странице плейлиста + videos = [item["video"] for item in rs["items"]] + + return [VideoInfo.from_dict(video) for video in videos] + + +def paginate_by_offset( + session: requests.Session, + url: str, + init_rq_data: dict[str, Any], + _: dict[str, Any], +) -> Generator[list[VideoInfo], None, None]: + """Генератор для постраничной пагинации (Альбомы).""" + + rq_data: dict[str, Any] = init_rq_data + rq_data["offset"] = int(rq_data["offset"]) + rq_data["count"] = int(rq_data["count"]) + + while True: + rq_data["offset"] += rq_data["count"] + + rs = session.post(url, data=rq_data) + rs.raise_for_status() + + rs_data = rs.json()["response"] + + videos = parse_videos(rs_data) + if not videos: + break + + yield videos + + +def paginate_by_token( + session: requests.Session, + url: str, + init_rq_data: dict[str, Any], + init_rs_data: dict[str, Any], +) -> Generator[list[VideoInfo], None, None]: + """Генератор для курсорной пагинации (Каталог).""" + + section_id, next_from = None, None + for section in init_rs_data["catalog"]["sections"]: + if "next_from" in section: + section_id, next_from = section["id"], section["next_from"] + break + + # Первый запрос к catalog.getVideo, а последующие через catalog.getSection + url = url.replace("/catalog.getVideo", "/catalog.getSection") + rq_data: dict[str, Any] = { + "section_id": section_id, + "start_from": next_from, + "access_token": init_rq_data["access_token"], + } + + while True: + if not rq_data.get("start_from"): + break + + rs = session.post(url, data=rq_data) + rs.raise_for_status() + + rs_data = rs.json()["response"] + + videos = parse_videos(rs_data) + if not videos: + break + + yield videos + + rq_data["start_from"] = rs_data.get("section", {}).get("next_from") + + +def get_videos( + url: str, + max_items: int | None = MAX_VIDEOS_SAFETY_LIMIT, + max_attempts: int = 5, +) -> list[VideoInfo]: + # Вернется первая порция запросов + api_info: ApiInfo | None = None + for attempt in range(1, max_attempts + 1): + try: + api_info = get_api_info(url) + break + except TimeoutError as e: + if attempt >= max_attempts: + raise e + + if not api_info: + raise Exception("Not found API") + + url: str = api_info.url + + if "/video.getFromAlbum" in url: + pagination_provider = paginate_by_offset + elif "/catalog.getVideo" in url: + pagination_provider = paginate_by_token + else: + raise Exception("Неизвестный тип API") + + rs_data: dict[str, Any] = api_info.rs_data["response"] + all_videos: list[VideoInfo] = parse_videos(rs_data) + + # NOTE: Был там zstd, но его наличие ломает парсер, т.к. не поддерживается + api_info.rq_headers["Accept-Encoding"] = "gzip, deflate, br" + + session = requests.Session() + session.headers.update(api_info.rq_headers) + + for chunk in pagination_provider(session, url, api_info.rq_data, rs_data): + all_videos += chunk + if max_items and len(all_videos) >= max_items: + break + + time.sleep(1) + + return all_videos[:max_items] if max_items else all_videos + + +if __name__ == "__main__": + + def _print_videos(videos: list[VideoInfo]): + print(f"Video ({len(videos)}):") + + width: int = len(str(len(videos))) + + for i, video in enumerate(videos, 1): + print(f" {i:>{width}}. {video}") + + assert videos != list(set(videos)) + + # Пример из плейлиста (один запрос вернет 25 шт.) + url: str = "https://vkvideo.ru/playlist/-1719791_48513772" + + print(url) + videos: list[VideoInfo] = get_videos(url, max_items=5) + _print_videos(videos) + assert len(videos) == 5 + """ + Video (5): + 1. VideoInfo(id=456265497, owner_id=-1719791, title='Этих видео НЕ БЫЛО в +100500 🤐', direct_url='https://vkvideo.ru/video-1719791_456265497?pl=-1719791_48513772', share_url='https://vkvideo.ru/video-1719791_456265497?pl=-1719791_48513772', date=datetime.datetime(2026, 5, 30, 17, 24, 7), description='Эпизод # 556 :D\nBOOSTY (этот выпуск с дополнительным обзором на ещё одно видео): https://boosty.to/max100500/posts/6b52091c-d9a7-4395-a9c1-1390baf39f7b?share=post_link\nTWITCH: https://www.twitch.tv/moran_plays\nTELEGRAM: https://t.me/vidowsov100500\nСООБЩЕСТВО +100500 ВКонтакте: https://vk.com/maximplus100500\nTikTok: https://www.tiktok.com/@maxim_golopolosov\n\nВидео из эпизода: https://t.me/vidowsov100500/18972\n\n00:00 ПРЕДИСЛОВИЕ\n00:29 КЛАССИЧЕСКОЕ ИНТРО\n00:40 ЯЗЬ!\n04:05 НИКИТА ЛИТВИНКОВ\n08:13 НОРМАЛЬНО\n11:22 НАТАЛЬЯ МОРСКАЯ ПЕХОТА\n14:15 КЛАССИЧЕСКОЕ АУТРО\n\nПо вопросам рекламы: maks100500@didenokteam.com', duration=880) + 2. VideoInfo(id=456265161, owner_id=-1719791, title='Пора ЗАВЯЗЫВАТЬ \U0001fae9 / +100500', direct_url='https://vkvideo.ru/video-1719791_456265161?pl=-1719791_48513772', share_url='https://vkvideo.ru/video-1719791_456265161?pl=-1719791_48513772', date=datetime.datetime(2026, 4, 18, 16, 47, 4), description='Эпизод # 555 :D\nBOOSTY (этот выпуск с дополнительным обзором на ещё одно видео): https://boosty.to/max100500/posts/2d5df23d-9454-4679-8c12-a27955fddbc9?share=post_link \nTWITCH: https://www.twitch.tv/moran_plays\nTELEGRAM: https://t.me/vidowsov100500\nСООБЩЕСТВО +100500 ВКонтакте: https://vk.com/maximplus100500\nTikTok: https://www.tiktok.com/@maxim_golopolosov\n\nВидео из эпизода: https://t.me/vidowsov100500/18884\n\n00:00 ПРИВЕТЛИВЫЙ ПАССАЖИР\n02:03 ИНТРО\n02:22 ЧЕЛОВЕК-РУЧНИК\n04:51 НЕВОЗМОЖНЫЙ УЗЕЛ\n07:43 МГНОВЕННАЯ ОБИДА\n09:59 МУЗЫКАЛЬНЫЙ КОНЕЦ\n\nПо вопросам рекламы: maks100500@didenokteam.com', duration=623) + 3. VideoInfo(id=456264517, owner_id=-1719791, title='ДАНИЛ КОЛБАСЕНКО / +100500', direct_url='https://vkvideo.ru/video-1719791_456264517?pl=-1719791_48513772', share_url='https://vkvideo.ru/video-1719791_456264517?pl=-1719791_48513772', date=datetime.datetime(2026, 3, 3, 21, 7, 41), description='Эпизод # 554 :D\nBOOSTY (этот выпуск с дополнительным обзором на ещё одно видео): https://boosty.to/max100500/posts/ad53a66d-54d3-43f9-80a2-41242cb7da8d?share=post_link\nTWITCH: https://www.twitch.tv/moran_plays\nTELEGRAM: https://t.me/vidowsov100500\nСООБЩЕСТВО +100500 ВКонтакте: https://vk.com/maximplus100500\nTikTok: https://www.tiktok.com/@maxim_golopolosov\n\nВидео из эпизода: https://t.me/vidowsov100500/18769\n\n00:00 ДАНИЛ КОЛБАСЕНКО\n02:55 ИНТРО\n03:13 ГОЛУБЯТНЯ В ДЕСЯТКЕ\n05:02 ПАРУСА ИЗ КАНАЛИЗАЦИИ\n07:03 АРОМАТНЫЕ ПАЛЬЧИКИ\n09:22 МУЗЫКАЛЬНЫЙ КОНЕЦ\n\nПо вопросам рекламы: maks100500@didenokteam.com', duration=599) + 4. VideoInfo(id=456264454, owner_id=-1719791, title='Чилловый козёл, который НА ЧИЛЛЕ 💤🐐 / +100500', direct_url='https://vkvideo.ru/video-1719791_456264454?pl=-1719791_48513772', share_url='https://vkvideo.ru/video-1719791_456264454?pl=-1719791_48513772', date=datetime.datetime(2026, 2, 2, 20, 48, 34), description='Эпизод # 553 :D\nBOOSTY (этот выпуск с дополнительным обзором на ещё одно видео): https://boosty.to/max100500/posts/2ae907c7-1183-475e-824c-7959a0de3030?share=post_link\nTWITCH: https://www.twitch.tv/moran_plays\nTELEGRAM: https://t.me/vidowsov100500\nСООБЩЕСТВО +100500 ВКонтакте: https://vk.com/maximplus100500\nTikTok: https://www.tiktok.com/@maxim_golopolosov\n\nВидео из эпизода: https://t.me/vidowsov100500/18693\n\n00:00 ДРУГ В ОТРАЖЕНИИ\n01:46 ИНТРО\n02:04 ХЛОПУШКА ОТ МУХ\n03:41 ЧИЛЛОВЫЙ КОЗЁЛ\n05:19 ОСВЕЖИТЕЛЬ С ДУШКОМ\n07:22 МУЗЫКАЛЬНЫЙ КОНЕЦ', duration=473) + 5. VideoInfo(id=456264437, owner_id=-1719791, title='ОБЛЕЗЛЫЙ НОВЫЙ ГОД 🎄 Ёлка-Ёршик и Розетки На Ковре', direct_url='https://vkvideo.ru/video-1719791_456264437?pl=-1719791_48513772', share_url='https://vkvideo.ru/video-1719791_456264437?pl=-1719791_48513772', date=datetime.datetime(2025, 12, 31, 20, 22, 31), description='Эпизод # 552 :D\nBOOSTY (этот выпуск с дополнительным обзором на ещё одно видео): https://boosty.to/max100500/posts/f81d5f16-a3ea-4aac-8fc2-aacff72fb645?share=post_link\nTWITCH: https://www.twitch.tv/moran_plays\nTELEGRAM: https://t.me/vidowsov100500\nСООБЩЕСТВО +100500 ВКонтакте: https://vk.com/maximplus100500\nTikTok: https://www.tiktok.com/@maxim_golopolosov\n\nВидео из эпизода: https://t.me/vidowsov100500/18571\n\n00:00 НОВОГОДНИЙ ЁРШИК\n02:04 ИНТРО\n02:23 ДЕД МОРОЗ ПОЛОЖИЛ\n03:48 ОЛИВЬЕШНЫЙ ГРИНЧ\n05:23 КРЕАТИВНЫЙ ЭЛЕКТРИК\n07:48 ПОЗДРАВЛЕНИЕ\n08:49 МУЗЫКАЛЬНЫЙ КОНЕЦ', duration=554) + """ + + print() + + print(url) + videos: list[VideoInfo] = get_videos(url, max_items=50) + _print_videos(videos) + assert len(videos) == 50 + """ + Video (50): + 1. VideoInfo(id=456265497, owner_id=-1719791, title='Этих видео НЕ БЫЛО в +100500 🤐', direct_url='https://vkvideo.ru/video-1719791_456265497?pl=-1719791_48513772', share_url='https://vkvideo.ru/video-1719791_456265497?pl=-1719791_48513772', date=datetime.datetime(2026, 5, 30, 17, 24, 7), description='Эпизод # 556 :D\nBOOSTY (этот выпуск с дополнительным обзором на ещё одно видео): https://boosty.to/max100500/posts/6b52091c-d9a7-4395-a9c1-1390baf39f7b?share=post_link\nTWITCH: https://www.twitch.tv/moran_plays\nTELEGRAM: https://t.me/vidowsov100500\nСООБЩЕСТВО +100500 ВКонтакте: https://vk.com/maximplus100500\nTikTok: https://www.tiktok.com/@maxim_golopolosov\n\nВидео из эпизода: https://t.me/vidowsov100500/18972\n\n00:00 ПРЕДИСЛОВИЕ\n00:29 КЛАССИЧЕСКОЕ ИНТРО\n00:40 ЯЗЬ!\n04:05 НИКИТА ЛИТВИНКОВ\n08:13 НОРМАЛЬНО\n11:22 НАТАЛЬЯ МОРСКАЯ ПЕХОТА\n14:15 КЛАССИЧЕСКОЕ АУТРО\n\nПо вопросам рекламы: maks100500@didenokteam.com', duration=880) + 2. VideoInfo(id=456265161, owner_id=-1719791, title='Пора ЗАВЯЗЫВАТЬ \U0001fae9 / +100500', direct_url='https://vkvideo.ru/video-1719791_456265161?pl=-1719791_48513772', share_url='https://vkvideo.ru/video-1719791_456265161?pl=-1719791_48513772', date=datetime.datetime(2026, 4, 18, 16, 47, 4), description='Эпизод # 555 :D\nBOOSTY (этот выпуск с дополнительным обзором на ещё одно видео): https://boosty.to/max100500/posts/2d5df23d-9454-4679-8c12-a27955fddbc9?share=post_link \nTWITCH: https://www.twitch.tv/moran_plays\nTELEGRAM: https://t.me/vidowsov100500\nСООБЩЕСТВО +100500 ВКонтакте: https://vk.com/maximplus100500\nTikTok: https://www.tiktok.com/@maxim_golopolosov\n\nВидео из эпизода: https://t.me/vidowsov100500/18884\n\n00:00 ПРИВЕТЛИВЫЙ ПАССАЖИР\n02:03 ИНТРО\n02:22 ЧЕЛОВЕК-РУЧНИК\n04:51 НЕВОЗМОЖНЫЙ УЗЕЛ\n07:43 МГНОВЕННАЯ ОБИДА\n09:59 МУЗЫКАЛЬНЫЙ КОНЕЦ\n\nПо вопросам рекламы: maks100500@didenokteam.com', duration=623) + 3. VideoInfo(id=456264517, owner_id=-1719791, title='ДАНИЛ КОЛБАСЕНКО / +100500', direct_url='https://vkvideo.ru/video-1719791_456264517?pl=-1719791_48513772', share_url='https://vkvideo.ru/video-1719791_456264517?pl=-1719791_48513772', date=datetime.datetime(2026, 3, 3, 21, 7, 41), description='Эпизод # 554 :D\nBOOSTY (этот выпуск с дополнительным обзором на ещё одно видео): https://boosty.to/max100500/posts/ad53a66d-54d3-43f9-80a2-41242cb7da8d?share=post_link\nTWITCH: https://www.twitch.tv/moran_plays\nTELEGRAM: https://t.me/vidowsov100500\nСООБЩЕСТВО +100500 ВКонтакте: https://vk.com/maximplus100500\nTikTok: https://www.tiktok.com/@maxim_golopolosov\n\nВидео из эпизода: https://t.me/vidowsov100500/18769\n\n00:00 ДАНИЛ КОЛБАСЕНКО\n02:55 ИНТРО\n03:13 ГОЛУБЯТНЯ В ДЕСЯТКЕ\n05:02 ПАРУСА ИЗ КАНАЛИЗАЦИИ\n07:03 АРОМАТНЫЕ ПАЛЬЧИКИ\n09:22 МУЗЫКАЛЬНЫЙ КОНЕЦ\n\nПо вопросам рекламы: maks100500@didenokteam.com', duration=599) + ... + 48. VideoInfo(id=456258671, owner_id=-1719791, title='+100500 - ТОП КОНТЕНТ ИЗ TikTok', direct_url='https://vkvideo.ru/video-1719791_456258671?pl=-1719791_48513772', share_url='https://vkvideo.ru/video-1719791_456258671?pl=-1719791_48513772', date=datetime.datetime(2021, 8, 5, 15, 25, 38), description='Эпизод # 506 :D\nСЛУШАТЬ ПЕСНЮ 2ND SEASON - ДАБЛ ОРАНЖ 👉🏼 https://ffm.to/2ndxseason_doubleorange\nTelegram канал: https://t.me/joinchat/AAAAAFN0AdiHBwyVZ2GWTw\nInstagram +100500 с видосами и мемами: https://www.instagram.com/100500_vidowsov/\n100500_Play (Telegram канал с новостями из мира видеоигр): https://t.me/joinchat/AAAAAFgiJqyAY4vl5UiIaQ\nПаблик +100500 ВКонтакте: https://vk.com/maximplus100500\nMoran Days (Второй Канал) : http://www.youtube.com/user/MoranDays\nInstagram: http://instagram.com/adam_moran\nTwitter: http://twitter.com/maxplus100500\n\nВидео из эпизода: https://vk.com/wall-1719791_1809374\n\n0:00 ПРЕДИСЛОВИЕ\n0:54 ИНТРО\n1:20 СПАСИТЕЛЬНОЕ ПИВО\n3:52 АНГЛИЧАНИН ВЫРАСТИЛ БАНАНЫ\n4:54 ЗДРАВЫЙ ПАЦАН\n6:43 ОЛИМПИЙСКОЕ ПРЕДЛОЖЕНИЕ\n7:50 Я ПРЫГНУ\n9:58 ПЛАТНОЕ СПАСЕНИЕ НА ВОДЕ\n11:40 КОМПЬЮТЕРНАЯ БУХТА\n14:39 ПРОЩАЛОЧКА\n15:11 МУЗЫКАЛЬНЫЙ КОНЕЦ\n15:58 СЦЕНА ПОСЛЕ ТИТРОВ\n\nВидео для обзора: https://docs.google.com/forms/d/1gx6iUl5Z', duration=994) + 49. VideoInfo(id=456258038, owner_id=-1719791, title='+100500 - ПИВО С ПРОДОЛЖЕНИЕМ 😏', direct_url='https://vkvideo.ru/video-1719791_456258038?pl=-1719791_48513772', share_url='https://vkvideo.ru/video-1719791_456258038?pl=-1719791_48513772', date=datetime.datetime(2021, 6, 23, 19, 27, 37), description='Эпизод # 505 :D\nСЛУШАТЬ ПЕСНЮ 2ND SEASON - ДАБЛ ОРАНЖ 👉🏼 https://ffm.to/2ndxseason_doubleorange\nTelegram канал: https://t.me/joinchat/AAAAAFN0AdiHBwyVZ2GWTw\nInstagram +100500 с видосами и мемами: https://www.instagram.com/100500_vidowsov/\n100500_Play (Telegram канал с новостями из мира видеоигр): https://t.me/joinchat/AAAAAFgiJqyAY4vl5UiIaQ\nПаблик +100500 ВКонтакте: https://vk.com/maximplus100500\nMoran Days (Второй Канал) : http://www.youtube.com/user/MoranDays\nInstagram: http://instagram.com/adam_moran\nTwitter: http://twitter.com/maxplus100500\n\nВидео из эпизода: https://vk.com/wall-1719791_1789398\n\n0:00 ИНТРО\n0:27 ЧЕСНОК ХОЧЕШЬ\n2:41 ПОТЕРЯЛ ПОДОШВУ\n4:01 ФУТБОЛЬНЫЙ ПАРАШЮТИСТ\n5:27 ПИВО С ПРОДОЛЖЕНИЕМ\n7:15 ПРОЩАЛОЧКА\n7:51 МУЗЫКАЛЬНЫЙ КОНЕЦ\n8:10 СЦЕНА ПОСЛЕ ТИТРОВ\n\nВидео для обзора: https://docs.google.com/forms/d/1gx6iUl5ZvEyI_01TvGZT97qAMx-4Uum6zOGM02nIvrE/viewform?usp=send_form\n\n#ПИВОСПРОДОЛЖЕНИЕМ', duration=577) + 50. VideoInfo(id=456257788, owner_id=-1719791, title='+100500 - ЖЁСТКАЯ РЫБАЛКА С МОТЕЙ', direct_url='https://vkvideo.ru/video-1719791_456257788?pl=-1719791_48513772', share_url='https://vkvideo.ru/video-1719791_456257788?pl=-1719791_48513772', date=datetime.datetime(2021, 6, 10, 22, 3, 19), description='Эпизод # 504 :D\nСЛУШАТЬ ПЕСНЮ 2ND SEASON - ДАБЛ ОРАНЖ 👉🏼 https://ffm.to/2ndxseason_doubleorange\nTelegram канал: https://t.me/joinchat/AAAAAFN0AdiHBwyVZ2GWTw\nInstagram +100500 с видосами и мемами: https://www.instagram.com/100500_vidowsov/\n100500_Play (Telegram канал с новостями из мира видеоигр): https://t.me/joinchat/AAAAAFgiJqyAY4vl5UiIaQ\nПаблик +100500 ВКонтакте: https://vk.com/maximplus100500\nMoran Days (Второй Канал) : http://www.youtube.com/user/MoranDays\nInstagram: http://instagram.com/adam_moran\nTwitter: http://twitter.com/maxplus100500\n\nВидео из эпизода: \n\n0:00 ИНТРО\n0:27 ЗА ВИАГРОЙ В ЛОМБАРД\n2:42 ЧАЙКА-ПАССАЖИР\n4:12 МОТЯ\n6:27 КАРТОФЕЛЬНЫЙ ЛАЙФХАК\n8:27 ПРОЩАЛОЧКА\n9:53 МУЗЫКАЛЬНЫЙ КОНЕЦ\n9:19 СЦЕНА ПОСЛЕ ТИТРОВ\n\nВидео для обзора: https://docs.google.com/forms/d/1gx6iUl5ZvEyI_01TvGZT97qAMx-4Uum6zOGM02nIvrE/viewform?usp=send_form\n\n#МОТЯ #РЫБАЛКА', duration=605) + """ + + print() + + print(url) + videos: list[VideoInfo] = get_videos(url, max_items=None) + _print_videos(videos) + assert len(videos) > 100 + """ + Video (122): + 1. VideoInfo(id=456265497, owner_id=-1719791, title='Этих видео НЕ БЫЛО в +100500 🤐', direct_url='https://vkvideo.ru/video-1719791_456265497?pl=-1719791_48513772', share_url='https://vkvideo.ru/video-1719791_456265497?pl=-1719791_48513772', date=datetime.datetime(2026, 5, 30, 17, 24, 7), description='Эпизод # 556 :D\nBOOSTY (этот выпуск с дополнительным обзором на ещё одно видео): https://boosty.to/max100500/posts/6b52091c-d9a7-4395-a9c1-1390baf39f7b?share=post_link\nTWITCH: https://www.twitch.tv/moran_plays\nTELEGRAM: https://t.me/vidowsov100500\nСООБЩЕСТВО +100500 ВКонтакте: https://vk.com/maximplus100500\nTikTok: https://www.tiktok.com/@maxim_golopolosov\n\nВидео из эпизода: https://t.me/vidowsov100500/18972\n\n00:00 ПРЕДИСЛОВИЕ\n00:29 КЛАССИЧЕСКОЕ ИНТРО\n00:40 ЯЗЬ!\n04:05 НИКИТА ЛИТВИНКОВ\n08:13 НОРМАЛЬНО\n11:22 НАТАЛЬЯ МОРСКАЯ ПЕХОТА\n14:15 КЛАССИЧЕСКОЕ АУТРО\n\nПо вопросам рекламы: maks100500@didenokteam.com', duration=880) + 2. VideoInfo(id=456265161, owner_id=-1719791, title='Пора ЗАВЯЗЫВАТЬ \U0001fae9 / +100500', direct_url='https://vkvideo.ru/video-1719791_456265161?pl=-1719791_48513772', share_url='https://vkvideo.ru/video-1719791_456265161?pl=-1719791_48513772', date=datetime.datetime(2026, 4, 18, 16, 47, 4), description='Эпизод # 555 :D\nBOOSTY (этот выпуск с дополнительным обзором на ещё одно видео): https://boosty.to/max100500/posts/2d5df23d-9454-4679-8c12-a27955fddbc9?share=post_link \nTWITCH: https://www.twitch.tv/moran_plays\nTELEGRAM: https://t.me/vidowsov100500\nСООБЩЕСТВО +100500 ВКонтакте: https://vk.com/maximplus100500\nTikTok: https://www.tiktok.com/@maxim_golopolosov\n\nВидео из эпизода: https://t.me/vidowsov100500/18884\n\n00:00 ПРИВЕТЛИВЫЙ ПАССАЖИР\n02:03 ИНТРО\n02:22 ЧЕЛОВЕК-РУЧНИК\n04:51 НЕВОЗМОЖНЫЙ УЗЕЛ\n07:43 МГНОВЕННАЯ ОБИДА\n09:59 МУЗЫКАЛЬНЫЙ КОНЕЦ\n\nПо вопросам рекламы: maks100500@didenokteam.com', duration=623) + 3. VideoInfo(id=456264517, owner_id=-1719791, title='ДАНИЛ КОЛБАСЕНКО / +100500', direct_url='https://vkvideo.ru/video-1719791_456264517?pl=-1719791_48513772', share_url='https://vkvideo.ru/video-1719791_456264517?pl=-1719791_48513772', date=datetime.datetime(2026, 3, 3, 21, 7, 41), description='Эпизод # 554 :D\nBOOSTY (этот выпуск с дополнительным обзором на ещё одно видео): https://boosty.to/max100500/posts/ad53a66d-54d3-43f9-80a2-41242cb7da8d?share=post_link\nTWITCH: https://www.twitch.tv/moran_plays\nTELEGRAM: https://t.me/vidowsov100500\nСООБЩЕСТВО +100500 ВКонтакте: https://vk.com/maximplus100500\nTikTok: https://www.tiktok.com/@maxim_golopolosov\n\nВидео из эпизода: https://t.me/vidowsov100500/18769\n\n00:00 ДАНИЛ КОЛБАСЕНКО\n02:55 ИНТРО\n03:13 ГОЛУБЯТНЯ В ДЕСЯТКЕ\n05:02 ПАРУСА ИЗ КАНАЛИЗАЦИИ\n07:03 АРОМАТНЫЕ ПАЛЬЧИКИ\n09:22 МУЗЫКАЛЬНЫЙ КОНЕЦ\n\nПо вопросам рекламы: maks100500@didenokteam.com', duration=599) + ... + 120. VideoInfo(id=456240348, owner_id=-1719791, title='+100500 - Порнография На Переезде', direct_url='https://vkvideo.ru/video-1719791_456240348?pl=-1719791_48513772', share_url='https://vkvideo.ru/video-1719791_456240348?pl=-1719791_48513772', date=datetime.datetime(2019, 9, 9, 21, 31, 39), description='Эпизод #435 :D\nПаблик +100500 ВКонтакте: https://vk.com/maximplus100500\nTelegram канал: https://tg.telepult.pro/vidowsov_100500\n\nMoran Days (Второй...', duration=750) + 121. VideoInfo(id=456240213, owner_id=-1719791, title='+100500 - Поцеловал Верблюда Сзади', direct_url='https://vkvideo.ru/video-1719791_456240213?pl=-1719791_48513772', share_url='https://vkvideo.ru/video-1719791_456240213?pl=-1719791_48513772', date=datetime.datetime(2019, 8, 30, 20, 49, 58), description='Эпизод #434 :D\nHONOR 20 PRO с подарками при покупке на официальном сайте: https://clck.ru/HpYMA\n\nMoran Days (Второй Канал) : http://www.youtube.com...', duration=732) + 122. VideoInfo(id=456239908, owner_id=-1719791, title='+100500 - НАШЕСТВИЕ 2019', direct_url='https://vkvideo.ru/video-1719791_456239908?pl=-1719791_48513772', share_url='https://vkvideo.ru/video-1719791_456239908?pl=-1719791_48513772', date=datetime.datetime(2019, 8, 5, 18, 22, 42), description='Эпизод #433 :D\nMoran Days (Второй Канал) : http://www.youtube.com/user/MoranDays\n\nInstagram: http://instagram.com/adam_moran\n\nTwitter: http://twitt...', duration=599) + """ + + print() + + # Пример из канала (один запрос вернет 20 шт.) + url = "https://vkvideo.ru/@public_redcynic/all" + + print(url) + videos: list[VideoInfo] = get_videos(url, max_items=50) + _print_videos(videos) + assert len(videos) == 50 + """ + Video (50): + 1. VideoInfo(id=456243328, owner_id=-58569409, title='«Хищник: Дикие земли». Обзор «Красного Циника» UNCUT', direct_url=None, share_url='https://vkvideo.ru/video-58569409_456243328', date=datetime.datetime(2026, 3, 25, 17, 26, 14), description=None, duration=0) + 2. VideoInfo(id=456243326, owner_id=-58569409, title='«Хищник: Дикие земли». Обзор «Красного Циника»', direct_url='https://vkvideo.ru/video-58569409_456243326', share_url='https://vkvideo.ru/video-58569409_456243326', date=datetime.datetime(2026, 3, 24, 17, 0, 38), description='https://boosty.to/redcynic – аккаунт на Бусти\nhttps://vk.com/public_redcynic – группа «В контакте»\nКошелёк Ю.Money: 410011854513048\nhttps://t.me/redcynic – канал в Телеграме\n\nhttp://www.donationalerts.ru/r/redcynic – взнос на Донейшн Алертс\nhttps://www.patreon.com/bePatron?u=5206451 – страница на Патреоне\nhttps://www.youtube.com/RedCynicRus/join – стать Спонсором канала\nhttp://redcynic.com – мой сайт\n\nДэн Трахтенберг, конечно, разошёлся по полной, за четыре года наваяв больше киношек про Хищнегов, чем было заснято за предыдущие восемнадцать лет. И в этот раз он замахнулся на сложнейшее, пообещав показать внутренний быт и культуру самих инопланетных охотников от их же лица... То есть уже на самом старте извратив саму суть изначальных картин. Когда же ещё и заявили про комедийные буга-гашечки в основе сюжета, стало ясно, что нас ожидает привычное от Трахтенберга. Очередная смесь бреда, идиотии и издевательств над культовой франшизой. Как в воду глядели… Но давайте-таки подробно разберём, что для него Хищники есть...', duration=3760) + 3. VideoInfo(id=456243317, owner_id=-58569409, title='«Одни из нас». Второй сезон. Обзор «Красного Циника» UNCUT', direct_url=None, share_url='https://vkvideo.ru/video-58569409_456243317', date=datetime.datetime(2026, 1, 4, 23, 19, 5), description=None, duration=0) + + ... + 48. VideoInfo(id=456242283, owner_id=-58569409, title='Вступление к Red Alert 2', direct_url='https://vkvideo.ru/video-58569409_456242283', share_url='https://vkvideo.ru/video-58569409_456242283', date=datetime.datetime(2021, 10, 27, 17, 51, 17), description='Red Alert 2 Intro — Озвучка City — AI Upscale 60 FPS by RC', duration=238) + 49. VideoInfo(id=456242254, owner_id=-58569409, title='«Власть огня». Обзор «Красного Циника»', direct_url='https://vkvideo.ru/video-58569409_456242254', share_url='https://vkvideo.ru/video-58569409_456242254', date=datetime.datetime(2021, 10, 11, 22, 6, 49), description='', duration=1564) + 50. VideoInfo(id=456242209, owner_id=-58569409, title='«Армия мертвецов». Обзор «Красного Циника»', direct_url='https://vkvideo.ru/video-58569409_456242209', share_url='https://vkvideo.ru/video-58569409_456242209', date=datetime.datetime(2021, 9, 4, 22, 59, 55), description='https://www.patreon.com/bePatron?u=5206451 – страница на Патреоне\nhttps://boosty.to/redcynic – аккаунт на Бусти\nhttps://www.youtube.com/RedCynicRus/join – стать Спонсором канала\nhttp://www.donationalerts.ru/r/redcynic – взнос на Донейшн Алертс\nhttp://redcynic.com – мой сайт\nhttps://vk.com/public_redcynic – группа «В контакте»\nhttps://twitter.com/RedCynicRus – мой Твиттер\nhttps://www.facebook.com/red.cynic – Фэйсбук\nhttps://www.instagram.com/red_cynic_rc – мой Инстаграм\n\nНе откладывая дело в долгий ящик, давайте взглянем на следующее, после «Лиги Справедливости», кино Зака Снайдера, дабы оценить все грани таланта сумрачного гения. И тем интереснее будет этот процесс, если знать, что в своё время именно с фильма про зомби мэтр начал свою карьеру. Фильм, в общем-то знаковый для всего жанра. Такого же уровня ждали сейчас. Тем более учитывая шумиху, которая поднялась вокруг создания картины. И тот факт, что Зак Снайдер лелеял замысел её снять начиная аж с 2007 года, а может быть и ран', duration=3562) + """ + + print() + + print(url) + videos: list[VideoInfo] = get_videos(url, max_items=None) + _print_videos(videos) + assert len(videos) > 100 + """ + Video (157): + 1. VideoInfo(id=456243328, owner_id=-58569409, title='«Хищник: Дикие земли». Обзор «Красного Циника» UNCUT', direct_url=None, share_url='https://vkvideo.ru/video-58569409_456243328', date=datetime.datetime(2026, 3, 25, 17, 26, 14), description=None, duration=0) + 2. VideoInfo(id=456243326, owner_id=-58569409, title='«Хищник: Дикие земли». Обзор «Красного Циника»', direct_url='https://vkvideo.ru/video-58569409_456243326', share_url='https://vkvideo.ru/video-58569409_456243326', date=datetime.datetime(2026, 3, 24, 17, 0, 38), description='https://boosty.to/redcynic – аккаунт на Бусти\nhttps://vk.com/public_redcynic – группа «В контакте»\nКошелёк Ю.Money: 410011854513048\nhttps://t.me/redcynic – канал в Телеграме\n\nhttp://www.donationalerts.ru/r/redcynic – взнос на Донейшн Алертс\nhttps://www.patreon.com/bePatron?u=5206451 – страница на Патреоне\nhttps://www.youtube.com/RedCynicRus/join – стать Спонсором канала\nhttp://redcynic.com – мой сайт\n\nДэн Трахтенберг, конечно, разошёлся по полной, за четыре года наваяв больше киношек про Хищнегов, чем было заснято за предыдущие восемнадцать лет. И в этот раз он замахнулся на сложнейшее, пообещав показать внутренний быт и культуру самих инопланетных охотников от их же лица... То есть уже на самом старте извратив саму суть изначальных картин. Когда же ещё и заявили про комедийные буга-гашечки в основе сюжета, стало ясно, что нас ожидает привычное от Трахтенберга. Очередная смесь бреда, идиотии и издевательств над культовой франшизой. Как в воду глядели… Но давайте-таки подробно разберём, что для него Хищники есть...', duration=3760) + 3. VideoInfo(id=456243317, owner_id=-58569409, title='«Одни из нас». Второй сезон. Обзор «Красного Циника» UNCUT', direct_url=None, share_url='https://vkvideo.ru/video-58569409_456243317', date=datetime.datetime(2026, 1, 4, 23, 19, 5), description=None, duration=0) + ... + 155. VideoInfo(id=166665571, owner_id=-58569409, title='«Игра престолов» - Сезон 1. Рецензия «Красного Циника»', direct_url='https://vkvideo.ru/video-58569409_166665571', share_url='https://vkvideo.ru/video-58569409_166665571', date=datetime.datetime(2013, 11, 1, 2, 42, 58), description='www.redcynic.com http://vk.com/redcynic\n\nВ 2011 году на телевизионные экраны вышел сериал, который произвел огромный фурор. Шоу заслуженно получило признание как зрителей, так и критиков. В принципе, такой же теплый прием получил в своё время и первоисточник - роман под одноименным названием, чьим автором является Джордж Мартин.\n\nНо так ли на самом деле хорош роман? Так ли безупречен сериал? Данная рецензия - это сравнение сериала, романа и... здравого смысла.

', duration=1608) + 156. VideoInfo(id=166305114, owner_id=-58569409, title='«Красный рассвет». Обзор «Красного Циника»', direct_url='https://vkvideo.ru/video-58569409_166305114', share_url='https://vkvideo.ru/video-58569409_166305114', date=datetime.datetime(2013, 9, 19, 0, 11, 25), description='группа в ВК - http://vk.com/redcynic\nпаблик в ВК - http://vk.com/public_redcynic \nсайт - www.redcynic.com \n\nКто такие красные орки? Откуда они берутся? Об этом вам расскажет Джон Милиус! Уж кто-кто, а он так точно разбирается во всех оттенках красно-буро-малинового! Давайте же рассмотрим один из самых примечательных продуктов холодной войны. А потом поставим диагноз и Милиусу, и его оркам.', duration=2041) + 157. VideoInfo(id=166305092, owner_id=-58569409, title='«Война Богов: Бессмертные». Обзор «Красного Циника»', direct_url='https://vkvideo.ru/video-58569409_166305092', share_url='https://vkvideo.ru/video-58569409_166305092', date=datetime.datetime(2013, 9, 19, 0, 9, 9), description='группа в ВК - http://vk.com/redcynic\nпаблик в ВК - http://vk.com/public_redcynic \nсайт - www.redcynic.com \n\nЧто получится, если режиссёру индийского происхождения поручить экранизацию древнегреческих легенд? Как Тарсем Синх подошёл к созданию своих «Бессмертных»? Какая муза куса... посещала его во время творческого процесса? А давайте это прямо сейчас и узнаем ...', duration=2166) + """ diff --git a/html_parsing/youtube_com/api/__init__.py b/video_parsers/youtube/api/__init__.py similarity index 100% rename from html_parsing/youtube_com/api/__init__.py rename to video_parsers/youtube/api/__init__.py diff --git a/html_parsing/youtube_com/api/channel.py b/video_parsers/youtube/api/channel.py similarity index 100% rename from html_parsing/youtube_com/api/channel.py rename to video_parsers/youtube/api/channel.py diff --git a/html_parsing/youtube_com/api/common.py b/video_parsers/youtube/api/common.py similarity index 75% rename from html_parsing/youtube_com/api/common.py rename to video_parsers/youtube/api/common.py index 26536afe0..d85a47517 100644 --- a/html_parsing/youtube_com/api/common.py +++ b/video_parsers/youtube/api/common.py @@ -10,8 +10,8 @@ from dataclasses import dataclass, field from datetime import datetime, date -from typing import Generator -from urllib.parse import urljoin, urlparse, parse_qs +from typing import Any, Generator +from urllib.parse import urljoin, urlparse, parse_qs, urlencode, urlunparse # pip install dpath==2.0.5 import dpath.util @@ -27,10 +27,10 @@ class AlertError(Exception): pass -USER_AGENT = ( +USER_AGENT: str = ( "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0" ) -BASE_URL = "https://www.youtube.com" +BASE_URL: str = "https://www.youtube.com" session = requests.Session() @@ -41,6 +41,17 @@ class AlertError(Exception): session.cookies["SOCS"] = "CAI" +def clean_youtube_url(url: str) -> str: + parsed_url = urlparse(url) + + query_params: dict[str, list[str]] = parse_qs(parsed_url.query) + query_params.pop("pp", None) + + new_query = urlencode(query_params, doseq=True) + + return urlunparse(parsed_url._replace(query=new_query)) + + def process_text(text: str) -> str: return text.strip().replace("\xa0", " ").replace("\u202f", " ") @@ -49,11 +60,37 @@ def parse_date(value: str) -> date | None: for regex_pattern, months in [ ( r"(?P%s) (?P\d{,2}), (?P\d{4})", - ['jan', 'feb', 'mar', 'apr', 'may', 'june', 'july', 'aug', 'sep', 'oct', 'nov', 'dec'], + [ + "jan", + "feb", + "mar", + "apr", + "may", + "june", + "july", + "aug", + "sep", + "oct", + "nov", + "dec", + ], ), ( r"(?P\d{,2}) (?P%s)\.? (?P\d{4})", - ['янв', 'февр', 'мар', 'апр', 'мая', 'июн', 'июл', 'авг', 'сент', 'окт', 'нояб', 'дек'], + [ + "янв", + "февр", + "мар", + "апр", + "мая", + "июн", + "июл", + "авг", + "сент", + "окт", + "нояб", + "дек", + ], ), ]: regex = regex_pattern % "|".join(months) @@ -98,7 +135,7 @@ def download_url_as_bytes(url: str) -> bytes: return rs.content -def get_yt_cfg_data(html: str) -> dict: +def get_yt_cfg_data(html: str) -> dict[str, Any]: m = re.search(r"ytcfg\.set\((\{.+?\})\);", html) if not m: raise Exception("Не удалось найти на странице ytcfg.set!") @@ -106,7 +143,7 @@ def get_yt_cfg_data(html: str) -> dict: return json.loads(m.group(1)) -def raise_if_error(yt_initial_data: dict): +def raise_if_error(yt_initial_data: dict[str, Any]): # NOTE: Example: """ ... @@ -146,7 +183,7 @@ def raise_if_error(yt_initial_data: dict): pass -def dict_merge(d1: dict, d2: dict): +def dict_merge(d1: dict[str, Any], d2: dict[str, Any]) -> None: for k, v in d2.items(): if k in d1 and isinstance(d1[k], dict) and isinstance(v, dict): dict_merge(d1[k], v) @@ -154,7 +191,7 @@ def dict_merge(d1: dict, d2: dict): d1[k] = v -def get_yt_initial_data(html: str) -> dict | None: +def get_yt_initial_data(html: str) -> dict[str, Any] | None: patterns = [ re.compile(r'window\["ytInitialData"\] = (\{.+?\});'), re.compile(r"var ytInitialData = (\{.+?\});"), @@ -167,7 +204,7 @@ def get_yt_initial_data(html: str) -> dict | None: return json.loads(data_str) -def load(url: str) -> tuple[requests.Response, dict]: +def load(url: str) -> tuple[requests.Response, dict[str, Any]]: rs = session.get(url) rs.raise_for_status() @@ -180,7 +217,7 @@ def load(url: str) -> tuple[requests.Response, dict]: return rs, data -def get_yt_initial_player_response(html: str) -> dict: +def get_yt_initial_player_response(html: str) -> dict[str, Any]: m = re.search(r"ytInitialPlayerResponse = (\{.+?\});", html) if not m: raise Exception("Не удалось найти на странице ytInitialPlayerResponse!") @@ -188,7 +225,7 @@ def get_yt_initial_player_response(html: str) -> dict: return json.loads(m.group(1)) -def get_context_data(url: str, innertube_context: dict) -> dict: +def get_context_data(url: str, innertube_context: dict[str, Any]) -> dict[str, Any]: local_zone = tzlocal.get_localzone() utc_offset_minutes = local_zone.utcoffset(datetime.now()).total_seconds() // 60 @@ -267,14 +304,22 @@ def get_context_data(url: str, innertube_context: dict) -> dict: def get_context_with_continuation( url: str, - yt_cfg_data: dict, - continuation_item: dict, -) -> dict: + yt_cfg_data: dict[str, Any], + continuation_item: dict[str, Any], +) -> dict[str, Any]: innertube_context = yt_cfg_data.get("INNERTUBE_CONTEXT") if not innertube_context: raise Exception("Значение INNERTUBE_CONTEXT должно быть задано в yt_cfg_data!") - continuation_endpoint: dict = continuation_item["continuationEndpoint"] + continuation_endpoint: dict[str, Any] + try: + continuation_endpoint = continuation_item["continuationEndpoint"] + except KeyError: + continuation_endpoint = dpath.util.get( + continuation_item, + "continuationCommand/innertubeCommand", + ) + click_tracking_params: str = continuation_endpoint["clickTrackingParams"] continuation_token: str = dpath.util.get( continuation_endpoint, @@ -290,12 +335,17 @@ def get_context_with_continuation( return pattern_next_page_data -def get_api_url_from_continuation_item(url: str, continuation_item: dict) -> str: +def get_api_url_from_continuation_item( + url: str, + continuation_item: dict[str, Any], +) -> str: api_url = dpath.util.get(continuation_item, "**/webCommandMetadata/apiUrl") return urljoin(url, api_url) -def get_raw_video_renderer_items(yt_initial_data: dict) -> list[dict]: +def get_raw_video_renderer_items( + yt_initial_data: dict[str, Any], +) -> list[dict[str, Any]]: items = [] for render in [ "**/gridVideoRenderer", @@ -303,16 +353,17 @@ def get_raw_video_renderer_items(yt_initial_data: dict) -> list[dict]: "**/playlistVideoRenderer", "**/playlistPanelVideoRenderer", "**/playlistRenderer", + "**/lockupViewModel", ]: items += dpath.util.values(yt_initial_data, render) return items -def get_generator_raw_video_list_from_data( - yt_initial_data: dict, +def get_generator_raw_items_from_data( + yt_initial_data: dict[str, Any], rs: requests.Response, -) -> Generator[dict, None, None]: +) -> Generator[dict[str, Any], None, None]: yt_cfg_data = get_yt_cfg_data(rs.text) innertube_api_key = yt_cfg_data["INNERTUBE_API_KEY"] @@ -325,11 +376,20 @@ def get_generator_raw_video_list_from_data( while True: time.sleep(0.5) + if error := data.get("error"): + raise Exception(f"[#] Error code {error['code']}: {error['message']}") + + continuation_item: dict[str, Any] try: # Может вернуться несколько continuationItemRenderer, берем первый - continuation_item = dpath.util.values(data, "**/continuationItemRenderer")[0] + glob_continuation: str = "**/continuationItemRenderer" + continuation_item = dpath.util.values(data, glob_continuation)[0] except (KeyError, IndexError): - break + try: + glob_continuation: str = "**/continuationItemViewModel" + continuation_item = dpath.util.values(data, glob_continuation)[0] + except (KeyError, IndexError): + break url_next_page_data = get_api_url_from_continuation_item( rs.url, continuation_item @@ -350,9 +410,9 @@ def get_generator_raw_video_list_from_data( @dataclass class Context: - data_video: dict | None = None - yt_initial_data: dict | None = None - yt_cfg_data: dict | None = None + data_video: dict[str, Any] | None = None + yt_initial_data: dict[str, Any] | None = None + yt_cfg_data: dict[str, Any] | None = None rs: requests.Response | None = None @@ -363,7 +423,7 @@ class Thumbnail: height: str @classmethod - def get_from(cls, thumbnail: dict) -> "Thumbnail": + def get_from(cls, thumbnail: dict[str, Any]) -> "Thumbnail": return cls( url=thumbnail["url"], width=thumbnail["width"], @@ -379,7 +439,7 @@ class TranscriptItem: text: str @classmethod - def get_from(cls, transcript_segment_renderer: dict) -> "TranscriptItem": + def get_from(cls, transcript_segment_renderer: dict[str, Any]) -> "TranscriptItem": return cls( start_ms=int(transcript_segment_renderer["startMs"]), end_ms=int(transcript_segment_renderer["endMs"]), @@ -401,43 +461,74 @@ class Video: is_live_now: bool = False thumbnails: list[Thumbnail] = field(default_factory=list, repr=False, compare=False) view_count: int | None = None + view_count_raw: str | None = None create_date: date | None = None create_date_raw: str | None = None is_lasy: bool = True context: Context = field(default=None, repr=False, compare=False) @classmethod - def parse_url(cls, data_video: dict) -> str: - url_video = dpath.util.get( - data_video, "navigationEndpoint/commandMetadata/webCommandMetadata/url" - ) - return urljoin(BASE_URL, url_video) + def get_video_id(cls, data_video: dict[str, Any]) -> str: + try: + return data_video["videoId"] + except KeyError: + return data_video["contentId"] @classmethod - def parse_title(cls, data_video: dict) -> str: + def parse_url(cls, data_video: dict[str, Any]) -> str: + try: + glob_url = "navigationEndpoint/commandMetadata/webCommandMetadata/url" + uri_video = dpath.util.get(data_video, glob_url) + except KeyError: + glob_url: str = ( + "rendererContext/commandContext/onTap/innertubeCommand/" + "commandMetadata/webCommandMetadata/url" + ) + uri_video = dpath.util.get(data_video, glob_url) + + uri_video = clean_youtube_url(uri_video) + + return urljoin(BASE_URL, uri_video) + + @classmethod + def parse_title(cls, data_video: dict[str, Any]) -> str: if title := data_video.get("title"): if title and isinstance(title, str): return title - try: - return dpath.util.get(data_video, "title/runs/0/text") - except KeyError: - return dpath.util.get(data_video, "title/simpleText") + for glob_title in [ + "title/runs/0/text", + "title/simpleText", + "metadata/lockupMetadataViewModel/title/content", + ]: + try: + return dpath.util.get(data_video, glob_title) + except KeyError: + pass + + raise ValueError("Not found any titles.") @classmethod - def parse_duration_seconds(cls, data_video: dict) -> int: + def parse_duration_seconds(cls, data_video: dict[str, Any]) -> int | None: # Если есть продолжительность в секундах try: - duration_seconds = int(data_video["lengthSeconds"]) + return int(data_video["lengthSeconds"]) except KeyError: # Если есть продолжительность в секундах в виде текста, пробуем распарсить try: text = dpath.util.get(data_video, "lengthText/simpleText") - duration_seconds = time_to_seconds(text) except KeyError: - duration_seconds = None - - return duration_seconds + glob_duration: str = ( + "contentImage/thumbnailViewModel/overlays/*/" + "thumbnailBottomOverlayViewModel/badges/*/" + "thumbnailBadgeViewModel/text" + ) + try: + text = dpath.util.get(data_video, glob_duration) + except KeyError: + return + + return time_to_seconds(text) def get_url_thumbnail_by_max_size(self) -> str: return max(self.thumbnails, key=lambda x: (x.width, x.height)).url @@ -463,7 +554,7 @@ def get_thumbnail_for_maxresdefault(self) -> bytes: return download_url_as_bytes(self.get_url_thumbnail_for_maxresdefault()) @classmethod - def get_is_live_now(cls, video: dict) -> bool: + def get_is_live_now(cls, video: dict[str, Any]) -> bool: # Стримы имеют значок BADGE_STYLE_TYPE_LIVE_NOW try: badges = dpath.util.values(video, "**/metadataBadgeRenderer/style") @@ -476,7 +567,7 @@ def get_is_live_now(cls, video: dict) -> bool: @classmethod def parse_from( cls, - data_video: dict, + data_video: dict[str, Any], parent_context: Context | None = None, url_video: str = "", ) -> "Video": @@ -494,10 +585,16 @@ def parse_from( else: duration_text = None + seq: int | None = None try: seq = int(data_video["index"]["simpleText"]) - except: - seq = None + except (ValueError, KeyError, TypeError): + # NOTE: "/watch?v=feWq4hDEZ2U&list=PLfCe0Mzdeup2haesPLO5tGwgVVLpI_hWu&index=55&pp=iAQB" -> 55 + parsed_url = urlparse(url_video) + query_params: dict[str, list[str]] = parse_qs(parsed_url.query) + values: list[str] = query_params.get("index", []) + if values: + seq = int(values[0]) try: create_date_raw: str | None = process_text( @@ -511,15 +608,28 @@ def parse_from( except: create_date = None - thumbnails = [ + thumbnails: list[Thumbnail] = [ Thumbnail.get_from(thumbnail) - for thumbnail in dpath.util.values(data_video, "thumbnail/thumbnails/*") + for thumbnail in ( + dpath.util.values(data_video, "thumbnail/thumbnails/*") + + dpath.util.values( + data_video, "contentImage/thumbnailViewModel/image/sources/*" + ) + ) ] + view_count: int | None = None + view_count_raw: str | None = None try: - view_count = int(data_video["viewCount"]) + view_count_raw = data_video["viewCount"] + view_count = int(view_count_raw) except: - view_count = None + try: + # "61 724 просмотра" -> 61724 + view_count_raw: str = data_video["viewCountText"]["simpleText"] + view_count = int(re.sub(r"\D+", "", view_count_raw)) + except: + pass context = Context(data_video=data_video) if parent_context: @@ -528,7 +638,7 @@ def parse_from( context.rs = parent_context.rs return cls( - id=data_video["videoId"], + id=cls.get_video_id(data_video), url=url_video, title=title, duration_seconds=duration_seconds, @@ -537,6 +647,7 @@ def parse_from( is_live_now=cls.get_is_live_now(data_video), thumbnails=thumbnails, view_count=view_count, + view_count_raw=view_count_raw, create_date=create_date, create_date_raw=create_date_raw, context=context, @@ -633,7 +744,7 @@ def get_url(cls, playlist_id: str) -> str: return urljoin(BASE_URL, f"playlist?list={playlist_id}") @classmethod - def get_title(cls, yt_initial_data: dict) -> str: + def get_title(cls, yt_initial_data: dict[str, Any]) -> str: try: # Playlist return dpath.util.get( @@ -674,7 +785,7 @@ def get_from(cls, url_or_id: str) -> "Playlist": total_seconds = 0 video_list = [] - for data_video in get_generator_raw_video_list_from_data(yt_initial_data, rs): + for data_video in get_generator_raw_items_from_data(yt_initial_data, rs): video = Video.parse_from(data_video, context) video_list.append(video) diff --git a/video_parsers/youtube/api/search.py b/video_parsers/youtube/api/search.py new file mode 100644 index 000000000..885bac377 --- /dev/null +++ b/video_parsers/youtube/api/search.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +from typing import Generator, Callable, Any +from urllib.parse import urljoin + +from .common import ( + BASE_URL, + Video, + load, + get_generator_raw_items_from_data, +) + +DEFAULT_MAX_ITEMS: int = 1_000 + + +def get_generator_raw_items(url: str) -> Generator[dict[str, Any], None, None]: + rs, data = load(url) + yield from get_generator_raw_items_from_data(data, rs) + + +def get_raw_items( + url: str, + max_items: int | None = DEFAULT_MAX_ITEMS, +) -> list[dict[str, Any]]: + items = [] + for i, video in enumerate(get_generator_raw_items(url)): + if max_items and i >= max_items: + break + + items.append(video) + + return items + + +def get_video_list( + url: str, + max_items: int | None = DEFAULT_MAX_ITEMS, +) -> list[Video]: + def _is_video(data: dict[str, Any]) -> bool: + try: + return Video.get_video_id(data) is not None + except KeyError: + return False + + return [ + Video.parse_from(video) + for video in get_raw_items(url, max_items=max_items) + if _is_video(video) + ] + + +def search_youtube( + text_or_url: str, + max_items: int | None = DEFAULT_MAX_ITEMS, +) -> list[Video]: + if text_or_url.startswith("http"): + url = text_or_url + else: + text = text_or_url + url = urljoin(BASE_URL, f"results?search_query={text}") + + return get_video_list(url, max_items=max_items) + + +def search_youtube_with_filter( + url: str, + sort: bool = False, + filter_func: Callable[[Any], bool] = None, +) -> list[str]: + video_title_list = [video.title for video in search_youtube(url)] + if sort: + video_title_list.sort() + + if callable(filter_func): + video_title_list = list(filter(filter_func, video_title_list)) + + return video_title_list diff --git "a/html_parsing/youtube_com/download_previews_playlist/Dark_Souls. PLndO6DOY2cLyxQYX7pkDspTJ42JWx07AO/1. \320\223\320\276\321\200\320\270\321\202_\320\276\321\202_\321\207\320\260\321\202\320\270\320\272\320\260_-_Dark_Souls_1. 4ewTMva83tQ.jpg" "b/video_parsers/youtube/download_previews_playlist/Dark_Souls. PLndO6DOY2cLyxQYX7pkDspTJ42JWx07AO/1. \320\223\320\276\321\200\320\270\321\202_\320\276\321\202_\321\207\320\260\321\202\320\270\320\272\320\260_-_Dark_Souls_1. 4ewTMva83tQ.jpg" similarity index 100% rename from "html_parsing/youtube_com/download_previews_playlist/Dark_Souls. PLndO6DOY2cLyxQYX7pkDspTJ42JWx07AO/1. \320\223\320\276\321\200\320\270\321\202_\320\276\321\202_\321\207\320\260\321\202\320\270\320\272\320\260_-_Dark_Souls_1. 4ewTMva83tQ.jpg" rename to "video_parsers/youtube/download_previews_playlist/Dark_Souls. PLndO6DOY2cLyxQYX7pkDspTJ42JWx07AO/1. \320\223\320\276\321\200\320\270\321\202_\320\276\321\202_\321\207\320\260\321\202\320\270\320\272\320\260_-_Dark_Souls_1. 4ewTMva83tQ.jpg" diff --git "a/html_parsing/youtube_com/download_previews_playlist/Dark_Souls. PLndO6DOY2cLyxQYX7pkDspTJ42JWx07AO/2. \320\235\320\260\321\210\320\265\321\201\321\202\320\262\320\270\320\265_\320\220\320\273\321\214\321\202\321\200\321\203\320\270\321\201\321\202\320\276\320\262_-_Dark_Souls_2. Urrjtb2Irs8.jpg" "b/video_parsers/youtube/download_previews_playlist/Dark_Souls. PLndO6DOY2cLyxQYX7pkDspTJ42JWx07AO/2. \320\235\320\260\321\210\320\265\321\201\321\202\320\262\320\270\320\265_\320\220\320\273\321\214\321\202\321\200\321\203\320\270\321\201\321\202\320\276\320\262_-_Dark_Souls_2. Urrjtb2Irs8.jpg" similarity index 100% rename from "html_parsing/youtube_com/download_previews_playlist/Dark_Souls. PLndO6DOY2cLyxQYX7pkDspTJ42JWx07AO/2. \320\235\320\260\321\210\320\265\321\201\321\202\320\262\320\270\320\265_\320\220\320\273\321\214\321\202\321\200\321\203\320\270\321\201\321\202\320\276\320\262_-_Dark_Souls_2. Urrjtb2Irs8.jpg" rename to "video_parsers/youtube/download_previews_playlist/Dark_Souls. PLndO6DOY2cLyxQYX7pkDspTJ42JWx07AO/2. \320\235\320\260\321\210\320\265\321\201\321\202\320\262\320\270\320\265_\320\220\320\273\321\214\321\202\321\200\321\203\320\270\321\201\321\202\320\276\320\262_-_Dark_Souls_2. Urrjtb2Irs8.jpg" diff --git "a/html_parsing/youtube_com/download_previews_playlist/Dark_Souls. PLndO6DOY2cLyxQYX7pkDspTJ42JWx07AO/3. \320\223\320\236\320\240\320\230\320\242_\320\236\320\247\320\220\320\223_-_Dark_Souls_3. Fc6TJ242zDw.jpg" "b/video_parsers/youtube/download_previews_playlist/Dark_Souls. PLndO6DOY2cLyxQYX7pkDspTJ42JWx07AO/3. \320\223\320\236\320\240\320\230\320\242_\320\236\320\247\320\220\320\223_-_Dark_Souls_3. Fc6TJ242zDw.jpg" similarity index 100% rename from "html_parsing/youtube_com/download_previews_playlist/Dark_Souls. PLndO6DOY2cLyxQYX7pkDspTJ42JWx07AO/3. \320\223\320\236\320\240\320\230\320\242_\320\236\320\247\320\220\320\223_-_Dark_Souls_3. Fc6TJ242zDw.jpg" rename to "video_parsers/youtube/download_previews_playlist/Dark_Souls. PLndO6DOY2cLyxQYX7pkDspTJ42JWx07AO/3. \320\223\320\236\320\240\320\230\320\242_\320\236\320\247\320\220\320\223_-_Dark_Souls_3. Fc6TJ242zDw.jpg" diff --git "a/html_parsing/youtube_com/download_previews_playlist/Dark_Souls. PLndO6DOY2cLyxQYX7pkDspTJ42JWx07AO/4. \320\221\320\236\320\233\320\254\320\250\320\225_\320\242\320\243\320\237\320\253\320\245_\320\241\320\236\320\222\320\225\320\242\320\236\320\222_-_Dark_Souls_4. 8iElHAzoSWw.jpg" "b/video_parsers/youtube/download_previews_playlist/Dark_Souls. PLndO6DOY2cLyxQYX7pkDspTJ42JWx07AO/4. \320\221\320\236\320\233\320\254\320\250\320\225_\320\242\320\243\320\237\320\253\320\245_\320\241\320\236\320\222\320\225\320\242\320\236\320\222_-_Dark_Souls_4. 8iElHAzoSWw.jpg" similarity index 100% rename from "html_parsing/youtube_com/download_previews_playlist/Dark_Souls. PLndO6DOY2cLyxQYX7pkDspTJ42JWx07AO/4. \320\221\320\236\320\233\320\254\320\250\320\225_\320\242\320\243\320\237\320\253\320\245_\320\241\320\236\320\222\320\225\320\242\320\236\320\222_-_Dark_Souls_4. 8iElHAzoSWw.jpg" rename to "video_parsers/youtube/download_previews_playlist/Dark_Souls. PLndO6DOY2cLyxQYX7pkDspTJ42JWx07AO/4. \320\221\320\236\320\233\320\254\320\250\320\225_\320\242\320\243\320\237\320\253\320\245_\320\241\320\236\320\222\320\225\320\242\320\236\320\222_-_Dark_Souls_4. 8iElHAzoSWw.jpg" diff --git "a/html_parsing/youtube_com/download_previews_playlist/Dark_Souls. PLndO6DOY2cLyxQYX7pkDspTJ42JWx07AO/5. \320\224\320\220_\320\235\320\220\320\247\320\235\320\225\320\242\320\241\320\257_\320\223\320\236\320\240\320\225\320\235\320\230\320\225_-_Dark_Souls_5. T0_b5NvXI0c.jpg" "b/video_parsers/youtube/download_previews_playlist/Dark_Souls. PLndO6DOY2cLyxQYX7pkDspTJ42JWx07AO/5. \320\224\320\220_\320\235\320\220\320\247\320\235\320\225\320\242\320\241\320\257_\320\223\320\236\320\240\320\225\320\235\320\230\320\225_-_Dark_Souls_5. T0_b5NvXI0c.jpg" similarity index 100% rename from "html_parsing/youtube_com/download_previews_playlist/Dark_Souls. PLndO6DOY2cLyxQYX7pkDspTJ42JWx07AO/5. \320\224\320\220_\320\235\320\220\320\247\320\235\320\225\320\242\320\241\320\257_\320\223\320\236\320\240\320\225\320\235\320\230\320\225_-_Dark_Souls_5. T0_b5NvXI0c.jpg" rename to "video_parsers/youtube/download_previews_playlist/Dark_Souls. PLndO6DOY2cLyxQYX7pkDspTJ42JWx07AO/5. \320\224\320\220_\320\235\320\220\320\247\320\235\320\225\320\242\320\241\320\257_\320\223\320\236\320\240\320\225\320\235\320\230\320\225_-_Dark_Souls_5. T0_b5NvXI0c.jpg" diff --git "a/html_parsing/youtube_com/download_previews_playlist/Dark_Souls. PLndO6DOY2cLyxQYX7pkDspTJ42JWx07AO/6. \320\226\320\220\320\240\320\254_\320\241\320\236\320\241\320\230\320\241\320\232\320\230_\320\235\320\220_\320\234\320\236\320\225\320\234_\320\237\320\225\320\240\320\224\320\220\320\232\320\225_-_Dark_Souls_6. ZiFNyxf7Coc.jpg" "b/video_parsers/youtube/download_previews_playlist/Dark_Souls. PLndO6DOY2cLyxQYX7pkDspTJ42JWx07AO/6. \320\226\320\220\320\240\320\254_\320\241\320\236\320\241\320\230\320\241\320\232\320\230_\320\235\320\220_\320\234\320\236\320\225\320\234_\320\237\320\225\320\240\320\224\320\220\320\232\320\225_-_Dark_Souls_6. ZiFNyxf7Coc.jpg" similarity index 100% rename from "html_parsing/youtube_com/download_previews_playlist/Dark_Souls. PLndO6DOY2cLyxQYX7pkDspTJ42JWx07AO/6. \320\226\320\220\320\240\320\254_\320\241\320\236\320\241\320\230\320\241\320\232\320\230_\320\235\320\220_\320\234\320\236\320\225\320\234_\320\237\320\225\320\240\320\224\320\220\320\232\320\225_-_Dark_Souls_6. ZiFNyxf7Coc.jpg" rename to "video_parsers/youtube/download_previews_playlist/Dark_Souls. PLndO6DOY2cLyxQYX7pkDspTJ42JWx07AO/6. \320\226\320\220\320\240\320\254_\320\241\320\236\320\241\320\230\320\241\320\232\320\230_\320\235\320\220_\320\234\320\236\320\225\320\234_\320\237\320\225\320\240\320\224\320\220\320\232\320\225_-_Dark_Souls_6. ZiFNyxf7Coc.jpg" diff --git "a/html_parsing/youtube_com/download_previews_playlist/Dark_Souls. PLndO6DOY2cLyxQYX7pkDspTJ42JWx07AO/7. \320\235\320\220\320\232\320\236\320\235\320\225\320\246-\320\242\320\236_-_Dark_Souls_7_\320\244\320\230\320\235\320\220\320\233. KpZNKQ8wASI.jpg" "b/video_parsers/youtube/download_previews_playlist/Dark_Souls. PLndO6DOY2cLyxQYX7pkDspTJ42JWx07AO/7. \320\235\320\220\320\232\320\236\320\235\320\225\320\246-\320\242\320\236_-_Dark_Souls_7_\320\244\320\230\320\235\320\220\320\233. KpZNKQ8wASI.jpg" similarity index 100% rename from "html_parsing/youtube_com/download_previews_playlist/Dark_Souls. PLndO6DOY2cLyxQYX7pkDspTJ42JWx07AO/7. \320\235\320\220\320\232\320\236\320\235\320\225\320\246-\320\242\320\236_-_Dark_Souls_7_\320\244\320\230\320\235\320\220\320\233. KpZNKQ8wASI.jpg" rename to "video_parsers/youtube/download_previews_playlist/Dark_Souls. PLndO6DOY2cLyxQYX7pkDspTJ42JWx07AO/7. \320\235\320\220\320\232\320\236\320\235\320\225\320\246-\320\242\320\236_-_Dark_Souls_7_\320\244\320\230\320\235\320\220\320\233. KpZNKQ8wASI.jpg" diff --git "a/html_parsing/youtube_com/download_previews_playlist/Lucius_3_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLKom48yw6lJrkPuqimEiH3PT1ibALMh0k/1. \320\224\321\214\321\217\320\262\320\276\320\273\321\214\321\201\320\272\320\260\321\217_\320\223\320\276\320\262\320\275\320\270\320\275\320\260__Lucius_3_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265_1. MRYeh6fwHg4.jpg" "b/video_parsers/youtube/download_previews_playlist/Lucius_3_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLKom48yw6lJrkPuqimEiH3PT1ibALMh0k/1. \320\224\321\214\321\217\320\262\320\276\320\273\321\214\321\201\320\272\320\260\321\217_\320\223\320\276\320\262\320\275\320\270\320\275\320\260__Lucius_3_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265_1. MRYeh6fwHg4.jpg" similarity index 100% rename from "html_parsing/youtube_com/download_previews_playlist/Lucius_3_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLKom48yw6lJrkPuqimEiH3PT1ibALMh0k/1. \320\224\321\214\321\217\320\262\320\276\320\273\321\214\321\201\320\272\320\260\321\217_\320\223\320\276\320\262\320\275\320\270\320\275\320\260__Lucius_3_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265_1. MRYeh6fwHg4.jpg" rename to "video_parsers/youtube/download_previews_playlist/Lucius_3_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLKom48yw6lJrkPuqimEiH3PT1ibALMh0k/1. \320\224\321\214\321\217\320\262\320\276\320\273\321\214\321\201\320\272\320\260\321\217_\320\223\320\276\320\262\320\275\320\270\320\275\320\260__Lucius_3_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265_1. MRYeh6fwHg4.jpg" diff --git "a/html_parsing/youtube_com/download_previews_playlist/Lucius_3_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLKom48yw6lJrkPuqimEiH3PT1ibALMh0k/2. \320\224\321\217\320\264\320\265\320\275\321\214\320\272\320\260_\320\245\320\276\321\207\320\265\321\202_\320\235\320\260\321\201__Lucius_3_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265_2. 3tqNs7M5rlQ.jpg" "b/video_parsers/youtube/download_previews_playlist/Lucius_3_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLKom48yw6lJrkPuqimEiH3PT1ibALMh0k/2. \320\224\321\217\320\264\320\265\320\275\321\214\320\272\320\260_\320\245\320\276\321\207\320\265\321\202_\320\235\320\260\321\201__Lucius_3_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265_2. 3tqNs7M5rlQ.jpg" similarity index 100% rename from "html_parsing/youtube_com/download_previews_playlist/Lucius_3_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLKom48yw6lJrkPuqimEiH3PT1ibALMh0k/2. \320\224\321\217\320\264\320\265\320\275\321\214\320\272\320\260_\320\245\320\276\321\207\320\265\321\202_\320\235\320\260\321\201__Lucius_3_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265_2. 3tqNs7M5rlQ.jpg" rename to "video_parsers/youtube/download_previews_playlist/Lucius_3_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLKom48yw6lJrkPuqimEiH3PT1ibALMh0k/2. \320\224\321\217\320\264\320\265\320\275\321\214\320\272\320\260_\320\245\320\276\321\207\320\265\321\202_\320\235\320\260\321\201__Lucius_3_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265_2. 3tqNs7M5rlQ.jpg" diff --git "a/html_parsing/youtube_com/download_previews_playlist/Lucius_3_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLKom48yw6lJrkPuqimEiH3PT1ibALMh0k/3. \320\250\320\276\320\272_\320\247\321\202\320\276_\320\237\321\200\320\276\320\270\321\201\321\205\320\276\320\264\320\270\321\202__Lucius_3_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265_3. 09gmUcXIzmg.jpg" "b/video_parsers/youtube/download_previews_playlist/Lucius_3_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLKom48yw6lJrkPuqimEiH3PT1ibALMh0k/3. \320\250\320\276\320\272_\320\247\321\202\320\276_\320\237\321\200\320\276\320\270\321\201\321\205\320\276\320\264\320\270\321\202__Lucius_3_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265_3. 09gmUcXIzmg.jpg" similarity index 100% rename from "html_parsing/youtube_com/download_previews_playlist/Lucius_3_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLKom48yw6lJrkPuqimEiH3PT1ibALMh0k/3. \320\250\320\276\320\272_\320\247\321\202\320\276_\320\237\321\200\320\276\320\270\321\201\321\205\320\276\320\264\320\270\321\202__Lucius_3_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265_3. 09gmUcXIzmg.jpg" rename to "video_parsers/youtube/download_previews_playlist/Lucius_3_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLKom48yw6lJrkPuqimEiH3PT1ibALMh0k/3. \320\250\320\276\320\272_\320\247\321\202\320\276_\320\237\321\200\320\276\320\270\321\201\321\205\320\276\320\264\320\270\321\202__Lucius_3_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265_3. 09gmUcXIzmg.jpg" diff --git "a/html_parsing/youtube_com/download_previews_playlist/Man_of_Medan_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLejGw9J2xE9XCDw_lFIo9RJCnzpr6P_0Z/1. \320\235\320\236\320\222\320\253\320\231_\320\230\320\235\320\242\320\225\320\240\320\220\320\232\320\242\320\230\320\222\320\235\320\253\320\231_\320\243\320\226\320\220\320\241__Man_of_Medan_1. npvpIdWrKh0.jpg" "b/video_parsers/youtube/download_previews_playlist/Man_of_Medan_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLejGw9J2xE9XCDw_lFIo9RJCnzpr6P_0Z/1. \320\235\320\236\320\222\320\253\320\231_\320\230\320\235\320\242\320\225\320\240\320\220\320\232\320\242\320\230\320\222\320\235\320\253\320\231_\320\243\320\226\320\220\320\241__Man_of_Medan_1. npvpIdWrKh0.jpg" similarity index 100% rename from "html_parsing/youtube_com/download_previews_playlist/Man_of_Medan_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLejGw9J2xE9XCDw_lFIo9RJCnzpr6P_0Z/1. \320\235\320\236\320\222\320\253\320\231_\320\230\320\235\320\242\320\225\320\240\320\220\320\232\320\242\320\230\320\222\320\235\320\253\320\231_\320\243\320\226\320\220\320\241__Man_of_Medan_1. npvpIdWrKh0.jpg" rename to "video_parsers/youtube/download_previews_playlist/Man_of_Medan_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLejGw9J2xE9XCDw_lFIo9RJCnzpr6P_0Z/1. \320\235\320\236\320\222\320\253\320\231_\320\230\320\235\320\242\320\225\320\240\320\220\320\232\320\242\320\230\320\222\320\235\320\253\320\231_\320\243\320\226\320\220\320\241__Man_of_Medan_1. npvpIdWrKh0.jpg" diff --git "a/html_parsing/youtube_com/download_previews_playlist/Man_of_Medan_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLejGw9J2xE9XCDw_lFIo9RJCnzpr6P_0Z/2. \320\243\320\226\320\220\320\241\320\253_\320\235\320\220_\320\232\320\236\320\240\320\220\320\221\320\233\320\225__Man_of_Medan_2. nXkL6-X8xgw.jpg" "b/video_parsers/youtube/download_previews_playlist/Man_of_Medan_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLejGw9J2xE9XCDw_lFIo9RJCnzpr6P_0Z/2. \320\243\320\226\320\220\320\241\320\253_\320\235\320\220_\320\232\320\236\320\240\320\220\320\221\320\233\320\225__Man_of_Medan_2. nXkL6-X8xgw.jpg" similarity index 100% rename from "html_parsing/youtube_com/download_previews_playlist/Man_of_Medan_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLejGw9J2xE9XCDw_lFIo9RJCnzpr6P_0Z/2. \320\243\320\226\320\220\320\241\320\253_\320\235\320\220_\320\232\320\236\320\240\320\220\320\221\320\233\320\225__Man_of_Medan_2. nXkL6-X8xgw.jpg" rename to "video_parsers/youtube/download_previews_playlist/Man_of_Medan_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLejGw9J2xE9XCDw_lFIo9RJCnzpr6P_0Z/2. \320\243\320\226\320\220\320\241\320\253_\320\235\320\220_\320\232\320\236\320\240\320\220\320\221\320\233\320\225__Man_of_Medan_2. nXkL6-X8xgw.jpg" diff --git "a/html_parsing/youtube_com/download_previews_playlist/Man_of_Medan_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLejGw9J2xE9XCDw_lFIo9RJCnzpr6P_0Z/3. \320\235\320\220\320\247\320\220\320\233\320\236_\320\232\320\240\320\230\320\237\320\236\320\242\320\253__Man_of_Medan_3. DEP8ADM8VuE.jpg" "b/video_parsers/youtube/download_previews_playlist/Man_of_Medan_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLejGw9J2xE9XCDw_lFIo9RJCnzpr6P_0Z/3. \320\235\320\220\320\247\320\220\320\233\320\236_\320\232\320\240\320\230\320\237\320\236\320\242\320\253__Man_of_Medan_3. DEP8ADM8VuE.jpg" similarity index 100% rename from "html_parsing/youtube_com/download_previews_playlist/Man_of_Medan_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLejGw9J2xE9XCDw_lFIo9RJCnzpr6P_0Z/3. \320\235\320\220\320\247\320\220\320\233\320\236_\320\232\320\240\320\230\320\237\320\236\320\242\320\253__Man_of_Medan_3. DEP8ADM8VuE.jpg" rename to "video_parsers/youtube/download_previews_playlist/Man_of_Medan_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLejGw9J2xE9XCDw_lFIo9RJCnzpr6P_0Z/3. \320\235\320\220\320\247\320\220\320\233\320\236_\320\232\320\240\320\230\320\237\320\236\320\242\320\253__Man_of_Medan_3. DEP8ADM8VuE.jpg" diff --git "a/html_parsing/youtube_com/download_previews_playlist/Man_of_Medan_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLejGw9J2xE9XCDw_lFIo9RJCnzpr6P_0Z/4. \320\226\320\201\320\241\320\242\320\232\320\220\320\257_\320\241\320\232\320\240\320\230\320\234\320\236\320\242\320\220__Man_of_Medan_4. sGgSTJba9qU.jpg" "b/video_parsers/youtube/download_previews_playlist/Man_of_Medan_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLejGw9J2xE9XCDw_lFIo9RJCnzpr6P_0Z/4. \320\226\320\201\320\241\320\242\320\232\320\220\320\257_\320\241\320\232\320\240\320\230\320\234\320\236\320\242\320\220__Man_of_Medan_4. sGgSTJba9qU.jpg" similarity index 100% rename from "html_parsing/youtube_com/download_previews_playlist/Man_of_Medan_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLejGw9J2xE9XCDw_lFIo9RJCnzpr6P_0Z/4. \320\226\320\201\320\241\320\242\320\232\320\220\320\257_\320\241\320\232\320\240\320\230\320\234\320\236\320\242\320\220__Man_of_Medan_4. sGgSTJba9qU.jpg" rename to "video_parsers/youtube/download_previews_playlist/Man_of_Medan_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLejGw9J2xE9XCDw_lFIo9RJCnzpr6P_0Z/4. \320\226\320\201\320\241\320\242\320\232\320\220\320\257_\320\241\320\232\320\240\320\230\320\234\320\236\320\242\320\220__Man_of_Medan_4. sGgSTJba9qU.jpg" diff --git "a/html_parsing/youtube_com/download_previews_playlist/Man_of_Medan_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLejGw9J2xE9XCDw_lFIo9RJCnzpr6P_0Z/5. \320\232\320\240\320\220\320\241\320\236\320\242\320\232\320\220_\320\235\320\220_\320\232\320\236\320\240\320\220\320\221\320\233\320\225__Man_of_Medan_5. tFE67sbnJI0.jpg" "b/video_parsers/youtube/download_previews_playlist/Man_of_Medan_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLejGw9J2xE9XCDw_lFIo9RJCnzpr6P_0Z/5. \320\232\320\240\320\220\320\241\320\236\320\242\320\232\320\220_\320\235\320\220_\320\232\320\236\320\240\320\220\320\221\320\233\320\225__Man_of_Medan_5. tFE67sbnJI0.jpg" similarity index 100% rename from "html_parsing/youtube_com/download_previews_playlist/Man_of_Medan_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLejGw9J2xE9XCDw_lFIo9RJCnzpr6P_0Z/5. \320\232\320\240\320\220\320\241\320\236\320\242\320\232\320\220_\320\235\320\220_\320\232\320\236\320\240\320\220\320\221\320\233\320\225__Man_of_Medan_5. tFE67sbnJI0.jpg" rename to "video_parsers/youtube/download_previews_playlist/Man_of_Medan_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLejGw9J2xE9XCDw_lFIo9RJCnzpr6P_0Z/5. \320\232\320\240\320\220\320\241\320\236\320\242\320\232\320\220_\320\235\320\220_\320\232\320\236\320\240\320\220\320\221\320\233\320\225__Man_of_Medan_5. tFE67sbnJI0.jpg" diff --git "a/html_parsing/youtube_com/download_previews_playlist/Man_of_Medan_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLejGw9J2xE9XCDw_lFIo9RJCnzpr6P_0Z/6. \320\244\320\230\320\235\320\220\320\233__Man_of_Medan_6. 77mE1zJq0es.jpg" "b/video_parsers/youtube/download_previews_playlist/Man_of_Medan_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLejGw9J2xE9XCDw_lFIo9RJCnzpr6P_0Z/6. \320\244\320\230\320\235\320\220\320\233__Man_of_Medan_6. 77mE1zJq0es.jpg" similarity index 100% rename from "html_parsing/youtube_com/download_previews_playlist/Man_of_Medan_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLejGw9J2xE9XCDw_lFIo9RJCnzpr6P_0Z/6. \320\244\320\230\320\235\320\220\320\233__Man_of_Medan_6. 77mE1zJq0es.jpg" rename to "video_parsers/youtube/download_previews_playlist/Man_of_Medan_\320\237\321\200\320\276\321\205\320\276\320\266\320\264\320\265\320\275\320\270\320\265. PLejGw9J2xE9XCDw_lFIo9RJCnzpr6P_0Z/6. \320\244\320\230\320\235\320\220\320\233__Man_of_Medan_6. 77mE1zJq0es.jpg" diff --git a/html_parsing/youtube_com/download_previews_playlist/main.py b/video_parsers/youtube/download_previews_playlist/main.py similarity index 98% rename from html_parsing/youtube_com/download_previews_playlist/main.py rename to video_parsers/youtube/download_previews_playlist/main.py index 079545979..781bcd596 100644 --- a/html_parsing/youtube_com/download_previews_playlist/main.py +++ b/video_parsers/youtube/download_previews_playlist/main.py @@ -16,7 +16,7 @@ from api.common import Playlist -def download_playlist_video_previews(url_or_id: str, save_dir: Path = DIR): +def download_playlist_video_previews(url_or_id: str, save_dir: Path = DIR) -> None: playlist = Playlist.get_from(url_or_id) safe_playlist_title = get_valid_filename(playlist.title) diff --git a/video_parsers/youtube/get_all_video_+100500.py b/video_parsers/youtube/get_all_video_+100500.py new file mode 100644 index 000000000..9c1cae9b5 --- /dev/null +++ b/video_parsers/youtube/get_all_video_+100500.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +__author__ = "ipetrash" + + +from api.common import Video +from api.search import search_youtube + +MINIMUM_NUMBER: int = 500 + +TARGETS: list[tuple[str, str]] = [ + # ("Playlist", "https://www.youtube.com/playlist?list=PLC6A0625DCA9AAE2D"), + ("Channel", "https://www.youtube.com/@adamthomasmoran/videos"), +] + +problems: list[str] = [] +for label, url in TARGETS: + videos: list[Video] = search_youtube(url) + count = len(videos) + + print(f"{label}: {count} videos") + titles: list[str] = [f"{i}. {v}" for i, v in enumerate(videos, 1)] + print(*titles[:5], sep="\n") + print("...") + print(*titles[-5:], sep="\n") + + print("\n" + "-" * 100 + "\n") + + if count <= MINIMUM_NUMBER: + problems.append(f"{label} videos: expected > {MINIMUM_NUMBER}, got {count}") + +if problems: + raise Exception("\n".join(problems)) diff --git a/html_parsing/youtube_com/get_channel_info.py b/video_parsers/youtube/get_channel_info.py similarity index 100% rename from html_parsing/youtube_com/get_channel_info.py rename to video_parsers/youtube/get_channel_info.py diff --git a/html_parsing/youtube_com/get_playlist_info.py b/video_parsers/youtube/get_playlist_info.py similarity index 100% rename from html_parsing/youtube_com/get_playlist_info.py rename to video_parsers/youtube/get_playlist_info.py diff --git a/html_parsing/youtube_com/get_transcriptions_from_video.py b/video_parsers/youtube/get_transcriptions_from_video.py similarity index 100% rename from html_parsing/youtube_com/get_transcriptions_from_video.py rename to video_parsers/youtube/get_transcriptions_from_video.py diff --git a/html_parsing/youtube_com/get_video_info.py b/video_parsers/youtube/get_video_info.py similarity index 100% rename from html_parsing/youtube_com/get_video_info.py rename to video_parsers/youtube/get_video_info.py diff --git a/html_parsing/youtube_com/number_of_swear_words.py b/video_parsers/youtube/number_of_swear_words.py similarity index 100% rename from html_parsing/youtube_com/number_of_swear_words.py rename to video_parsers/youtube/number_of_swear_words.py diff --git a/html_parsing/youtube_com/playlist_show_delta_between_videos.py b/video_parsers/youtube/playlist_show_delta_between_videos.py similarity index 100% rename from html_parsing/youtube_com/playlist_show_delta_between_videos.py rename to video_parsers/youtube/playlist_show_delta_between_videos.py diff --git a/html_parsing/youtube_com/print_long_videos_plus100500.py b/video_parsers/youtube/print_long_videos_plus100500.py similarity index 100% rename from html_parsing/youtube_com/print_long_videos_plus100500.py rename to video_parsers/youtube/print_long_videos_plus100500.py diff --git a/html_parsing/youtube_com/results_search_query.py b/video_parsers/youtube/results_search_query.py similarity index 96% rename from html_parsing/youtube_com/results_search_query.py rename to video_parsers/youtube/results_search_query.py index cca606657..d4ef31622 100644 --- a/html_parsing/youtube_com/results_search_query.py +++ b/video_parsers/youtube/results_search_query.py @@ -11,13 +11,12 @@ search_youtube_with_filter, ) - -url_playlist = ( +url_playlist: str = ( "https://www.youtube.com/playlist?list=PLWKjhJtqVAbknyJ7hSrf1WKh_Xnv9RL1r" ) -def __print_video_list(items: list[Video]): +def __print_video_list(items: list[Video]) -> None: print(f"Items ({len(items)}):") for i, video in enumerate(items, 1): print(f" {i:3}. {video.title!r}: {video.url}") @@ -38,7 +37,7 @@ def __print_video_list(items: list[Video]): print("\n" + "-" * 100 + "\n") -url_playlist = ( +url_playlist: str = ( "https://www.youtube.com/playlist?list=PLWKjhJtqVAbnRT_hue-3zyiuIYj0OlpyG" ) items = search_youtube(url_playlist) @@ -56,6 +55,11 @@ def __print_video_list(items: list[Video]): print("\n" + "-" * 100 + "\n") +items = search_youtube(url_playlist, max_items=None) +__print_video_list(items) + +print("\n" + "-" * 100 + "\n") + # Testing for: youtube, channel, channel videos print(len(get_video_list("https://www.youtube.com/"))) # TODO: Под вопросом print(len(get_video_list("https://www.youtube.com/c/TheBadComedian"))) @@ -81,7 +85,7 @@ def __print_video_list(items: list[Video]): print("\n" + "-" * 100 + "\n") -items = search_youtube("щенки", maximum_items=25) +items = search_youtube("щенки", max_items=25) __print_video_list(items) """ Items (25): @@ -98,7 +102,7 @@ def __print_video_list(items: list[Video]): items = search_youtube( "https://www.youtube.com/results?search_query=slipknot official", - maximum_items=50, + max_items=50, ) __print_video_list(items) """ diff --git a/html_parsing/youtube_com/search_video_in_channels.py b/video_parsers/youtube/search_video_in_channels.py similarity index 98% rename from html_parsing/youtube_com/search_video_in_channels.py rename to video_parsers/youtube/search_video_in_channels.py index cb1e20082..1be2f29c6 100644 --- a/html_parsing/youtube_com/search_video_in_channels.py +++ b/video_parsers/youtube/search_video_in_channels.py @@ -10,7 +10,7 @@ from collections import defaultdict from api.common import Video, Playlist -from api.search import get_raw_video_list +from api.search import get_raw_items def smart_comparing(game_name: str, playlist_title: str) -> bool: @@ -33,7 +33,7 @@ def search_video_and_playlist( items = [] url = f"{channel_url}/search?query={game_name}" - for obj in get_raw_video_list(url, maximum_items=100): + for obj in get_raw_items(url, max_items=100): if playlist_id := obj.get("playlistId"): title = Playlist.get_title(obj) if smart_comparing(game_name, title): diff --git a/total_time_playlist_youtube/gui.py b/video_parsers/youtube/total_time_playlist_youtube/gui.py similarity index 97% rename from total_time_playlist_youtube/gui.py rename to video_parsers/youtube/total_time_playlist_youtube/gui.py index 4cd2ee8c0..516810606 100644 --- a/total_time_playlist_youtube/gui.py +++ b/video_parsers/youtube/total_time_playlist_youtube/gui.py @@ -48,7 +48,7 @@ class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("total_time_playlist_youtube") @@ -73,7 +73,7 @@ def __init__(self): central_widget.setLayout(main_layout) self.setCentralWidget(central_widget) - def go(self): + def go(self) -> None: try: url = self.url_line_edit.text() title, total_seconds, total_seconds_text, items = parse_playlist_time(url) diff --git a/total_time_playlist_youtube/main.py b/video_parsers/youtube/total_time_playlist_youtube/main.py similarity index 94% rename from total_time_playlist_youtube/main.py rename to video_parsers/youtube/total_time_playlist_youtube/main.py index 376c06715..d6dae668e 100644 --- a/total_time_playlist_youtube/main.py +++ b/video_parsers/youtube/total_time_playlist_youtube/main.py @@ -6,8 +6,9 @@ import sys -sys.path.append("../html_parsing") -from youtube_com__results_search_query import Playlist +sys.path.append("../") +sys.path.append("../../") +from youtube.results_search_query import Playlist def parse_playlist_time(url_or_id: str) -> tuple[str, int, list[tuple[str, str]]]: diff --git a/html_parsing/yummyani_me/main.py b/video_parsers/yummyani_me/main.py similarity index 100% rename from html_parsing/yummyani_me/main.py rename to video_parsers/yummyani_me/main.py diff --git a/visual_diff_two_structures/main.py b/visual_diff_two_structures/main.py index 9cc9fe6e8..d8bd574ac 100644 --- a/visual_diff_two_structures/main.py +++ b/visual_diff_two_structures/main.py @@ -16,7 +16,7 @@ from utils import get_filling_in_missing, xml_to_flatten_dict, json_to_flatten_dict -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -106,7 +106,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): # TODO: ... или еще и цветом? # TODO: Надо бы и поле заголовка выделить class MainWindow(QMainWindow): - def __init__(self): + def __init__(self) -> None: super().__init__() self.ui = Ui_MainWindow() @@ -117,7 +117,7 @@ def __init__(self): self.ui.push_button_diff.clicked.connect(self._do_diff) self.ui.cb_only_diff.clicked.connect(self._show_only_diff) - def _add_row_to_table(self, *values): + def _add_row_to_table(self, *values) -> None: name1, value1, value2, name2 = values no_match = name1 != name2 or value1 != value2 @@ -144,7 +144,7 @@ def _add_row_to_table(self, *values): self.ui.table_widget.setItem(row, i, item) - def _do_diff(self): + def _do_diff(self) -> None: source_1 = self.ui.edit_source_1.toPlainText() source_2 = self.ui.edit_source_2.toPlainText() @@ -178,7 +178,7 @@ def _do_diff(self): self._show_only_diff(self.ui.cb_only_diff.isChecked()) - def _show_only_diff(self, checked: bool): + def _show_only_diff(self, checked: bool) -> None: for row in range(self.ui.table_widget.rowCount()): no_match = self.ui.table_widget.item(row, 0).data(Qt.ItemDataRole.UserRole) diff --git a/visual_diff_two_structures/tests.py b/visual_diff_two_structures/tests.py index b582c3bd3..662daf464 100644 --- a/visual_diff_two_structures/tests.py +++ b/visual_diff_two_structures/tests.py @@ -9,7 +9,7 @@ class TestCaseUtils(unittest.TestCase): - def test_get_filling_in_missing(self): + def test_get_filling_in_missing(self) -> None: items_1 = ["F1", "F2", "F3/SF1", "F3/SF2", "F4", "F3", "F6", "F7"] items_2 = ["F3/SF1", "F5", "F3", "F6"] @@ -115,13 +115,13 @@ def test_get_filling_in_missing(self): self.assertEqual(result_1, ["F1", "F2", "F3", " ", " ", " "]) self.assertEqual(result_2, [" ", " ", " ", "F4", "F5", "F6"]) - def test_flatten(self): + def test_flatten(self) -> None: dict_data = {"a": 1, "c": {"a": 2, "b": {"x": 5, "y": 10}}, "d": [1, 2, 3]} actual_dict = utils.flatten(dict_data, separator="/") expected_dict = {"a": 1, "c/a": 2, "c/b/x": 5, "d": [1, 2, 3], "c/b/y": 10} self.assertEqual(actual_dict, expected_dict) - def test_xml_to_flatten_dict(self): + def test_xml_to_flatten_dict(self) -> None: xml_str = """ @@ -143,7 +143,7 @@ def test_xml_to_flatten_dict(self): actual_dict_flatten = utils.xml_to_flatten_dict(xml_str) self.assertEqual(actual_dict_flatten, expected_dict_flatten) - def test_json_to_flatten_dict(self): + def test_json_to_flatten_dict(self) -> None: json_str = """ { "mydocument": { diff --git a/vk_api__examples/audio_getPopular__downloads.py b/vk_api__examples/audio_getPopular__downloads.py index 2c9aa59b6..b38440af8 100644 --- a/vk_api__examples/audio_getPopular__downloads.py +++ b/vk_api__examples/audio_getPopular__downloads.py @@ -21,12 +21,12 @@ _BLACK_LIST_ARTIST = [] -def add_artist_to_black_list(artist): +def add_artist_to_black_list(artist) -> None: """Функция добавляет исполнителя в черный список.""" _BLACK_LIST_ARTIST.append(artist.lower()) -def artist_in_black_list(artist): +def artist_in_black_list(artist) -> bool: """Функция вернет True, если исполнитель в черном списке.""" return artist.lower() in _BLACK_LIST_ARTIST diff --git a/vk_api__examples/audio_get__downloads.py b/vk_api__examples/audio_get__downloads.py index 98d47c629..5c60c9fc9 100644 --- a/vk_api__examples/audio_get__downloads.py +++ b/vk_api__examples/audio_get__downloads.py @@ -37,7 +37,7 @@ # TODO: возможность выбирать диапазоны индексов скачиваемых песен -def make_pretty_id3(audio_file_name: str, performer: str, title: str): +def make_pretty_id3(audio_file_name: str, performer: str, title: str) -> None: """ Функция удаляет из тега фреймы (COMM, PRIV, ...), добавляет (а если есть переписывает) фреймы TPE1 (имя группы) и TIT2 (название песни) diff --git a/vk_api__examples/newsfeed.get_gui.py b/vk_api__examples/newsfeed.get_gui.py index bcca10a48..20630fce3 100644 --- a/vk_api__examples/newsfeed.get_gui.py +++ b/vk_api__examples/newsfeed.get_gui.py @@ -23,7 +23,7 @@ class Widget(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.line_edit_login = QLineEdit(LOGIN) @@ -50,7 +50,7 @@ def __init__(self): self.setLayout(main_layout) - def get_newsfeed(self): + def get_newsfeed(self) -> None: try: vk_session = vk_auth( self.line_edit_login.text(), self.line_edit_password.text() diff --git a/vk_api__examples/vk_spam_wall/vk_spam_wall.py b/vk_api__examples/vk_spam_wall/vk_spam_wall.py index 9864b51e8..5631aed3d 100644 --- a/vk_api__examples/vk_spam_wall/vk_spam_wall.py +++ b/vk_api__examples/vk_spam_wall/vk_spam_wall.py @@ -39,7 +39,7 @@ def vk_auth(login: str, password: str) -> vk_api.VkApi: return vk -def wall_post(logger, vk_session: vk_api.VkApi, owner_id: int, quote_href: str): +def wall_post(logger, vk_session: vk_api.VkApi, owner_id: int, quote_href: str) -> None: logger.debug("Размещаю сообщение на стену.") # Добавление сообщения на стену пользователя (owner_id это id пользователя) @@ -55,7 +55,7 @@ def wall_post(logger, vk_session: vk_api.VkApi, owner_id: int, quote_href: str): logger.debug("post_id: %s, quote href: %s.", rs["post_id"], quote_href) -def run(logger, vk_session: vk_api.VkApi, owner_id: int, quote_count: int): +def run(logger, vk_session: vk_api.VkApi, owner_id: int, quote_count: int) -> None: # Начинаем постить на стену for quote in get_random_quotes()[:quote_count]: wall_post(logger, vk_session, owner_id, quote.url) diff --git a/vk_api__examples/wall_post__bash_quotes.py b/vk_api__examples/wall_post__bash_quotes.py index 373da05c8..24c6fc4ae 100644 --- a/vk_api__examples/wall_post__bash_quotes.py +++ b/vk_api__examples/wall_post__bash_quotes.py @@ -31,7 +31,7 @@ def main( password: str = None, owner_id: int = None, timeout: int = 60 * 60, -): +) -> None: if not login and not password: vk_session = get_vk_session() else: diff --git a/wait/wait.py b/wait/wait.py index 77a0a3c7f..323bbc06c 100644 --- a/wait/wait.py +++ b/wait/wait.py @@ -13,7 +13,7 @@ def wait( days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0 -): +) -> None: try: progress_bar = cycle(("|", "/", "-", "\\")) diff --git a/walk_dict.py b/walk_dict.py index 025d8c4c9..c4b453082 100644 --- a/walk_dict.py +++ b/walk_dict.py @@ -10,7 +10,7 @@ def walk_dict( node: dict, value_process_func: Callable[[Any, Any], Any] | None = None, -): +) -> None: for key, value in node.items(): if value_process_func: value = value_process_func(key, value) diff --git a/watchdog__examples/custom_event_handler.py b/watchdog__examples/custom_event_handler.py index 4839d7c51..431359410 100644 --- a/watchdog__examples/custom_event_handler.py +++ b/watchdog__examples/custom_event_handler.py @@ -18,25 +18,25 @@ # NOTE: It will probably be more functional to inherit # from RegexMatchingEventHandler or PatternMatchingEventHandler class CustomEventHandler(FileSystemEventHandler): - def on_moved(self, event): + def on_moved(self, event) -> None: super().on_moved(event) what = "directory" if event.is_directory else "file" print(f"Moved {what}: from {event.src_path} to {event.dest_path}") - def on_created(self, event): + def on_created(self, event) -> None: super().on_created(event) what = "directory" if event.is_directory else "file" print(f"Created {what}: {event.src_path}") - def on_deleted(self, event): + def on_deleted(self, event) -> None: super().on_deleted(event) what = "directory" if event.is_directory else "file" print(f"Deleted {what}: {event.src_path}") - def on_modified(self, event): + def on_modified(self, event) -> None: super().on_modified(event) what = "directory" if event.is_directory else "file" diff --git a/webserver__cherrypy__examples/ajax_json.py b/webserver__cherrypy__examples/ajax_json.py index cbfe935ef..2418b3483 100644 --- a/webserver__cherrypy__examples/ajax_json.py +++ b/webserver__cherrypy__examples/ajax_json.py @@ -13,7 +13,7 @@ class Root(object): @cherrypy.expose @cherrypy.tools.json_in() - def update(self): + def update(self) -> str: input_json = cherrypy.request.json print("input_json:", input_json) # do_something_with(input_json) @@ -21,7 +21,7 @@ def update(self): return "Updated %r." % (input_json,) @cherrypy.expose - def index(self): + def index(self) -> str: return """ diff --git a/webserver__cherrypy__examples/all_exception_handler.py b/webserver__cherrypy__examples/all_exception_handler.py index c685ebd34..0aaa8b3b7 100644 --- a/webserver__cherrypy__examples/all_exception_handler.py +++ b/webserver__cherrypy__examples/all_exception_handler.py @@ -10,7 +10,7 @@ class Root: - def __init__(self): + def __init__(self) -> None: # Set a custom response for errors. self._cp_config = {"error_page.default": Root.all_exception_handler} # # OR: @@ -19,7 +19,7 @@ def __init__(self): # Expose the index method through the web. CherryPy will never # publish methods that don't have the exposed attribute set to True. @cherrypy.expose - def index(self): + def index(self) -> str: # CherryPy will call this method for the root URI ("/") and send # its return value to the client. Because this is tutorial # lesson number 01, we'll just send something really simple. @@ -27,7 +27,7 @@ def index(self): return 'Hello world!
Get error' @cherrypy.expose - def error(self): + def error(self) -> str: _ = 1 / 0 return "Bad!" diff --git a/webserver__cherrypy__examples/all_exception_handler__2.py b/webserver__cherrypy__examples/all_exception_handler__2.py index 3be5d4419..83af92db0 100644 --- a/webserver__cherrypy__examples/all_exception_handler__2.py +++ b/webserver__cherrypy__examples/all_exception_handler__2.py @@ -32,7 +32,7 @@ class Root: # Expose the index method through the web. CherryPy will never # publish methods that don't have the exposed attribute set to True. @cherrypy.expose - def index(self): + def index(self) -> str: # CherryPy will call this method for the root URI ("/") and send # its return value to the client. Because this is tutorial # lesson number 01, we'll just send something really simple. @@ -40,7 +40,7 @@ def index(self): return 'Hello world!
Get error' @cherrypy.expose - def error(self): + def error(self) -> str: _ = 1 / 0 return "Bad!" diff --git a/webserver__cherrypy__examples/arguments.py b/webserver__cherrypy__examples/arguments.py index 1a303dcae..3f398f693 100644 --- a/webserver__cherrypy__examples/arguments.py +++ b/webserver__cherrypy__examples/arguments.py @@ -15,7 +15,7 @@ class HelloWorld: # NOTE: try http://127.0.0.1:9090/?a=1&b=2&c=123 @cherrypy.expose - def index(self, **kwargs): + def index(self, **kwargs) -> str: return f"Hello world!: {kwargs}" diff --git a/webserver__cherrypy__examples/autoreload_off.py b/webserver__cherrypy__examples/autoreload_off.py index a645e2a3f..64b6c99ab 100644 --- a/webserver__cherrypy__examples/autoreload_off.py +++ b/webserver__cherrypy__examples/autoreload_off.py @@ -13,7 +13,7 @@ class HelloWorld: # Expose the index method through the web. CherryPy will never # publish methods that don't have the exposed attribute set to True. @cherrypy.expose - def index(self): + def index(self) -> str: # CherryPy will call this method for the root URI ("/") and send # its return value to the client. Because this is tutorial # lesson number 01, we'll just send something really simple. diff --git a/webserver__cherrypy__examples/complex_site.py b/webserver__cherrypy__examples/complex_site.py index 3440cd58c..41982505d 100644 --- a/webserver__cherrypy__examples/complex_site.py +++ b/webserver__cherrypy__examples/complex_site.py @@ -13,7 +13,7 @@ class HomePage: @cherrypy.expose - def index(self): + def index(self) -> str: return """

Hi, this is the home page! Check out the other fun stuff on this site:

@@ -25,7 +25,7 @@ def index(self): class JokePage: @cherrypy.expose - def index(self): + def index(self) -> str: return """

"In Python, how do you create a string of random characters?" -- "Read a Perl file!"

@@ -33,14 +33,14 @@ def index(self): class LinksPage: - def __init__(self): + def __init__(self) -> None: # Request handler objects can create their own nested request # handler objects. Simply create them inside their __init__ # methods! self.extra = ExtraLinksPage() @cherrypy.expose - def index(self): + def index(self) -> str: # Note the way we link to the extra links page (and back). # As you can see, this object doesn't really care about its # absolute position in the site tree, since we use relative @@ -63,7 +63,7 @@ def index(self): class ExtraLinksPage: @cherrypy.expose - def index(self): + def index(self) -> str: # Note the relative link back to the Links page! return """

Here are some extra useful links:

diff --git a/webserver__cherrypy__examples/default_method__uri.py b/webserver__cherrypy__examples/default_method__uri.py index 5124e5a61..b5275a9ba 100644 --- a/webserver__cherrypy__examples/default_method__uri.py +++ b/webserver__cherrypy__examples/default_method__uri.py @@ -22,7 +22,7 @@ class UsersPage: @cherrypy.expose - def index(self): + def index(self) -> str: # Since this is just a stupid little example, we'll simply # display a list of links to random, made-up users. In a real # application, this could be generated from a database result set. @@ -33,7 +33,7 @@ def index(self): """ @cherrypy.expose - def default(self, user): + def default(self, user) -> str: # Here we react depending on the virtualPath -- the part of the # path that could not be mapped to an object method. In a real # application, we would probably do some database lookups here diff --git a/webserver__cherrypy__examples/expose_methods.py b/webserver__cherrypy__examples/expose_methods.py index 3d90492e1..b7b3b143b 100644 --- a/webserver__cherrypy__examples/expose_methods.py +++ b/webserver__cherrypy__examples/expose_methods.py @@ -12,12 +12,12 @@ class HelloWorld: @cherrypy.expose - def index(self): + def index(self) -> str: # Let's link to another method here. return 'We have an important message for you!' @cherrypy.expose - def show_msg(self): + def show_msg(self) -> str: # Here's the important message! return "Hello world!" diff --git a/webserver__cherrypy__examples/files/main.py b/webserver__cherrypy__examples/files/main.py index 3a0e4902c..136a963a7 100644 --- a/webserver__cherrypy__examples/files/main.py +++ b/webserver__cherrypy__examples/files/main.py @@ -46,7 +46,7 @@ class FileDemo(object): @cherrypy.expose - def index(self): + def index(self) -> str: return """

Upload a file

@@ -60,7 +60,7 @@ def index(self): """ @cherrypy.expose - def upload(self, myFile): + def upload(self, myFile) -> str: out = """ myFile length: %s
diff --git a/webserver__cherrypy__examples/generators_and_yield.py b/webserver__cherrypy__examples/generators_and_yield.py index 200a8fa49..4f5e7855c 100644 --- a/webserver__cherrypy__examples/generators_and_yield.py +++ b/webserver__cherrypy__examples/generators_and_yield.py @@ -14,10 +14,10 @@ class GeneratorDemo: - def header(self): + def header(self) -> str: return "

Generators rule!

" - def footer(self): + def footer(self) -> str: return "" @cherrypy.expose diff --git a/webserver__cherrypy__examples/get__post.py b/webserver__cherrypy__examples/get__post.py index 9c806cd87..25b49c706 100644 --- a/webserver__cherrypy__examples/get__post.py +++ b/webserver__cherrypy__examples/get__post.py @@ -12,7 +12,7 @@ class WelcomePage: @cherrypy.expose - def index(self): + def index(self) -> str: # Ask for the user's name. return """

GET:

@@ -32,7 +32,7 @@ def index(self): """ @cherrypy.expose - def greet_user(self, name=None): + def greet_user(self, name=None) -> str: # CherryPy passes all GET and POST variables as method parameters. # It doesn't make a difference where the variables come from, how # large their contents are, and so on. diff --git a/webserver__cherrypy__examples/hello_world.py b/webserver__cherrypy__examples/hello_world.py index bab390efc..70d90d560 100644 --- a/webserver__cherrypy__examples/hello_world.py +++ b/webserver__cherrypy__examples/hello_world.py @@ -16,7 +16,7 @@ class HelloWorld: # Expose the index method through the web. CherryPy will never # publish methods that don't have the exposed attribute set to True. @cherrypy.expose - def index(self): + def index(self) -> str: # CherryPy will call this method for the root URI ("/") and send # its return value to the client. Because this is tutorial # lesson number 01, we'll just send something really simple. diff --git a/webserver__cherrypy__examples/inheritance/base_server.py b/webserver__cherrypy__examples/inheritance/base_server.py index 3e3a35ab3..2f1362ff6 100644 --- a/webserver__cherrypy__examples/inheritance/base_server.py +++ b/webserver__cherrypy__examples/inheritance/base_server.py @@ -3,6 +3,7 @@ import json +from typing import Any # pip install cherrypy # https://github.com/cherrypy/cherrypy @@ -14,7 +15,7 @@ class BaseServer: json_in = cherrypy.tools.json_in() json_out = cherrypy.tools.json_out() - def __init__(self): + def __init__(self) -> None: # Set a custom response for errors. self._cp_config = {"error_page.default": self.all_exception_handler} # # OR: @@ -23,24 +24,24 @@ def __init__(self): self.name = "BaseServer" @cherrypy.expose - def get_name(self): + def get_name(self) -> str: return self.name @cherrypy.expose - def execute(self): + def execute(self) -> Any: return "Not implement" @cherrypy.expose - def execute_func(self): + def execute_func(self) -> str: return self._execute_func() - def _execute_func(self): + def _execute_func(self) -> str: return "Not implement" # Expose the index method through the web. CherryPy will never # publish methods that don't have the exposed attribute set to True. @cherrypy.expose - def index(self): + def index(self) -> str: return f""" This is: {self.name}
Get error
@@ -50,12 +51,12 @@ def index(self): """ @cherrypy.expose - def error(self): + def error(self) -> str: _ = 1 / 0 return "Bad!" - def all_exception_handler(self, status, message, traceback, version): + def all_exception_handler(self, status, message, traceback, version) -> str: response = cherrypy.response response.headers["Content-Type"] = "application/json" @@ -70,7 +71,7 @@ def all_exception_handler(self, status, message, traceback, version): } ) - def run(self, port=9090): + def run(self, port=9090) -> None: # Set port cherrypy.config.update({"server.socket_port": port}) diff --git a/webserver__cherrypy__examples/inheritance/child_server_1.py b/webserver__cherrypy__examples/inheritance/child_server_1.py index 3ea7d11e8..045d365cc 100644 --- a/webserver__cherrypy__examples/inheritance/child_server_1.py +++ b/webserver__cherrypy__examples/inheritance/child_server_1.py @@ -8,16 +8,16 @@ class ChildServer(BaseServer): - def __init__(self): + def __init__(self) -> None: super().__init__() self.name = "ChildServer_1" @BaseServer.expose - def execute(self): + def execute(self) -> str: return "ChildServer_1.execute!" - def _execute_func(self): + def _execute_func(self) -> str: return "ChildServer_1 _execute_func" @BaseServer.expose diff --git a/webserver__cherrypy__examples/inheritance/child_server_2.py b/webserver__cherrypy__examples/inheritance/child_server_2.py index 507135742..d56cc3187 100644 --- a/webserver__cherrypy__examples/inheritance/child_server_2.py +++ b/webserver__cherrypy__examples/inheritance/child_server_2.py @@ -8,20 +8,20 @@ class ChildServer(BaseServer): - def __init__(self): + def __init__(self) -> None: super().__init__() self.name = "ChildServer_2" @BaseServer.expose @BaseServer.json_out - def execute(self): + def execute(self) -> dict: return { "text": "ChildServer_2.execute!", } @BaseServer.expose - def error(self): + def error(self) -> None: _ = list()[0] diff --git a/webserver__cherrypy__examples/jquery__static_dir/main.py b/webserver__cherrypy__examples/jquery__static_dir/main.py index 9738d43b6..ef03235c0 100644 --- a/webserver__cherrypy__examples/jquery__static_dir/main.py +++ b/webserver__cherrypy__examples/jquery__static_dir/main.py @@ -10,7 +10,7 @@ class RootServer: @cherrypy.expose - def index(self): + def index(self) -> str: return """ diff --git a/webserver__cherrypy__examples/run_with_auto_port.py b/webserver__cherrypy__examples/run_with_auto_port.py index 9c3ebc21c..0a570ec9d 100644 --- a/webserver__cherrypy__examples/run_with_auto_port.py +++ b/webserver__cherrypy__examples/run_with_auto_port.py @@ -15,15 +15,15 @@ class RootServer: port = None url = None - def __init__(self): + def __init__(self) -> None: cherrypy.engine.subscribe("start", self.on_start) @cherrypy.expose - def index(self): + def index(self) -> str: return f"{self.host}:{self.port} / {self.url}" - def on_start(self): - def _wait_server_running(): + def on_start(self) -> None: + def _wait_server_running() -> None: # Wait running while not cherrypy.server.running: time.sleep(0.1) diff --git a/webserver__cherrypy__examples/sessions.py b/webserver__cherrypy__examples/sessions.py index dcbc2097b..e73860dd5 100644 --- a/webserver__cherrypy__examples/sessions.py +++ b/webserver__cherrypy__examples/sessions.py @@ -18,7 +18,7 @@ class HitCounter: _cp_config = {"tools.sessions.on": True} @cherrypy.expose - def index(self): + def index(self) -> str: # Increase the silly hit counter count = cherrypy.session.get("count", 0) + 1 diff --git a/webserver__cherrypy__examples/set log/hello_world.py b/webserver__cherrypy__examples/set log/hello_world.py index d350e4669..65f7c452a 100644 --- a/webserver__cherrypy__examples/set log/hello_world.py +++ b/webserver__cherrypy__examples/set log/hello_world.py @@ -16,7 +16,7 @@ class HelloWorld: # Expose the index method through the web. CherryPy will never # publish methods that don't have the exposed attribute set to True. @cherrypy.expose - def index(self): + def index(self) -> str: # CherryPy will call this method for the root URI ("/") and send # its return value to the client. Because this is tutorial # lesson number 01, we'll just send something really simple. @@ -24,7 +24,7 @@ def index(self): return 'Hello world!
Get error' @cherrypy.expose - def error(self): + def error(self) -> str: 1 / 0 return "Bad!" diff --git a/webserver__cherrypy__examples/subscribe_to__on_start.py b/webserver__cherrypy__examples/subscribe_to__on_start.py index bcb920333..87ddde235 100644 --- a/webserver__cherrypy__examples/subscribe_to__on_start.py +++ b/webserver__cherrypy__examples/subscribe_to__on_start.py @@ -8,25 +8,25 @@ class RootServer: - def __init__(self): + def __init__(self) -> None: self.running = False cherrypy.engine.subscribe("start", self.on_start) cherrypy.engine.subscribe("stop", self.on_stop) cherrypy.engine.subscribe("exit", self.on_exit) - def on_start(self): + def on_start(self) -> None: print("start") self.running = True # Exit! cherrypy.engine.exit() - def on_stop(self): + def on_stop(self) -> None: print("stop") self.running = False - def on_exit(self): + def on_exit(self) -> None: print("exit") diff --git a/websocket__examples/echo_client__using_websockets.py b/websocket__examples/echo_client__using_websockets.py index a8c11c8bb..8d6161f3a 100644 --- a/websocket__examples/echo_client__using_websockets.py +++ b/websocket__examples/echo_client__using_websockets.py @@ -13,7 +13,7 @@ import websockets -async def hello(url: str): +async def hello(url: str) -> None: async with websockets.connect(url) as websocket: await websocket.send("Hello World!") diff --git a/websocket__examples/using__websocket-client/echo_client__long_lived_connection.py b/websocket__examples/using__websocket-client/echo_client__long_lived_connection.py index caf480415..206b75ab3 100644 --- a/websocket__examples/using__websocket-client/echo_client__long_lived_connection.py +++ b/websocket__examples/using__websocket-client/echo_client__long_lived_connection.py @@ -18,10 +18,10 @@ import websocket -def on_open(ws: websocket.WebSocketApp): +def on_open(ws: websocket.WebSocketApp) -> None: print(f"[on_open]") - def run(*args): + def run(*args) -> None: for i in range(3): time.sleep(1) ws.send(f"Hello {i}") @@ -34,11 +34,11 @@ def run(*args): thread.start_new_thread(run, ()) -def on_message(ws: websocket.WebSocketApp, message: str): +def on_message(ws: websocket.WebSocketApp, message: str) -> None: print(f"[on_message] {message}") -def on_error(ws: websocket.WebSocketApp, error: Exception): +def on_error(ws: websocket.WebSocketApp, error: Exception) -> None: print(f"[on_error] {error}") @@ -46,7 +46,7 @@ def on_close( ws: websocket.WebSocketApp, close_status_code: int | None, close_msg: str | None, -): +) -> None: print(f"[on_close] close_status_code={close_status_code} close_msg={close_msg}") diff --git a/win_create_shortcut_lnk.py b/win_create_shortcut_lnk.py index d98190d2c..594aef543 100644 --- a/win_create_shortcut_lnk.py +++ b/win_create_shortcut_lnk.py @@ -8,7 +8,7 @@ from win32com.client import Dispatch -def create_shortcut(file_name: str, target: str, work_dir: str, arguments: str = ""): +def create_shortcut(file_name: str, target: str, work_dir: str, arguments: str = "") -> None: shell = Dispatch("WScript.Shell") shortcut = shell.CreateShortCut(file_name) shortcut.TargetPath = target diff --git a/winapi__windows__ctypes/close_ad_window_avast/close_ad_window_avast.py b/winapi__windows__ctypes/close_ad_window_avast/close_ad_window_avast.py index aa22f1c1f..6aa79e1f7 100644 --- a/winapi__windows__ctypes/close_ad_window_avast/close_ad_window_avast.py +++ b/winapi__windows__ctypes/close_ad_window_avast/close_ad_window_avast.py @@ -41,7 +41,7 @@ def get_logger(): # TODO: не все окна являются рекламными, это может быть окно сканирования системы -def close_ad(): +def close_ad() -> None: hwnd = win32gui.FindWindow("asw_av_popup_wndclass", None) if hwnd: log.debug("Found Avast advertising window, close it.") diff --git a/winapi__windows__ctypes/log_window_focus__trackwindow.py b/winapi__windows__ctypes/log_window_focus__trackwindow.py index adedcbdf0..58872c015 100644 --- a/winapi__windows__ctypes/log_window_focus__trackwindow.py +++ b/winapi__windows__ctypes/log_window_focus__trackwindow.py @@ -64,11 +64,11 @@ lastTime = 0 -def log(msg): +def log(msg) -> None: print(msg) -def logError(msg): +def logError(msg) -> None: print(msg, file=sys.stderr) @@ -129,7 +129,7 @@ def getProcessFilename(processID): kernel32.CloseHandle(hProcess) -def callback(hWinEventHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime): +def callback(hWinEventHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime) -> None: global lastTime length = user32.GetWindowTextLengthW(hwnd) title = ctypes.create_unicode_buffer(length + 1) @@ -169,7 +169,7 @@ def setHook(WinEventProc, eventType): ) -def main(): +def main() -> None: ole32.CoInitialize(0) WinEventProc = WinEventProcType(callback) diff --git a/winapi__windows__ctypes/set_wallpaper_on_win/set_wallpaper.py b/winapi__windows__ctypes/set_wallpaper_on_win/set_wallpaper.py index ac734ba83..f6230eed0 100644 --- a/winapi__windows__ctypes/set_wallpaper_on_win/set_wallpaper.py +++ b/winapi__windows__ctypes/set_wallpaper_on_win/set_wallpaper.py @@ -13,7 +13,7 @@ import win32gui -def set_wallpaper(file_name): +def set_wallpaper(file_name) -> None: key = win32api.RegOpenKeyEx( win32con.HKEY_CURRENT_USER, "Control Panel\\Desktop", 0, win32con.KEY_SET_VALUE ) diff --git a/winapi__windows__ctypes/set_wallpaper_on_win/set_wallpaper_with_ctypes.py b/winapi__windows__ctypes/set_wallpaper_on_win/set_wallpaper_with_ctypes.py index 6d66e9c79..569702d34 100644 --- a/winapi__windows__ctypes/set_wallpaper_on_win/set_wallpaper_with_ctypes.py +++ b/winapi__windows__ctypes/set_wallpaper_on_win/set_wallpaper_with_ctypes.py @@ -13,7 +13,7 @@ SPI_SETDESKWALLPAPER = 20 -def set_wallpaper_with_ctypes(file_name): +def set_wallpaper_with_ctypes(file_name) -> None: # This code is based on the following two links # http://mail.python.org/pipermail/python-win32/2005-January/002893.html # http://code.activestate.com/recipes/435877-change-the-wallpaper-under-windows/ diff --git a/winapi__windows__ctypes/winapi_SetThreadExecutionState__preventing system entering sleep or turning off display/gui.py b/winapi__windows__ctypes/winapi_SetThreadExecutionState__preventing system entering sleep or turning off display/gui.py index 74065caeb..88b062e5f 100644 --- a/winapi__windows__ctypes/winapi_SetThreadExecutionState__preventing system entering sleep or turning off display/gui.py +++ b/winapi__windows__ctypes/winapi_SetThreadExecutionState__preventing system entering sleep or turning off display/gui.py @@ -15,7 +15,7 @@ w.setWindowTitle("Preventing entering sleep or turning off the display") w.setLayout(qtw.QVBoxLayout()) - def button_clicked(checked): + def button_clicked(checked) -> None: if checked: button.setText("On") preventing_on() diff --git a/winapi__windows__ctypes/winapi_SetThreadExecutionState__preventing system entering sleep or turning off display/main.py b/winapi__windows__ctypes/winapi_SetThreadExecutionState__preventing system entering sleep or turning off display/main.py index 691e64c97..f50033a94 100644 --- a/winapi__windows__ctypes/winapi_SetThreadExecutionState__preventing system entering sleep or turning off display/main.py +++ b/winapi__windows__ctypes/winapi_SetThreadExecutionState__preventing system entering sleep or turning off display/main.py @@ -18,14 +18,14 @@ SetThreadExecutionState = ctypes.windll.kernel32.SetThreadExecutionState -def preventing_on(): +def preventing_on() -> None: # Television recording is beginning. Enable away mode and prevent the sleep idle time-out. SetThreadExecutionState( ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_AWAYMODE_REQUIRED | ES_DISPLAY_REQUIRED ) -def preventing_off(): +def preventing_off() -> None: # Clear EXECUTION_STATE flags to disable away mode and allow the system to idle to sleep normally. SetThreadExecutionState(ES_CONTINUOUS) diff --git a/winapi__windows__ctypes/winapi__GetTextLastError.py b/winapi__windows__ctypes/winapi__GetTextLastError.py index c6457ad8b..7323c7be6 100644 --- a/winapi__windows__ctypes/winapi__GetTextLastError.py +++ b/winapi__windows__ctypes/winapi__GetTextLastError.py @@ -13,7 +13,7 @@ ) -def GetTextLastError(error_code=None): +def GetTextLastError(error_code=None) -> str: """ Функция возвращает текстовое описание ошибки. Если не передавать код ошибки, будет возвращаться описание ошибки из GetLastError(). diff --git a/winapi__windows__ctypes/winapi__close_child_windows.py b/winapi__windows__ctypes/winapi__close_child_windows.py index 352cf4341..d22d938d9 100644 --- a/winapi__windows__ctypes/winapi__close_child_windows.py +++ b/winapi__windows__ctypes/winapi__close_child_windows.py @@ -15,7 +15,7 @@ import win32con -def all_ok(hwnd, param): +def all_ok(hwnd, param) -> bool: text = win32gui.GetWindowText(hwnd) class_name = win32gui.GetClassName(hwnd) print(f'#{hwnd:0>8x} "{text}": {class_name}') @@ -27,7 +27,7 @@ def all_ok(hwnd, param): return True -def close_toolbars(): +def close_toolbars() -> None: hwnd = win32gui.FindWindow("Notepad++", None) if not hwnd: print('Window "Notepad++" not found!') diff --git a/winapi__windows__ctypes/winapi__process_list.py b/winapi__windows__ctypes/winapi__process_list.py index b3b1971be..2594518de 100644 --- a/winapi__windows__ctypes/winapi__process_list.py +++ b/winapi__windows__ctypes/winapi__process_list.py @@ -32,7 +32,7 @@ class PROCESSENTRY32(ctypes.Structure): ("szExeFile", ctypes.c_char * 260), ] - def __str__(self): + def __str__(self) -> str: return ( "szExeFile={} " "th32ProcessID={} " diff --git a/winapi__windows__ctypes/windows__toast_balloontip_notifications/notifications.py b/winapi__windows__ctypes/windows__toast_balloontip_notifications/notifications.py index 2b67f2fd0..cf785ea67 100644 --- a/winapi__windows__ctypes/windows__toast_balloontip_notifications/notifications.py +++ b/winapi__windows__ctypes/windows__toast_balloontip_notifications/notifications.py @@ -21,7 +21,7 @@ class WindowsBalloonTip: @staticmethod - def balloon_tip(title, msg, duration=5, icon_path_name=None): + def balloon_tip(title, msg, duration=5, icon_path_name=None) -> None: message_map = { win32con.WM_DESTROY: WindowsBalloonTip.on_destroy, } @@ -90,7 +90,7 @@ def balloon_tip(title, msg, duration=5, icon_path_name=None): UnregisterClass(wc.lpszClassName, None) @staticmethod - def on_destroy(hwnd, msg, wparam, lparam): + def on_destroy(hwnd, msg, wparam, lparam) -> None: nid = (hwnd, 0) Shell_NotifyIcon(NIM_DELETE, nid) PostQuitMessage(0) # Terminate the app. diff --git a/winapi__windows__ctypes/windows__toast_balloontip_notifications/run_notify.py b/winapi__windows__ctypes/windows__toast_balloontip_notifications/run_notify.py index af762a7da..d078d1628 100644 --- a/winapi__windows__ctypes/windows__toast_balloontip_notifications/run_notify.py +++ b/winapi__windows__ctypes/windows__toast_balloontip_notifications/run_notify.py @@ -8,7 +8,7 @@ from notifications import WindowsBalloonTip -def run(title: str, text: str, duration: int = 20): +def run(title: str, text: str, duration: int = 20) -> None: WindowsBalloonTip.balloon_tip(title, text, duration) @@ -16,7 +16,7 @@ def run(title: str, text: str, duration: int = 20): # Process(target=run, args=(title, text, duration)).start() -def run_in_thread(title: str, text: str, duration: int = 20): +def run_in_thread(title: str, text: str, duration: int = 20) -> None: Thread(target=run, args=(title, text, duration)).start() diff --git a/winreg__examples/common.py b/winreg__examples/common.py index 031e61aed..353de325c 100644 --- a/winreg__examples/common.py +++ b/winreg__examples/common.py @@ -56,7 +56,7 @@ def get_key(path: str) -> Optional[HKEYType]: class RegistryValue: - def __init__(self, name: str, value_type: int, value: Any): + def __init__(self, name: str, value_type: int, value: Any) -> None: self.name: str = name self.value_type: int = value_type @@ -72,7 +72,7 @@ def __repr__(self) -> str: class RegistryKey: - def __init__(self, path: str): + def __init__(self, path: str) -> None: path = expand_path(path) self.hkey: HKEYType = get_key(path) diff --git a/winreg__examples/exceptions.py b/winreg__examples/exceptions.py index 9d8c0eeae..cd7643799 100644 --- a/winreg__examples/exceptions.py +++ b/winreg__examples/exceptions.py @@ -9,14 +9,14 @@ class RegistryException(Exception): class RegistryKeyNotFoundException(RegistryException): - def __init__(self, path: str): + def __init__(self, path: str) -> None: self.path = path super().__init__(f"Registry key not found, path='{self.path}'") class RegistryValueNotFoundException(RegistryException): - def __init__(self, path: str, name: str): + def __init__(self, path: str, name: str) -> None: self.path = path self.name = name diff --git a/winreg__examples/get_active_setup_installed_components.py b/winreg__examples/get_active_setup_installed_components.py index ddd0cc2bb..442ee1b80 100644 --- a/winreg__examples/get_active_setup_installed_components.py +++ b/winreg__examples/get_active_setup_installed_components.py @@ -73,7 +73,7 @@ def get_active_setup_components(exists_stub_path=True) -> dict[str, list[Compone if __name__ == "__main__": - def _print_this(path_by_components: dict[str, list[Component]]): + def _print_this(path_by_components: dict[str, list[Component]]) -> None: for path, components in path_by_components.items(): print(f"{path} ({len(components)}):") for component in components: diff --git a/word_to_emoji/db.py b/word_to_emoji/db.py index d00d13779..0b07edcf9 100644 --- a/word_to_emoji/db.py +++ b/word_to_emoji/db.py @@ -54,7 +54,7 @@ class BaseModel(Model): class Meta: database = db - def __str__(self): + def __str__(self) -> str: fields = [] for k, field in self._meta.fields.items(): v = getattr(self, k) @@ -78,7 +78,7 @@ class Word2Emoji(BaseModel): emoji = TextField(null=True) @classmethod - def add(cls, word: str, emoji: str = None, convert_to_normal_form=True): + def add(cls, word: str, emoji: str = None, convert_to_normal_form=True) -> None: word = word.strip() if convert_to_normal_form: word = get_normal_form(word) diff --git a/world_seed_in_binary_2D.py b/world_seed_in_binary_2D.py index 892a767c5..b7a2a5239 100644 --- a/world_seed_in_binary_2D.py +++ b/world_seed_in_binary_2D.py @@ -24,11 +24,11 @@ def create_world(rows: int, cols: int) -> list[list[int]]: return [[0] * cols for _ in range(rows)] -def print_world(world: list[list[int]]): +def print_world(world: list[list[int]]) -> None: print("\n".join(" ".join(map(str, row)) for row in world)) -def fill_world(world: list[list[int]], seed: str): +def fill_world(world: list[list[int]], seed: str) -> None: bits = get_bits_seed(seed) bits = cycle(bits) diff --git a/x == 1 and x == 2 and x == 3.py b/x == 1 and x == 2 and x == 3.py index 38738e45b..a67655a4d 100644 --- a/x == 1 and x == 2 and x == 3.py +++ b/x == 1 and x == 2 and x == 3.py @@ -5,7 +5,7 @@ class X: - def __eq__(self, other): + def __eq__(self, other) -> bool: return True diff --git a/xml_html__xpath__css_selector__gui/main.py b/xml_html__xpath__css_selector__gui/main.py index 9c156dfce..b75782410 100644 --- a/xml_html__xpath__css_selector__gui/main.py +++ b/xml_html__xpath__css_selector__gui/main.py @@ -37,7 +37,7 @@ def to_str(el: "Element") -> str: return str(el) -def log_uncaught_exceptions(ex_cls, ex, tb): +def log_uncaught_exceptions(ex_cls, ex, tb) -> None: text = f"{ex_cls.__name__}: {ex}:\n" text += "".join(traceback.format_tb(tb)) @@ -50,7 +50,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb): class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.setWindowTitle("xml_html__xpath__css_selector__gui") @@ -123,7 +123,7 @@ def __init__(self): self.setLayout(layout) - def on_process(self): + def on_process(self) -> None: self.text_edit_output.clear() self.label_error.clear() self.button_detail_error.hide() @@ -170,7 +170,7 @@ def on_process(self): self.label_error.setText("Error: " + self.last_error_message) - def show_detail_error_message(self): + def show_detail_error_message(self) -> None: message = self.last_error_message + "\n\n" + self.last_detail_error_message mb = QErrorMessage() diff --git a/ya_test_task.py b/ya_test_task.py index bfbe02b04..1466174be 100644 --- a/ya_test_task.py +++ b/ya_test_task.py @@ -47,7 +47,7 @@ def get_stop_route(stop_id): class MainWindow(QWidget): - def __init__(self): + def __init__(self) -> None: super().__init__() self.stop_list_widget = QListWidget() @@ -69,7 +69,7 @@ def __init__(self): self.setLayout(main_layout) - def fill_list_stops(self): + def fill_list_stops(self) -> None: self.route_list_widget.clear() self.stop_list_widget.clear() @@ -82,7 +82,7 @@ def fill_list_stops(self): self.stop_list_widget.addItem(item) - def item_stop_click(self, item): + def item_stop_click(self, item) -> None: stop_id = item.data(Qt.UserRole) self.route_list_widget.clear() diff --git a/zip_file_example/append_directory/main.py b/zip_file_example/append_directory/main.py index 7f57f6777..0d08fda08 100644 --- a/zip_file_example/append_directory/main.py +++ b/zip_file_example/append_directory/main.py @@ -8,7 +8,7 @@ import zipfile -def make_zipfile(source_dir, output_filename): +def make_zipfile(source_dir, output_filename) -> None: relroot = os.path.abspath(os.path.join(source_dir, os.pardir)) with zipfile.ZipFile(output_filename, "w", zipfile.ZIP_DEFLATED) as zip: for root, dirs, files in os.walk(source_dir): diff --git a/zip_file_example/download_volume_readmanga.py b/zip_file_example/download_volume_readmanga.py index 8702ce5f2..8aedeff5d 100644 --- a/zip_file_example/download_volume_readmanga.py +++ b/zip_file_example/download_volume_readmanga.py @@ -40,7 +40,7 @@ def get_url_images(url): ) -def save_urls_to_zip(zip_file_name, urls): +def save_urls_to_zip(zip_file_name, urls) -> None: if not urls: print("Cписок изображений пустой.") return diff --git a/zip_file_example/remove_unnecessary_files_from_xpi_zip_file/remove_all_but_included_files_from_xpi_zip_file.py b/zip_file_example/remove_unnecessary_files_from_xpi_zip_file/remove_all_but_included_files_from_xpi_zip_file.py index adda5bf14..7794f864f 100644 --- a/zip_file_example/remove_unnecessary_files_from_xpi_zip_file/remove_all_but_included_files_from_xpi_zip_file.py +++ b/zip_file_example/remove_unnecessary_files_from_xpi_zip_file/remove_all_but_included_files_from_xpi_zip_file.py @@ -32,7 +32,7 @@ def create_parser(): return parser.parse_args() -def do(zip_file_name, include): +def do(zip_file_name, include) -> None: print("zip_file_name:", zip_file_name) print("Include files:", include) diff --git a/zip_file_example/remove_unnecessary_files_from_xpi_zip_file/remove_exclude_files_from_xpi_zip_file.py b/zip_file_example/remove_unnecessary_files_from_xpi_zip_file/remove_exclude_files_from_xpi_zip_file.py index b46bd4b93..6249333d6 100644 --- a/zip_file_example/remove_unnecessary_files_from_xpi_zip_file/remove_exclude_files_from_xpi_zip_file.py +++ b/zip_file_example/remove_unnecessary_files_from_xpi_zip_file/remove_exclude_files_from_xpi_zip_file.py @@ -31,7 +31,7 @@ def create_parser(): return parser.parse_args() -def do(zip_file_name, exclude): +def do(zip_file_name, exclude) -> None: print("zip_file_name:", zip_file_name) print("Delete files:", EXCLUDE)