Replace all double blank lines with single, improve hash headers.

There was always some semblance that two blank lines has some kind of
meaning or structure that's different from single blank lines, but
in reality it was mostly arbitrary and I can't stand to look at it
any more.
This commit is contained in:
voussoir 2020-09-19 03:13:23 -07:00
parent a7cc6d2383
commit adb1d0ef39
31 changed files with 38 additions and 71 deletions

View file

@ -129,7 +129,6 @@ CREATE INDEX IF NOT EXISTS index_tags_name on tags(name);
CREATE INDEX IF NOT EXISTS index_tags_author_id on tags(author_id);
----------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS album_associated_directories(
albumid TEXT NOT NULL,

View file

@ -4,7 +4,6 @@ import warnings
from . import exceptions
def _get_relevant_photodb(instance):
from . import objects
if isinstance(instance, objects.ObjectBase):

View file

@ -44,8 +44,8 @@ class EtiquetteException(Exception, metaclass=ErrorTypeAdder):
def __str__(self):
return self.error_type + '\n' + self.error_message
# NO SUCH ##########################################################################################
# NO SUCH
class NoSuch(EtiquetteException):
pass
@ -70,8 +70,8 @@ class NoSuchTag(NoSuch):
class NoSuchUser(NoSuch):
error_message = 'User "{}" does not exist.'
# EXISTS ###########################################################################################
# EXISTS
class Exists(EtiquetteException):
pass
@ -106,8 +106,8 @@ class UserExists(Exists):
self.user = user
EtiquetteException.__init__(self, user)
# TAG ERRORS #######################################################################################
# TAG ERRORS
class CantGroupSelf(EtiquetteException):
error_message = 'Cannot group {} into itself.'
@ -126,8 +126,8 @@ class TagTooLong(EtiquetteException):
class TagTooShort(EtiquetteException):
error_message = 'Tag "{}" has too few valid characters.'
# USER ERRORS ######################################################################################
# USER ERRORS
class AlreadySignedIn(EtiquetteException):
error_message = 'You\'re already signed in.'
@ -155,16 +155,16 @@ class DisplayNameTooLong(EtiquetteException):
class WrongLogin(EtiquetteException):
error_message = 'Wrong username-password combination.'
# SQL ERRORS #######################################################################################
# SQL ERRORS
class BadSQL(EtiquetteException):
pass
class BadTable(BadSQL):
error_message = 'Table "{}" does not exist.'
# GENERAL ERRORS ###################################################################################
# GENERAL ERRORS
class BadDataDirectory(EtiquetteException):
'''
Raised by PhotoDB __init__ if the requested data_directory is invalid.

View file

@ -19,7 +19,6 @@ from . import decorators
from . import exceptions
from . import helpers
BAIL = sentinel.Sentinel('BAIL')
def normalize_db_row(db_row, table):
@ -27,7 +26,6 @@ def normalize_db_row(db_row, table):
db_row = dict(zip(constants.SQL_COLUMNS[table], db_row))
return db_row
class ObjectBase:
def __init__(self, photodb):
super().__init__()
@ -71,7 +69,6 @@ class ObjectBase:
return None
return self.photodb.get_user(id=self.author_id)
class GroupableMixin:
group_getter = None
group_getter_many = None
@ -227,7 +224,6 @@ class GroupableMixin:
more_parents = more_parents.difference(seen)
todo.extend(more_parents)
class Album(ObjectBase, GroupableMixin):
table = 'albums'
group_table = 'album_group_rel'
@ -546,7 +542,6 @@ class Album(ObjectBase, GroupableMixin):
for child in children:
yield from child.walk_photos()
class Bookmark(ObjectBase):
table = 'bookmarks'
@ -1168,7 +1163,6 @@ class Photo(ObjectBase):
self.photodb.sql_update(table='photos', pairs=data, where_key='id')
self.searchhidden = searchhidden
class Tag(ObjectBase, GroupableMixin):
'''
A Tag, which can be applied to Photos for organization.
@ -1465,7 +1459,6 @@ class Tag(ObjectBase, GroupableMixin):
self.name = new_name
self._uncache()
class User(ObjectBase):
'''
A dear friend of ours.
@ -1529,7 +1522,6 @@ class User(ObjectBase):
self.photodb.sql_update(table='users', pairs=data, where_key='id')
self._display_name = display_name
class WarningBag:
def __init__(self):
self.warnings = set()

View file

@ -24,10 +24,7 @@ from . import objects
from . import searchhelpers
from . import tag_export
####################################################################################################
####################################################################################################
class PDBAlbumMixin:
def __init__(self):
@ -143,6 +140,7 @@ class PDBAlbumMixin:
to_check.update(album.get_parents())
album.delete()
####################################################################################################
class PDBBookmarkMixin:
def __init__(self):
@ -185,6 +183,7 @@ class PDBBookmarkMixin:
return bookmark
####################################################################################################
class PDBCacheManagerMixin:
_THING_CLASSES = {
@ -380,6 +379,7 @@ class PDBCacheManagerMixin:
thing_cache[thing.id] = thing
yield thing
####################################################################################################
class PDBPhotoMixin:
def __init__(self):
@ -896,6 +896,7 @@ class PDBPhotoMixin:
end_time = time.time()
print('Search took:', end_time - start_time)
####################################################################################################
class PDBSQLMixin:
def __init__(self):
@ -1050,6 +1051,7 @@ class PDBSQLMixin:
query = f'UPDATE {table} {qmarks}'
self.sql_execute(query, bindings)
####################################################################################################
class PDBTagMixin:
def __init__(self):
@ -1196,6 +1198,7 @@ class PDBTagMixin:
)
return tagname
####################################################################################################
class PDBUserMixin:
def __init__(self):
@ -1359,6 +1362,7 @@ class PDBUserMixin:
return self.get_cached_instance('user', data)
####################################################################################################
class PDBUtilMixin:
def __init__(self):
@ -1625,6 +1629,7 @@ class PDBUtilMixin:
return output_notes
####################################################################################################
class PhotoDB(
PDBAlbumMixin,
@ -1820,7 +1825,6 @@ class PhotoDB(
with open(self.config_filepath.absolute_path, 'w', encoding='utf-8') as handle:
handle.write(json.dumps(self.config, indent=4, sort_keys=True))
if __name__ == '__main__':
p = PhotoDB()
print(p)

View file

@ -11,7 +11,6 @@ from . import objects
from voussoirkit import expressionmatch
from voussoirkit import sqlhelpers
def expand_mmf(tag_musts, tag_mays, tag_forbids):
'''
In order to generate SQL queries for `tagid IN (options)`, we need to

View file

@ -6,7 +6,6 @@ from voussoirkit import cacheclass
import etiquette
def cached_endpoint(max_age):
'''
The cached_endpoint decorator can be used on slow endpoints that don't need
@ -63,7 +62,6 @@ def cached_endpoint(max_age):
return wrapped
return wrapper
class FileCacheManager:
'''
The FileCacheManager serves ETag and Cache-Control headers for disk files.
@ -116,7 +114,6 @@ class FileCacheManager:
return server_value.get_headers()
class CacheFile:
def __init__(self, filepath, max_age):
self.filepath = filepath

View file

@ -15,6 +15,8 @@ from . import jinja_filters
from . import jsonify
from . import sessions
# Runtime init #####################################################################################
root_dir = pathclass.Path(__file__).parent.parent
TEMPLATE_DIR = root_dir.with_child('templates')
@ -46,6 +48,8 @@ file_cache_manager = caching.FileCacheManager(
max_age=BROWSER_CACHE_DURATION,
)
# Response wrappers ################################################################################
# Flask provides decorators for before_request and after_request, but not for
# wrapping the whole request. The decorators I am using need to wrap the whole
# request, either to catch exceptions (which don't get passed through
@ -98,6 +102,8 @@ def after_request(response):
return response
# P functions ######################################################################################
def P_wrapper(function):
def P_wrapped(thingid, response_type):
if response_type not in {'html', 'json'}:
@ -160,6 +166,11 @@ def P_user(username):
def P_user_id(user_id):
return P.get_user(id=user_id)
# Other functions ##################################################################################
def back_url():
return request.args.get('goto') or request.referrer or '/'
def render_template(request, template_name, **kwargs):
session = session_manager.get(request)
@ -186,9 +197,6 @@ def render_template(request, template_name, **kwargs):
return response
def back_url():
return request.args.get('goto') or request.referrer or '/'
def send_file(filepath, override_mimetype=None):
'''
Range-enabled file sending.

View file

@ -6,7 +6,6 @@ import etiquette
from . import jsonify
def catch_etiquette_exception(function):
'''
If an EtiquetteException is raised, automatically catch it and convert it

View file

@ -10,7 +10,6 @@ from .. import jsonify
site = common.site
session_manager = common.session_manager
# Individual albums ################################################################################
@site.route('/album/<album_id>')

View file

@ -6,7 +6,6 @@ from .. import common
site = common.site
session_manager = common.session_manager
####################################################################################################
@site.route('/')

View file

@ -9,7 +9,6 @@ from .. import jsonify
site = common.site
session_manager = common.session_manager
# Individual bookmarks #############################################################################
@site.route('/bookmark/<bookmark_id>.json')

View file

@ -15,7 +15,6 @@ site = common.site
session_manager = common.session_manager
photo_download_zip_tokens = cacheclass.Cache(maxlen=100)
# Individual photos ################################################################################
@site.route('/photo/<photo_id>')

View file

@ -10,7 +10,6 @@ from .. import jsonify
site = common.site
session_manager = common.session_manager
# Individual tags ##################################################################################
@site.route('/tags/<specific_tag>')

View file

@ -10,7 +10,6 @@ from .. import sessions
site = common.site
session_manager = common.session_manager
# Individual users #################################################################################
@site.route('/user/<username>')

View file

@ -21,6 +21,8 @@ def register_all(site):
for function in global_functions:
site.jinja_env.globals[function.__name__] = function
####################################################################################################
@filter_function
def bytestring(x):
try:
@ -41,14 +43,6 @@ def file_link(photo, short=False):
basename = jinja2.filters.do_urlencode(photo.basename)
return f'/file/{photo.id}/{basename}'
@global_function
def make_attributes(*booleans, **keyvalues):
keyvalues = {key: value for (key, value) in keyvalues.items() if value is not None}
attributes = [f'{key}="{jinja2.filters.escape(value)}"' for (key, value) in keyvalues.items()]
attributes.extend(booleans)
attributes = ' '.join(attributes)
return attributes
@filter_function
def sort_tags(tags):
tags = sorted(tags, key=lambda x: x.name)
@ -72,3 +66,13 @@ def users_to_usernames(users):
if not users:
return []
return [user.username for user in users]
####################################################################################################
@global_function
def make_attributes(*booleans, **keyvalues):
keyvalues = {key: value for (key, value) in keyvalues.items() if value is not None}
attributes = [f'{key}="{jinja2.filters.escape(value)}"' for (key, value) in keyvalues.items()]
attributes.extend(booleans)
attributes = ' '.join(attributes)
return attributes

View file

@ -1,7 +1,6 @@
import flask
import json
def make_json_response(j, *args, **kwargs):
dumped = json.dumps(j)
response = flask.Response(dumped, *args, **kwargs)

View file

@ -7,7 +7,6 @@ from voussoirkit import cacheclass
import etiquette
SESSION_MAX_AGE = 86400
REQUEST_TYPES = (flask.Request, werkzeug.wrappers.Request, werkzeug.local.LocalProxy)
RESPONSE_TYPES = (flask.Response, werkzeug.wrappers.Response)
@ -31,7 +30,6 @@ def _normalize_token(token):
raise TypeError('Unsupported token normalization', type(token))
return token
class SessionManager:
def __init__(self, maxlen=None):
self.sessions = cacheclass.Cache(maxlen=maxlen)
@ -106,7 +104,6 @@ class SessionManager:
except KeyError:
pass
class Session:
def __init__(self, request, user):
self.token = _normalize_token(request)

View file

@ -90,7 +90,6 @@ h2, h3
{{shared_css()}}
</head>
<body>
{{header.make_header(session=session)}}
<div id="content_body" class="sticky_side_right sticky_bottom_right">
@ -121,7 +120,6 @@ h2, h3
</div>
</body>
<script id="album_listing_script" type="text/javascript">
const ALBUM_ID = undefined;
</script>
@ -151,7 +149,6 @@ const ALBUM_ID = undefined;
{{shared_css()}}
</head>
<body>
{{header.make_header(session=session)}}
<div id="content_body" class="sticky_side_right sticky_bottom_right">
@ -289,7 +286,6 @@ const ALBUM_ID = undefined;
</div>
</body>
<script id="album_individual_script" type="text/javascript">
const ALBUM_ID = "{{album.id}}";

View file

@ -44,7 +44,6 @@
</style>
</head>
<body>
{{header.make_header(session=session)}}
<div id="content_body">
@ -95,7 +94,6 @@
</div>
</body>
<script type="text/javascript">
function create_bookmark_form()
{

View file

@ -85,7 +85,6 @@
</style>
</head>
<body>
{{header.make_header(session=session)}}
<div id="content_body" class="sticky_side_right sticky_bottom_right">
@ -129,7 +128,6 @@
</div>
</body>
<script type="text/javascript">
const divs = {};
const needed = new Set();

View file

@ -69,7 +69,6 @@ form h2
</style>
</head>
<body>
{{header.make_header(session=session)}}
<div id="content_body">
@ -92,7 +91,6 @@ form h2
</div>
</body>
<script type="text/javascript">
const message_area = document.getElementById("message_area");

View file

@ -129,7 +129,6 @@
</style>
</head>
<body>
{{header.make_header(session=session)}}
<div id="content_body">
@ -191,7 +190,6 @@
</li>
</ul>
<!-- CONTAINING ALBUMS -->
{% set albums = photo.get_containing_albums() %}
{% if albums %}
@ -262,7 +260,6 @@
</div>
</body>
<script type="text/javascript">
const PHOTO_ID = "{{photo.id}}";

View file

@ -45,7 +45,6 @@ body, .nice_link
</style>
</head>
<body>
<span id="motd">{{motd}}</span>
<a class="nice_link" href="/search">Search</a>
@ -60,7 +59,6 @@ body, .nice_link
<a class="plain_link" href="http://www.github.com/voussoir/etiquette">GitHub</a>
</body>
<script type="text/javascript">
</script>
</html>

View file

@ -175,7 +175,6 @@
{% endmacro %}
</head>
<body>
{{header.make_header(session=session)}}
<div id="content_body">
@ -363,7 +362,6 @@
{{clipboard_tray.clipboard_tray()}}
</body>
<script type="text/javascript">
/*
These values should match those of the server itself. The purpose of this dict

View file

@ -88,7 +88,6 @@ h2, h3
</style>
</head>
<body>
{{header.make_header(session=session)}}
<div id="content_body" class="sticky_side_right sticky_bottom_right">
@ -252,7 +251,6 @@ h2, h3
</div>
</body>
<script type="text/javascript">
let SPECIFIC_TAG = "{{specific_tag.name}}";

View file

@ -15,7 +15,6 @@
</style>
</head>
<body>
{{header.make_header(session=session)}}
<div id="content_body">
@ -23,7 +22,6 @@
</div>
</body>
<script type="text/javascript">
</script>
</html>

View file

@ -20,7 +20,6 @@
</style>
</head>
<body>
{{header.make_header(session=session)}}
<div id="content_body">
@ -31,7 +30,6 @@
</div>
</body>
<script type="text/javascript">
</script>
</html>

View file

@ -36,6 +36,7 @@ def photag(photo_id):
get = P.get_tag
################################################################################
def erepl_argparse(args):
if args.exec_statement:
exec(args.exec_statement)

View file

@ -359,7 +359,6 @@ def upgrade_all(data_directory):
current_version = version_number
print('Upgrades finished.')
def upgrade_all_argparse(args):
return upgrade_all(data_directory=args.data_directory)

View file

@ -73,7 +73,6 @@ CREATE INDEX IF NOT EXISTS index_tags_name on tags(name);
CREATE INDEX IF NOT EXISTS index_tags_author_id on tags(author_id);
----------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS album_associated_directories(
albumid TEXT NOT NULL,