123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- import os
- from threading import Thread
- from typing import Tuple
- from bottle import (
- route, request, response,
- static_file,
- FormsDict,
- )
- from psycopg import Cursor, connect
- from psycopg.rows import TupleRow
- from urllib.parse import parse_qs
- from .QueryCache import QueryCache
- from .route_decorators import cache, cursor
- from .query_to_xml import get_categories, get_groups, get_products, get_tags
- from .CachedLoadingPage import CachedLoadingPage
- from .PageCache import PageCache
- from . import trend as worker
- host = f"host={os.getenv('HOST')}"
- db = f"dbname={os.getenv('DB', 'grocery')}"
- user = f"user={os.getenv('USER', 'das')}"
- password = f"password={os.getenv('PASSWORD','')}"
- if not password.split('=',1)[1]:
- password = ''
- conn = connect(f"{host} {db} {user} {password}")
- @route('/grocery/static/<filename:path>')
- def send_static(filename):
- return static_file(filename, root='app/rest/static')
- def trend_thread(conn, path, forms):
- def cb(queue):
- return Thread(target=worker.trend, args=(
- queue, conn, path, forms
- )).start()
- return cb
- PAGE_CACHE = PageCache(100)
- QUERY_CACHE = QueryCache(None)
- @route('/grocery/trend', method=['GET', 'POST'])
- @cache(query_cache=QUERY_CACHE, page_cache=PAGE_CACHE)
- def trend(key: Tuple[str, int], cache: PageCache):
- _, _, path, *_ = request.urlparts
- page = cache[key]
- if page is None:
- form = key_to_form(key)
- page = cache.add(key, CachedLoadingPage([], trend_thread(conn, path, form)))
-
- for i in iter_page(page):
- yield i
- def query_to_form(query):
- form = FormsDict()
- for k, v in parse_qs(query).items():
- for item in v:
- form.append(k, item)
- return form
- def key_to_form(key):
- query, _ = key
- return query_to_form(query)
- def iter_page(page):
-
- resp = list(page.value)
- pos = len(resp)
- yield ''.join(resp)
-
- while not page.loaded:
- page.update()
-
- resp = list(page.value[pos:])
- pos = pos + len(resp)
- yield ''.join(resp)
-
-
- if pos < len(page.value):
- yield ''.join(page.value[pos:])
- @route('/grocery/groups', method=['GET', 'POST'])
- @cache(query_cache=QUERY_CACHE, page_cache=PAGE_CACHE)
- @cursor(connection=conn)
- def groups(cur: Cursor[TupleRow], key: Tuple[str, int], cache: PageCache):
- form = key_to_form(key)
- response.content_type = 'application/xhtml+xml; charset=utf-8'
- return get_groups(cur, form)
- @route('/grocery/categories', method=['GET', 'POST'])
- @cache(query_cache=QUERY_CACHE, page_cache=PAGE_CACHE)
- @cursor(connection=conn)
- def categories(cur: Cursor[TupleRow], key: Tuple[str, int], cache: PageCache):
- form = key_to_form(key)
- response.content_type = 'application/xhtml+xml; charset=utf-8'
- return get_categories(cur, form)
- @route('/grocery/products', method=['GET', 'POST'])
- @cache(query_cache=QUERY_CACHE, page_cache=PAGE_CACHE)
- @cursor(connection=conn)
- def products(cur: Cursor[TupleRow], key: Tuple[str, int], cache: PageCache):
- form = key_to_form(key)
- response.content_type = 'application/xhtml+xml; charset=utf-8'
- return get_products(cur, form)
- @route('/grocery/tags', method=['GET', 'POST'])
- @cache(query_cache=QUERY_CACHE, page_cache=PAGE_CACHE)
- @cursor(connection=conn)
- def tags(cur: Cursor[TupleRow], key: Tuple[str, int], cache: PageCache):
- form = key_to_form(key)
- response.content_type = 'application/xhtml+xml; charset=utf-8'
- return get_tags(cur, form)
|