Add wutta make-appdir
subcommand
This commit is contained in:
parent
5e971e4b0c
commit
13472a5ab5
6
docs/api/wuttjamaican/commands.make_appdir.rst
Normal file
6
docs/api/wuttjamaican/commands.make_appdir.rst
Normal file
|
@ -0,0 +1,6 @@
|
|||
|
||||
``wuttjamaican.commands.make_appdir``
|
||||
=====================================
|
||||
|
||||
.. automodule:: wuttjamaican.commands.make_appdir
|
||||
:members:
|
|
@ -10,6 +10,7 @@
|
|||
app
|
||||
commands
|
||||
commands.base
|
||||
commands.make_appdir
|
||||
commands.setup
|
||||
conf
|
||||
db
|
||||
|
|
|
@ -15,6 +15,11 @@ Glossary
|
|||
just one database (for simple apps) which uses PostgreSQL for the
|
||||
backend.
|
||||
|
||||
app dir
|
||||
Folder containing app-specific config files, log files, etc.
|
||||
Usually this is named ``app`` and is located at the root of the
|
||||
virtual environment.
|
||||
|
||||
app handler
|
||||
Python object representing the core of the :term:`app`. There is
|
||||
normally just one "global" app handler, which is an instance of
|
||||
|
|
|
@ -51,4 +51,5 @@ console_scripts =
|
|||
wutta = wuttjamaican.commands.base:main
|
||||
|
||||
wutta.subcommands =
|
||||
make-appdir = wuttjamaican.commands.make_appdir:MakeAppDir
|
||||
setup = wuttjamaican.commands.setup:Setup
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
WuttJamaican - app handler
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from wuttjamaican.util import load_entry_points, load_object, parse_bool
|
||||
|
||||
|
||||
|
@ -47,6 +49,35 @@ class AppHandler:
|
|||
self.config = config
|
||||
self.handlers = {}
|
||||
|
||||
def make_appdir(self, path, subfolders=None, **kwargs):
|
||||
"""
|
||||
Establish an :term:`app dir` at the given path.
|
||||
|
||||
Default logic only creates a few subfolders, meant to help
|
||||
steer the admin toward a convention for sake of where to put
|
||||
things. But custom app handlers are free to do whatever.
|
||||
|
||||
:param path: Path to the desired app dir. If the path does
|
||||
not yet exist then it will be created. But regardless it
|
||||
should be "refreshed" (e.g. missing subfolders created)
|
||||
when this method is called.
|
||||
|
||||
:param subfolders: Optional list of subfolder names to create
|
||||
within the app dir. If not specified, defaults will be:
|
||||
``['data', 'log', 'work']``.
|
||||
"""
|
||||
appdir = path
|
||||
if not os.path.exists(appdir):
|
||||
os.makedirs(appdir)
|
||||
|
||||
if not subfolders:
|
||||
subfolders = ['data', 'log', 'work']
|
||||
|
||||
for name in subfolders:
|
||||
path = os.path.join(appdir, name)
|
||||
if not os.path.exists(path):
|
||||
os.mkdir(path)
|
||||
|
||||
def make_engine_from_config(
|
||||
self,
|
||||
config_dict,
|
||||
|
|
62
src/wuttjamaican/commands/make_appdir.py
Normal file
62
src/wuttjamaican/commands/make_appdir.py
Normal file
|
@ -0,0 +1,62 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# WuttJamaican -- Base package for Wutta Framework
|
||||
# Copyright © 2023 Lance Edgar
|
||||
#
|
||||
# This file is part of Wutta Framework.
|
||||
#
|
||||
# Wutta Framework is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation, either version 3 of the License, or (at your option) any
|
||||
# later version.
|
||||
#
|
||||
# Wutta Framework is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# Wutta Framework. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
WuttJamaican - subcommand: make-appdir
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
from .base import Subcommand
|
||||
|
||||
|
||||
class MakeAppDir(Subcommand):
|
||||
"""
|
||||
Make or refresh the "app dir" for virtual environment
|
||||
"""
|
||||
name = 'make-appdir'
|
||||
description = __doc__.strip()
|
||||
|
||||
def add_args(self):
|
||||
""" """
|
||||
self.parser.add_argument('--path', metavar='APPDIR',
|
||||
help="Optional path to desired app dir. If not specified "
|
||||
"it will be named ``app`` and placed in the root of the "
|
||||
"virtual environment.")
|
||||
|
||||
def run(self, args):
|
||||
"""
|
||||
This may be used during setup to establish the :term:`app dir`
|
||||
for a virtual environment. This folder will contain config
|
||||
files, log files etc. used by the app.
|
||||
|
||||
Calls :meth:`~wuttjamaican.app.AppHandler.make_appdir()` to do
|
||||
the heavy lifting.
|
||||
"""
|
||||
if args.path:
|
||||
appdir = os.path.abspath(args.path)
|
||||
else:
|
||||
appdir = os.path.join(sys.prefix, 'app')
|
||||
|
||||
self.app.make_appdir(appdir)
|
||||
self.stdout.write(f"established appdir: {appdir}\n")
|
|
@ -29,7 +29,7 @@ from .base import Subcommand
|
|||
|
||||
class Setup(Subcommand):
|
||||
"""
|
||||
Install and configure misc. software
|
||||
Install and configure various software
|
||||
"""
|
||||
name = 'setup'
|
||||
description = __doc__.strip()
|
||||
|
|
49
tests/commands/test_make_appdir.py
Normal file
49
tests/commands/test_make_appdir.py
Normal file
|
@ -0,0 +1,49 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
from unittest import TestCase
|
||||
from unittest.mock import patch
|
||||
|
||||
from wuttjamaican.conf import WuttaConfig
|
||||
from wuttjamaican.commands import Command, make_appdir
|
||||
|
||||
|
||||
class TestMakeAppDir(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.config = WuttaConfig(appname='wuttatest')
|
||||
self.command = Command(self.config, subcommands={
|
||||
'make-appdir': make_appdir.MakeAppDir,
|
||||
})
|
||||
|
||||
def test_run(self):
|
||||
|
||||
# appdir is created, and 3 subfolders added by default
|
||||
tempdir = tempfile.mkdtemp()
|
||||
appdir = os.path.join(tempdir, 'app')
|
||||
self.assertFalse(os.path.exists(appdir))
|
||||
self.command.run('make-appdir', '--path', appdir)
|
||||
self.assertTrue(os.path.exists(appdir))
|
||||
self.assertEqual(len(os.listdir(appdir)), 3)
|
||||
shutil.rmtree(tempdir)
|
||||
|
||||
# subfolders still added if appdir already exists
|
||||
tempdir = tempfile.mkdtemp()
|
||||
self.assertTrue(os.path.exists(tempdir))
|
||||
self.assertEqual(len(os.listdir(tempdir)), 0)
|
||||
self.command.run('make-appdir', '--path', tempdir)
|
||||
self.assertEqual(len(os.listdir(tempdir)), 3)
|
||||
shutil.rmtree(tempdir)
|
||||
|
||||
# mock out sys.prefix to get coverage
|
||||
with patch('wuttjamaican.commands.make_appdir.sys') as sys:
|
||||
tempdir = tempfile.mkdtemp()
|
||||
appdir = os.path.join(tempdir, 'app')
|
||||
sys.prefix = tempdir
|
||||
self.assertFalse(os.path.exists(appdir))
|
||||
self.command.run('make-appdir')
|
||||
self.assertTrue(os.path.exists(appdir))
|
||||
self.assertEqual(len(os.listdir(appdir)), 3)
|
||||
shutil.rmtree(tempdir)
|
|
@ -1,5 +1,8 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
from unittest import TestCase
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
|
@ -9,18 +12,38 @@ from sqlalchemy.engine import Engine
|
|||
from sqlalchemy.pool import NullPool
|
||||
|
||||
from wuttjamaican import app, db
|
||||
from wuttjamaican.conf import WuttaConfig
|
||||
|
||||
|
||||
class TestAppHandler(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.config = MagicMock()
|
||||
self.config = WuttaConfig(appname='wuttatest')
|
||||
self.app = app.AppHandler(self.config)
|
||||
|
||||
def test_init(self):
|
||||
self.assertIs(self.app.config, self.config)
|
||||
self.assertEqual(self.app.handlers, {})
|
||||
|
||||
def test_make_appdir(self):
|
||||
|
||||
# appdir is created, and 3 subfolders added by default
|
||||
tempdir = tempfile.mkdtemp()
|
||||
appdir = os.path.join(tempdir, 'app')
|
||||
self.assertFalse(os.path.exists(appdir))
|
||||
self.app.make_appdir(appdir)
|
||||
self.assertTrue(os.path.exists(appdir))
|
||||
self.assertEqual(len(os.listdir(appdir)), 3)
|
||||
shutil.rmtree(tempdir)
|
||||
|
||||
# subfolders still added if appdir already exists
|
||||
tempdir = tempfile.mkdtemp()
|
||||
self.assertTrue(os.path.exists(tempdir))
|
||||
self.assertEqual(len(os.listdir(tempdir)), 0)
|
||||
self.app.make_appdir(tempdir)
|
||||
self.assertEqual(len(os.listdir(tempdir)), 3)
|
||||
shutil.rmtree(tempdir)
|
||||
|
||||
def test_make_engine_from_config_basic(self):
|
||||
engine = self.app.make_engine_from_config({
|
||||
'sqlalchemy.url': 'sqlite://',
|
||||
|
|
Loading…
Reference in a new issue