From 5cc7f57b1c1f115c9f56811d2fb8aa4e0c858bfb Mon Sep 17 00:00:00 2001 From: Roland Geider Date: Wed, 2 Sep 2020 12:58:13 +0200 Subject: [PATCH] Simplify create-settings tasks and others Create settings now uses the current path per default, which simplifies the initial project setup --- README.rst | 18 +-- docs/development.rst | 9 +- docs/production.rst | 6 +- extras/docker/apache/Dockerfile | 8 +- extras/docker/development-venv/Dockerfile | 8 +- extras/docker/development/entrypoint.sh | 4 +- manage.py | 4 +- wger/settings.tpl | 4 +- wger/tasks.py | 162 +++++----------------- 9 files changed, 57 insertions(+), 166 deletions(-) diff --git a/README.rst b/README.rst index d29c700ba..b8f221b50 100644 --- a/README.rst +++ b/README.rst @@ -24,8 +24,8 @@ parameters. Docker ------ -Useful to just try it out. Check the documentation on how to use the wger/devel -docker image or the docker-compose file for development:: +Useful to just try it out. Check the REAMES in wger/extras/docker on how to use +the wger/devel docker image or the docker-compose file for development:: docker run -ti --name wger.apache --publish 8000:80 wger/apache @@ -62,8 +62,8 @@ Then install the python packages from pypi in the virtualenv:: $ cd wger $ pip install -r requirements.txt $ python setup.py develop - $ wger create-settings --settings-path $(pwd)/settings.py --database-path $(pwd)/database.sqlite - $ wger bootstrap --settings-path $(pwd)/settings.py --no-start-server + $ wger create-settings + $ wger bootstrap $ python manage.py runserver 3) Log in as: **admin**, password **admin** @@ -109,10 +109,12 @@ You can get a list of all available commands by calling ``wger`` without any arguments:: Available tasks: - - bootstrap Performs all steps necessary to bootstrap the application - config-location Returns the default location for the settings file and the data folder - create-or-reset-admin Creates an admin user or resets the password for an existing one + bootstrap Performs all steps necessary to bootstrap the + application + config-location Returns the default location for the settings file + and the data folder + create-or-reset-admin Creates an admin user or resets the password for an + existing one create-settings Creates a local settings file load-fixtures Loads all fixtures migrate-db Run all database migrations diff --git a/docs/development.rst b/docs/development.rst index a8e95daa7..967108a51 100644 --- a/docs/development.rst +++ b/docs/development.rst @@ -21,7 +21,6 @@ Get the code $ git clone https://github.com/wger-project/wger.git src $ cd src - $ WGER_PATH=$(pwd) Install Requirements ~~~~~~~~~~~~~~~~~~~~ @@ -38,12 +37,8 @@ This will download the required JS and CSS libraries and create a SQlite database and populate it with data on the first run:: - $ wger create-settings \ - --settings-path $WGER_PATH/settings.py \ - --database-path $WGER_PATH/database.sqlite - $ wger bootstrap \ - --settings-path $WGER_PATH/settings.py \ - --no-start-server + $ wger create-settings + $ wger bootstrap You can of course also use other databases such as postgres or mariaDB. Create a database and user and edit the DATABASES settings before calling bootstrap. diff --git a/docs/production.rst b/docs/production.rst index 7ccba2dc9..ccbcbce67 100644 --- a/docs/production.rst +++ b/docs/production.rst @@ -116,9 +116,7 @@ Get the application:: npm install -g yarn sass python setup.py develop pip install psycopg2 # Only if using postgres - wger create-settings \ - --settings-path /home/wger/src/settings.py \ - --database-path /home/wger/db/database.sqlite + wger create-settings --database-path /home/wger/db/database.sqlite If you are using postgres, you need to edit the settings file and set the correct values for the database (use ``django.db.backends.postgresql_psycopg2`` @@ -128,7 +126,7 @@ for the engine). Also set ``MEDIA_ROOT`` to ``/home/wger/media`` and Run the installation script, this will download some CSS and JS libraries and load all initial data:: - wger bootstrap --settings-path /home/wger/src/settings.py --no-start-server + wger bootstrap Collect all static resources:: diff --git a/extras/docker/apache/Dockerfile b/extras/docker/apache/Dockerfile index 3e1a6feea..7301c59f5 100644 --- a/extras/docker/apache/Dockerfile +++ b/extras/docker/apache/Dockerfile @@ -85,12 +85,8 @@ RUN . /home/wger/venv/bin/activate \ && pip install wheel \ && pip install --no-cache /wheels/* \ && python setup.py develop \ - && wger create-settings \ - --settings-path /home/wger/src/settings.py \ - --database-path /home/wger/db/database.sqlite \ - && wger bootstrap \ - --settings-path /home/wger/src/settings.py \ - --no-start-server + && wger create-settings --database-path /home/wger/db/database.sqlite \ + && wger bootstrap # Change permissions of some files and folders so the apache process diff --git a/extras/docker/development-venv/Dockerfile b/extras/docker/development-venv/Dockerfile index 41148195a..341e9406c 100644 --- a/extras/docker/development-venv/Dockerfile +++ b/extras/docker/development-venv/Dockerfile @@ -66,12 +66,8 @@ RUN . /home/wger/venv/bin/activate \ && pip install --upgrade pip \ && pip install --no-cache /wheels/* \ && python setup.py develop \ - && wger create-settings \ - --settings-path /home/wger/src/settings.py \ - --database-path /home/wger/db/database.sqlite \ - && wger bootstrap \ - --settings-path /home/wger/src/settings.py \ - --no-start-server + && wger create-settings --database-path /home/wger/db/database.sqlite \ + && wger bootstrap # Download the exercise images RUN mkdir ~/media \ diff --git a/extras/docker/development/entrypoint.sh b/extras/docker/development/entrypoint.sh index 6265ab7c3..4a7f45994 100644 --- a/extras/docker/development/entrypoint.sh +++ b/extras/docker/development/entrypoint.sh @@ -17,9 +17,7 @@ if [[ "$DJANGO_DB_PORT" == "5432" ]]; then fi # Bootstrap the application -wger bootstrap \ - --settings-path /home/wger/src/settings.py \ - --no-start-server +wger bootstrap if [[ "$WGER_DOWNLOAD_IMGS" == "TRUE" ]]; then diff --git a/manage.py b/manage.py index f79cb6c7e..c35ed859a 100644 --- a/manage.py +++ b/manage.py @@ -8,7 +8,7 @@ from django.core.management import execute_from_command_line # wger from wger.tasks import ( - get_user_config_path, + get_path, setup_django_environment ) @@ -17,7 +17,7 @@ if __name__ == "__main__": # If user passed the settings flag ignore the default wger settings if not any('--settings' in s for s in sys.argv): - setup_django_environment(get_user_config_path('wger', 'settings.py')) + setup_django_environment(get_path('settings.py')) # Alternative to above # os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings") diff --git a/wger/settings.tpl b/wger/settings.tpl index b1b875615..fa4136214 100644 --- a/wger/settings.tpl +++ b/wger/settings.tpl @@ -18,7 +18,7 @@ MANAGERS = ADMINS DATABASES = {{ 'default': {{ 'ENGINE': 'django.db.backends.{dbengine}', - 'NAME': {dbname}, + 'NAME': '{dbname}', 'USER': '{dbuser}', 'PASSWORD': '{dbpassword}', 'HOST': '{dbhost}', @@ -44,7 +44,7 @@ SITE_URL = '{siteurl}' # Path to uploaded files # Absolute filesystem path to the directory that will hold user-uploaded files. -MEDIA_ROOT = {media_folder_path} +MEDIA_ROOT = '{media_folder_path}' MEDIA_URL = '/media/' # Allow all hosts to access the application. Change if used in production. diff --git a/wger/tasks.py b/wger/tasks.py index f6a1dea31..4d6d5f4a6 100644 --- a/wger/tasks.py +++ b/wger/tasks.py @@ -15,14 +15,11 @@ # You should have received a copy of the GNU Affero General Public License # Standard Library -import ctypes import logging import os +import pathlib import socket import sys -import threading -import time -import webbrowser # Django import django @@ -41,8 +38,7 @@ logger = logging.getLogger(__name__) @task(help={'address': 'Address to bind to. Default: localhost', 'port': 'Port to use. Default: 8000', - 'browser': 'Whether to open the application in a browser window. Default: false', - 'settings-path': 'Path to settings file (absolute path recommended). Leave empty for ' + 'settings-path': 'Path to settings file (absolute path). Leave empty for ' 'default', 'extra-args': 'Additional arguments to pass to the builtin server. Pass as string: ' '"--arg1 --arg2=value". Default: none'}) @@ -51,8 +47,6 @@ def start(context, address='localhost', port=8000, browser=False, settings_path= """ Start the application using django's built in webserver """ - if browser: - start_browser("http://{0}:{1}".format(address, port)) # Find the path to the settings and setup the django environment setup_django_environment(settings_path) @@ -65,37 +59,22 @@ def start(context, address='localhost', port=8000, browser=False, settings_path= execute_from_command_line(argv) -@task(help={'settings-path': 'Path to settings file (absolute path recommended). Leave empty for ' +@task(help={'settings-path': 'Path to settings file (absolute path). Leave empty for ' 'default', - 'database-path': 'Path to sqlite database (absolute path recommended). Leave empty ' - 'for default', - 'address': 'Address to use. Default: localhost', - 'port': 'Port to use. Default: 8000', - 'browser': 'Whether to open the application in a browser window. Default: false', - 'start-server': 'Whether to start the development server. Default: true'}) + 'database-path': 'Path to sqlite database (absolute path). Leave empty ' + 'for default'}) def bootstrap(context, settings_path=None, - database_path=None, - address='localhost', - port=8000, - browser=False, - start_server=True): + database_path=None): """ Performs all steps necessary to bootstrap the application """ - # Find url to wger - address, port = detect_listen_opts(address, port) - if port == 80: - url = "http://{0}".format(address) - else: - url = "http://{0}:{1}".format(address, port) - # Create settings if necessary if settings_path is None: - settings_path = get_user_config_path('wger', 'settings.py') + settings_path = get_path('settings.py') if not os.path.exists(settings_path): - create_settings(context, settings_path=settings_path, database_path=database_path, url=url) + create_settings(context, settings_path=settings_path, database_path=database_path) # Find the path to the settings and setup the django environment setup_django_environment(settings_path) @@ -111,39 +90,36 @@ def bootstrap(context, context.run("yarn install") context.run("sass core/static/scss/main.scss:core/static/yarn/bootstrap-compiled.css") - # Start the webserver - if start_server: - print('*** Bootstraping complete, starting application') - start(context, address=address, port=port, browser=browser, settings_path=settings_path) - -@task(help={'settings-path': 'Path to settings file (absolute path recommended). Leave empty for ' +@task(help={'settings-path': 'Path to settings file (absolute path). Leave empty for ' 'default', - 'database-path': 'Path to sqlite database (absolute path recommended). Leave empty ' + 'database-path': 'Path to sqlite database (absolute path). Leave empty ' 'for default', 'database-type': 'Database type to use. Supported: sqlite3, postgresql. Default: ' 'sqlite3', - 'key-length': 'Lenght of the generated secret key. Default: 50'}) -def create_settings(context, settings_path=None, database_path=None, url=None, - database_type='sqlite3', key_length=50): + 'key-length': 'Length of the generated secret key. Default: 50'}) +def create_settings(context, + settings_path=None, + database_path=None, + database_type='sqlite3', + key_length=50): """ Creates a local settings file """ if settings_path is None: - settings_path = get_user_config_path('wger', 'settings.py') + settings_path = get_path('settings.py') settings_module = os.path.dirname(settings_path) print("*** Creating settings file at {0}".format(settings_module)) if database_path is None: - database_path = get_user_data_path('wger', 'database.sqlite') - dbpath_value = repr(database_path) + database_path = get_path('database.sqlite').as_posix() + dbpath_value = database_path - media_folder_path = repr(get_user_data_path('wger', 'media')) + media_folder_path = get_path('media').as_posix() # Use localhost with default django port if no URL given - if url is None: - url = 'http://localhost:8000' + url = 'http://localhost:8000' # Fill in the config file template settings_template = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'settings.tpl') @@ -153,7 +129,7 @@ def create_settings(context, settings_path=None, database_path=None, url=None, # The environment variable is set by travis during testing if database_type == 'postgresql': dbengine = 'postgresql_psycopg2' - dbname = "'test_wger'" + dbname = 'test_wger' dbuser = 'postgres' dbpassword = '' dbhost = '127.0.0.1' @@ -191,7 +167,7 @@ def create_settings(context, settings_path=None, database_path=None, url=None, settings_file.write(settings_content) -@task(help={'settings-path': 'Path to settings file (absolute path recommended). Leave empty for ' +@task(help={'settings-path': 'Path to settings file (absolute path). Leave empty for ' 'default'}) def create_or_reset_admin(context, settings_path=None): """ @@ -217,7 +193,7 @@ def create_or_reset_admin(context, settings_path=None): call_command("loaddata", path + "users.json") -@task(help={'settings-path': 'Path to settings file (absolute path recommended). Leave empty for ' +@task(help={'settings-path': 'Path to settings file (absolute path). Leave empty for ' 'default'}) def migrate_db(context, settings_path=None): """ @@ -230,7 +206,7 @@ def migrate_db(context, settings_path=None): call_command("migrate") -@task(help={'settings-path': 'Path to settings file (absolute path recommended). Leave empty for ' +@task(help={'settings-path': 'Path to settings file (absolute path). Leave empty for ' 'default'}) def load_fixtures(context, settings_path=None): """ @@ -290,9 +266,9 @@ def config_location(context): Returns the default location for the settings file and the data folder """ print('Default locations:') - print('* settings: {0}'.format(get_user_config_path('wger', 'settings.py'))) - print('* media folder: {0}'.format(get_user_data_path('wger', 'media'))) - print('* database path: {0}'.format(get_user_data_path('wger', 'database.sqlite'))) + print('* settings: {0}'.format(get_path('settings.py'))) + print('* media folder: {0}'.format(get_path('media'))) + print('* database path: {0}'.format(get_path('database.sqlite'))) # @@ -304,67 +280,11 @@ def config_location(context): # packaged has a different sys path than the local one) # - -def get_user_data_path(*args): - if sys.platform == "win32": - return win32_get_app_data_path(*args) - - data_home = os.environ.get( - 'XDG_DATA_HOME', os.path.join( - os.path.expanduser('~'), '.local', 'share')) - - return os.path.join(data_home, *args) - - -def get_user_config_path(*args): - if sys.platform == "win32": - return win32_get_app_data_path(*args) - - config_home = os.environ.get( - 'XDG_CONFIG_HOME', os.path.join(os.path.expanduser('~'), '.config')) - - return os.path.join(config_home, *args) - - -def win32_get_app_data_path(*args): - shell32 = ctypes.WinDLL("shell32.dll") - SHGetFolderPath = shell32.SHGetFolderPathW - SHGetFolderPath.argtypes = ( - ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_uint32, - ctypes.c_wchar_p) - SHGetFolderPath.restype = ctypes.c_uint32 - - CSIDL_LOCAL_APPDATA = 0x001c - MAX_PATH = 260 - - buf = ctypes.create_unicode_buffer(MAX_PATH) - res = SHGetFolderPath(0, CSIDL_LOCAL_APPDATA, 0, 0, buf) - if res != 0: - raise Exception("Could not deterime APPDATA path") - - return os.path.join(buf.value, *args) - - -def detect_listen_opts(address, port): - if address is None: - try: - address = socket.gethostbyname(socket.gethostname()) - except socket.error: - address = "127.0.0.1" - - if port is None: - # test if we can use port 80 - s = socket.socket() - port = 80 - try: - s.bind((address, port)) - s.listen(-1) - except socket.error: - port = 8000 - finally: - s.close() - - return address, port +def get_path(file="settings.py") -> pathlib.Path: + """ + Return the path of the given file relatively to the wger source folder + """ + return pathlib.Path(__file__).parent.absolute() / file def setup_django_environment(settings_path): @@ -374,7 +294,7 @@ def setup_django_environment(settings_path): # Use default settings if the user didn't specify something else if settings_path is None: - settings_path = get_user_config_path('wger', 'settings.py') + settings_path = get_path('settings.py').as_posix() print('*** No settings given, using {0}'.format(settings_path)) # Find out file path and fine name of settings and setup django @@ -411,17 +331,3 @@ def database_exists(): sys.exit(0) else: return True - - -def start_browser(url): - """ - Start the web browser with the given URL - """ - browser = webbrowser.get() - - def function(): - time.sleep(1) - browser.open(url) - - thread = threading.Thread(target=function) - thread.start()