Add PhotoDB.closest_photodb for frontend instantiation.
This commit is contained in:
parent
84bf9b90de
commit
e5be26f8b0
7 changed files with 75 additions and 36 deletions
|
@ -252,7 +252,7 @@ ADDITIONAL_MIMETYPES = {
|
|||
|
||||
# Photodb ##########################################################################################
|
||||
|
||||
DEFAULT_DATADIR = '.\\_etiquette'
|
||||
DEFAULT_DATADIR = '_etiquette'
|
||||
DEFAULT_DBNAME = 'phototagger.db'
|
||||
DEFAULT_CONFIGNAME = 'config.json'
|
||||
DEFAULT_THUMBDIR = 'site_thumbnails'
|
||||
|
|
|
@ -192,6 +192,13 @@ class FeatureDisabled(EtiquetteException):
|
|||
'''
|
||||
error_message = 'This feature has been disabled. Requires {}.'
|
||||
|
||||
class NoClosestPhotoDB(EtiquetteException):
|
||||
'''
|
||||
For calls to PhotoDB.closest_photodb where none exists between cwd and
|
||||
drive root.
|
||||
'''
|
||||
error_message = 'There is no PhotoDB in {} or its parents.'
|
||||
|
||||
class NoYields(EtiquetteException):
|
||||
'''
|
||||
For when all of the yield_* arguments have been provided as False, and thus
|
||||
|
|
|
@ -1805,7 +1805,7 @@ class PhotoDB(
|
|||
self.ephemeral_directory = tempfile.TemporaryDirectory(prefix='etiquette_ephem_')
|
||||
data_directory = self.ephemeral_directory.name
|
||||
else:
|
||||
data_directory = constants.DEFAULT_DATADIR
|
||||
data_directory = pathclass.cwd().with_child(constants.DEFAULT_DATADIR)
|
||||
|
||||
if isinstance(data_directory, str):
|
||||
data_directory = helpers.remove_path_badchars(data_directory, allowed=':/\\')
|
||||
|
@ -1880,6 +1880,34 @@ class PhotoDB(
|
|||
self.sql_executescript(constants.DB_PRAGMAS)
|
||||
self.sql.commit()
|
||||
|
||||
@classmethod
|
||||
def closest_photodb(cls, *args, **kwargs):
|
||||
'''
|
||||
Starting from the cwd and climbing upwards towards the filesystem root,
|
||||
look for an existing Etiquette data directory and return the PhotoDB
|
||||
object. If none exists, raise exceptions.NoClosestPhotoDB.
|
||||
'''
|
||||
cwd = pathclass.cwd()
|
||||
|
||||
path = cwd
|
||||
while True:
|
||||
if path.with_child(constants.DEFAULT_DATADIR).is_dir:
|
||||
break
|
||||
parent = path.parent
|
||||
if path == parent:
|
||||
raise exceptions.NoClosestPhotoDB(cwd)
|
||||
path = parent
|
||||
|
||||
path = path.with_child(constants.DEFAULT_DATADIR)
|
||||
photodb = cls(
|
||||
path,
|
||||
create=False,
|
||||
*args,
|
||||
**kwargs,
|
||||
)
|
||||
photodb.log.debug('Found closest PhotoDB at %s.', path)
|
||||
return photodb
|
||||
|
||||
def __del__(self):
|
||||
self.close()
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import sys
|
|||
from voussoirkit import betterhelp
|
||||
from voussoirkit import interactive
|
||||
from voussoirkit import pathclass
|
||||
from voussoirkit import pipeable
|
||||
from voussoirkit import spinal
|
||||
from voussoirkit import stringtools
|
||||
from voussoirkit import vlogging
|
||||
|
@ -14,31 +15,19 @@ import etiquette
|
|||
|
||||
LOG_LEVEL = vlogging.NOTSET
|
||||
|
||||
class CantFindPhotoDB(Exception):
|
||||
pass
|
||||
|
||||
photodbs = {}
|
||||
|
||||
def find_photodb():
|
||||
path = pathclass.cwd()
|
||||
|
||||
while True:
|
||||
cwd = pathclass.cwd()
|
||||
try:
|
||||
return photodbs[path]
|
||||
return photodbs[cwd]
|
||||
except KeyError:
|
||||
pass
|
||||
if path.with_child('_etiquette').is_dir:
|
||||
break
|
||||
if path == path.parent:
|
||||
raise CantFindPhotoDB()
|
||||
path = path.parent
|
||||
|
||||
photodb = etiquette.photodb.PhotoDB(
|
||||
path.with_child('_etiquette'),
|
||||
create=False,
|
||||
log_level=LOG_LEVEL,
|
||||
)
|
||||
photodbs[path] = photodb
|
||||
# If this raises, main will catch it.
|
||||
photodb = etiquette.photodb.PhotoDB.closest_photodb()
|
||||
photodbs[cwd] = photodb
|
||||
return photodb
|
||||
|
||||
# HELPERS ##########################################################################################
|
||||
|
@ -780,6 +769,7 @@ def main(argv):
|
|||
)
|
||||
return args
|
||||
|
||||
try:
|
||||
return betterhelp.subparser_main(
|
||||
primary_args,
|
||||
parser,
|
||||
|
@ -787,6 +777,10 @@ def main(argv):
|
|||
sub_docstrings=SUB_DOCSTRINGS,
|
||||
args_postprocessor=pp,
|
||||
)
|
||||
except etiquette.exceptions.NoClosestPhotoDB as exc:
|
||||
pipeable.stderr(exc.error_message)
|
||||
pipeable.stderr('Try etiquette_cli init')
|
||||
return 1
|
||||
|
||||
if __name__ == '__main__':
|
||||
raise SystemExit(main(sys.argv[1:]))
|
||||
|
|
|
@ -320,4 +320,4 @@ def send_file(filepath, override_mimetype=None):
|
|||
|
||||
def init_photodb(*args, **kwargs):
|
||||
global P
|
||||
P = etiquette.photodb.PhotoDB(*args, **kwargs)
|
||||
P = etiquette.photodb.PhotoDB.closest_photodb(*args, **kwargs)
|
||||
|
|
|
@ -18,8 +18,10 @@ import os
|
|||
import sys
|
||||
|
||||
from voussoirkit import pathclass
|
||||
from voussoirkit import pipeable
|
||||
from voussoirkit import vlogging
|
||||
|
||||
import etiquette
|
||||
import backend
|
||||
|
||||
site = backend.site
|
||||
|
@ -31,7 +33,6 @@ LOG_LEVEL = vlogging.NOTSET
|
|||
|
||||
def etiquette_flask_launch(
|
||||
*,
|
||||
create,
|
||||
localhost_only,
|
||||
port,
|
||||
use_https,
|
||||
|
@ -55,7 +56,12 @@ def etiquette_flask_launch(
|
|||
if localhost_only:
|
||||
site.localhost_only = True
|
||||
|
||||
backend.common.init_photodb(create=create, log_level=LOG_LEVEL)
|
||||
try:
|
||||
backend.common.init_photodb(log_level=LOG_LEVEL)
|
||||
except etiquette.exceptions.NoClosestPhotoDB as exc:
|
||||
pipeable.stderr(exc.error_message)
|
||||
pipeable.stderr('Try etiquette_cli init')
|
||||
return 1
|
||||
|
||||
message = f'Starting server on port {port}, pid={os.getpid()}'
|
||||
if use_https:
|
||||
|
@ -69,7 +75,6 @@ def etiquette_flask_launch(
|
|||
|
||||
def etiquette_flask_launch_argparse(args):
|
||||
return etiquette_flask_launch(
|
||||
create=args.create,
|
||||
localhost_only=args.localhost_only,
|
||||
port=args.port,
|
||||
use_https=args.use_https,
|
||||
|
@ -82,7 +87,6 @@ def main(argv):
|
|||
parser = argparse.ArgumentParser()
|
||||
|
||||
parser.add_argument('port', nargs='?', type=int, default=5000)
|
||||
parser.add_argument('--dont_create', '--dont-create', '--no-create', dest='create', action='store_false', default=True)
|
||||
parser.add_argument('--https', dest='use_https', action='store_true', default=None)
|
||||
parser.add_argument('--localhost_only', '--localhost-only', dest='localhost_only', action='store_true')
|
||||
parser.set_defaults(func=etiquette_flask_launch_argparse)
|
||||
|
|
|
@ -10,6 +10,7 @@ import sys
|
|||
import traceback
|
||||
|
||||
from voussoirkit import interactive
|
||||
from voussoirkit import pipeable
|
||||
from voussoirkit import vlogging
|
||||
|
||||
import etiquette
|
||||
|
@ -38,7 +39,13 @@ def photag(photo_id):
|
|||
|
||||
def erepl_argparse(args):
|
||||
global P
|
||||
P = etiquette.photodb.PhotoDB(create=args.create, log_level=LOG_LEVEL)
|
||||
|
||||
try:
|
||||
P = etiquette.photodb.PhotoDB.closest_photodb(log_level=LOG_LEVEL)
|
||||
except etiquette.exceptions.NoClosestPhotoDB as exc:
|
||||
pipeable.stderr(exc.error_message)
|
||||
pipeable.stderr('Try etiquette_cli init')
|
||||
return 1
|
||||
|
||||
if args.exec_statement:
|
||||
exec(args.exec_statement)
|
||||
|
@ -62,7 +69,6 @@ def main(argv):
|
|||
parser = argparse.ArgumentParser()
|
||||
|
||||
parser.add_argument('--exec', dest='exec_statement', default=None)
|
||||
parser.add_argument('--dont_create', '--dont-create', '--no-create', dest='create', action='store_false', default=True)
|
||||
parser.set_defaults(func=erepl_argparse)
|
||||
|
||||
args = parser.parse_args(argv)
|
||||
|
|
Loading…
Reference in a new issue