Browse Source

fix sqlite support

master
dave 1 year ago
parent
commit
06dea40d24
8 changed files with 52 additions and 25 deletions
  1. +1
    -0
      .dockerignore
  2. +1
    -2
      Dockerfile
  3. +5
    -3
      photoapp/api.py
  4. +5
    -1
      photoapp/cli.py
  5. +11
    -8
      photoapp/daemon.py
  6. +21
    -0
      photoapp/dbutils.py
  7. +1
    -3
      photoapp/image.py
  8. +7
    -8
      templates/dates.html

+ 1
- 0
.dockerignore View File

@@ -14,3 +14,4 @@ source/
source_copy/
raws/
*.sql
vidtest/

+ 1
- 2
Dockerfile View File

@@ -22,8 +22,7 @@ RUN apt-get update && \

COPY --from=frontend /tmp/code/styles/dist/style.css /tmp/code/styles/dist/style.css

RUN pip3 install -U pip && \
cd /tmp/code && \
RUN cd /tmp/code && \
pip3 install -r requirements.txt && \
python3 setup.py install && \
useradd --uid 1000 app && \


+ 5
- 3
photoapp/api.py View File

@@ -40,7 +40,8 @@ class PhotosApiV1(object):
"""
upload accepts one photoset (multiple images)
"""
# load and verify metadata
# TODO stage files in tmp storage since this can DEFINITELY lead to data loss
# TODO refactor function
stored_files = []

def abort_upload(reason):
@@ -72,9 +73,10 @@ class PhotosApiV1(object):
ext = get_extension(file.filename)
assert ext in known_extensions
photo_path = generate_storage_path(photo_date, photo_meta['hash'][0:8], ext)
# shouldn't we just trust the database?
if self.library.storage.exists(photo_path):
return abort_upload(f"file already in library: {photo_path}")
pass
# we trust that the database has enforced uniqueness of this image
# return abort_upload(f"file already in library: {photo_path}")

# write file to the path (and copy sha while in flight)
with closing(self.library.storage.open(photo_path, 'wb')) as f:


+ 5
- 1
photoapp/cli.py View File

@@ -4,7 +4,7 @@ import argparse
import requests
from requests.exceptions import HTTPError
from photoapp.utils import get_extension
from photoapp.types import known_extensions, PhotoStatus, Tag
from photoapp.types import known_extensions, PhotoStatus
from photoapp.common import pwhash
from photoapp.ingest import get_photosets
from urllib.parse import urlparse
@@ -233,6 +233,10 @@ def main():
raise

elif args.action == "ingest":
if args.copy_of and args.tag:
raise NotImplementedError("--copy-of not allowed with --tag")

# TODO refactor this to be less ugly
tag = None
if args.tag:
tag = args.tag.lower()


+ 11
- 8
photoapp/daemon.py View File

@@ -9,7 +9,7 @@ from photoapp.types import Photo, PhotoSet, Tag, TagItem, PhotoStatus, User
from photoapp.dbsession import DatabaseSession
from photoapp.common import pwhash
from photoapp.api import PhotosApi, LibraryManager
from photoapp.dbutils import SAEnginePlugin, SATool, db, get_db_engine
from photoapp.dbutils import SAEnginePlugin, SATool, db, get_db_engine, driver_statement
from photoapp.utils import mime2ext, auth, require_auth, photoset_auth_filter, slugify
from photoapp.storage import uri_to_storage
from jinja2 import Environment, FileSystemLoader, select_autoescape
@@ -218,13 +218,16 @@ class DateView(object):
yield self.master.render("date.html", page=page, pgsize=pgsize, total_sets=total_sets,
images=[i for i in images], date=dt)
return
images = photoset_auth_filter(db.query(PhotoSet, func.strftime('%Y-%m-%d',
PhotoSet.date).label('gdate'),
func.count('photos.id'),
func.strftime('%Y', PhotoSet.date).label('year'),
func.strftime('%m', PhotoSet.date).label('month'),
func.strftime('%d', PhotoSet.date).label('day'))). \
group_by('gdate').order_by(desc('year'), 'month', 'day').all()

date_format = driver_statement({"sqlite": lambda date_format, value: func.strftime(date_format, value),
"mysql": lambda date_format, value: func.date_format(value, date_format)})

images = photoset_auth_filter(db.query(
func.count(PhotoSet.id),
date_format('%Y', PhotoSet.date).label('year'),
date_format('%m', PhotoSet.date).label('month'),
date_format('%d', PhotoSet.date).label('day'))). \
group_by('year', 'month', 'day').order_by(desc('year'), 'month', 'day').all()
yield self.master.render("dates.html", images=images)




+ 21
- 0
photoapp/dbutils.py View File

@@ -35,6 +35,27 @@ def get_db_session(uri):
return session


def driver_statement(statements):
"""
Select a value from the passed dict based on the sql driver in use. Must be used in request context. For example:
Sqlite and mysql use different date functions. This function can be used to build queries supporting either:

date_format = driver_statement({"sqlite": lambda date_format, value: func.strftime(date_format, value),
"mysql": lambda date_format, value: func.date_format(value, date_format)})

rows = db.query(PhotoSet.id, date_format('%Y-%m=%d', PhotoSet.date).label('year')).all()

:param statements: dict of driver_type->value. since sqlalchemy drivers vary per language (e.g. pymysql, pysqlite),
it is checked if the driver_type is a substring of sqlalchemy's driver name.
:type statements: dict
"""
driver = cherrypy.request.db.connection().engine.driver
for key, lambda_ in statements.items():
if key in driver:
return lambda_
raise Exception(f"Statement not supported for driver {driver}")


class DbAlias(object):
"""
This provides a shorter alias for the cherrypy.request.db object, which is a database session created bound to the


+ 1
- 3
photoapp/image.py View File

@@ -14,9 +14,7 @@ def get_jpg_info(fpath):
date, gps, dimensions, orientation = get_exif_data(fpath)

if date is None:
import pdb
pdb.set_trace()
raise Exception("fuk")
raise Exception("No date found, panicing for unknown reasons!")

# gps is set to 0,0 if unavailable
lat, lon = gps or [None, None]


+ 7
- 8
templates/dates.html View File

@@ -13,16 +13,15 @@
<div class="date-feed">
{% set locals.year = "" %}
{% set locals.month = "" %}
{% for item, date, count, _, _, _ in images %}
{% if item.date.year != locals.year %}
{% set locals.year = item.date.year %}
<div class="feed-divider year"><h4>{{ item.date.year }}</h4></div>
{% for count, year, month, day in images %}
{% if year != locals.year %}
{% set locals.year = year %}
<div class="feed-divider year"><h4>{{ year }}</h4></div>
{% endif %}
{% if item.date.month != locals.month %}
{% set locals.month = item.date.month %}
<div class="feed-divider month"><h4>{{ item.date.strftime("%B") }}</h4></div>
{% if month != locals.month %}
{% set locals.month = month %}
{% endif %}
<a class="date-item{% if count > 50 %} many{% endif %}" href="/date/{{ date }}">{{ date }} ({{ count }})</a>
<a class="date-item{% if count > 50 %} many{% endif %}" href="/date/{{ year }}-{{ month }}-{{ day }}">{{ month }}-{{ day }} ({{ count }})</a>
{% endfor %}
</div>



Loading…
Cancel
Save