From: Guillaume Pellerin Date: Wed, 2 Dec 2015 08:31:27 +0000 (+0100) Subject: try to simplify docker composition X-Git-Tag: 1.6b~7^2~39^2~14 X-Git-Url: https://git.parisson.com/?a=commitdiff_plain;h=ef5144103658b7db73792f7a76f7599355fcb46a;p=telemeta.git try to simplify docker composition --- diff --git a/Dockerfile b/Dockerfile index 138c9d35..59842d76 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,13 +19,17 @@ FROM parisson/timeside:latest-dev MAINTAINER Guillaume Pellerin , Thomas fillon -# Clone app -RUN mkdir /opt/Telemeta -ADD . /opt/Telemeta -WORKDIR /opt/Telemeta - -# Install deps +RUN mkdir /opt/app RUN mkdir /opt/src + +WORKDIR /opt/app + +ADD requirements.txt /opt/app/ +ADD requirements-dev.txt /opt/app/ +ADD setup.py /opt/app/ +ADD README.rst /opt/app/ +ADD telemeta /opt/app/ + RUN pip install -r requirements.txt RUN pip install -r requirements-dev.txt --src /opt/src diff --git a/app/__init__.py b/app/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/app/deploy/apt-app.list b/app/deploy/apt-app.list new file mode 100644 index 00000000..81a807a5 --- /dev/null +++ b/app/deploy/apt-app.list @@ -0,0 +1,12 @@ +deb http://ftp.debian.org/debian/ wheezy-backports main contrib non-free +deb-src http://ftp.debian.org/debian/ wheezy-backports main contrib non-free + +deb http://security.debian.org/ wheezy/updates main +deb-src http://security.debian.org/ wheezy/updates main + +deb http://www.deb-multimedia.org wheezy main non-free +deb http://www.deb-multimedia.org wheezy-backports main + +deb http://debian.parisson.com/debian/ wheezy main +deb-src http://debian.parisson.com/debian wheezy main + diff --git a/app/deploy/celery_app.sh b/app/deploy/celery_app.sh new file mode 100644 index 00000000..87fda082 --- /dev/null +++ b/app/deploy/celery_app.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +# paths +app='/opt/app' +manage=$app'/manage.py' +wsgi=$app'/wsgi.py' + +# stating apps +pip install django-haystack elasticsearch + +# waiting for other services +sh $app/deploy/wait.sh + +# Starting celery worker with the --autoreload option will enable the worker to watch for file system changes +# This is an experimental feature intended for use in development only +# see http://celery.readthedocs.org/en/latest/userguide/workers.html#autoreloading +$manage celery worker --autoreload -A celery_app diff --git a/app/deploy/nginx-app.conf b/app/deploy/nginx-app.conf new file mode 100644 index 00000000..d1f07b92 --- /dev/null +++ b/app/deploy/nginx-app.conf @@ -0,0 +1,27 @@ +server_tokens off; + +server { + listen 80; + server_name nginx; + charset utf-8; + + access_log /var/log/nginx/app-access.log; + error_log /var/log/nginx/app-error.log; + + # max upload size + client_max_body_size 4096M; # adjust to taste + + # Django media + location /media { + alias /opt/media; # your Django project's media files - amend as required + } + # Django static + location /static { + alias /opt/static; # your Django project's static files - amend as required + } + + location / { + uwsgi_pass app:8000; + include /etc/nginx/uwsgi_params; + } +} diff --git a/app/deploy/start_app.sh b/app/deploy/start_app.sh new file mode 100644 index 00000000..9f6cc120 --- /dev/null +++ b/app/deploy/start_app.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +# paths + + +app='/opt/app' +manage=$app'/manage.py' +wsgi=$app'/wsgi.py' +static='/opt/static/' + +# stating apps +pip install django-haystack elasticsearch + +# waiting for other services +sh $app/deploy/wait.sh + +# django init +python $manage syncdb --noinput +python $manage migrate --noinput +python $manage collectstatic --noinput +python $manage telemeta-create-admin-user +python $manage telemeta-create-boilerplate +python $manage update_index + +# static files auto update +watchmedo shell-command --patterns="*.js;*.css" --recursive \ + --command='python '$manage' collectstatic --noinput' $static & + +# app start +uwsgi --socket :8000 --wsgi-file $wsgi --chdir $app --master --processes 4 --threads 2 --py-autoreload 3 diff --git a/app/deploy/wait.sh b/app/deploy/wait.sh new file mode 100644 index 00000000..a3341e05 --- /dev/null +++ b/app/deploy/wait.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +apt-get install -y --force-yes netcat + +set -e + +host=$(env | grep _TCP_ADDR | cut -d = -f 2) +port=$(env | grep _TCP_PORT | cut -d = -f 2) + +echo -n "waiting for TCP connection to $host:$port..." + +while ! nc -w 1 $host $port 2>/dev/null +do + echo -n . + sleep 1 +done + +echo 'ok' \ No newline at end of file diff --git a/app/fixtures/original_format.txt b/app/fixtures/original_format.txt new file mode 100644 index 00000000..1a5bc133 --- /dev/null +++ b/app/fixtures/original_format.txt @@ -0,0 +1,38 @@ +Bande magnétique 6,25mm (1/4') +Bande magnétique mini-Nagra 3,81mm +Cassette analogique +Cassette analogique Type I (Fe) +Cassette analogique Type II (CrO2) +Cassette analogique Type IV (Metal) +Cylindre de cire à gravure directe +Cylindre de cire édité +Fil magnétique +Disque à gravure directe +Disque 78 tours +Disque 45 tours +Disque 33 tours +Cassette audionumérique PCM F1 Betamax +Cassette audionumérique PCM 1610/1630 U-Matic +Cassette audionumérique DAT +Cassette audionumérique DAT 48 kHz +Cassette audionumérique DAT 44,1 kHz +Cassette audionumérique DAT 32 kHz +Bande magnétique audionumérique 1/4" (DASH, ProDigi, EIAJ-C, Nagra-D) +Mini-Disc +CD-A (Audio édité) +CD-R Audio +CD-RW Audio +CD-R Data +CD-ROM édité +CD-RW Data +DVD-R Data +DVD+R Data +DVD-ROM édité +DVD-RW Data +DVD+RW Data +BD-ROM édité (Blu-ray) +BD-R (Blu-ray enregistrable) +BD-RE (Blu-ray réinscriptible) +Disque dur (HDD) +Carte mémoire +SSD diff --git a/app/manage.py b/app/manage.py new file mode 100755 index 00000000..d18fd971 --- /dev/null +++ b/app/manage.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python +import os, sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "sandbox.settings") + + from django.core.management import execute_from_command_line + + execute_from_command_line(sys.argv) diff --git a/app/sandbox/__init__.py b/app/sandbox/__init__.py new file mode 100644 index 00000000..40a96afc --- /dev/null +++ b/app/sandbox/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/app/sandbox/celery_app.py b/app/sandbox/celery_app.py new file mode 100644 index 00000000..7e9d7f86 --- /dev/null +++ b/app/sandbox/celery_app.py @@ -0,0 +1,24 @@ +from __future__ import absolute_import + +import os + +from celery import Celery + +from django.conf import settings + +# set the default Django settings module for the 'celery' program. +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings') + +app = Celery('sandbox') + +# Using a string here means the worker will not have to +# pickle the object when using Windows. +app.config_from_object('django.conf:settings') +app.autodiscover_tasks(lambda: settings.INSTALLED_APPS) +# app.conf.update( +# CELERY_RESULT_BACKEND='djcelery.backends.database:DatabaseBackend', +# ) + +@app.task(bind=True) +def debug_task(self): + print('Request: {0!r}'.format(self.request)) diff --git a/app/sandbox/diag.sh b/app/sandbox/diag.sh new file mode 100755 index 00000000..5f6c1e59 --- /dev/null +++ b/app/sandbox/diag.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +app="telemeta" +dir="../../doc/devel" + +python modelviz.py -a > $dir/$app-all.dot +python modelviz.py $app > $dir/$app.dot + +dot $dir/$app-all.dot -Tpdf -o $dir/$app-all.pdf +dot $dir/$app.dot -Tpdf -o $dir/$app.pdf + +rsync -a $dir/ doc.parisson.com:/var/www/files/doc/$app/diagram/ diff --git a/app/sandbox/modelviz.py b/app/sandbox/modelviz.py new file mode 100644 index 00000000..24af0627 --- /dev/null +++ b/app/sandbox/modelviz.py @@ -0,0 +1,359 @@ +#!/usr/bin/env python + +"""Django model to DOT (Graphviz) converter +by Antonio Cavedoni + +Make sure your DJANGO_SETTINGS_MODULE is set to your project or +place this script in the same directory of the project and call +the script like this: + +$ python modelviz.py [-h] [-a] [-d] [-g] [-n] [-L ] [-i ] ... > .dot +$ dot .dot -Tpng -o .png + +options: + -h, --help + show this help message and exit. + + -a, --all_applications + show models from all applications. + + -d, --disable_fields + don't show the class member fields. + + -g, --group_models + draw an enclosing box around models from the same app. + + -i, --include_models=User,Person,Car + only include selected models in graph. + + -n, --verbose_names + use verbose_name for field and models. + + -L, --language + specify language used for verrbose_name localization + + -x, --exclude_columns + exclude specific column(s) from the graph. + + -X, --exclude_models + exclude specific model(s) from the graph. + + -e, --inheritance + show inheritance arrows. +""" +__version__ = "0.9" +__svnid__ = "$Id$" +__license__ = "Python" +__author__ = "Antonio Cavedoni " +__contributors__ = [ + "Stefano J. Attardi ", + "limodou ", + "Carlo C8E Miron", + "Andre Campos ", + "Justin Findlay ", + "Alexander Houben ", + "Bas van Oostveen ", + "Joern Hees " +] + +import os +import sys +import getopt + +from django.core.management import setup_environ + +try: + import settings +except ImportError: + pass +else: + setup_environ(settings) + +from django.utils.translation import activate as activate_language +from django.utils.safestring import mark_safe +from django.template import Template, Context, loader +from django.db import models +from django.db.models import get_models +from django.db.models.fields.related import \ + ForeignKey, OneToOneField, ManyToManyField, RelatedField + +try: + from django.db.models.fields.generic import GenericRelation +except ImportError: + from django.contrib.contenttypes.generic import GenericRelation + +def parse_file_or_list(arg): + if not arg: + return [] + if not ',' in arg and os.path.isfile(arg): + return [e.strip() for e in open(arg).readlines()] + return arg.split(',') + + +def generate_dot(app_labels, **kwargs): + disable_fields = kwargs.get('disable_fields', False) + include_models = parse_file_or_list(kwargs.get('include_models', "")) + all_applications = kwargs.get('all_applications', False) + use_subgraph = kwargs.get('group_models', False) + verbose_names = kwargs.get('verbose_names', False) + inheritance = kwargs.get('inheritance', False) + language = kwargs.get('language', None) + if language is not None: + activate_language(language) + exclude_columns = parse_file_or_list(kwargs.get('exclude_columns', "")) + exclude_models = parse_file_or_list(kwargs.get('exclude_models', "")) + + def skip_field(field): + if exclude_columns: + if verbose_names and field.verbose_name: + if field.verbose_name in exclude_columns: + return True + if field.name in exclude_columns: + return True + return False + + + + + t = loader.get_template('django_extensions/graph_models/head.html') + c = Context({}) + dot = t.render(c) + + apps = [] + if all_applications: + apps = models.get_apps() + + for app_label in app_labels: + app = models.get_app(app_label) + if not app in apps: + apps.append(app) + + graphs = [] + for app in apps: + graph = Context({ + 'name': '"%s"' % app.__name__, + 'app_name': "%s" % '.'.join(app.__name__.split('.')[:-1]), + 'cluster_app_name': "cluster_%s" % app.__name__.replace(".", "_"), + 'disable_fields': disable_fields, + 'use_subgraph': use_subgraph, + 'models': [] + }) + + appmodels = get_models(app) + abstract_models = [] + for appmodel in appmodels: + abstract_models = abstract_models + [abstract_model for abstract_model in appmodel.__bases__ if hasattr(abstract_model, '_meta') and abstract_model._meta.abstract] + abstract_models = list(set(abstract_models)) # remove duplicates + appmodels = abstract_models + appmodels + + + for appmodel in appmodels: + appmodel_abstracts = [abstract_model.__name__ for abstract_model in appmodel.__bases__ if hasattr(abstract_model, '_meta') and abstract_model._meta.abstract] + + # collect all attribs of abstract superclasses + def getBasesAbstractFields(c): + _abstract_fields = [] + for e in c.__bases__: + if hasattr(e, '_meta') and e._meta.abstract: + _abstract_fields.extend(e._meta.fields) + _abstract_fields.extend(getBasesAbstractFields(e)) + return _abstract_fields + abstract_fields = getBasesAbstractFields(appmodel) + + model = { + 'app_name': appmodel.__module__.replace(".", "_"), + 'name': appmodel.__name__, + 'abstracts': appmodel_abstracts, + 'fields': [], + 'relations': [] + } + + # consider given model name ? + def consider(model_name): + if exclude_models and model_name in exclude_models: + return False + return not include_models or model_name in include_models + + if not consider(appmodel._meta.object_name): + continue + + if verbose_names and appmodel._meta.verbose_name: + model['label'] = appmodel._meta.verbose_name + else: + model['label'] = model['name'] + + # model attributes + def add_attributes(field): + if verbose_names and field.verbose_name: + label = field.verbose_name + else: + label = field.name + + t = type(field).__name__ + if isinstance(field, (OneToOneField, ForeignKey)): + t += " ({0})".format(field.rel.field_name) + # TODO: ManyToManyField, GenericRelation + + model['fields'].append({ + 'name': field.name, + 'label': label, + 'type': t, + 'blank': field.blank, + 'abstract': field in abstract_fields, + }) + + # Find all the real attributes. Relations are depicted as graph edges instead of attributes + attributes = [field for field in appmodel._meta.local_fields if not isinstance(field, RelatedField)] + + # find primary key and print it first, ignoring implicit id if other pk exists + pk = appmodel._meta.pk + if not appmodel._meta.abstract and pk in attributes: + add_attributes(pk) + for field in attributes: + if skip_field(field): + continue + if not field.primary_key: + add_attributes(field) + + # FIXME: actually many_to_many fields aren't saved in this model's db table, so why should we add an attribute-line for them in the resulting graph? + #if appmodel._meta.many_to_many: + # for field in appmodel._meta.many_to_many: + # if skip_field(field): + # continue + # add_attributes(field) + + # relations + def add_relation(field, extras=""): + if verbose_names and field.verbose_name: + label = field.verbose_name + else: + label = field.name + + # show related field name + if hasattr(field, 'related_query_name'): + label += ' (%s)' % field.related_query_name() + + _rel = { + 'target_app': field.rel.to.__module__.replace('.', '_'), + 'target': field.rel.to.__name__, + 'type': type(field).__name__, + 'name': field.name, + 'label': label, + 'arrows': extras, + 'needs_node': True + } + if _rel not in model['relations'] and consider(_rel['target']): + model['relations'].append(_rel) + + for field in appmodel._meta.local_fields: + if field.attname.endswith('_ptr_id'): # excluding field redundant with inheritance relation + continue + if field in abstract_fields: # excluding fields inherited from abstract classes. they too show as local_fields + continue + if skip_field(field): + continue + if isinstance(field, OneToOneField): + add_relation(field, '[arrowhead=none, arrowtail=none]') + elif isinstance(field, ForeignKey): + add_relation(field, '[arrowhead=none, arrowtail=dot]') + + for field in appmodel._meta.local_many_to_many: + if skip_field(field): + continue + if isinstance(field, ManyToManyField): + if (getattr(field, 'creates_table', False) or # django 1.1. + (hasattr(field.rel.through, '_meta') and field.rel.through._meta.auto_created)): # django 1.2 + add_relation(field, '[arrowhead=dot arrowtail=dot, dir=both]') + elif isinstance(field, GenericRelation): + add_relation(field, mark_safe('[style="dotted", arrowhead=normal, arrowtail=normal, dir=both]')) + + if inheritance: + # add inheritance arrows + for parent in appmodel.__bases__: + if hasattr(parent, "_meta"): # parent is a model + l = "multi-table" + if parent._meta.abstract: + l = "abstract" + if appmodel._meta.proxy: + l = "proxy" + l += r"\ninheritance" + _rel = { + 'target_app': parent.__module__.replace(".", "_"), + 'target': parent.__name__, + 'type': "inheritance", + 'name': "inheritance", + 'label': l, + 'arrows': '[arrowhead=empty, arrowtail=none]', + 'needs_node': True + } + # TODO: seems as if abstract models aren't part of models.getModels, which is why they are printed by this without any attributes. + if _rel not in model['relations'] and consider(_rel['target']): + model['relations'].append(_rel) + + graph['models'].append(model) + graphs.append(graph) + + nodes = [] + for graph in graphs: + nodes.extend([e['name'] for e in graph['models']]) + + for graph in graphs: + # don't draw duplication nodes because of relations + for model in graph['models']: + for relation in model['relations']: + if relation['target'] in nodes: + relation['needs_node'] = False + # render templates + t = loader.get_template('django_extensions/graph_models/body.html') + dot += '\n' + t.render(graph) + + for graph in graphs: + t = loader.get_template('django_extensions/graph_models/rel.html') + dot += '\n' + t.render(graph) + + + t = loader.get_template('django_extensions/graph_models/tail.html') + c = Context({}) + dot += '\n' + t.render(c) + return dot + +def main(): + try: + opts, args = getopt.getopt(sys.argv[1:], "hadgi:L:x:X:en", + ["help", "all_applications", "disable_fields", "group_models", "include_models=", "inheritance", "verbose_names", "language=", "exclude_columns=", "exclude_models="]) + except getopt.GetoptError, error: + print __doc__ + sys.exit(error) + + kwargs = {} + for opt, arg in opts: + if opt in ("-h", "--help"): + print __doc__ + sys.exit() + if opt in ("-a", "--all_applications"): + kwargs['all_applications'] = True + if opt in ("-d", "--disable_fields"): + kwargs['disable_fields'] = True + if opt in ("-g", "--group_models"): + kwargs['group_models'] = True + if opt in ("-i", "--include_models"): + kwargs['include_models'] = arg + if opt in ("-e", "--inheritance"): + kwargs['inheritance'] = True + if opt in ("-n", "--verbose-names"): + kwargs['verbose_names'] = True + if opt in ("-L", "--language"): + kwargs['language'] = arg + if opt in ("-x", "--exclude_columns"): + kwargs['exclude_columns'] = arg + if opt in ("-X", "--exclude_models"): + kwargs['exclude_models'] = arg + + if not args and not kwargs.get('all_applications', False): + print __doc__ + sys.exit() + + print generate_dot(args, **kwargs) + +if __name__ == "__main__": + main() diff --git a/app/sandbox/robots.txt b/app/sandbox/robots.txt new file mode 100644 index 00000000..5ac75ebe --- /dev/null +++ b/app/sandbox/robots.txt @@ -0,0 +1,4 @@ +User-agent: * +Disallow: *.mp3$ +Disallow: */WIDTHxHEIGHT/ +Disallow: */xml/ diff --git a/app/sandbox/settings.py b/app/sandbox/settings.py new file mode 100644 index 00000000..271f14b2 --- /dev/null +++ b/app/sandbox/settings.py @@ -0,0 +1,304 @@ +# -*- coding: utf-8 -*- +# Django settings for sandbox project. + +import os, sys +from django.core.urlresolvers import reverse_lazy, reverse + +sys.dont_write_bytecode = True + +DEBUG = True +TEMPLATE_DEBUG = DEBUG + +ALLOWED_HOSTS = ['*'] + +ADMINS = ( + ('Guillaume Pellerin', 'yomguy@parisson.com'), +) + +MANAGERS = ADMINS + +# Full filesystem path to the project. +#PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__)) +PROJECT_ROOT = '/opt/app/' + +DATABASES = { + 'default': { + # SQLite config + # 'ENGINE': 'django.db.backends.sqlite', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'. + # 'NAME': os.path.join(PROJECT_ROOT, 'telemeta.sql'), # Or path to database file if using sqlite3. + # 'OPTIONS': { + # 'timeout': 60, + # } + + # MySQL config + 'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'. + 'USER': 'telemeta', # Not used with sqlite3. + 'PASSWORD': 'iuvIlkyisFit2', # Not used with sqlite3. + 'NAME': 'telemeta', + 'HOST': 'db', # Set to empty string for localhost. Not used with sqlite3. + 'PORT': '3306', # Set to empty string for default. Not used with sqlite3. + } +} + +# Local time zone for this installation. Choices can be found here: +# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name +# although not all choices may be available on all operating systems. +# On Unix systems, a value of None will cause Django to use the same +# timezone as the operating system. +# If running in a Windows environment this must be set to the same as your +# system time zone. +TIME_ZONE = 'Europe/Paris' + +# Language code for this installation. All choices can be found here: +# http://www.i18nguy.com/unicode/language-identifiers.html +#LANGUAGE_CODE = 'fr_FR' + +LANGUAGES = [ ('fr', 'French'), + ('en', 'English'), + ('de', 'German'), + ('zh_CN', 'Simplified Chinese'), + ('ar_TN', 'Arabic'), + ('pt_BR', 'Portuguese'), +] + +SITE_ID = 1 + +# If you set this to False, Django will make some optimizations so as not +# to load the internationalization machinery. +USE_I18N = True + +# If you set this to False, Django will not format dates, numbers and +# calendars according to the current locale +USE_L10N = True + +# Absolute path to the directory that holds media. +# Example: "/home/media/media.lawrence.com/" +# MEDIA_ROOT = PROJECT_ROOT + '/media/' +# +# if not os.path.exists(MEDIA_ROOT): +# os.makedirs(MEDIA_ROOT) + +MEDIA_ROOT = '/opt/media/' + +# URL that handles the media served from MEDIA_ROOT. Make sure to use a +# trailing slash if there is a path component (optional in other cases). +# Examples: "http://media.lawrence.com", "http://example.com/media/" +MEDIA_URL = '/media/' + +# Absolute path to the directory static files should be collected to. +# Don't put anything in this directory yourself; store your static files +# in apps' "static/" subdirectories and in STATICFILES_DIRS. +# Example: "/home/media/media.lawrence.com/static/" +# STATIC_ROOT = '/var/www/static' +STATIC_ROOT = '/opt/static/' + +# URL prefix for static files. +# Example: "http://media.lawrence.com/static/" +STATIC_URL = '/static/' + +# Additional locations of static files +STATICFILES_DIRS = ( +# Put strings here, like "/home/html/static" or "C:/www/django/static". +# Always use forward slashes, even on Windows. +# Don't forget to use absolute paths, not relative paths. +) + +# List of finder classes that know how to find static files in +# various locations. +STATICFILES_FINDERS = ( +'django.contrib.staticfiles.finders.FileSystemFinder', +'django.contrib.staticfiles.finders.AppDirectoriesFinder', +# 'django.contrib.staticfiles.finders.DefaultStorageFinder', +) +# Make this unique, and don't share it with anybody. +SECRET_KEY = 'a8l7%06wr2k+3=%#*#@#rvop2mmzko)44%7k(zx%lls^ihm9^5' + +# List of callables that know how to import templates from various sources. +TEMPLATE_LOADERS = ( + 'django.template.loaders.filesystem.Loader', + 'django.template.loaders.app_directories.Loader', +# 'django.template.loaders.eggs.Loader', +) + + +MIDDLEWARE_CLASSES = ( + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.locale.LocaleMiddleware', + # 'pagination.middleware.PaginationMiddleware', +) + +ROOT_URLCONF = 'sandbox.urls' + +TEMPLATE_DIRS = ( + # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". + # Always use forward slashes, even on Windows. + # Don't forget to use absolute paths, not relative paths. +) + +INSTALLED_APPS = ( + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.sites', + 'django.contrib.messages', + 'suit', + 'django.contrib.admin', + 'django.contrib.staticfiles', + 'django_extensions', + 'telemeta', + 'timeside.player', + 'timeside.server', + 'jsonrpc', + 'south', + 'sorl.thumbnail', + 'timezones', + 'jqchat', + 'ipauth', + 'extra_views', + 'debug_toolbar', + 'bootstrap3', + 'bootstrap_pagination', + 'googletools', + 'registration', + 'rest_framework', + 'djcelery', + 'haystack', +) + +TEMPLATE_CONTEXT_PROCESSORS = ( + 'django.core.context_processors.request', + 'django.contrib.auth.context_processors.auth', + "django.core.context_processors.i18n", + "django.core.context_processors.media", + 'django.core.context_processors.static', + 'django.contrib.messages.context_processors.messages', +) + + +AUTHENTICATION_BACKENDS = ( + 'django.contrib.auth.backends.ModelBackend', + 'ipauth.backend.RangeBackend', +) + +SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies" + +TELEMETA_ORGANIZATION = 'Telemeta' +TELEMETA_SUBJECTS = ('Telemeta', 'web', 'platform', 'audio', 'semantics') +TELEMETA_DESCRIPTION = "Open web audio platform with semantics" +TELEMETA_LOGO = STATIC_URL + 'telemeta/images/logo_telemeta_2.png' + +TELEMETA_GMAP_KEY = 'ABQIAAAArg7eSfnfTkBRma8glnGrlxRVbMrhnNNvToCbZQtWdaMbZTA_3RRGObu5PDoiBImgalVnnLU2yN4RMA' + +TELEMETA_CACHE_DIR = os.path.join(MEDIA_ROOT, 'cache') +TELEMETA_EXPORT_CACHE_DIR = os.path.join(MEDIA_ROOT, 'export') +TELEMETA_DATA_CACHE_DIR = os.path.join(TELEMETA_CACHE_DIR, 'data') + +TELEMETA_DOWNLOAD_ENABLED = True +TELEMETA_STREAMING_FORMATS = ('mp3', 'ogg') +TELEMETA_DOWNLOAD_FORMATS = ('wav', 'mp3', 'ogg', 'flac') +TELEMETA_PUBLIC_ACCESS_PERIOD = 51 + +TELEMETA_STRICT_CODE = False + +AUTH_PROFILE_MODULE = 'telemeta.userprofile' +SESSION_EXPIRE_AT_BROWSER_CLOSE = False + +LOGIN_URL = '/login/' +LOGIN_REDIRECT_URL = '/desk/lists/' + +EMAIL_HOST = 'localhost' +DEFAULT_FROM_EMAIL = 'webmaster@parisson.com' + +TIMESIDE_DEFAULT_GRAPHER_ID = 'waveform_centroid' +TIMESIDE_DEFAULT_WAVEFORM_SIZES = ['346x130', '640x130'] +TIMESIDE_AUTO_ZOOM = False + +# Settings for django-bootstrap3 +BOOTSTRAP3 = { + 'set_required': True, + 'set_placeholder': False, + 'error_css_class': 'has-error', + 'required_css_class': 'has-warning', + 'javascript_in_head': True, +} + +PAGINATION_SETTINGS = { + 'PAGE_RANGE_DISPLAYED': 10, + 'MARGIN_PAGES_DISPLAYED': 2, +} + +DEBUG_TOOLBAR_PATCH_SETTINGS = False +DEBUG_TOOLBAR_PANELS = [ + 'debug_toolbar.panels.versions.VersionsPanel', + 'debug_toolbar.panels.timer.TimerPanel', + 'debug_toolbar.panels.settings.SettingsPanel', + 'debug_toolbar.panels.headers.HeadersPanel', + 'debug_toolbar.panels.request.RequestPanel', + 'debug_toolbar.panels.sql.SQLPanel', + 'debug_toolbar.panels.staticfiles.StaticFilesPanel', + 'debug_toolbar.panels.templates.TemplatesPanel', + 'debug_toolbar.panels.cache.CachePanel', + 'debug_toolbar.panels.signals.SignalsPanel', + 'debug_toolbar.panels.logging.LoggingPanel', + 'debug_toolbar.panels.redirects.RedirectsPanel', +] + +SUIT_CONFIG = { + 'ADMIN_NAME': 'Telemeta Admin' +} + +# A sample logging configuration. The only tangible logging +# performed by this configuration is to send an email to +# the site admins on every HTTP 500 error when DEBUG=False. +# See http://docs.djangoproject.com/en/dev/topics/logging for +# more details on how to customize your logging configuration. +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'filters': { + 'require_debug_false': { + '()': 'django.utils.log.RequireDebugFalse' + } + }, + 'handlers': { + 'mail_admins': { + 'level': 'ERROR', + 'filters': ['require_debug_false'], + 'class': 'django.utils.log.AdminEmailHandler' + } + }, + 'loggers': { + 'django.request': { + 'handlers': ['mail_admins'], + 'level': 'ERROR', + 'propagate': True, + }, + } +} + +# replace rabbitmq by localhost if you start your app outside docker-compose +BROKER_URL = 'amqp://guest:guest@broker//' + +CELERY_IMPORTS = ("timeside.server.tasks",) +CELERY_RESULT_BACKEND='djcelery.backends.database:DatabaseBackend' +CELERY_TASK_SERIALIZER = "json" +CELERY_ACCEPT_CONTENT = ['application/json'] + +from celery_app import app + + +HAYSTACK_CONNECTIONS = { + 'default': { + 'ENGINE': 'haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine', + 'URL': 'http://search:9200/', + 'INDEX_NAME': 'haystack', + }, +} + +HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor' + +HAYSTACK_SEARCH_RESULTS_PER_PAGE = 50 diff --git a/app/sandbox/update_schema.sh b/app/sandbox/update_schema.sh new file mode 100755 index 00000000..31c658a1 --- /dev/null +++ b/app/sandbox/update_schema.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +./manage.py schemamigration telemeta --auto +./manage.py migrate telemeta + diff --git a/app/sandbox/urls.py b/app/sandbox/urls.py new file mode 100644 index 00000000..b1950363 --- /dev/null +++ b/app/sandbox/urls.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +from django.conf.urls import patterns, url, include +from django.http import HttpResponse +import os + +# Uncomment the next two lines to enable the admin: +from django.contrib import admin +admin.autodiscover() + +js_info_dict = { + 'packages': ('telemeta',), +} + +PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__)) +robots_rules = open(PROJECT_ROOT + os.sep + 'robots.txt', 'r').read() + +urlpatterns = patterns('', + # Example: + # (r'^sandbox/', include('sandbox.foo.urls')), + + # Uncomment the admin/doc line below and add 'django.contrib.admindocs' + # to INSTALLED_APPS to enable admin documentation: + # (r'^admin/doc/', include('django.contrib.admindocs.urls')), + + # Uncomment the next line to enable the admin: + (r'^admin/django/', include(admin.site.urls)), + #(r'^grappelli/', include('grappelli.urls')), # grappelli URLS + + # Telemeta + (r'^', include('telemeta.urls')), + + # Languages + (r'^i18n/', include('django.conf.urls.i18n')), + (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict), + (r'^robots\.txt$', lambda r: HttpResponse(robots_rules, mimetype="text/plain")), + + ) diff --git a/app/wsgi.py b/app/wsgi.py new file mode 100644 index 00000000..6b05fff1 --- /dev/null +++ b/app/wsgi.py @@ -0,0 +1,18 @@ +#!/usr/bin/python2.5 +# -*- coding: utf-8 -*- + +import os +import sys + +here = os.path.dirname(__file__) +sys.path.append(here) + +# os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' +# +# import django.core.handlers.wsgi +# application = django.core.handlers.wsgi.WSGIHandler() + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "sandbox.settings") + +from django.core.wsgi import get_wsgi_application +application = get_wsgi_application() diff --git a/doc/content/README.rst b/doc/content/README.rst index 3b3e2d4d..7ea21365 100644 --- a/doc/content/README.rst +++ b/doc/content/README.rst @@ -5,7 +5,7 @@ Telemeta: open web audio platform with semantics :category: About :Pin: true -.. image:: /Telemeta/images/logo_telemeta_2.png +.. image:: /images/logo_telemeta_2.png :alt: Telemeta logo Overview @@ -205,4 +205,3 @@ The Telemeta project is developed by Parisson. It is sponsored by : http://www.mmsh.univ-aix.fr/ * MNHN : Museum d'Histoire Naturelle (Paris, France) http://www.mnhn.fr - diff --git a/doc/pelicanconf.py b/doc/pelicanconf.py index 2591ffa3..55f32129 100644 --- a/doc/pelicanconf.py +++ b/doc/pelicanconf.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- # from __future__ import unicode_literals -AUTHOR = u'Parisson Sarl' +AUTHOR = u'Parisson SARL' SITENAME = u'Telemeta project' TIMEZONE = 'Europe/Paris' @@ -45,7 +45,10 @@ SOCIAL = (('GitHub', 'https://github.com/Parisson/Telemeta'), #RELATIVE_URLS = True PLUGIN_PATHS = ['pelican-plugins'] -PLUGINS = ['pin_to_top'] +PLUGINS = ['pin_to_top', 'sitemap', 'gallery', 'render_math', + 'liquid_tags.img', 'liquid_tags.video', + 'liquid_tags.youtube', 'liquid_tags.vimeo', + 'liquid_tags.include_code', 'liquid_tags.notebook',] STATIC_PATHS = ['images', 'css'] CUSTOM_CSS = 'css/custom.css' @@ -68,3 +71,18 @@ GITHUB_USER = 'Parisson' # Content licensing: CC-BY CC_LICENSE = "CC-BY" + +SITEMAP = { + + 'format': 'xml', + 'priorities': { + 'articles': 0.5, + 'indexes': 0.5, + 'pages': 0.5 + }, + 'changefreqs': { + 'articles': 'monthly', + 'indexes': 'daily', + 'pages': 'monthly' + } +} diff --git a/docker-compose.yml b/docker-compose.yml index 68633642..446b5354 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -22,16 +22,11 @@ # Thomas Fillon -static: +media: image: debian:wheezy volumes: - - /var/www/static - command: "true" - -home: - image: debian:wheezy - volumes: - - ./examples/sandbox:/home/sandbox + - ./media/:/opt/media + - ./static/:/opt/static command: "true" db: @@ -45,7 +40,7 @@ db: - MYSQL_USER=telemeta - MYSQL_PASSWORD=iuvIlkyisFit2 -rabbitmq: +broker: image: rabbitmq:3-management ports: - "15672:15672" @@ -56,18 +51,16 @@ search: app: build: . volumes: - - .:/opt/Telemeta - - /var/log/uwsgi + - ./app/:/opt/app volumes_from: - - static - - home - command: /bin/sh /opt/Telemeta/examples/deploy/start_app.sh + - media + command: /bin/sh deploy/start_app.sh ports: - "9000:9000" expose: - "8000" links: - - rabbitmq + - broker - db - search @@ -75,10 +68,9 @@ worker: build: . volumes_from: - app - - home - command: /bin/sh /opt/Telemeta/examples/deploy/celery_app.sh + command: /bin/sh deploy/celery_app.sh links: - - rabbitmq + - broker - db nginx: @@ -86,10 +78,9 @@ nginx: ports: - "8000:80" volumes: - - ./examples/deploy/nginx-app.conf:/etc/nginx/conf.d/default.conf - - /var/log/nginx + - ./app/deploy/nginx-app.conf:/etc/nginx/conf.d/default.conf + - ./log/:/var/log/nginx volumes_from: - - static - - home + - media links: - app diff --git a/examples/deploy/apt-app.list b/examples/deploy/apt-app.list deleted file mode 100644 index 81a807a5..00000000 --- a/examples/deploy/apt-app.list +++ /dev/null @@ -1,12 +0,0 @@ -deb http://ftp.debian.org/debian/ wheezy-backports main contrib non-free -deb-src http://ftp.debian.org/debian/ wheezy-backports main contrib non-free - -deb http://security.debian.org/ wheezy/updates main -deb-src http://security.debian.org/ wheezy/updates main - -deb http://www.deb-multimedia.org wheezy main non-free -deb http://www.deb-multimedia.org wheezy-backports main - -deb http://debian.parisson.com/debian/ wheezy main -deb-src http://debian.parisson.com/debian wheezy main - diff --git a/examples/deploy/celery_app.sh b/examples/deploy/celery_app.sh deleted file mode 100644 index ac08e3c3..00000000 --- a/examples/deploy/celery_app.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh - -# paths -app_dir='/opt/Telemeta' -sandbox='/home/sandbox' -manage=$sandbox'/manage.py' -wsgi=$sandbox'/wsgi.py' - -# stating apps -pip install django-haystack elasticsearch - -# waiting for other services -sh $app_dir/examples/deploy/wait.sh - -# Starting celery worker with the --autoreload option will enable the worker to watch for file system changes -# This is an experimental feature intended for use in development only -# see http://celery.readthedocs.org/en/latest/userguide/workers.html#autoreloading -$manage celery worker --autoreload -A celery_app diff --git a/examples/deploy/nginx-app.conf b/examples/deploy/nginx-app.conf deleted file mode 100644 index 53cba5f9..00000000 --- a/examples/deploy/nginx-app.conf +++ /dev/null @@ -1,30 +0,0 @@ -server_tokens off; - -server { - listen 80; - server_name nginx; - charset utf-8; - - access_log /var/log/nginx/app-access.log; - error_log /var/log/nginx/app-error.log; - - # max upload size - client_max_body_size 4096M; # adjust to taste - - # Django media - location /media { - alias /home/sandbox/media; # your Django project's media files - amend as required - autoindex on; - } - # Django static - location /static { - alias /var/www/static; # your Django project's static files - amend as required - autoindex on; - } - - location / { - uwsgi_pass app:8000; - include /etc/nginx/uwsgi_params; - } -} - diff --git a/examples/deploy/start_app.sh b/examples/deploy/start_app.sh deleted file mode 100644 index 47179f85..00000000 --- a/examples/deploy/start_app.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/sh - -# paths -app_dir='/opt/Telemeta' -static=$app_dir'/telemeta/static/' -sandbox='/home/sandbox' -manage=$sandbox'/manage.py' -wsgi=$sandbox'/wsgi.py' - -# stating apps -pip install django-haystack elasticsearch - -# waiting for other services -sh $app_dir/examples/deploy/wait.sh - -# django init -python $manage syncdb --noinput -python $manage migrate --noinput -python $manage collectstatic --noinput -python $manage telemeta-create-admin-user -python $manage telemeta-create-boilerplate -python $manage update_index - -# static files auto update -watchmedo shell-command --patterns="*.js;*.css" --recursive \ - --command='python '$manage' collectstatic --noinput' $static & - -# app start -uwsgi --socket :8000 --wsgi-file $wsgi --chdir $sandbox --master --processes 4 --threads 2 --py-autoreload 3 diff --git a/examples/deploy/wait.sh b/examples/deploy/wait.sh deleted file mode 100644 index a3341e05..00000000 --- a/examples/deploy/wait.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh - -apt-get install -y --force-yes netcat - -set -e - -host=$(env | grep _TCP_ADDR | cut -d = -f 2) -port=$(env | grep _TCP_PORT | cut -d = -f 2) - -echo -n "waiting for TCP connection to $host:$port..." - -while ! nc -w 1 $host $port 2>/dev/null -do - echo -n . - sleep 1 -done - -echo 'ok' \ No newline at end of file diff --git a/examples/fixtures/original_format.txt b/examples/fixtures/original_format.txt deleted file mode 100644 index 1a5bc133..00000000 --- a/examples/fixtures/original_format.txt +++ /dev/null @@ -1,38 +0,0 @@ -Bande magnétique 6,25mm (1/4') -Bande magnétique mini-Nagra 3,81mm -Cassette analogique -Cassette analogique Type I (Fe) -Cassette analogique Type II (CrO2) -Cassette analogique Type IV (Metal) -Cylindre de cire à gravure directe -Cylindre de cire édité -Fil magnétique -Disque à gravure directe -Disque 78 tours -Disque 45 tours -Disque 33 tours -Cassette audionumérique PCM F1 Betamax -Cassette audionumérique PCM 1610/1630 U-Matic -Cassette audionumérique DAT -Cassette audionumérique DAT 48 kHz -Cassette audionumérique DAT 44,1 kHz -Cassette audionumérique DAT 32 kHz -Bande magnétique audionumérique 1/4" (DASH, ProDigi, EIAJ-C, Nagra-D) -Mini-Disc -CD-A (Audio édité) -CD-R Audio -CD-RW Audio -CD-R Data -CD-ROM édité -CD-RW Data -DVD-R Data -DVD+R Data -DVD-ROM édité -DVD-RW Data -DVD+RW Data -BD-ROM édité (Blu-ray) -BD-R (Blu-ray enregistrable) -BD-RE (Blu-ray réinscriptible) -Disque dur (HDD) -Carte mémoire -SSD diff --git a/examples/sandbox/__init__.py b/examples/sandbox/__init__.py deleted file mode 100644 index 40a96afc..00000000 --- a/examples/sandbox/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/examples/sandbox/celery_app.py b/examples/sandbox/celery_app.py deleted file mode 100644 index 7e9d7f86..00000000 --- a/examples/sandbox/celery_app.py +++ /dev/null @@ -1,24 +0,0 @@ -from __future__ import absolute_import - -import os - -from celery import Celery - -from django.conf import settings - -# set the default Django settings module for the 'celery' program. -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings') - -app = Celery('sandbox') - -# Using a string here means the worker will not have to -# pickle the object when using Windows. -app.config_from_object('django.conf:settings') -app.autodiscover_tasks(lambda: settings.INSTALLED_APPS) -# app.conf.update( -# CELERY_RESULT_BACKEND='djcelery.backends.database:DatabaseBackend', -# ) - -@app.task(bind=True) -def debug_task(self): - print('Request: {0!r}'.format(self.request)) diff --git a/examples/sandbox/diag.sh b/examples/sandbox/diag.sh deleted file mode 100755 index 5f6c1e59..00000000 --- a/examples/sandbox/diag.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh - -app="telemeta" -dir="../../doc/devel" - -python modelviz.py -a > $dir/$app-all.dot -python modelviz.py $app > $dir/$app.dot - -dot $dir/$app-all.dot -Tpdf -o $dir/$app-all.pdf -dot $dir/$app.dot -Tpdf -o $dir/$app.pdf - -rsync -a $dir/ doc.parisson.com:/var/www/files/doc/$app/diagram/ diff --git a/examples/sandbox/manage.py b/examples/sandbox/manage.py deleted file mode 100755 index c632a8a3..00000000 --- a/examples/sandbox/manage.py +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env python -import os, sys - -if __name__ == "__main__": - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings") - - from django.core.management import execute_from_command_line - - execute_from_command_line(sys.argv) diff --git a/examples/sandbox/modelviz.py b/examples/sandbox/modelviz.py deleted file mode 100644 index 24af0627..00000000 --- a/examples/sandbox/modelviz.py +++ /dev/null @@ -1,359 +0,0 @@ -#!/usr/bin/env python - -"""Django model to DOT (Graphviz) converter -by Antonio Cavedoni - -Make sure your DJANGO_SETTINGS_MODULE is set to your project or -place this script in the same directory of the project and call -the script like this: - -$ python modelviz.py [-h] [-a] [-d] [-g] [-n] [-L ] [-i ] ... > .dot -$ dot .dot -Tpng -o .png - -options: - -h, --help - show this help message and exit. - - -a, --all_applications - show models from all applications. - - -d, --disable_fields - don't show the class member fields. - - -g, --group_models - draw an enclosing box around models from the same app. - - -i, --include_models=User,Person,Car - only include selected models in graph. - - -n, --verbose_names - use verbose_name for field and models. - - -L, --language - specify language used for verrbose_name localization - - -x, --exclude_columns - exclude specific column(s) from the graph. - - -X, --exclude_models - exclude specific model(s) from the graph. - - -e, --inheritance - show inheritance arrows. -""" -__version__ = "0.9" -__svnid__ = "$Id$" -__license__ = "Python" -__author__ = "Antonio Cavedoni " -__contributors__ = [ - "Stefano J. Attardi ", - "limodou ", - "Carlo C8E Miron", - "Andre Campos ", - "Justin Findlay ", - "Alexander Houben ", - "Bas van Oostveen ", - "Joern Hees " -] - -import os -import sys -import getopt - -from django.core.management import setup_environ - -try: - import settings -except ImportError: - pass -else: - setup_environ(settings) - -from django.utils.translation import activate as activate_language -from django.utils.safestring import mark_safe -from django.template import Template, Context, loader -from django.db import models -from django.db.models import get_models -from django.db.models.fields.related import \ - ForeignKey, OneToOneField, ManyToManyField, RelatedField - -try: - from django.db.models.fields.generic import GenericRelation -except ImportError: - from django.contrib.contenttypes.generic import GenericRelation - -def parse_file_or_list(arg): - if not arg: - return [] - if not ',' in arg and os.path.isfile(arg): - return [e.strip() for e in open(arg).readlines()] - return arg.split(',') - - -def generate_dot(app_labels, **kwargs): - disable_fields = kwargs.get('disable_fields', False) - include_models = parse_file_or_list(kwargs.get('include_models', "")) - all_applications = kwargs.get('all_applications', False) - use_subgraph = kwargs.get('group_models', False) - verbose_names = kwargs.get('verbose_names', False) - inheritance = kwargs.get('inheritance', False) - language = kwargs.get('language', None) - if language is not None: - activate_language(language) - exclude_columns = parse_file_or_list(kwargs.get('exclude_columns', "")) - exclude_models = parse_file_or_list(kwargs.get('exclude_models', "")) - - def skip_field(field): - if exclude_columns: - if verbose_names and field.verbose_name: - if field.verbose_name in exclude_columns: - return True - if field.name in exclude_columns: - return True - return False - - - - - t = loader.get_template('django_extensions/graph_models/head.html') - c = Context({}) - dot = t.render(c) - - apps = [] - if all_applications: - apps = models.get_apps() - - for app_label in app_labels: - app = models.get_app(app_label) - if not app in apps: - apps.append(app) - - graphs = [] - for app in apps: - graph = Context({ - 'name': '"%s"' % app.__name__, - 'app_name': "%s" % '.'.join(app.__name__.split('.')[:-1]), - 'cluster_app_name': "cluster_%s" % app.__name__.replace(".", "_"), - 'disable_fields': disable_fields, - 'use_subgraph': use_subgraph, - 'models': [] - }) - - appmodels = get_models(app) - abstract_models = [] - for appmodel in appmodels: - abstract_models = abstract_models + [abstract_model for abstract_model in appmodel.__bases__ if hasattr(abstract_model, '_meta') and abstract_model._meta.abstract] - abstract_models = list(set(abstract_models)) # remove duplicates - appmodels = abstract_models + appmodels - - - for appmodel in appmodels: - appmodel_abstracts = [abstract_model.__name__ for abstract_model in appmodel.__bases__ if hasattr(abstract_model, '_meta') and abstract_model._meta.abstract] - - # collect all attribs of abstract superclasses - def getBasesAbstractFields(c): - _abstract_fields = [] - for e in c.__bases__: - if hasattr(e, '_meta') and e._meta.abstract: - _abstract_fields.extend(e._meta.fields) - _abstract_fields.extend(getBasesAbstractFields(e)) - return _abstract_fields - abstract_fields = getBasesAbstractFields(appmodel) - - model = { - 'app_name': appmodel.__module__.replace(".", "_"), - 'name': appmodel.__name__, - 'abstracts': appmodel_abstracts, - 'fields': [], - 'relations': [] - } - - # consider given model name ? - def consider(model_name): - if exclude_models and model_name in exclude_models: - return False - return not include_models or model_name in include_models - - if not consider(appmodel._meta.object_name): - continue - - if verbose_names and appmodel._meta.verbose_name: - model['label'] = appmodel._meta.verbose_name - else: - model['label'] = model['name'] - - # model attributes - def add_attributes(field): - if verbose_names and field.verbose_name: - label = field.verbose_name - else: - label = field.name - - t = type(field).__name__ - if isinstance(field, (OneToOneField, ForeignKey)): - t += " ({0})".format(field.rel.field_name) - # TODO: ManyToManyField, GenericRelation - - model['fields'].append({ - 'name': field.name, - 'label': label, - 'type': t, - 'blank': field.blank, - 'abstract': field in abstract_fields, - }) - - # Find all the real attributes. Relations are depicted as graph edges instead of attributes - attributes = [field for field in appmodel._meta.local_fields if not isinstance(field, RelatedField)] - - # find primary key and print it first, ignoring implicit id if other pk exists - pk = appmodel._meta.pk - if not appmodel._meta.abstract and pk in attributes: - add_attributes(pk) - for field in attributes: - if skip_field(field): - continue - if not field.primary_key: - add_attributes(field) - - # FIXME: actually many_to_many fields aren't saved in this model's db table, so why should we add an attribute-line for them in the resulting graph? - #if appmodel._meta.many_to_many: - # for field in appmodel._meta.many_to_many: - # if skip_field(field): - # continue - # add_attributes(field) - - # relations - def add_relation(field, extras=""): - if verbose_names and field.verbose_name: - label = field.verbose_name - else: - label = field.name - - # show related field name - if hasattr(field, 'related_query_name'): - label += ' (%s)' % field.related_query_name() - - _rel = { - 'target_app': field.rel.to.__module__.replace('.', '_'), - 'target': field.rel.to.__name__, - 'type': type(field).__name__, - 'name': field.name, - 'label': label, - 'arrows': extras, - 'needs_node': True - } - if _rel not in model['relations'] and consider(_rel['target']): - model['relations'].append(_rel) - - for field in appmodel._meta.local_fields: - if field.attname.endswith('_ptr_id'): # excluding field redundant with inheritance relation - continue - if field in abstract_fields: # excluding fields inherited from abstract classes. they too show as local_fields - continue - if skip_field(field): - continue - if isinstance(field, OneToOneField): - add_relation(field, '[arrowhead=none, arrowtail=none]') - elif isinstance(field, ForeignKey): - add_relation(field, '[arrowhead=none, arrowtail=dot]') - - for field in appmodel._meta.local_many_to_many: - if skip_field(field): - continue - if isinstance(field, ManyToManyField): - if (getattr(field, 'creates_table', False) or # django 1.1. - (hasattr(field.rel.through, '_meta') and field.rel.through._meta.auto_created)): # django 1.2 - add_relation(field, '[arrowhead=dot arrowtail=dot, dir=both]') - elif isinstance(field, GenericRelation): - add_relation(field, mark_safe('[style="dotted", arrowhead=normal, arrowtail=normal, dir=both]')) - - if inheritance: - # add inheritance arrows - for parent in appmodel.__bases__: - if hasattr(parent, "_meta"): # parent is a model - l = "multi-table" - if parent._meta.abstract: - l = "abstract" - if appmodel._meta.proxy: - l = "proxy" - l += r"\ninheritance" - _rel = { - 'target_app': parent.__module__.replace(".", "_"), - 'target': parent.__name__, - 'type': "inheritance", - 'name': "inheritance", - 'label': l, - 'arrows': '[arrowhead=empty, arrowtail=none]', - 'needs_node': True - } - # TODO: seems as if abstract models aren't part of models.getModels, which is why they are printed by this without any attributes. - if _rel not in model['relations'] and consider(_rel['target']): - model['relations'].append(_rel) - - graph['models'].append(model) - graphs.append(graph) - - nodes = [] - for graph in graphs: - nodes.extend([e['name'] for e in graph['models']]) - - for graph in graphs: - # don't draw duplication nodes because of relations - for model in graph['models']: - for relation in model['relations']: - if relation['target'] in nodes: - relation['needs_node'] = False - # render templates - t = loader.get_template('django_extensions/graph_models/body.html') - dot += '\n' + t.render(graph) - - for graph in graphs: - t = loader.get_template('django_extensions/graph_models/rel.html') - dot += '\n' + t.render(graph) - - - t = loader.get_template('django_extensions/graph_models/tail.html') - c = Context({}) - dot += '\n' + t.render(c) - return dot - -def main(): - try: - opts, args = getopt.getopt(sys.argv[1:], "hadgi:L:x:X:en", - ["help", "all_applications", "disable_fields", "group_models", "include_models=", "inheritance", "verbose_names", "language=", "exclude_columns=", "exclude_models="]) - except getopt.GetoptError, error: - print __doc__ - sys.exit(error) - - kwargs = {} - for opt, arg in opts: - if opt in ("-h", "--help"): - print __doc__ - sys.exit() - if opt in ("-a", "--all_applications"): - kwargs['all_applications'] = True - if opt in ("-d", "--disable_fields"): - kwargs['disable_fields'] = True - if opt in ("-g", "--group_models"): - kwargs['group_models'] = True - if opt in ("-i", "--include_models"): - kwargs['include_models'] = arg - if opt in ("-e", "--inheritance"): - kwargs['inheritance'] = True - if opt in ("-n", "--verbose-names"): - kwargs['verbose_names'] = True - if opt in ("-L", "--language"): - kwargs['language'] = arg - if opt in ("-x", "--exclude_columns"): - kwargs['exclude_columns'] = arg - if opt in ("-X", "--exclude_models"): - kwargs['exclude_models'] = arg - - if not args and not kwargs.get('all_applications', False): - print __doc__ - sys.exit() - - print generate_dot(args, **kwargs) - -if __name__ == "__main__": - main() diff --git a/examples/sandbox/robots.txt b/examples/sandbox/robots.txt deleted file mode 100644 index 5ac75ebe..00000000 --- a/examples/sandbox/robots.txt +++ /dev/null @@ -1,4 +0,0 @@ -User-agent: * -Disallow: *.mp3$ -Disallow: */WIDTHxHEIGHT/ -Disallow: */xml/ diff --git a/examples/sandbox/settings.py b/examples/sandbox/settings.py deleted file mode 100644 index 039dcd54..00000000 --- a/examples/sandbox/settings.py +++ /dev/null @@ -1,303 +0,0 @@ -# -*- coding: utf-8 -*- -# Django settings for sandbox project. - -import os, sys -from django.core.urlresolvers import reverse_lazy, reverse - -sys.dont_write_bytecode = True - -DEBUG = True -TEMPLATE_DEBUG = DEBUG - -ALLOWED_HOSTS = ['*'] - -ADMINS = ( - ('Guillaume Pellerin', 'yomguy@parisson.com'), -) - -MANAGERS = ADMINS - -# Full filesystem path to the project. -#PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__)) -PROJECT_ROOT = '/home/sandbox' - -DATABASES = { - 'default': { - # SQLite config - # 'ENGINE': 'django.db.backends.sqlite', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'. - # 'NAME': os.path.join(PROJECT_ROOT, 'telemeta.sql'), # Or path to database file if using sqlite3. - # 'OPTIONS': { - # 'timeout': 60, - # } - - # MySQL config - 'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'. - 'USER': 'telemeta', # Not used with sqlite3. - 'PASSWORD': 'iuvIlkyisFit2', # Not used with sqlite3. - 'NAME': 'telemeta', - 'HOST': 'db', # Set to empty string for localhost. Not used with sqlite3. - 'PORT': '3306', # Set to empty string for default. Not used with sqlite3. - } -} - -# Local time zone for this installation. Choices can be found here: -# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name -# although not all choices may be available on all operating systems. -# On Unix systems, a value of None will cause Django to use the same -# timezone as the operating system. -# If running in a Windows environment this must be set to the same as your -# system time zone. -TIME_ZONE = 'Europe/Paris' - -# Language code for this installation. All choices can be found here: -# http://www.i18nguy.com/unicode/language-identifiers.html -#LANGUAGE_CODE = 'fr_FR' - -LANGUAGES = [ ('fr', 'French'), - ('en', 'English'), - ('de', 'German'), - ('zh_CN', 'Simplified Chinese'), - ('ar_TN', 'Arabic'), - ('pt_BR', 'Portuguese'), -] - -SITE_ID = 1 - -# If you set this to False, Django will make some optimizations so as not -# to load the internationalization machinery. -USE_I18N = True - -# If you set this to False, Django will not format dates, numbers and -# calendars according to the current locale -USE_L10N = True - -# Absolute path to the directory that holds media. -# Example: "/home/media/media.lawrence.com/" -MEDIA_ROOT = PROJECT_ROOT + '/media/' - -if not os.path.exists(MEDIA_ROOT): - os.makedirs(MEDIA_ROOT) - -# URL that handles the media served from MEDIA_ROOT. Make sure to use a -# trailing slash if there is a path component (optional in other cases). -# Examples: "http://media.lawrence.com", "http://example.com/media/" -MEDIA_URL = '/media/' - -# Absolute path to the directory static files should be collected to. -# Don't put anything in this directory yourself; store your static files -# in apps' "static/" subdirectories and in STATICFILES_DIRS. -# Example: "/home/media/media.lawrence.com/static/" -STATIC_ROOT = '/var/www/static' - -# URL prefix for static files. -# Example: "http://media.lawrence.com/static/" -STATIC_URL = '/static/' - -# Additional locations of static files -STATICFILES_DIRS = ( -# Put strings here, like "/home/html/static" or "C:/www/django/static". -# Always use forward slashes, even on Windows. -# Don't forget to use absolute paths, not relative paths. -) - -# List of finder classes that know how to find static files in -# various locations. -STATICFILES_FINDERS = ( -'django.contrib.staticfiles.finders.FileSystemFinder', -'django.contrib.staticfiles.finders.AppDirectoriesFinder', -# 'django.contrib.staticfiles.finders.DefaultStorageFinder', -) -# Make this unique, and don't share it with anybody. -SECRET_KEY = 'a8l7%06wr2k+3=%#*#@#rvop2mmzko)44%7k(zx%lls^ihm9^5' - -# List of callables that know how to import templates from various sources. -TEMPLATE_LOADERS = ( - 'django.template.loaders.filesystem.Loader', - 'django.template.loaders.app_directories.Loader', -# 'django.template.loaders.eggs.Loader', -) - - -MIDDLEWARE_CLASSES = ( - 'django.middleware.common.CommonMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.locale.LocaleMiddleware', - # 'pagination.middleware.PaginationMiddleware', -) - -ROOT_URLCONF = 'urls' - -TEMPLATE_DIRS = ( - # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". - # Always use forward slashes, even on Windows. - # Don't forget to use absolute paths, not relative paths. -) - -INSTALLED_APPS = ( - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.sites', - 'django.contrib.messages', - 'suit', - 'django.contrib.admin', - 'django.contrib.staticfiles', - 'django_extensions', - 'telemeta', - 'timeside.player', - 'timeside.server', - 'jsonrpc', - 'south', - 'sorl.thumbnail', - 'timezones', - 'jqchat', - 'ipauth', - 'extra_views', - 'debug_toolbar', - 'bootstrap3', - 'bootstrap_pagination', - 'googletools', - 'registration', - 'rest_framework', - 'djcelery', - 'haystack', -) - -TEMPLATE_CONTEXT_PROCESSORS = ( - 'django.core.context_processors.request', - 'django.contrib.auth.context_processors.auth', - "django.core.context_processors.i18n", - "django.core.context_processors.media", - 'django.core.context_processors.static', - 'django.contrib.messages.context_processors.messages', -) - - -AUTHENTICATION_BACKENDS = ( - 'django.contrib.auth.backends.ModelBackend', - 'ipauth.backend.RangeBackend', -) - -SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies" - -TELEMETA_ORGANIZATION = 'Telemeta' -TELEMETA_SUBJECTS = ('Telemeta', 'web', 'platform', 'audio', 'semantics') -TELEMETA_DESCRIPTION = "Open web audio platform with semantics" -TELEMETA_LOGO = STATIC_URL + 'telemeta/images/logo_telemeta_2.png' - -TELEMETA_GMAP_KEY = 'ABQIAAAArg7eSfnfTkBRma8glnGrlxRVbMrhnNNvToCbZQtWdaMbZTA_3RRGObu5PDoiBImgalVnnLU2yN4RMA' - -TELEMETA_CACHE_DIR = os.path.join(MEDIA_ROOT, 'cache') -TELEMETA_EXPORT_CACHE_DIR = os.path.join(MEDIA_ROOT, 'export') -TELEMETA_DATA_CACHE_DIR = os.path.join(TELEMETA_CACHE_DIR, 'data') - -TELEMETA_DOWNLOAD_ENABLED = True -TELEMETA_STREAMING_FORMATS = ('mp3', 'ogg') -TELEMETA_DOWNLOAD_FORMATS = ('wav', 'mp3', 'ogg', 'flac') -TELEMETA_PUBLIC_ACCESS_PERIOD = 51 - -TELEMETA_STRICT_CODE = False - -AUTH_PROFILE_MODULE = 'telemeta.userprofile' -SESSION_EXPIRE_AT_BROWSER_CLOSE = False - -LOGIN_URL = '/login/' -LOGIN_REDIRECT_URL = '/desk/lists/' - -EMAIL_HOST = 'localhost' -DEFAULT_FROM_EMAIL = 'webmaster@parisson.com' - -TIMESIDE_DEFAULT_GRAPHER_ID = 'waveform_centroid' -TIMESIDE_DEFAULT_WAVEFORM_SIZES = ['346x130', '640x130'] -TIMESIDE_AUTO_ZOOM = False - -# Settings for django-bootstrap3 -BOOTSTRAP3 = { - 'set_required': True, - 'set_placeholder': False, - 'error_css_class': 'has-error', - 'required_css_class': 'has-warning', - 'javascript_in_head': True, -} - -PAGINATION_SETTINGS = { - 'PAGE_RANGE_DISPLAYED': 10, - 'MARGIN_PAGES_DISPLAYED': 2, -} - -DEBUG_TOOLBAR_PATCH_SETTINGS = False -DEBUG_TOOLBAR_PANELS = [ - 'debug_toolbar.panels.versions.VersionsPanel', - 'debug_toolbar.panels.timer.TimerPanel', - 'debug_toolbar.panels.settings.SettingsPanel', - 'debug_toolbar.panels.headers.HeadersPanel', - 'debug_toolbar.panels.request.RequestPanel', - 'debug_toolbar.panels.sql.SQLPanel', - 'debug_toolbar.panels.staticfiles.StaticFilesPanel', - 'debug_toolbar.panels.templates.TemplatesPanel', - 'debug_toolbar.panels.cache.CachePanel', - 'debug_toolbar.panels.signals.SignalsPanel', - 'debug_toolbar.panels.logging.LoggingPanel', - 'debug_toolbar.panels.redirects.RedirectsPanel', -] - -SUIT_CONFIG = { - 'ADMIN_NAME': 'Telemeta Admin' -} - -# A sample logging configuration. The only tangible logging -# performed by this configuration is to send an email to -# the site admins on every HTTP 500 error when DEBUG=False. -# See http://docs.djangoproject.com/en/dev/topics/logging for -# more details on how to customize your logging configuration. -LOGGING = { - 'version': 1, - 'disable_existing_loggers': False, - 'filters': { - 'require_debug_false': { - '()': 'django.utils.log.RequireDebugFalse' - } - }, - 'handlers': { - 'mail_admins': { - 'level': 'ERROR', - 'filters': ['require_debug_false'], - 'class': 'django.utils.log.AdminEmailHandler' - } - }, - 'loggers': { - 'django.request': { - 'handlers': ['mail_admins'], - 'level': 'ERROR', - 'propagate': True, - }, - } -} - -# replace rabbitmq by localhost if you start your app outside docker-compose -BROKER_URL = 'amqp://guest:guest@rabbitmq//' - -CELERY_IMPORTS = ("timeside.server.tasks",) -CELERY_RESULT_BACKEND='djcelery.backends.database:DatabaseBackend' -CELERY_TASK_SERIALIZER = "json" -CELERY_ACCEPT_CONTENT = ['application/json'] - -from celery_app import app - - -HAYSTACK_CONNECTIONS = { - 'default': { - 'ENGINE': 'haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine', - 'URL': 'http://search:9200/', - 'INDEX_NAME': 'haystack', - }, -} - -HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor' - -HAYSTACK_SEARCH_RESULTS_PER_PAGE = 50 - - diff --git a/examples/sandbox/update_schema.sh b/examples/sandbox/update_schema.sh deleted file mode 100755 index 31c658a1..00000000 --- a/examples/sandbox/update_schema.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -./manage.py schemamigration telemeta --auto -./manage.py migrate telemeta - diff --git a/examples/sandbox/urls.py b/examples/sandbox/urls.py deleted file mode 100644 index b1950363..00000000 --- a/examples/sandbox/urls.py +++ /dev/null @@ -1,37 +0,0 @@ -# -*- coding: utf-8 -*- -from django.conf.urls import patterns, url, include -from django.http import HttpResponse -import os - -# Uncomment the next two lines to enable the admin: -from django.contrib import admin -admin.autodiscover() - -js_info_dict = { - 'packages': ('telemeta',), -} - -PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__)) -robots_rules = open(PROJECT_ROOT + os.sep + 'robots.txt', 'r').read() - -urlpatterns = patterns('', - # Example: - # (r'^sandbox/', include('sandbox.foo.urls')), - - # Uncomment the admin/doc line below and add 'django.contrib.admindocs' - # to INSTALLED_APPS to enable admin documentation: - # (r'^admin/doc/', include('django.contrib.admindocs.urls')), - - # Uncomment the next line to enable the admin: - (r'^admin/django/', include(admin.site.urls)), - #(r'^grappelli/', include('grappelli.urls')), # grappelli URLS - - # Telemeta - (r'^', include('telemeta.urls')), - - # Languages - (r'^i18n/', include('django.conf.urls.i18n')), - (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict), - (r'^robots\.txt$', lambda r: HttpResponse(robots_rules, mimetype="text/plain")), - - ) diff --git a/examples/sandbox/wsgi.py b/examples/sandbox/wsgi.py deleted file mode 100644 index c3642fec..00000000 --- a/examples/sandbox/wsgi.py +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/python2.5 -# -*- coding: utf-8 -*- - -import os -import sys - -here = os.path.dirname(__file__) -sys.path.append(here) - -os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' - -import django.core.handlers.wsgi -application = django.core.handlers.wsgi.WSGIHandler() - diff --git a/telemeta/locale b/telemeta/locale index 4534a3d4..91973b13 160000 --- a/telemeta/locale +++ b/telemeta/locale @@ -1 +1 @@ -Subproject commit 4534a3d47e7909554637e87a637b1959db277941 +Subproject commit 91973b13f9dc9405052727c0c525d342dee15562 diff --git a/telemeta/pages b/telemeta/pages index 771dfcc5..f8324093 160000 --- a/telemeta/pages +++ b/telemeta/pages @@ -1 +1 @@ -Subproject commit 771dfcc58e26f43a507c3bc48fcb5ddde55ca0b1 +Subproject commit f8324093174d077b674ac2c52eb0db6eaf815ab5 diff --git a/telemeta/templates/telemeta/collection_detail.html b/telemeta/templates/telemeta/collection_detail.html index 7184d11e..361e456d 100644 --- a/telemeta/templates/telemeta/collection_detail.html +++ b/telemeta/templates/telemeta/collection_detail.html @@ -100,10 +100,10 @@
{% trans "Document status" %}
{{ collection.document_status }}
{% if collection.description %} -
{% trans "Description" %}
-
{{ collection.description|html_line_break|safe }}
- {% endif %} - {% dl_field collection "recording_context" %} +
{% trans "Description" %}
+
{{ collection.description|html_line_break|safe }}
+ {% endif %} + {% dl_field collection "recording_context" %}
{% trans "Recording period" %}
{% if collection.recorded_from_year %}{{ collection.recorded_from_year }}{% endif %}{% if collection.recorded_from_year and collection.recorded_to_year %} - {% endif %}{% if collection.recorded_to_year %}{{ collection.recorded_to_year}}{% endif %}
{% if '_E_' in collection.public_id %} @@ -270,4 +270,3 @@ {% else %}

No such collection

{% endif %} -