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 ##########################################################################################
|
# Photodb ##########################################################################################
|
||||||
|
|
||||||
DEFAULT_DATADIR = '.\\_etiquette'
|
DEFAULT_DATADIR = '_etiquette'
|
||||||
DEFAULT_DBNAME = 'phototagger.db'
|
DEFAULT_DBNAME = 'phototagger.db'
|
||||||
DEFAULT_CONFIGNAME = 'config.json'
|
DEFAULT_CONFIGNAME = 'config.json'
|
||||||
DEFAULT_THUMBDIR = 'site_thumbnails'
|
DEFAULT_THUMBDIR = 'site_thumbnails'
|
||||||
|
|
|
@ -192,6 +192,13 @@ class FeatureDisabled(EtiquetteException):
|
||||||
'''
|
'''
|
||||||
error_message = 'This feature has been disabled. Requires {}.'
|
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):
|
class NoYields(EtiquetteException):
|
||||||
'''
|
'''
|
||||||
For when all of the yield_* arguments have been provided as False, and thus
|
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_')
|
self.ephemeral_directory = tempfile.TemporaryDirectory(prefix='etiquette_ephem_')
|
||||||
data_directory = self.ephemeral_directory.name
|
data_directory = self.ephemeral_directory.name
|
||||||
else:
|
else:
|
||||||
data_directory = constants.DEFAULT_DATADIR
|
data_directory = pathclass.cwd().with_child(constants.DEFAULT_DATADIR)
|
||||||
|
|
||||||
if isinstance(data_directory, str):
|
if isinstance(data_directory, str):
|
||||||
data_directory = helpers.remove_path_badchars(data_directory, allowed=':/\\')
|
data_directory = helpers.remove_path_badchars(data_directory, allowed=':/\\')
|
||||||
|
@ -1880,6 +1880,34 @@ class PhotoDB(
|
||||||
self.sql_executescript(constants.DB_PRAGMAS)
|
self.sql_executescript(constants.DB_PRAGMAS)
|
||||||
self.sql.commit()
|
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):
|
def __del__(self):
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import sys
|
||||||
from voussoirkit import betterhelp
|
from voussoirkit import betterhelp
|
||||||
from voussoirkit import interactive
|
from voussoirkit import interactive
|
||||||
from voussoirkit import pathclass
|
from voussoirkit import pathclass
|
||||||
|
from voussoirkit import pipeable
|
||||||
from voussoirkit import spinal
|
from voussoirkit import spinal
|
||||||
from voussoirkit import stringtools
|
from voussoirkit import stringtools
|
||||||
from voussoirkit import vlogging
|
from voussoirkit import vlogging
|
||||||
|
@ -14,31 +15,19 @@ import etiquette
|
||||||
|
|
||||||
LOG_LEVEL = vlogging.NOTSET
|
LOG_LEVEL = vlogging.NOTSET
|
||||||
|
|
||||||
class CantFindPhotoDB(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
photodbs = {}
|
photodbs = {}
|
||||||
|
|
||||||
def find_photodb():
|
def find_photodb():
|
||||||
path = pathclass.cwd()
|
cwd = pathclass.cwd()
|
||||||
|
try:
|
||||||
|
return photodbs[cwd]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
while True:
|
# If this raises, main will catch it.
|
||||||
try:
|
photodb = etiquette.photodb.PhotoDB.closest_photodb()
|
||||||
return photodbs[path]
|
photodbs[cwd] = photodb
|
||||||
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
|
|
||||||
return photodb
|
return photodb
|
||||||
|
|
||||||
# HELPERS ##########################################################################################
|
# HELPERS ##########################################################################################
|
||||||
|
@ -780,13 +769,18 @@ def main(argv):
|
||||||
)
|
)
|
||||||
return args
|
return args
|
||||||
|
|
||||||
return betterhelp.subparser_main(
|
try:
|
||||||
primary_args,
|
return betterhelp.subparser_main(
|
||||||
parser,
|
primary_args,
|
||||||
main_docstring=DOCSTRING,
|
parser,
|
||||||
sub_docstrings=SUB_DOCSTRINGS,
|
main_docstring=DOCSTRING,
|
||||||
args_postprocessor=pp,
|
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__':
|
if __name__ == '__main__':
|
||||||
raise SystemExit(main(sys.argv[1:]))
|
raise SystemExit(main(sys.argv[1:]))
|
||||||
|
|
|
@ -320,4 +320,4 @@ def send_file(filepath, override_mimetype=None):
|
||||||
|
|
||||||
def init_photodb(*args, **kwargs):
|
def init_photodb(*args, **kwargs):
|
||||||
global P
|
global P
|
||||||
P = etiquette.photodb.PhotoDB(*args, **kwargs)
|
P = etiquette.photodb.PhotoDB.closest_photodb(*args, **kwargs)
|
||||||
|
|
|
@ -18,8 +18,10 @@ import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from voussoirkit import pathclass
|
from voussoirkit import pathclass
|
||||||
|
from voussoirkit import pipeable
|
||||||
from voussoirkit import vlogging
|
from voussoirkit import vlogging
|
||||||
|
|
||||||
|
import etiquette
|
||||||
import backend
|
import backend
|
||||||
|
|
||||||
site = backend.site
|
site = backend.site
|
||||||
|
@ -31,7 +33,6 @@ LOG_LEVEL = vlogging.NOTSET
|
||||||
|
|
||||||
def etiquette_flask_launch(
|
def etiquette_flask_launch(
|
||||||
*,
|
*,
|
||||||
create,
|
|
||||||
localhost_only,
|
localhost_only,
|
||||||
port,
|
port,
|
||||||
use_https,
|
use_https,
|
||||||
|
@ -55,7 +56,12 @@ def etiquette_flask_launch(
|
||||||
if localhost_only:
|
if localhost_only:
|
||||||
site.localhost_only = True
|
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()}'
|
message = f'Starting server on port {port}, pid={os.getpid()}'
|
||||||
if use_https:
|
if use_https:
|
||||||
|
@ -69,7 +75,6 @@ def etiquette_flask_launch(
|
||||||
|
|
||||||
def etiquette_flask_launch_argparse(args):
|
def etiquette_flask_launch_argparse(args):
|
||||||
return etiquette_flask_launch(
|
return etiquette_flask_launch(
|
||||||
create=args.create,
|
|
||||||
localhost_only=args.localhost_only,
|
localhost_only=args.localhost_only,
|
||||||
port=args.port,
|
port=args.port,
|
||||||
use_https=args.use_https,
|
use_https=args.use_https,
|
||||||
|
@ -82,7 +87,6 @@ def main(argv):
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
|
|
||||||
parser.add_argument('port', nargs='?', type=int, default=5000)
|
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('--https', dest='use_https', action='store_true', default=None)
|
||||||
parser.add_argument('--localhost_only', '--localhost-only', dest='localhost_only', action='store_true')
|
parser.add_argument('--localhost_only', '--localhost-only', dest='localhost_only', action='store_true')
|
||||||
parser.set_defaults(func=etiquette_flask_launch_argparse)
|
parser.set_defaults(func=etiquette_flask_launch_argparse)
|
||||||
|
|
|
@ -10,6 +10,7 @@ import sys
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from voussoirkit import interactive
|
from voussoirkit import interactive
|
||||||
|
from voussoirkit import pipeable
|
||||||
from voussoirkit import vlogging
|
from voussoirkit import vlogging
|
||||||
|
|
||||||
import etiquette
|
import etiquette
|
||||||
|
@ -38,7 +39,13 @@ def photag(photo_id):
|
||||||
|
|
||||||
def erepl_argparse(args):
|
def erepl_argparse(args):
|
||||||
global P
|
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:
|
if args.exec_statement:
|
||||||
exec(args.exec_statement)
|
exec(args.exec_statement)
|
||||||
|
@ -62,7 +69,6 @@ def main(argv):
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
|
|
||||||
parser.add_argument('--exec', dest='exec_statement', default=None)
|
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)
|
parser.set_defaults(func=erepl_argparse)
|
||||||
|
|
||||||
args = parser.parse_args(argv)
|
args = parser.parse_args(argv)
|
||||||
|
|
Loading…
Reference in a new issue