From 7ad6160d3865f4b7ce0f8c7118fe63b5c872a0a4 Mon Sep 17 00:00:00 2001 From: Ethan Dalool Date: Sat, 5 Nov 2016 17:58:37 -0700 Subject: [PATCH] album .tar --- etiquette/bad_search.txt | 114 -------------------------------- etiquette/decorators.py | 27 ++++++++ etiquette/etiquette.py | 53 +++++++-------- etiquette/etiquette_launch.py | 4 +- etiquette/phototagger.py | 11 ++- etiquette/reider.py | 16 ----- etiquette/templates/album.html | 3 + etiquette/templates/search.html | 5 +- 8 files changed, 69 insertions(+), 164 deletions(-) delete mode 100644 etiquette/bad_search.txt create mode 100644 etiquette/decorators.py delete mode 100644 etiquette/reider.py diff --git a/etiquette/bad_search.txt b/etiquette/bad_search.txt deleted file mode 100644 index d6f5e86..0000000 --- a/etiquette/bad_search.txt +++ /dev/null @@ -1,114 +0,0 @@ - start_time = time.time() - - - # Raise for cases where the minimum > maximum - for (maxkey, maxval) in maximums.items(): - if maxkey not in minimums: - continue - minval = minimums[maxkey] - if minval > maxval: - raise ValueError('Impossible min-max for %s' % maxkey) - - conditions = [] - minmaxers = {'<=': maximums, '>=': minimums} - - # Convert the min-max parameters into query strings - print('Writing minmaxers') - for (comparator, minmaxer) in minmaxers.items(): - for (field, value) in minmaxer.items(): - if field not in Photo.int_properties: - raise ValueError('Unknown Photo property: %s' % field) - - value = str(value) - query = min_max_query_builder(field, comparator, value) - conditions.append(query) - - print(conditions) - - print('Writing extension rule') - if extension is not None: - if isinstance(extension, str): - extension = [extension] - - # Normalize to prevent injections - extension = [normalize_tagname(e) for e in extension] - extension = ['extension == "%s"' % e for e in extension] - extension = ' OR '.join(extension) - extension = '(%s)' % extension - conditions.append(extension) - - def setify(l): - if l is None: - return set() - else: - return set(self.get_tag_by_name(t) for t in l) - - tag_musts = setify(tag_musts) - tag_mays = setify(tag_mays) - tag_forbids = setify(tag_forbids) - - base = ''' - {negator} EXISTS( - SELECT 1 FROM photo_tag_rel - WHERE photo_tag_rel.photoid == photos.id - AND photo_tag_rel.tagid {operator} {value} - )''' - - print('Writing musts') - for tag in tag_musts: - # tagid == must - query = base.format( - negator='', - operator='==', - value='"%s"' % tag.id, - ) - conditions.append(query) - - print('Writing mays') - if len(tag_mays) > 0: - # not any(tagid not in mays) - acceptable = tag_mays.union(tag_musts) - acceptable = ['"%s"' % t.id for t in acceptable] - acceptable = ', '.join(acceptable) - query = base.format( - negator='', - operator='IN', - value='(%s)' % acceptable, - ) - conditions.append(query) - - print('Writing forbids') - if len(tag_forbids) > 0: - # not any(tagid in forbids) - forbids = ['"%s"' % t.id for t in tag_forbids] - forbids = ', '.join(forbids) - query = base.format( - negator='NOT', - operator='IN', - value='(%s)' % forbids - ) - conditions.append(query) - - if len(conditions) == 0: - raise ValueError('No search query provided') - - conditions = [query for query in conditions if query is not None] - conditions = ['(%s)' % c for c in conditions] - conditions = ' AND '.join(conditions) - conditions = 'WHERE %s' % conditions - - query = 'SELECT * FROM photos %s' % conditions - query = query.replace('\n', ' ') - while ' ' in query: - query = query.replace(' ', ' ') - print(query) - - temp_cur = self.sql.cursor() - temp_cur.execute(query) - - for fetch in fetch_generator(temp_cur): - photo = Photo(self, fetch) - yield photo - - end_time = time.time() - print(end_time - start_time) \ No newline at end of file diff --git a/etiquette/decorators.py b/etiquette/decorators.py new file mode 100644 index 0000000..0bbe766 --- /dev/null +++ b/etiquette/decorators.py @@ -0,0 +1,27 @@ +from flask import request +import uuid + + +def _generate_session_token(): + token = str(uuid.uuid4()) + #print('MAKE SESSION', token) + return token +def give_session_token(function): + @functools.wraps(function) + def wrapped(*args, **kwargs): + # Inject new token so the function doesn't know the difference + token = request.cookies.get('etiquette_session', None) + if not token: + token = _generate_session_token() + request.cookies = dict(request.cookies) + request.cookies['etiquette_session'] = token + + ret = function(*args, **kwargs) + + # Send the token back to the client + if not isinstance(ret, flask.Response): + ret = flask.Response(ret) + ret.set_cookie('etiquette_session', value=token, max_age=60) + + return ret + return wrapped \ No newline at end of file diff --git a/etiquette/etiquette.py b/etiquette/etiquette.py index 89fa35c..0ac81bc 100644 --- a/etiquette/etiquette.py +++ b/etiquette/etiquette.py @@ -11,11 +11,20 @@ import re import requests import sys import time -import uuid import warnings import phototagger -sys.path.append('C:\\git\\else\\Bytestring'); import bytestring + +try: + sys.path.append('C:\\git\\else\\Bytestring') + sys.path.append('C:\\git\\else\\WebstreamZip') + import bytestring + import webstreamzip +except ImportError: + # pip install + # https://raw.githubusercontent.com/voussoir/else/master/_voussoirkit/voussoirkit.zip + from vousoirkit import bytestring + from vousoirkit import webstreamzip site = flask.Flask(__name__) site.config.update( @@ -23,6 +32,7 @@ site.config.update( TEMPLATES_AUTO_RELOAD=True, ) site.jinja_env.add_extension('jinja2.ext.do') +#site.debug = True P = phototagger.PhotoDB() @@ -45,25 +55,7 @@ ERROR_NO_SUCH_TAG = 'Doesn\'t exist' #################################################################################################### #################################################################################################### -def give_session_token(function): - @functools.wraps(function) - def wrapped(*args, **kwargs): - # Inject new token so the function doesn't know the difference - token = request.cookies.get('etiquette_session', None) - if not token: - token = generate_session_token() - request.cookies = dict(request.cookies) - request.cookies['etiquette_session'] = token - ret = function(*args, **kwargs) - - # Send the token back to the client - if not isinstance(ret, flask.Response): - ret = flask.Response(ret) - ret.set_cookie('etiquette_session', value=token, max_age=60) - - return ret - return wrapped def _helper_comma_split(s): if s is None: @@ -109,11 +101,6 @@ def edit_params(original, modifications): new_params = '?' + new_params return new_params -def generate_session_token(): - token = str(uuid.uuid4()) - #print('MAKE SESSION', token) - return token - def make_json_response(j, *args, **kwargs): dumped = json.dumps(j) response = flask.Response(dumped, *args, **kwargs) @@ -124,7 +111,7 @@ def P_album(albumid): try: return P.get_album(albumid) except phototagger.NoSuchAlbum: - flask.abort(404, 'That tag doesnt exist') + flask.abort(404, 'That album doesnt exist') def P_photo(photoid): try: @@ -329,6 +316,16 @@ def get_album_json(albumid): album = get_album_core(albumid) return make_json_response(album) +@site.route('/album/.tar') +def get_album_tar(albumid): + album = P_album(albumid) + photos = list(album.walk_photos()) + zipname_map = {p.real_filepath: '%s - %s' % (p.id, p.basename) for p in photos} + streamed_zip = webstreamzip.stream_tar(zipname_map) + content_length = sum(p.bytes for p in photos) + outgoing_headers = {'Content-Type': 'application/octet-stream'} + return flask.Response(streamed_zip, headers=outgoing_headers) + @site.route('/albums') @give_session_token def get_albums_html(): @@ -391,7 +388,7 @@ def get_photo_json(photoid): return photo def get_search_core(): - print(request.args) + #print(request.args) # FILENAME & EXTENSION filename_terms = request.args.get('filename', None) @@ -480,7 +477,7 @@ def get_search_core(): 'warn_bad_tags': True, } - print(search_kwargs) + #print(search_kwargs) with warnings.catch_warnings(record=True) as catcher: photos = list(P.search(**search_kwargs)) photos = [jsonify_photo(photo) for photo in photos] diff --git a/etiquette/etiquette_launch.py b/etiquette/etiquette_launch.py index dc61bf7..4f43beb 100644 --- a/etiquette/etiquette_launch.py +++ b/etiquette/etiquette_launch.py @@ -15,8 +15,8 @@ if port == 443: http = gevent.pywsgi.WSGIServer( ('', port), etiquette.site, - keyfile='etiquette.key', - certfile='etiquette.crt', + keyfile='https\\etiquette.key', + certfile='https\\etiquette.crt', ) else: http = gevent.wsgi.WSGIServer(('', port), etiquette.site) diff --git a/etiquette/phototagger.py b/etiquette/phototagger.py index b548dfc..334d618 100644 --- a/etiquette/phototagger.py +++ b/etiquette/phototagger.py @@ -220,6 +220,8 @@ def _helper_extension(ext): def _helper_filenamefilter(subject, terms): basename = subject.lower() + #print(basename) + #print(terms) return all(term in basename for term in terms) def _helper_minmax(key, value, minimums, maximums): @@ -320,6 +322,8 @@ def _helper_unitconvert(value): return None if ':' in value: return hms_to_seconds(value) + elif all(c in '0123456789.' for c in value): + return float(value) else: return bytestring.parsebytes(value) @@ -1638,10 +1642,10 @@ class Album(ObjectBase, GroupableMixin): return 'Album:{id}'.format(id=self.id) def add_photo(self, photo, commit=True): - if self.has_photo(photo): - return if self.photodb != photo.photodb: raise ValueError('Not the same PhotoDB') + if self.has_photo(photo): + return self.photodb.cur.execute('INSERT INTO album_photo_rel VALUES(?, ?)', [self.id, photo.id]) if commit: log.debug('Committing - add photo to album') @@ -1687,6 +1691,7 @@ class Album(ObjectBase, GroupableMixin): 'SELECT * FROM album_photo_rel WHERE albumid == ? AND photoid == ?', [self.id, photo.id] ) + return self.photodb.cur.fetchone() is not None def photos(self): photos = [] @@ -1832,7 +1837,7 @@ class Photo(ObjectBase): return_filepath = hopeful_filepath elif mime == 'video' and ffmpeg: - print('video') + #print('video') probe = ffmpeg.probe(self.real_filepath) try: if probe.video: diff --git a/etiquette/reider.py b/etiquette/reider.py deleted file mode 100644 index d467805..0000000 --- a/etiquette/reider.py +++ /dev/null @@ -1,16 +0,0 @@ -for p in P.get_photos(): - g=P.cur.execute('UPDATE photos SET id==? WHERE id==?', [p.id[-12:], p.id]) - g=P.cur.execute('UPDATE photo_tag_rel SET photoid==? WHERE photoid==?', [p.id[-12:], p.id]) - g=P.cur.execute('UPDATE album_photo_rel SET photoid==? WHERE photoid==?', [p.id[-12:], p.id]) - -for t in P.get_tags(): - g=P.cur.execute('UPDATE tags SET id==? WHERE id==?', [t.id[-12:], t.id]) - g=P.cur.execute('UPDATE photo_tag_rel SET tagid==? WHERE tagid==?', [t.id[-12:], t.id]) - g=P.cur.execute('UPDATE tag_group_rel SET parentid==? WHERE parentid==?', [t.id[-12:], t.id]) - g=P.cur.execute('UPDATE tag_group_rel SET memberid==? WHERE memberid==?', [t.id[-12:], t.id]) - -for a in P.get_albums(): - g=P.cur.execute('UPDATE albums SET id==? WHERE id==?', [a.id[-12:], a.id]) - g=P.cur.execute('UPDATE tag_group_rel SET parentid==? WHERE parentid==?', [a.id[-12:], a.id]) - g=P.cur.execute('UPDATE tag_group_rel SET memberid==? WHERE memberid==?', [a.id[-12:], a.id]) - g=P.cur.execute('UPDATE album_photo_rel SET albumid==? WHERE albumid==?', [a.id[-12:], a.id]) \ No newline at end of file diff --git a/etiquette/templates/album.html b/etiquette/templates/album.html index 8181800..3113120 100644 --- a/etiquette/templates/album.html +++ b/etiquette/templates/album.html @@ -22,6 +22,8 @@ {% set parent=album["parent"] %} {% if parent %}

Parent: {{parent.title}}

+ {% else %} +

Parent: Albums

{% endif %} {% if child_albums %}

Sub-albums

@@ -37,6 +39,7 @@ {% endfor %} {% endif %} + (download .tar) {% if photos %}

Photos