general: finish removal of wcsctl (#86980)
gitea/wcs/pipeline/head This commit looks good Details

This commit is contained in:
Frédéric Péters 2024-02-14 19:43:05 +01:00
parent 8ee2a8cee6
commit 5faf53489b
8 changed files with 1 additions and 297 deletions

2
debian/rules vendored
View File

@ -8,8 +8,6 @@ export PYBUILD_NAME=wcs
override_dh_install: override_dh_install:
dh_install dh_install
mv $(CURDIR)/debian/wcs/usr/bin/wcsctl.py \
$(CURDIR)/debian/wcs/usr/bin/wcsctl
mv $(CURDIR)/debian/wcs/usr/bin/manage.py \ mv $(CURDIR)/debian/wcs/usr/bin/manage.py \
$(CURDIR)/debian/wcs/usr/lib/wcs/ $(CURDIR)/debian/wcs/usr/lib/wcs/
install -d $(CURDIR)/debian/wcs/etc/wcs install -d $(CURDIR)/debian/wcs/etc/wcs

1
debian/wcs.init vendored
View File

@ -17,7 +17,6 @@ set -e
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DESC="Web Forms Manager" DESC="Web Forms Manager"
NAME=wcs NAME=wcs
WCSCTL=/usr/bin/wcsctl
DAEMON=/usr/bin/uwsgi DAEMON=/usr/bin/uwsgi
RUN_DIR=/run/$NAME RUN_DIR=/run/$NAME
PIDFILE=$RUN_DIR/$NAME.pid PIDFILE=$RUN_DIR/$NAME.pid

View File

@ -208,7 +208,7 @@ setup(
package_dir={'wcs': 'wcs'}, package_dir={'wcs': 'wcs'},
packages=find_packages(), packages=find_packages(),
cmdclass=cmdclass, cmdclass=cmdclass,
scripts=['wcsctl.py', 'manage.py'], scripts=['manage.py'],
include_package_data=True, include_package_data=True,
data_files=data_tree('share/wcs/web/', 'data/web/') data_files=data_tree('share/wcs/web/', 'data/web/')
+ data_tree('share/wcs/themes/', 'data/themes/') + data_tree('share/wcs/themes/', 'data/themes/')

View File

@ -3,7 +3,6 @@ import json
import os import os
import pickle import pickle
import shutil import shutil
import sys
import tempfile import tempfile
import zipfile import zipfile
from unittest import mock from unittest import mock
@ -14,7 +13,6 @@ import pytest
import responses import responses
from django.core.management import CommandError, call_command from django.core.management import CommandError, call_command
import wcs.qommon.ctl
from wcs.blocks import BlockDef from wcs.blocks import BlockDef
from wcs.carddef import CardDef from wcs.carddef import CardDef
from wcs.ctl.management.commands.trigger_jumps import select_and_jump_formdata from wcs.ctl.management.commands.trigger_jumps import select_and_jump_formdata
@ -54,16 +52,6 @@ def alt_tempdir():
shutil.rmtree(alt_tempdir) shutil.rmtree(alt_tempdir)
def test_loading():
ctl = wcs.qommon.ctl.Ctl(cmd_prefixes=['wcs.ctl'])
ctl.load_all_commands(ignore_errors=False)
# noqa pylint: disable=consider-iterating-dictionary
assert 'shell' in ctl.get_commands().keys()
# call all __init__() methods
for cmd in ctl.get_commands().values():
cmd()
def test_collectstatic(pub, tmp_path): def test_collectstatic(pub, tmp_path):
CmdCollectStatic.collectstatic(pub) CmdCollectStatic.collectstatic(pub)
assert os.path.exists(os.path.join(pub.app_dir, 'collectstatic', 'css', 'required.png')) assert os.path.exists(os.path.join(pub.app_dir, 'collectstatic', 'css', 'required.png'))
@ -517,26 +505,6 @@ def test_runjob(pub):
call_command('runjob', '--domain=example.net', '--job-id=%s' % job.id, '--force-replay', '--raise') call_command('runjob', '--domain=example.net', '--job-id=%s' % job.id, '--force-replay', '--raise')
def test_ctl_print_help(capsys):
ctl = wcs.qommon.ctl.Ctl(cmd_prefixes=['wcs.ctl'])
with pytest.raises(SystemExit):
ctl.print_help()
captured = capsys.readouterr()
assert 'runscript' in captured.out
def test_ctl_no_command(capsys):
ctl = wcs.qommon.ctl.Ctl(cmd_prefixes=['wcs.ctl'])
old_argv, sys.argv = sys.argv, ['wcsctl']
try:
with pytest.raises(SystemExit):
ctl.run(None)
captured = capsys.readouterr()
assert 'error: You must use a command' in captured.err
finally:
sys.argv = old_argv
def test_dbshell(pub): def test_dbshell(pub):
with pytest.raises(CommandError): with pytest.raises(CommandError):
call_command('dbshell') # missing tenant name call_command('dbshell') # missing tenant name

View File

@ -1,53 +0,0 @@
# w.c.s. - web application for online forms
# Copyright (C) 2005-2013 Entr'ouvert
#
# This program 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 2 of the License, or
# (at your option) any later version.
#
# This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
import os.path
import runpy
import sys
import warnings
from ..qommon.ctl import Command, make_option
class CmdRunScript(Command):
'''Run a script within a given host publisher context'''
name = 'runscript'
def __init__(self):
Command.__init__(
self,
[
make_option('--vhost', metavar='VHOST', action='store', dest='vhost'),
],
)
def execute(self, base_options, sub_options, args):
warnings.warn('Deprecated command, use management command', DeprecationWarning)
from .. import publisher
self.config.remove_option('main', 'error_log')
publisher.WcsPublisher.configure(self.config)
publisher = publisher.WcsPublisher.create_publisher(register_tld_names=False)
publisher.set_tenant_by_hostname(sub_options.vhost)
fullpath = os.path.dirname(os.path.abspath(args[0]))
sys.path.insert(0, fullpath)
module_name = os.path.splitext(os.path.basename(args[0]))[0]
sys.argv = args
runpy.run_module(module_name)
CmdRunScript.register()

View File

@ -1,36 +0,0 @@
# w.c.s. - web application for online forms
# Copyright (C) 2005-2010 Entr'ouvert
#
# This program 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 2 of the License, or
# (at your option) any later version.
#
# This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
# Most of this code is copied from the shell command [1] of the project Django
# release 1.4. Many thanks to them.
#
# [1]: file django/core/management/commands/shell.py
import sys
from ..qommon.ctl import Command
class CmdShell(Command):
'''(obsolete) Launch a shell and initialize a publisher on a given host'''
name = 'shell'
def execute(self, base_options, sub_options, args):
print('Error: use wcs-manage shell command', file=sys.stderr)
CmdShell.register()

View File

@ -1,161 +0,0 @@
# w.c.s. - web application for online forms
# Copyright (C) 2005-2010 Entr'ouvert
#
# This program 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 2 of the License, or
# (at your option) any later version.
#
# This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
import configparser
import optparse # noqa pylint: disable=deprecated-module
import os
import sys
from optparse import make_option # noqa pylint: disable=deprecated-module
__all__ = [
'Command',
]
from wcs import qommon
from . import _
qommon._commands = {}
class Command:
doc = ''
name = None
usage_args = '[ options ... ]'
def __init__(self, options=None):
options = options or []
self.config = configparser.ConfigParser()
self.options = options + [
make_option('--app-dir', metavar='DIR', action='store', dest='app_dir', default=None),
make_option('--data-dir', metavar='DIR', action='store', dest='data_dir', default=None),
]
def run(self, args, base_options):
if base_options.configfile:
if not os.path.exists(base_options.configfile):
print('Missing configuration file %s' % base_options.configfile, file=sys.stderr)
sys.exit(1)
try:
self.config.read(base_options.configfile)
except configparser.ParsingError as e:
print('Invalid configuration file %s' % base_options.configfile, file=sys.stderr)
print(e, file=sys.stderr)
sys.exit(1)
if not self.config.has_section('main'):
self.config.add_section('main')
sub_options, args = self.parse_args(args)
if sub_options.app_dir:
self.config.set('main', 'app_dir', sub_options.app_dir)
if sub_options.data_dir:
self.config.set('main', 'data_dir', sub_options.data_dir)
return self.execute(base_options, sub_options, args)
def parse_args(self, args):
self.parser = optparse.OptionParser(
usage='%%prog %s %s' % (self.name, _(self.usage_args)), description=self.doc
)
self.parser.add_options(self.options)
return self.parser.parse_args(args)
def execute(self, base_options, sub_options, args):
"""The body of the command"""
raise NotImplementedError
@classmethod
def register(cls):
qommon._commands[cls.name] = cls
class Ctl:
def __init__(self, cmd_prefixes=None):
self.cmd_prefixes = cmd_prefixes or []
self.parser = optparse.OptionParser(
usage='%prog [ -f config ] command [ options ... ]', add_help_option=False
)
self.parser.disable_interspersed_args()
self.parser.add_option(
'-f',
'--file',
action='store',
metavar='CONFIG',
type='string',
dest='configfile',
help=_('use a non default configuration file'),
)
self.parser.add_option(
'--help', action='callback', callback=self.print_help, help=_('Display this help and exit')
)
def load_all_commands(self, ignore_errors=True):
for cmd_prefix in self.cmd_prefixes:
if not cmd_prefix in sys.modules:
__import__(cmd_prefix)
mod = sys.modules.get(cmd_prefix)
if not mod:
continue
if os.path.isdir(mod.__file__):
cmddir = os.path.abspath(mod.__file__)
else:
cmddir = os.path.abspath(os.path.dirname(mod.__file__))
for fname in os.listdir(os.path.join(cmddir)):
name, ext = os.path.splitext(fname)
if not ext == '.py':
continue
if name.startswith('_'):
continue
try:
__import__('%s.%s' % (cmd_prefix, name))
except ImportError as e:
if not ignore_errors:
raise e
def get_commands(self):
return qommon._commands
def print_help(self, *args):
self.parser.print_help()
self.load_all_commands()
print()
commands = sorted((x.name, x.doc) for x in self.get_commands().values())
print('Available commands:')
for name, description in commands:
print(' %-15s %s' % (name, description))
sys.exit(0)
def run(self, args):
options, args = self.parser.parse_args(args)
if not args:
self.parser.error('You must use a command')
command, args = args[0], args[1:]
if command not in self.get_commands():
# load a module named like the command, this is the common case
for cmd_prefix in self.cmd_prefixes:
try:
__import__('%s.%s' % (cmd_prefix, command))
except ImportError:
pass
if command not in self.get_commands():
# if the command could not be loaded from a same-name module,
# go over all modules
self.load_all_commands()
command_class = self.get_commands()[command]
cmd = command_class()
return cmd.run(args, options)

View File

@ -1,11 +0,0 @@
#! /usr/bin/env python3
import os
import sys
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'wcs.settings')
import wcs.qommon.ctl
ctl = wcs.qommon.ctl.Ctl(cmd_prefixes=['wcs.ctl'])
ctl.run(sys.argv[1:])