Skip to content

Commit 242453c

Browse files
committed
2026-06-27T0823Z
1 parent 12dc3fe commit 242453c

21 files changed

Lines changed: 2582 additions & 40 deletions

File tree

Source/pretasks/download.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import ssl
88

99
# Third-party imports
10-
import tqdm_vendored as tqdm
10+
from vendored import tqdm
1111
import py7zr
1212

1313
# Local application/library specific imports

Source/requirements.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,5 @@ urllib3>=2.7.0
33
pyzstd~=0.19.1
44
py7zr~=1.1.0
55
lz4~=4.4.5
6-
tqdm_vendored @ git+https://github.com/Windows81/Vendored-Tqdm
7-
sqlite-worker @ git+https://github.com/Windows81/SQLite-Worker
86
pywin32 ; sys_platform == 'win32'
97
dracopy~=2.0.0

Source/storage/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import sqlite_worker
1+
from vendored import sqlite_worker
22
import os.path
33

44
from . import (

Source/storage/_logic.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from typing import ClassVar
2-
import sqlite_worker
2+
from vendored import sqlite_worker
33

44

55
class sqlite_connector_base:
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import logging
2+
import sqlite3
3+
import threading
4+
import uuid
5+
import queue
6+
7+
LOGGER = logging.getLogger("SqliteWorker")
8+
SILENT_TOKEN_SUFFIX = '-silent'
9+
10+
11+
class SqliteWorker:
12+
"""Sqlite thread-safe object."""
13+
14+
def __init__(self, file_name, max_queue_size=100, execute_init=(), max_count=50):
15+
self._file_name = file_name
16+
self._sql_queue = queue.Queue(maxsize=max_queue_size)
17+
self._results = {}
18+
self._tokens = set()
19+
self._select_events = {}
20+
self._lock = threading.Lock()
21+
self._close_event = threading.Event()
22+
self._thread = threading.Thread(target=self._run, daemon=True)
23+
self._thread.start()
24+
self.execute_init = execute_init
25+
self.max_count = max_count
26+
27+
def _run(self):
28+
try:
29+
self._process_queries()
30+
except Exception as err:
31+
LOGGER.critical(
32+
"Unhandled exception in query processor: %s", err, exc_info=True)
33+
raise
34+
35+
def _process_queries(self):
36+
with sqlite3.connect(self._file_name, check_same_thread=False, detect_types=sqlite3.PARSE_DECLTYPES) as conn:
37+
cursor = conn.cursor()
38+
for action in self.execute_init:
39+
cursor.execute(action)
40+
conn.commit()
41+
42+
count = 0
43+
while not self._close_event.is_set() or not self._sql_queue.empty():
44+
try:
45+
token, query, values = self._sql_queue.get(timeout=1)
46+
except queue.Empty:
47+
continue
48+
if query:
49+
count += 1
50+
self._execute_query(cursor, token, query, values)
51+
52+
if count >= self.max_count or self._sql_queue.empty():
53+
count = 0
54+
conn.commit()
55+
56+
def _execute_query(self, cursor, token: str, query, values):
57+
try:
58+
cursor.execute(query, values)
59+
if not token.endswith(SILENT_TOKEN_SUFFIX):
60+
with self._lock:
61+
self._results[token] = cursor.fetchall()
62+
except sqlite3.Error as err:
63+
LOGGER.error("Query error: %s: %s: %s", query, values, err)
64+
self._handle_query_error(token, err)
65+
self._notify_query_done(token)
66+
67+
def _is_select_query(self, query):
68+
return query.lower().lstrip().startswith("select")
69+
70+
def _notify_query_begin(self, token):
71+
self._select_events.setdefault(token, threading.Event())
72+
73+
def _notify_query_done(self, token):
74+
self._select_events[token].set()
75+
76+
def _handle_query_error(self, token, err):
77+
with self._lock:
78+
self._results[token] = err
79+
80+
def close(self):
81+
self._close_event.set()
82+
self._sql_queue.put((None, None, None), timeout=5)
83+
self._thread.join()
84+
85+
def execute(self, query, values=None, always_return_token=False):
86+
if self._close_event.is_set():
87+
raise RuntimeError("Worker is closed")
88+
89+
should_return_token = (
90+
always_return_token or
91+
self._is_select_query(query)
92+
)
93+
94+
token = uuid.uuid4().hex
95+
if should_return_token is None:
96+
token += SILENT_TOKEN_SUFFIX
97+
98+
self._sql_queue.put((token, query, values or []), timeout=5)
99+
self._notify_query_begin(token)
100+
101+
if should_return_token:
102+
return token
103+
return None
104+
105+
def execute_and_fetch(self, query, values=None, always_synchronous=True):
106+
return self.fetch_results(self.execute(query, values, always_return_token=always_synchronous))
107+
108+
def fetch_results(self, token):
109+
if token is None:
110+
return
111+
with self._lock:
112+
event = self._select_events.get(token)
113+
if event is None:
114+
return
115+
event.wait()
116+
with self._lock:
117+
return self._results.pop(token, None)
118+
119+
@property
120+
def queue_size(self):
121+
return self._sql_queue.qsize()

Source/vendored/tqdm/__init__.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from ._monitor import TMonitor, TqdmSynchronisationWarning
2+
from .cli import main # TODO: remove in v5.0.0
3+
from .std import (
4+
TqdmDeprecationWarning, TqdmExperimentalWarning, TqdmKeyError, TqdmMonitorWarning,
5+
TqdmTypeError, TqdmWarning, tqdm, trange)
6+
from .version import __version__
7+
8+
__all__ = ['tqdm', 'trange', 'main', 'TMonitor',
9+
'TqdmTypeError', 'TqdmKeyError',
10+
'TqdmWarning', 'TqdmDeprecationWarning',
11+
'TqdmExperimentalWarning',
12+
'TqdmMonitorWarning', 'TqdmSynchronisationWarning',
13+
'__version__']

Source/vendored/tqdm/__main__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from .cli import main
2+
3+
main()

Source/vendored/tqdm/_main.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from warnings import warn
2+
3+
from .cli import * # NOQA
4+
from .cli import __all__ # NOQA
5+
from .std import TqdmDeprecationWarning
6+
7+
warn("This function will be removed in tqdm==5.0.0\n"
8+
"Please use `tqdm.cli.*` instead of `tqdm._main.*`",
9+
TqdmDeprecationWarning, stacklevel=2)

Source/vendored/tqdm/_monitor.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import atexit
2+
from threading import Event, Thread, current_thread
3+
from time import time
4+
from warnings import warn
5+
6+
__all__ = ["TMonitor", "TqdmSynchronisationWarning"]
7+
8+
9+
class TqdmSynchronisationWarning(RuntimeWarning):
10+
"""tqdm multi-thread/-process errors which may cause incorrect nesting
11+
but otherwise no adverse effects"""
12+
pass
13+
14+
15+
class TMonitor(Thread):
16+
"""
17+
Monitoring thread for tqdm bars.
18+
Monitors if tqdm bars are taking too much time to display
19+
and readjusts miniters automatically if necessary.
20+
21+
Parameters
22+
----------
23+
tqdm_cls : class
24+
tqdm class to use (can be core tqdm or a submodule).
25+
sleep_interval : fload
26+
Time to sleep between monitoring checks.
27+
"""
28+
_test = {} # internal vars for unit testing
29+
30+
def __init__(self, tqdm_cls, sleep_interval):
31+
Thread.__init__(self)
32+
self.daemon = True # kill thread when main killed (KeyboardInterrupt)
33+
self.woken = 0 # last time woken up, to sync with monitor
34+
self.tqdm_cls = tqdm_cls
35+
self.sleep_interval = sleep_interval
36+
self._time = self._test.get("time", time)
37+
self.was_killed = self._test.get("Event", Event)()
38+
atexit.register(self.exit)
39+
self.start()
40+
41+
def exit(self):
42+
self.was_killed.set()
43+
if self is not current_thread():
44+
self.join()
45+
return self.report()
46+
47+
def get_instances(self):
48+
# returns a copy of started `tqdm_cls` instances
49+
return [i for i in self.tqdm_cls._instances.copy()
50+
# Avoid race by checking that the instance started
51+
if hasattr(i, 'start_t')]
52+
53+
def run(self):
54+
cur_t = self._time()
55+
while True:
56+
# After processing and before sleeping, notify that we woke
57+
# Need to be done just before sleeping
58+
self.woken = cur_t
59+
# Sleep some time...
60+
self.was_killed.wait(self.sleep_interval)
61+
# Quit if killed
62+
if self.was_killed.is_set():
63+
return
64+
# Then monitor!
65+
# Acquire lock (to access _instances)
66+
with self.tqdm_cls.get_lock():
67+
cur_t = self._time()
68+
# Check tqdm instances are waiting too long to print
69+
instances = self.get_instances()
70+
for instance in instances:
71+
# Check event in loop to reduce blocking time on exit
72+
if self.was_killed.is_set():
73+
return
74+
# Only if mininterval > 1 (else iterations are just slow)
75+
# and last refresh exceeded maxinterval
76+
if instance.miniters > 1 and \
77+
(cur_t - instance.last_print_t) >= \
78+
instance.maxinterval:
79+
# force bypassing miniters on next iteration
80+
# (dynamic_miniters adjusts mininterval automatically)
81+
instance.miniters = 1
82+
# Refresh now! (works only for manual tqdm)
83+
instance.refresh(nolock=True)
84+
# Remove accidental long-lived strong reference
85+
del instance
86+
if instances != self.get_instances(): # pragma: nocover
87+
warn("Set changed size during iteration" +
88+
" (see https://github.com/tqdm/tqdm/issues/481)",
89+
TqdmSynchronisationWarning, stacklevel=2)
90+
# Remove accidental long-lived strong references
91+
del instances
92+
93+
def report(self):
94+
return not self.was_killed.is_set()

Source/vendored/tqdm/_tqdm.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from warnings import warn
2+
3+
from .std import * # NOQA
4+
from .std import __all__ # NOQA
5+
from .std import TqdmDeprecationWarning
6+
7+
warn("This function will be removed in tqdm==5.0.0\n"
8+
"Please use `tqdm.std.*` instead of `tqdm._tqdm.*`",
9+
TqdmDeprecationWarning, stacklevel=2)

0 commit comments

Comments
 (0)