Compare commits

...
8 Commits
Author SHA1 Message Date
C 86d6e5a61d mk test in test because test 2025-10-11 13:57:02 -07:00
C 5d580d68f6 modulize it >:( stupid wsl 2025-10-11 13:56:53 -07:00
C 2308d183e9 misc fixes 2025-10-11 13:56:34 -07:00
C 67891e5222 fix up db fetch and insert 2025-10-11 13:56:13 -07:00
C 04cfd42b4b remove previous stuff from asquare and put it in glue 2025-10-11 13:56:01 -07:00
C d612003f32 make middleware module (glue) 2025-10-11 13:55:39 -07:00
C 8ded841d44 global throttler implementation 2025-10-11 13:55:15 -07:00
C 76fa9a8db1 ignore venv 2025-10-11 13:54:10 -07:00
9 changed files with 95 additions and 38 deletions

No files matched your search

+3
View File
@@ -24,3 +24,6 @@ doc/pw-inventory/square_inventory_export_2025-06-18-0137.xlsx
square-src.code-workspace
doc/pw-inventory/
edderkop.db-journal
.venv
View File
Whitespace-only changes.
+2 -1
View File
@@ -53,7 +53,7 @@ class AsyncBricksetAPI:
self.logger.info("Successfully authenticated with Brickset API")
return result
async def get_set(self, set_number: str) -> Dict[str, Any]:
async def get_set(self, set_number: int) -> Dict[str, Any]:
"""
Fetch LEGO set information asynchronously
@@ -72,6 +72,7 @@ class AsyncBricksetAPI:
"userHash": self.user_hash,
"params": json.dumps({"setNumber": f"{set_number}-1"}),
}
print(f"[@DEBUG] {params}...")
async with aiohttp.ClientSession() as session:
async with session.get(
-23
View File
@@ -120,28 +120,6 @@ async def acat2id(cat_id: str):
return items
async def do_review() -> bool:
result = await acat2id(LEGO_CAT_ID)
for item in result:
if not re.match(r".*\d{5}.*", item["name"]):
missing = []
print(f"{item} is missing its set number!")
print(f"[@DEBUG] Upserting {item['id']} into REVIEW table")
item_sanitized = {
"sq_object": item["id"],
"set_name": item["name"],
"set_number": None,
"time_added": time
}
missing.append(item_sanitized)
for item in missing:
sq_item = await db.fetch(item["id"]) #
if item["id"] != sq_item["sq_object"]:
await db.upsert("REVIEW", item_sanitized, "sq_object")
print(f"[@DEBUG] Upserted {item['id']} into REVIEW table")
print(f"[@DEBUG] {item['id']} already in REVIEW table")
return True
async def test() -> None:
task = asyncio.create_task(acat2id(LEGO_CAT_ID)) # type: ignore
@@ -162,7 +140,6 @@ async def test() -> None:
if __name__ == "__main__":
print("Spooling up..")
print(f"@[DEBUG] ENV:\t{ENVIRONMENT}")
print(f"@[DEBUG] CATID:\t{LEGO_CAT_ID}")
asyncio.run(test())
+11 -11
View File
@@ -3,7 +3,11 @@ from time import time
time = int(time()) # we dont need no stinkin floats
# db = await aiosqlite.connect("edderkop.db") # type: ignore
async def fetch(sqobj):
async def close(db):
await db.close()
async def fetch(table, sqobj):
"""
Asynchronously fetch a record from the REVIEW table by sq_object.
@@ -13,21 +17,17 @@ async def fetch(sqobj):
dict or None: The fetched record as a dictionary, or None if not found.
"""
async with aiosqlite.connect("edderkop.db") as db: # type: ignore
db.row_factory = aiosqlite.Row # type: ignore
async with db.execute(
"SELECT * FROM REVIEW WHERE sq_object = ?", (sqobj,)
) as cursor:
row = await cursor.fetchone()
if row:
return dict(row)
async with db.execute(f"SELECT * FROM {table} WHERE sq_object = {sqobj}") as cursor:
async for row in cursor:
return row
return None
async def upsert(table: str, data: dict, unique_key: str) -> None:
async def upsert(table: str, data: dict, unique_key: str) -> bool:
"""
Asynchronously insert or update a record in the specified table.
Args:
sq_ib (aiosqlite.Connection): The SQLite database connection.
table (str): The name of the table to upsert into.
data (dict): A dictionary of column-value pairs to insert or update.
unique_key (str): The column name that serves as the unique key for upsert.
@@ -50,4 +50,4 @@ async def upsert(table: str, data: dict, unique_key: str) -> None:
async with aiosqlite.connect("edderkop.db") as db: # type: ignore
async with db.execute(sql, tuple(data.values())) as cursor:
await db.commit()
#await db.close()
return True
+32
View File
@@ -0,0 +1,32 @@
import asyncio
import json
import get_sq_env
import aiosqlite
import asquare
import db
import abricksetapi
from . throttler import GlobalThrottler
async def do_review() -> bool:
result = await asquare.acat2id(LEGO_CAT_ID)
for item in result:
if not re.match(r".*\d{5}.*", item["name"]):
missing = []
print(f"{item} is missing its set number!")
print(f"[@DEBUG] Upserting {item['id']} into REVIEW table")
item_sanitized = {
"sq_object": item["id"],
"set_name": item["name"],
"set_number": None,
"time_added": time
}
missing.append(item_sanitized)
for item in missing:
sq_item = await db.fetch(item["id"]) #
if item["id"] != sq_item["sq_object"]:
await db.upsert("REVIEW", item_sanitized, "sq_object")
print(f"[@DEBUG] Upserted {item['id']} into REVIEW table")
print(f"[@DEBUG] {item['id']} already in REVIEW table")
return True
+14 -3
View File
@@ -11,8 +11,8 @@ import re
import logging
from logging.handlers import RotatingFileHandler
from pathlib import Path
print("Creating log directory if it doesn't exist...")
Path("./logs/").mkdir(parents=True, exist_ok=True)
#print("Creating log directory if it doesn't exist...")
#Path("./logs/").mkdir(parents=True, exist_ok=True)
import banner
import get_sq_env
@@ -47,7 +47,18 @@ UA = re.compile(r"^kopling\/?", re.IGNORECASE)
async def run_update():
set_list = await sq.acat2id(SQUARE_LEGO_CAT_ID)
print(f"[@DEBUG]\t {set_list}") # type: ignore
#print(f"[@DEBUG]\t {set_list}") # type: ignore
for l_set in set_list:
#print(f"[@DEBUG]{l_set}")
try:
l_setinfo = await lego.throttled_get_set(l_set["number"])
print(f"[@DEBUG] Found {l_setinfo["pw_name"]}")
except Exception as e:
print(f"Error fetching set\t: {l_set}: {str(e)}")
continue
#print(f"[@DEBUG]{l_setinfo}")
#await sq.update_itm(l_set, l_setinfo)
"""for l_set in set_list:
print(f"[@DEBUG]{l_set}")
try:
+33
View File
@@ -0,0 +1,33 @@
import asyncio
from asyncio_throttle import Throttler as AsyncThrottler
class GlobalThrottler:
_instance = None
_lock = asyncio.Lock()
def __init__(self, rate_limit: int = 500, period: int = 60) -> None:
if not hasattr(self, '_initialized'):
self.rate_limit = rate_limit
self.period = period
self.throttler = AsyncThrottler(rate_limit=self.rate_limit, period=self.period)
self._initialized = True
@classmethod
async def get_instance(cls, rate_limit: int = 500, period: int = 60) -> 'GlobalThrottler':
async with cls._lock:
if not cls._instance:
cls._instance = cls(rate_limit, period)
return cls._instance
async def acquire(self):
await self.throttler.acquire()
def release(self):
self.throttler.release()
async def __aenter__(self):
await self.acquire()
return self
async def __aexit__(self, exc_type, exc_val, exc_tb):
self.release()
View File
File renamed without changes.