Merge pull request #2948 from ostcar/getgeiss
Added the command getgeiss
This commit is contained in:
commit
f1c0821dd0
@ -115,7 +115,8 @@ Other:
|
||||
- Added function utils.auth.anonymous_is_enabled which returns true, if it is.
|
||||
- Changed has_perm to support an user id or None (for anyonmous) as first argument.
|
||||
- Removed our AnonymousUser. Make sure not to use user.has_perm() anymore.
|
||||
- Added Russia translation (Thanks to Andreas Engler).
|
||||
- Add the command getgeiss to download the latest version of Geiss.
|
||||
- Added Russian translation (Thanks to Andreas Engler).
|
||||
|
||||
|
||||
Version 2.0 (2016-04-18)
|
||||
|
@ -47,6 +47,7 @@ virtual environment::
|
||||
$ cd OpenSlides
|
||||
$ python3 -m venv .virtualenv
|
||||
$ source .virtualenv/bin/activate
|
||||
$ pip install -U setuptools
|
||||
|
||||
|
||||
c. Install OpenSlides
|
||||
|
@ -1,19 +1,22 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from django.core.management import execute_from_command_line
|
||||
import django
|
||||
from django.core.management import call_command, execute_from_command_line
|
||||
|
||||
from openslides import __version__ as openslides_version
|
||||
from openslides.utils.main import (
|
||||
ExceptionArgumentParser,
|
||||
UnknownCommand,
|
||||
get_default_settings_path,
|
||||
get_geiss_path,
|
||||
get_local_settings_path,
|
||||
is_local_installation,
|
||||
open_browser,
|
||||
setup_django_settings_module,
|
||||
start_browser,
|
||||
write_settings,
|
||||
)
|
||||
|
||||
@ -98,6 +101,7 @@ def get_parser():
|
||||
'start',
|
||||
description=start_help,
|
||||
help=start_help)
|
||||
subcommand_start.set_defaults(callback=start)
|
||||
subcommand_start.add_argument(
|
||||
'--no-browser',
|
||||
action='store_true',
|
||||
@ -117,11 +121,14 @@ def get_parser():
|
||||
action='store',
|
||||
default=None,
|
||||
help='The used settings file. The file is created, if it does not exist.')
|
||||
subcommand_start.set_defaults(callback=start)
|
||||
subcommand_start.add_argument(
|
||||
'--local-installation',
|
||||
action='store_true',
|
||||
help='Store settings and user files in a local directory.')
|
||||
subcommand_start.add_argument(
|
||||
'--use-geiss',
|
||||
action='store_true',
|
||||
help='Use Geiss instead of Daphne as ASGI protocol server.')
|
||||
|
||||
# Subcommand createsettings
|
||||
createsettings_help = 'Creates the settings file.'
|
||||
@ -177,29 +184,62 @@ def start(args):
|
||||
# Set the django setting module and run migrations
|
||||
# A manual given environment variable will be overwritten
|
||||
setup_django_settings_module(settings_path, local_installation=local_installation)
|
||||
django.setup()
|
||||
from django.conf import settings
|
||||
|
||||
execute_from_command_line(['manage.py', 'migrate'])
|
||||
# Migrate database
|
||||
call_command('migrate')
|
||||
|
||||
# Open the browser
|
||||
if not args.no_browser:
|
||||
if args.host == '0.0.0.0':
|
||||
# Windows does not support 0.0.0.0, so use 'localhost' instead
|
||||
start_browser('http://localhost:%s' % args.port)
|
||||
else:
|
||||
start_browser('http://%s:%s' % (args.host, args.port))
|
||||
if args.use_geiss:
|
||||
# Make sure Redis is used.
|
||||
if settings.CHANNEL_LAYERS['default']['BACKEND'] != 'asgi_redis.RedisChannelLayer':
|
||||
raise RuntimeError("You have to use the ASGI Redis backend in the settings to use Geiss.")
|
||||
|
||||
# Start the webserver
|
||||
# Use flag --noreload to tell Django not to reload the server.
|
||||
# Use flag --insecure to serve static files even if DEBUG is False.
|
||||
# Use flag --nothreading to tell Django Channels to run in single thread mode.
|
||||
execute_from_command_line([
|
||||
'manage.py',
|
||||
'runserver',
|
||||
'{}:{}'.format(args.host, args.port),
|
||||
'--noreload',
|
||||
'--insecure',
|
||||
'--nothreading',
|
||||
])
|
||||
# Download Geiss and collect the static files.
|
||||
call_command('getgeiss')
|
||||
call_command('collectstatic', interactive=False)
|
||||
|
||||
# Open the browser
|
||||
if not args.no_browser:
|
||||
open_browser(args.host, args.port)
|
||||
|
||||
# Start Geiss in its own thread
|
||||
subprocess.Popen([
|
||||
get_geiss_path(),
|
||||
'--host', args.host,
|
||||
'--port', args.port,
|
||||
'--static', '/static/:{}'.format(settings.STATIC_ROOT),
|
||||
'--static', '/media/:{}'.format(settings.MEDIA_ROOT),
|
||||
])
|
||||
|
||||
# Start one worker in this thread. There can be only one worker as
|
||||
# long as SQLite3 is used.
|
||||
call_command('runworker')
|
||||
|
||||
else:
|
||||
# Open the browser
|
||||
if not args.no_browser:
|
||||
open_browser(args.host, args.port)
|
||||
|
||||
# Start Daphne and one worker
|
||||
#
|
||||
# Use flag --noreload to tell Django not to reload the server.
|
||||
# Therefor we have to set the keyword noreload to False because Django
|
||||
# parses this directly to the use_reloader keyword.
|
||||
#
|
||||
# Use flag --insecure to serve static files even if DEBUG is False.
|
||||
#
|
||||
# Use flag --nothreading to tell Django Channels to run in single
|
||||
# thread mode with one worker only. Therefor we have to set the keyword
|
||||
# nothreading to False because Django parses this directly to
|
||||
# use_threading keyword.
|
||||
call_command(
|
||||
'runserver',
|
||||
'{}:{}'.format(args.host, args.port),
|
||||
noreload=False, # Means True, see above.
|
||||
insecure=True,
|
||||
nothreading=False, # Means True, see above.
|
||||
)
|
||||
|
||||
|
||||
def createsettings(args):
|
||||
|
75
openslides/core/management/commands/getgeiss.py
Normal file
75
openslides/core/management/commands/getgeiss.py
Normal file
@ -0,0 +1,75 @@
|
||||
import json
|
||||
import os
|
||||
import stat
|
||||
import sys
|
||||
from urllib.request import urlopen, urlretrieve
|
||||
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
|
||||
from openslides.utils.main import get_geiss_path
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
"""
|
||||
Command to get the latest release of Geiss from GitHub.
|
||||
"""
|
||||
help = 'Get the latest Geiss release from GitHub.'
|
||||
|
||||
def handle(self, *args, **options):
|
||||
geiss_github_name = self.get_geiss_github_name()
|
||||
download_file = get_geiss_path()
|
||||
|
||||
if os.path.isfile(download_file):
|
||||
# Geiss does probably exist. Do nothing.
|
||||
# TODO: Add an update flag, that downloads geiss anyway.
|
||||
return
|
||||
|
||||
response = urlopen(self.get_geiss_url()).read()
|
||||
release = json.loads(response.decode())
|
||||
download_url = None
|
||||
for asset in release['assets']:
|
||||
if asset['name'] == geiss_github_name:
|
||||
download_url = asset['browser_download_url']
|
||||
break
|
||||
if download_url is None:
|
||||
raise CommandError("Could not find download URL in release.")
|
||||
|
||||
urlretrieve(download_url, download_file)
|
||||
|
||||
# Set the executable bit on the file. This will do nothing on windows
|
||||
st = os.stat(download_file)
|
||||
os.chmod(download_file, st.st_mode | stat.S_IEXEC)
|
||||
|
||||
self.stdout.write(self.style.SUCCESS('Geiss successfully downloaded.'))
|
||||
|
||||
def get_geiss_url(self):
|
||||
"""
|
||||
Returns the URL to the API which gives the information which Geiss
|
||||
binary has to be downloaded.
|
||||
|
||||
Currently this is a static GitHub URL to the repository where geiss
|
||||
is hosted at the moment.
|
||||
"""
|
||||
# TODO: Use a settings variable or a command line flag in the future.
|
||||
return 'https://api.github.com/repos/ostcar/geiss/releases/latest'
|
||||
|
||||
def get_geiss_github_name(self):
|
||||
"""
|
||||
Returns the name of the Geiss executable for the current operating
|
||||
system.
|
||||
|
||||
For example geiss_windows_64 on a windows64 platform.
|
||||
"""
|
||||
# This will be 32 if the current python interpreter has only
|
||||
# 32 bit, even if it is run on a 64 bit operating sysem.
|
||||
bits = '64' if sys.maxsize > 2**32 else '32'
|
||||
|
||||
geiss_names = {
|
||||
'linux': 'geiss_linux_{bits}',
|
||||
'win32': 'geiss_windows_{bits}.exe', # Yes, it is win32, even on a win64 system!
|
||||
'darwin': 'geiss_mac_{bits}'}
|
||||
|
||||
try:
|
||||
return geiss_names[sys.platform].format(bits=bits)
|
||||
except KeyError:
|
||||
raise CommandError("Plattform {} is not supported by Geiss".format(sys.platform))
|
@ -81,8 +81,6 @@ LOCALE_PATHS = [
|
||||
|
||||
STATIC_URL = '/static/'
|
||||
|
||||
STATIC_ROOT = os.path.join(MODULE_DIR, '..', 'collected-static')
|
||||
|
||||
STATICFILES_DIRS = [
|
||||
os.path.join(MODULE_DIR, 'static'),
|
||||
]
|
||||
@ -134,6 +132,7 @@ CACHES = {
|
||||
|
||||
# Django Channels
|
||||
# http://channels.readthedocs.io/en/latest/
|
||||
# https://github.com/ostcar/geiss
|
||||
|
||||
CHANNEL_LAYERS = {
|
||||
'default': {
|
||||
|
@ -261,6 +261,18 @@ def write_settings(settings_path=None, template=None, **context):
|
||||
return os.path.realpath(settings_path)
|
||||
|
||||
|
||||
def open_browser(host, port):
|
||||
"""
|
||||
Launches the default web browser at the given host and port and opens
|
||||
the webinterface. Uses start_browser internally.
|
||||
"""
|
||||
if host == '0.0.0.0':
|
||||
# Windows does not support 0.0.0.0, so use 'localhost' instead
|
||||
start_browser('http://localhost:%s' % port)
|
||||
else:
|
||||
start_browser('http://%s:%s' % (host, port))
|
||||
|
||||
|
||||
def start_browser(browser_url):
|
||||
"""
|
||||
Launches the default web browser at the given url and opens the
|
||||
@ -323,3 +335,20 @@ def is_local_installation():
|
||||
This is the case if manage.py is used, or when the --local-installation flag is set.
|
||||
"""
|
||||
return True if '--local-installation' in sys.argv or 'manage.py' in sys.argv[0] else False
|
||||
|
||||
|
||||
def get_geiss_path():
|
||||
"""
|
||||
Returns the path and file to the Geiss binary.
|
||||
"""
|
||||
from django.conf import settings
|
||||
download_path = getattr(settings, 'OPENSLIDES_USER_DATA_PATH', '')
|
||||
bin_name = 'geiss.exe' if is_windows() else 'geiss'
|
||||
return os.path.join(download_path, bin_name)
|
||||
|
||||
|
||||
def is_windows():
|
||||
"""
|
||||
Returns True if the current system is Windows. Returns False otherwise.
|
||||
"""
|
||||
return sys.platform == 'win32'
|
||||
|
@ -123,6 +123,8 @@ TIME_ZONE = 'Europe/Berlin'
|
||||
|
||||
STATICFILES_DIRS = [os.path.join(OPENSLIDES_USER_DATA_PATH, 'static')] + STATICFILES_DIRS
|
||||
|
||||
STATIC_ROOT = os.path.join(OPENSLIDES_USER_DATA_PATH, 'collected-static')
|
||||
|
||||
|
||||
# Files
|
||||
# https://docs.djangoproject.com/en/1.10/topics/files/
|
||||
|
@ -1,6 +1,6 @@
|
||||
import re
|
||||
import roman
|
||||
|
||||
import roman
|
||||
|
||||
CAMEL_CASE_TO_PSEUDO_SNAKE_CASE_CONVERSION_REGEX_1 = re.compile('(.)([A-Z][a-z]+)')
|
||||
CAMEL_CASE_TO_PSEUDO_SNAKE_CASE_CONVERSION_REGEX_2 = re.compile('([a-z0-9])([A-Z])')
|
||||
|
Loading…
Reference in New Issue
Block a user