<commit_before># -*- coding: utf-8 -*-

from django.db.models.loading import get_model

from rest_framework.response import Response
from rest_framework import viewsets

from haystack import query, inputs

from greenmine.base import exceptions as excp

from .serializers import SearchSerializer

class SearchViewSet(viewsets.ViewSet):
    def list(self, request, **kwargs):
        project_model = get_model("projects", "Project")
        text = request.QUERY_PARAMS.get('text', "")
        project_id = request.QUERY_PARAMS.get('project', None)

        try:
            project = self._get_project(project_id)
        except (project_model.DoesNotExist, TypeError):
            raise excp.PermissionDenied({"detail": "Wrong project id"})

        #if not text:
        #    raise excp.BadRequest("text parameter must be contains text")

        queryset = query.SearchQuerySet()
        queryset = queryset.filter(text=inputs.AutoQuery(text))
        queryset = queryset.filter(project_id=project_id)

        return_data = SearchSerializer(queryset, many=True)
        return Response(return_data.data)

    def _get_project(self, project_id):
        project_model = get_model("projects", "Project")
        own_projects = (project_model.objects
                            .filter(members=self.request.user))

        return own_projects.get(pk=project_id)
<commit_msg>Reimplemented search api using postgresql full-text-search capability.<commit_after># -*- coding: utf-8 -*-

from django.db.models.loading import get_model

from rest_framework.response import Response
from rest_framework import viewsets

from greenmine.base import exceptions as excp
from greenmine.projects.userstories.serializers import UserStorySerializer
from greenmine.projects.tasks.serializers import TaskSerializer
from greenmine.projects.issues.serializers import IssueSerializer

class SearchViewSet(viewsets.ViewSet):
    def list(self, request, **kwargs):
        project_model = get_model("projects", "Project")
        text = request.QUERY_PARAMS.get('text', "")
        project_id = request.QUERY_PARAMS.get('project', None)

        try:
            project = self._get_project(project_id)
        except (project_model.DoesNotExist, TypeError):
            raise excp.PermissionDenied({"detail": "Wrong project id"})

        result = {
            "userstories": self._search_user_stories(project, text),
            "tasks": self._search_tasks(project, text),
            "issues": self._search_issues(project, text)
        }

        result["count"] = sum(map(lambda x: len(x), result.values()))
        return Response(result)

    def _get_project(self, project_id):
        project_model = get_model("projects", "Project")
        own_projects = (project_model.objects
                            .filter(members=self.request.user))

        return own_projects.get(pk=project_id)

    def _search_user_stories(self, project, text):
        where_clause = ("to_tsvector(userstories_userstory.subject || "
                        "userstories_userstory.description) @@ plainto_tsquery(%s)")

        model_cls = get_model("userstories", "UserStory")
        queryset = (model_cls.objects
                        .extra(where=[where_clause], params=[text])
                        .filter(project_id=project.pk)[:50])

        serializer = UserStorySerializer(queryset, many=True)
        return serializer.data

    def _search_tasks(self, project, text):
        where_clause = ("to_tsvector(tasks_task.subject || tasks_task.description) "
                        "@@ plainto_tsquery(%s)")

        model_cls = get_model("tasks", "Task")
        queryset = (model_cls.objects
                        .extra(where=[where_clause], params=[text])
                        .filter(project_id=project.pk)[:50])

        serializer = TaskSerializer(queryset, many=True)
        return serializer.data

    def _search_issues(self, project, text):
        where_clause = ("to_tsvector(issues_issue.subject || issues_issue.description) "
                        "@@ plainto_tsquery(%s)")

        model_cls = get_model("issues", "Issue")
        queryset = (model_cls.objects
                        .extra(where=[where_clause], params=[text])
                        .filter(project_id=project.pk)[:50])

        serializer = IssueSerializer(queryset, many=True)
        return serializer.data
<|endoftext|>


<commit_before># coding: utf-8
#
# This file is part of Progdupeupl.
#
# Progdupeupl is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Progdupeupl 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 Progdupeupl. If not, see <http://www.gnu.org/licenses/>.

import os
import sys
import platform
import locale

# Python is platform-independent...or is it?
if platform.system() == "Windows":
    locale.setlocale(locale.LC_TIME, 'fra')
else:
    locale.setlocale(locale.LC_TIME, 'fr_FR.UTF-8')

DEBUG = True
TEMPLATE_DEBUG = DEBUG
INTERNAL_IPS = ('127.0.0.1',)  # debug toolbar

ADMINS = (
    ('user', 'mail'),
)

MANAGERS = ADMINS

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'base.db',
        'USER': '',
        'PASSWORD': '',
        'HOST': '',
        'PORT': '',
    }
}

# 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.
# In a Windows environment this must be set to 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'

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

# If you set this to False, Django will not use timezone-aware datetimes.
USE_TZ = False

SITE_ROOT = os.path.realpath(os.path.dirname(os.path.dirname(__file__)))

# Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/home/media/media.lawrence.com/media/"
MEDIA_ROOT = os.path.join(SITE_ROOT, 'media')

# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash.
# Examples: "http://media.lawrence.com/media/", "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 = os.path.join(SITE_ROOT, '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.
    os.path.join(SITE_ROOT, 'assets'),
)

# 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',
)

STATICFILES_STORAGE = 'pipeline.storage.PipelineStorage'

# You need to have yuglify installed, except for DEBUG builds
if DEBUG:
    PIPELINE_JS_COMPRESSOR = None
    PIPELINE_CSS_COMPRESSOR = None

PIPELINE_JS = {
    'base': {
        'source_filenames': (
            'js/vendor/custom.modernizr.js',
            'js/vendor/jquery.js',
            'js/foundation.min.js',
        ),
        'output_filename': 'js/base.js'
    },
    'custom': {
        'source_filenames': {
            'js/custom/ajax-csrf.js',
            'js/custom/editor.js',
            'js/custom/section.js',
        },
        'output_filename': 'js/custom.js'
    },
}

PIPELINE_CSS = {
    'pdp': {
        'source_filenames': (
            'css/progdupeupl.css',
        ),
        'output_filename': 'css/pdp.css',
        'extra_content': {
            'media': 'screen,projection',
        },
    },
    'print': {
        'source_filenames': (
            'css/print.css',
        ),
        'output_filename': 'css/print.css',
        'extra_content': {
            'media': 'print',
        },
    },
}

PIPELINE_DISABLE_WRAPPER = True

# Make this unique, and don't share it with anybody.
SECRET_KEY = 'n!01nl+318#x75_%le8#s0=-*ysw&y49uc#t=*wvi(9hnyii0z'

# 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.middleware.csrf.CsrfViewMiddleware',

    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    # Uncomment the next line for simple clickjacking protection:
    # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'pdp.utils.ThreadLocals',
    'debug_toolbar.middleware.DebugToolbarMiddleware',
)

ROOT_URLCONF = 'pdp.urls'

# Python dotted path to the WSGI application used by Django's runserver.
WSGI_APPLICATION = 'pdp.wsgi.application'

# Absolute path to template directory
TEMPLATE_DIRS = (
    os.path.join(SITE_ROOT, 'templates')
)

TEMPLATE_CONTEXT_PROCESSORS = (
    # Default context processors
    'django.contrib.auth.context_processors.auth',
    'django.core.context_processors.debug',
    'django.core.context_processors.i18n',
    'django.core.context_processors.media',
    'django.core.context_processors.static',
    'django.core.context_processors.tz',
    'django.contrib.messages.context_processors.messages',

    # Custom context processors
    'pdp.utils.context_processors.versions',
    'pdp.utils.context_processors.git_version',
)

INSTALLED_APPS = (
    'pdp.member',
    'pdp.forum',
    'pdp.utils',
    'pdp.pages',
    'pdp.tutorial',
    'pdp.article',
    'pdp.gallery',
    'pdp.messages',

    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'south',
    'crispy_forms',
    'crispy_forms_foundation',
    'captcha',
    'email_obfuscator',
    'debug_toolbar',
    'taggit',
    'taggit_templatetags',
    'pipeline',
    'rest_framework',
    'provider',
    'provider.oauth2',
    'rest_framework_swagger',
    'haystack',
    'celery',

    # Better use RabbitMQ or Redis in production
    'kombu.transport.django',

    # Uncomment the next line to enable the admin:
    'django.contrib.admin',
    # Uncomment the next line to enable admin documentation:
    # 'django.contrib.admindocs',
)

# 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,
        },
    }
}

# Cache(s) used in order to store rendered pages or parts for some time. This
# is a fake cache that does not cache anything, for developement purposes only.
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
    }
}

REST_FRAMEWORK = {

    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.YAMLRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.XMLRenderer',
    ),

    'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.DjangoFilterBackend',),

    'DEFAULT_MODEL_SERIALIZER_CLASS':
    'rest_framework.serializers.HyperlinkedModelSerializer',

    # Use Django's standard `django.contrib.auth` permissions,
    # or allow read-only access for unauthenticated users.
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
    ]
}

SWAGGER_SETTINGS = {
    "exclude_namespaces": [],  # List URL namespaces to ignore
    "api_version": '0.1',  # Specify your API's version
    "api_path": "/",  # Specify the path to your API not a root level
    "enabled_methods": [  # Specify which methods to enable in Swagger UI
        'get',
        'post',
        'put',
        'patch',
        'delete'
    ],
    "api_key": '',  # An API key
    "is_authenticated": False,  # Set to True to enforce user authentication,
    "is_superuser": False,  # Set to True to enforce admin only access
}

HAYSTACK_CONNECTIONS = {
    'default': {
        'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
        'PATH': os.path.join(os.path.dirname(__file__), 'whoosh'),
    },
}

AUTH_PROFILE_MODULE = 'member.Profile'
LOGIN_URL = '/membres/connexion'

ABSOLUTE_URL_OVERRIDES = {
    'auth.user': lambda u: '/membres/voir/{0}'.format(
        u.username.encode('utf-8'))
}

CRISPY_FAIL_SILENTLY = not DEBUG
CRISPY_TEMPLATE_PACK = 'foundation'

# Bot settings
BOT_ENABLED = False
BOT_USER_PK = 1
BOT_TUTORIAL_FORUM_PK = 1
BOT_ARTICLE_FORUM_PK = 2

# Paginator settings for forum
POSTS_PER_PAGE = 21
TOPICS_PER_PAGE = 21
FOLLOWED_TOPICS_PER_PAGE = 21

# Settings for antispam
SPAM_LIMIT_SECONDS = 60 * 15
SPAM_LIMIT_PARTICIPANT = 2

# Paginator settings for members
MEMBERS_PER_PAGE = 10 * 10

# Should Django serve the static and media files ? This should not be set to
# True in a production environment
SERVE = False

# Max size image upload (in bytes)
IMAGE_MAX_SIZE = 1024 * 512

# Do use RabbitMQ or Redis in production
BROKER_URL = 'django://'

# Do not allow pickle in production
CELERY_ACCEPT_CONTENT = ['json', 'pickle']

TESTING = 'test' in sys.argv

# Load the production settings, overwrite the existing ones if needed
try:
    from pdp.settings_prod import *
except ImportError:
    pass
<commit_msg>Updated configuration for new taggit and crispy_foundation versions<commit_after># coding: utf-8
#
# This file is part of Progdupeupl.
#
# Progdupeupl is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Progdupeupl 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 Progdupeupl. If not, see <http://www.gnu.org/licenses/>.

import os
import sys
import platform
import locale

# Python is platform-independent...or is it?
if platform.system() == "Windows":
    locale.setlocale(locale.LC_TIME, 'fra')
else:
    locale.setlocale(locale.LC_TIME, 'fr_FR.UTF-8')

DEBUG = True
TEMPLATE_DEBUG = DEBUG
INTERNAL_IPS = ('127.0.0.1',)  # debug toolbar

ADMINS = (
    ('user', 'mail'),
)

MANAGERS = ADMINS

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'base.db',
        'USER': '',
        'PASSWORD': '',
        'HOST': '',
        'PORT': '',
    }
}

# 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.
# In a Windows environment this must be set to 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'

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

# If you set this to False, Django will not use timezone-aware datetimes.
USE_TZ = False

SITE_ROOT = os.path.realpath(os.path.dirname(os.path.dirname(__file__)))

# Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/home/media/media.lawrence.com/media/"
MEDIA_ROOT = os.path.join(SITE_ROOT, 'media')

# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash.
# Examples: "http://media.lawrence.com/media/", "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 = os.path.join(SITE_ROOT, '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.
    os.path.join(SITE_ROOT, 'assets'),
)

# 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',
)

STATICFILES_STORAGE = 'pipeline.storage.PipelineStorage'

# You need to have yuglify installed, except for DEBUG builds
if DEBUG:
    PIPELINE_JS_COMPRESSOR = None
    PIPELINE_CSS_COMPRESSOR = None

PIPELINE_JS = {
    'base': {
        'source_filenames': (
            'js/vendor/custom.modernizr.js',
            'js/vendor/jquery.js',
            'js/foundation.min.js',
        ),
        'output_filename': 'js/base.js'
    },
    'custom': {
        'source_filenames': {
            'js/custom/ajax-csrf.js',
            'js/custom/editor.js',
            'js/custom/section.js',
        },
        'output_filename': 'js/custom.js'
    },
}

PIPELINE_CSS = {
    'pdp': {
        'source_filenames': (
            'css/progdupeupl.css',
        ),
        'output_filename': 'css/pdp.css',
        'extra_content': {
            'media': 'screen,projection',
        },
    },
    'print': {
        'source_filenames': (
            'css/print.css',
        ),
        'output_filename': 'css/print.css',
        'extra_content': {
            'media': 'print',
        },
    },
}

PIPELINE_DISABLE_WRAPPER = True

# Make this unique, and don't share it with anybody.
SECRET_KEY = 'n!01nl+318#x75_%le8#s0=-*ysw&y49uc#t=*wvi(9hnyii0z'

# 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.middleware.csrf.CsrfViewMiddleware',

    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    # Uncomment the next line for simple clickjacking protection:
    # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'pdp.utils.ThreadLocals',
    'debug_toolbar.middleware.DebugToolbarMiddleware',
)

ROOT_URLCONF = 'pdp.urls'

# Python dotted path to the WSGI application used by Django's runserver.
WSGI_APPLICATION = 'pdp.wsgi.application'

# Absolute path to template directory
TEMPLATE_DIRS = (
    os.path.join(SITE_ROOT, 'templates')
)

TEMPLATE_CONTEXT_PROCESSORS = (
    # Default context processors
    'django.contrib.auth.context_processors.auth',
    'django.core.context_processors.debug',
    'django.core.context_processors.i18n',
    'django.core.context_processors.media',
    'django.core.context_processors.static',
    'django.core.context_processors.tz',
    'django.contrib.messages.context_processors.messages',

    # Custom context processors
    'pdp.utils.context_processors.versions',
    'pdp.utils.context_processors.git_version',
)

INSTALLED_APPS = (
    'pdp.member',
    'pdp.forum',
    'pdp.utils',
    'pdp.pages',
    'pdp.tutorial',
    'pdp.article',
    'pdp.gallery',
    'pdp.messages',

    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'south',
    'crispy_forms',
    'crispy_forms_foundation',
    'captcha',
    'email_obfuscator',
    'debug_toolbar',
    'taggit',
    'taggit_templatetags',
    'pipeline',
    'rest_framework',
    'provider',
    'provider.oauth2',
    'rest_framework_swagger',
    'haystack',
    'celery',

    # Better use RabbitMQ or Redis in production
    'kombu.transport.django',

    # Uncomment the next line to enable the admin:
    'django.contrib.admin',
    # Uncomment the next line to enable admin documentation:
    # 'django.contrib.admindocs',
)

# 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,
        },
    }
}

# Cache(s) used in order to store rendered pages or parts for some time. This
# is a fake cache that does not cache anything, for developement purposes only.
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
    }
}

REST_FRAMEWORK = {

    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.YAMLRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.XMLRenderer',
    ),

    'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.DjangoFilterBackend',),

    'DEFAULT_MODEL_SERIALIZER_CLASS':
    'rest_framework.serializers.HyperlinkedModelSerializer',

    # Use Django's standard `django.contrib.auth` permissions,
    # or allow read-only access for unauthenticated users.
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
    ]
}

SWAGGER_SETTINGS = {
    "exclude_namespaces": [],  # List URL namespaces to ignore
    "api_version": '0.1',  # Specify your API's version
    "api_path": "/",  # Specify the path to your API not a root level
    "enabled_methods": [  # Specify which methods to enable in Swagger UI
        'get',
        'post',
        'put',
        'patch',
        'delete'
    ],
    "api_key": '',  # An API key
    "is_authenticated": False,  # Set to True to enforce user authentication,
    "is_superuser": False,  # Set to True to enforce admin only access
}

HAYSTACK_CONNECTIONS = {
    'default': {
        'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
        'PATH': os.path.join(os.path.dirname(__file__), 'whoosh'),
    },
}

AUTH_PROFILE_MODULE = 'member.Profile'
LOGIN_URL = '/membres/connexion'

ABSOLUTE_URL_OVERRIDES = {
    'auth.user': lambda u: '/membres/voir/{0}'.format(
        u.username.encode('utf-8'))
}

SOUTH_MIGRATION_MODULES = {
    'taggit': 'taggit.south_migrations',
}

CRISPY_FAIL_SILENTLY = not DEBUG
CRISPY_TEMPLATE_PACK = 'foundation-5'

# Bot settings
BOT_ENABLED = False
BOT_USER_PK = 1
BOT_TUTORIAL_FORUM_PK = 1
BOT_ARTICLE_FORUM_PK = 2

# Paginator settings for forum
POSTS_PER_PAGE = 21
TOPICS_PER_PAGE = 21
FOLLOWED_TOPICS_PER_PAGE = 21

# Settings for antispam
SPAM_LIMIT_SECONDS = 60 * 15
SPAM_LIMIT_PARTICIPANT = 2

# Paginator settings for members
MEMBERS_PER_PAGE = 10 * 10

# Should Django serve the static and media files ? This should not be set to
# True in a production environment
SERVE = False

# Max size image upload (in bytes)
IMAGE_MAX_SIZE = 1024 * 512

# Do use RabbitMQ or Redis in production
BROKER_URL = 'django://'

# Do not allow pickle in production
CELERY_ACCEPT_CONTENT = ['json', 'pickle']

TESTING = 'test' in sys.argv

# Load the production settings, overwrite the existing ones if needed
try:
    from pdp.settings_prod import *
except ImportError:
    pass
<|endoftext|>


<commit_before>import os
import yaml

from pocs.utils.database import PanMongo
from pocs.utils.logger import get_root_logger
from pocs.utils.messaging import PanMessaging
from pocs.utils.rs232 import SerialData

from . import load_config

class ArduinoSerialMonitor(object):

    """
        Monitors the serial lines and tries to parse any data recevied
        as JSON.

        Checks for the `camera_box` and `computer_box` entries in the config
        and tries to connect. Values are updated in the mongo db.
    """

    def __init__(self, auto_detect=False, *args, **kwargs):
        self.config = load_config()
        self.logger = get_root_logger()

        assert 'environment' in self.config
        assert type(self.config['environment']) is dict, \
            self.logger.warning("Environment config variable not set correctly. No sensors listed")

        self.db = None
        self.messaging = None

        # Store each serial reader
        self.serial_readers = dict()

        if auto_detect:
            for port_num in range(9):
                port = '/dev/ttyACM{}'.format(port_num)
                if os.path.exists(port):
                    self.logger.debug("Trying to connect on {}".format(port))

                    sensor_name = None
                    serial_reader = self._connect_serial(port)

                    num_tries = 5
                    self.logger.debug("Getting name on {}".format(port))
                    while num_tries > 0:
                        try:
                            data = serial_reader.get_reading()
                        except yaml.parser.ParserError:
                            pass
                        except AttributeError:
                            pass
                        else:
                            try:
                                if 'name' in data:
                                    sensor_name = data['name']
                                    num_tries = 0
                            except Exception as e:
                                self.logger.warning("Read on serial: {}".format(e))
                        num_tries -= 1

                    if sensor_name is not None:
                        self.serial_readers[sensor_name] = {
                            'reader': serial_reader,
                        }
        else:
            # Try to connect to a range of ports
            for sensor_name in self.config['environment'].keys():
                try:
                    port = self.config['environment'][sensor_name]['serial_port']
                except TypeError:
                    continue
                except KeyError:
                    continue

                serial_reader = self._connect_serial(port)
                self.serial_readers[sensor_name] = {
                    'reader': serial_reader,
                    'port': port,
                }

    def _connect_serial(self, port):
        if port is not None:
            self.logger.debug('Attempting to connect to serial port: {}'.format(port))
            serial_reader = SerialData(port=port, threaded=True)
            self.logger.debug(serial_reader)

            try:
                serial_reader.connect()
                serial_reader.start()
            except Exception as e:
                self.logger.warning('Could not connect to port: {}'.format(port))

            return serial_reader

    def disconnect(self):
        for sensor_name, reader_info in self.serial_readers.items():
            reader = reader_info['reader']
            reader.stop()

    def send_message(self, msg, channel='environment'):
        if self.messaging is None:
            self.messaging = PanMessaging.create_publisher(6510)

        self.messaging.send_message(channel, msg)

    def capture(self, use_mongo=True, send_message=True):
        """
        Helper function to return serial sensor info.

        Reads each of the connected sensors. If a value is received, attempts
        to parse the value as json.

        Returns:
            sensor_data (dict):     Dictionary of sensors keyed by sensor name.
        """

        sensor_data = dict()

        # Read from all the readers
        for sensor_name, reader_info in self.serial_readers.items():
            reader = reader_info['reader']

            # Get the values
            self.logger.debug("Reading next serial value")
            sensor_info = reader.get_reading()

            time_stamp = sensor_info[0]
            sensor_value = sensor_info[1]
            try:
                self.logger.debug("Got sensor_value from {}".format(sensor_name))
                data = yaml.load(sensor_value.replace('nan', 'null'))
                data['date'] = time_stamp

                sensor_data[sensor_name] = data

                if send_message:
                    self.send_message({'data': data}, channel='environment')
            except yaml.parser.ParserError:
                self.logger.warning("Bad JSON: {0}".format(sensor_value))
            except ValueError:
                self.logger.warning("Bad JSON: {0}".format(sensor_value))
            except TypeError:
                self.logger.warning("Bad JSON: {0}".format(sensor_value))
            except Exception as e:
                self.logger.warning("Bad JSON: {0}".format(sensor_value))

            if use_mongo and len(sensor_data) > 0:
                if self.db is None:
                    self.db = PanMongo()
                    self.logger.info('Connected to PanMongo')
                self.db.insert_current('environment', sensor_data)
        else:
            self.logger.debug("No sensor data received")

        return sensor_data
<commit_msg>* Handle the error (missed add)<commit_after>import os
import yaml

from pocs.utils.database import PanMongo
from pocs.utils.logger import get_root_logger
from pocs.utils.messaging import PanMessaging
from pocs.utils.rs232 import SerialData

from . import load_config

class ArduinoSerialMonitor(object):

    """
        Monitors the serial lines and tries to parse any data recevied
        as JSON.

        Checks for the `camera_box` and `computer_box` entries in the config
        and tries to connect. Values are updated in the mongo db.
    """

    def __init__(self, auto_detect=False, *args, **kwargs):
        self.config = load_config()
        self.logger = get_root_logger()

        assert 'environment' in self.config
        assert type(self.config['environment']) is dict, \
            self.logger.warning("Environment config variable not set correctly. No sensors listed")

        self.db = None
        self.messaging = None

        # Store each serial reader
        self.serial_readers = dict()

        if auto_detect:
            for port_num in range(9):
                port = '/dev/ttyACM{}'.format(port_num)
                if os.path.exists(port):
                    self.logger.debug("Trying to connect on {}".format(port))

                    sensor_name = None
                    serial_reader = self._connect_serial(port)

                    num_tries = 5
                    self.logger.debug("Getting name on {}".format(port))
                    while num_tries > 0:
                        try:
                            data = serial_reader.get_reading()
                        except yaml.parser.ParserError:
                            pass
                        except AttributeError:
                            pass
                        else:
                            try:
                                if 'name' in data:
                                    sensor_name = data['name']
                                    num_tries = 0
                            except Exception as e:
                                self.logger.warning("Read on serial: {}".format(e))
                        num_tries -= 1

                    if sensor_name is not None:
                        self.serial_readers[sensor_name] = {
                            'reader': serial_reader,
                        }
        else:
            # Try to connect to a range of ports
            for sensor_name in self.config['environment'].keys():
                try:
                    port = self.config['environment'][sensor_name]['serial_port']
                except TypeError:
                    continue
                except KeyError:
                    continue

                serial_reader = self._connect_serial(port)
                self.serial_readers[sensor_name] = {
                    'reader': serial_reader,
                    'port': port,
                }

    def _connect_serial(self, port):
        if port is not None:
            self.logger.debug('Attempting to connect to serial port: {}'.format(port))
            serial_reader = SerialData(port=port, threaded=True)
            self.logger.debug(serial_reader)

            try:
                serial_reader.connect()
                serial_reader.start()
            except Exception as e:
                self.logger.warning('Could not connect to port: {}'.format(port))

            return serial_reader

    def disconnect(self):
        for sensor_name, reader_info in self.serial_readers.items():
            reader = reader_info['reader']
            reader.stop()

    def send_message(self, msg, channel='environment'):
        if self.messaging is None:
            self.messaging = PanMessaging.create_publisher(6510)

        self.messaging.send_message(channel, msg)

    def capture(self, use_mongo=True, send_message=True):
        """
        Helper function to return serial sensor info.

        Reads each of the connected sensors. If a value is received, attempts
        to parse the value as json.

        Returns:
            sensor_data (dict):     Dictionary of sensors keyed by sensor name.
        """

        sensor_data = dict()

        # Read from all the readers
        for sensor_name, reader_info in self.serial_readers.items():
            reader = reader_info['reader']

            # Get the values
            self.logger.debug("Reading next serial value")
            try:
                sensor_info = reader.get_reading()
            except IndexError:
                continue

            time_stamp = sensor_info[0]
            sensor_value = sensor_info[1]
            try:
                self.logger.debug("Got sensor_value from {}".format(sensor_name))
                data = yaml.load(sensor_value.replace('nan', 'null'))
                data['date'] = time_stamp

                sensor_data[sensor_name] = data

                if send_message:
                    self.send_message({'data': data}, channel='environment')
            except yaml.parser.ParserError:
                self.logger.warning("Bad JSON: {0}".format(sensor_value))
            except ValueError:
                self.logger.warning("Bad JSON: {0}".format(sensor_value))
            except TypeError:
                self.logger.warning("Bad JSON: {0}".format(sensor_value))
            except Exception as e:
                self.logger.warning("Bad JSON: {0}".format(sensor_value))

            if use_mongo and len(sensor_data) > 0:
                if self.db is None:
                    self.db = PanMongo()
                    self.logger.info('Connected to PanMongo')
                self.db.insert_current('environment', sensor_data)
        else:
            self.logger.debug("No sensor data received")

        return sensor_data
<|endoftext|>


<commit_before>#!/usr/bin/env python
# Truncate.py
#   Copyright (C) 2006 CCLRC, Graeme Winter
#
#   This code is distributed under the BSD license, a copy of which is
#   included in the root directory of this package.

#
# 26th October 2006
#
# A wrapper for the CCP4 program Truncate, which calculates F's from
# I's and gives a few useful statistics about the data set.
#
# FIXME 26/OCT/06 this needs to be able to take into account the solvent
#                 content of the crystal (at the moment it will be assumed
#                 to be 50%.)
#
# FIXME 16/NOV/06 need to be able to get the estimates B factor from the
#                 Wilson plot and also second moment stuff, perhaps?

import os
import sys

if not os.environ.has_key('XIA2CORE_ROOT'):
    raise RuntimeError, 'XIA2CORE_ROOT not defined'

if not os.path.join(os.environ['XIA2CORE_ROOT'], 'Python') in sys.path:
    sys.path.append(os.path.join(os.environ['XIA2CORE_ROOT'],
                                 'Python'))

from Driver.DriverFactory import DriverFactory
from Decorators.DecoratorFactory import DecoratorFactory

def Truncate(DriverType = None):
    '''A factory for TruncateWrapper classes.'''

    DriverInstance = DriverFactory.Driver(DriverType)
    CCP4DriverInstance = DecoratorFactory.Decorate(DriverInstance, 'ccp4')

    class TruncateWrapper(CCP4DriverInstance.__class__):
        '''A wrapper for Truncate, using the CCP4-ified Driver.'''

        def __init__(self):
            # generic things
            CCP4DriverInstance.__class__.__init__(self)
            self.set_executable('truncate')

            self._b_factor = 0.0

            return

        def truncate(self):
            '''Actually perform the truncation procedure.'''

            self.check_hklin()
            self.check_hklout()

            self.start()

            self.close_wait()

            try:
                self.check_for_errors()
                self.check_ccp4_errors()

            except RuntimeError, e:
                try:
                    os.remove(self.get_hklout())
                except:
                    pass

            # FIXME need to parse the output for interesting things here!

            for line in self.get_all_output():
                if 'Least squares straight line gives' in line:
                    list = line.split()
                    self._b_factor = float(list[7])

            return

        def get_b_factor(self):
            return self._b_factor

    return TruncateWrapper()
<commit_msg>Fix for bug 2109 - how harvest to cwd.<commit_after>#!/usr/bin/env python
# Truncate.py
#   Copyright (C) 2006 CCLRC, Graeme Winter
#
#   This code is distributed under the BSD license, a copy of which is
#   included in the root directory of this package.
#
# 26th October 2006
#
# A wrapper for the CCP4 program Truncate, which calculates F's from
# I's and gives a few useful statistics about the data set.
#
# FIXME 26/OCT/06 this needs to be able to take into account the solvent
#                 content of the crystal (at the moment it will be assumed
#                 to be 50%.)
#
# FIXME 16/NOV/06 need to be able to get the estimates B factor from the
#                 Wilson plot and also second moment stuff, perhaps?

import os
import sys

if not os.environ.has_key('XIA2CORE_ROOT'):
    raise RuntimeError, 'XIA2CORE_ROOT not defined'

if not os.path.join(os.environ['XIA2CORE_ROOT'], 'Python') in sys.path:
    sys.path.append(os.path.join(os.environ['XIA2CORE_ROOT'],
                                 'Python'))

from Driver.DriverFactory import DriverFactory
from Decorators.DecoratorFactory import DecoratorFactory

def Truncate(DriverType = None):
    '''A factory for TruncateWrapper classes.'''

    DriverInstance = DriverFactory.Driver(DriverType)
    CCP4DriverInstance = DecoratorFactory.Decorate(DriverInstance, 'ccp4')

    class TruncateWrapper(CCP4DriverInstance.__class__):
        '''A wrapper for Truncate, using the CCP4-ified Driver.'''

        def __init__(self):
            # generic things
            CCP4DriverInstance.__class__.__init__(self)
            self.set_executable('truncate')

            self._b_factor = 0.0

            return

        def truncate(self):
            '''Actually perform the truncation procedure.'''

            self.check_hklin()
            self.check_hklout()

            self.start()

            # write the harvest files in the local directory, not
            # in $HARVESTHOME.
            self.input('usecwd')

            self.close_wait()

            try:
                self.check_for_errors()
                self.check_ccp4_errors()

            except RuntimeError, e:
                try:
                    os.remove(self.get_hklout())
                except:
                    pass

            # FIXME need to parse the output for interesting things here!

            for line in self.get_all_output():
                if 'Least squares straight line gives' in line:
                    list = line.split()
                    self._b_factor = float(list[7])

            return

        def get_b_factor(self):
            return self._b_factor

    return TruncateWrapper()
<|endoftext|>


<commit_before>__version__='0.1.8-dev'
<commit_msg>Version bump<commit_after>__version__='0.1.8'
<|endoftext|>


<commit_before>#!/usr/bin/env python

import logging
import os

from subprocess import Popen, PIPE

from xml.etree.ElementTree import Element, SubElement, ElementTree

from penchy import __version__ as penchy_version
from penchy.util import memoized, tree_pp, dict2tree, dict2string, sha1sum

log = logging.getLogger("maven")

@memoized
def get_classpath():
    """
    Returns the Java classpath using Maven.

    This method expects a Maven POM (pom.xml) in the current
    working directory. A POM can be generated using the
    :class:`BootstrapPOM` or :class:`POM` class::

        >>> from penchy.maven import BootstrapPOM, get_classpath
        >>> from penchy.jobs.workloads import ScalaBench
        >>> pom = BootstrapPOM()
        >>> for dep in ScalaBench.DEPENDENCIES:
        ...     pom.add_dependency(dep)
        ...
        >>> pom.write()
        >>> get_classpath()
        '/home/fabian/.m2/repository/de/tu_darmstadt/penchy/penchy/0.1/penchy-0.1-py.zip:/home/fabian/.m2/repository/org/scalabench/benchmarks/scala-benchmark-suite/0.1.0-SNAPSHOT/scala-benchmark-suite-0.1.0-SNAPSHOT.jar'

    :returns: java classpath
    :rtype: string
    """
    if not os.path.exists('pom.xml'):
        raise OSError("No pom.xml found in the current directory")

    proc = Popen(['mvn', 'dependency:build-classpath'], stdout=PIPE)
    stdout, _ = proc.communicate()

    if proc.returncode is not 0:
        log.error(stdout)
        raise MavenError("The classpath could not be determined")

    for line in stdout.split("\n"):
        if not line.startswith("["):
            return line

    raise MavenError("The classpath was not in maven's output")

class MavenError(Exception):
    pass

class IntegrityError(Exception):
    pass

class MavenDependency(object):
    """
    This class represents a Maven Dependency.

    A sample Maven Dependency might look like::

        dep = MavenDependency('de.tu_darmstadt.penchy',
                              'pia', '2.0.0.0', 'http://mvn.0x0b.de')
    """
    POM_ATTRIBS = ('version', 'groupId', 'artifactId', 'version',
            'classifier', 'packaging', 'type')

    def __init__(self, groupId, artifactId, version, repo=None,
            classifier=None, artifact_type=None, packaging=None,
            filename=None, checksum=None):
        """
        :param groupId: the maven group id.
        :type groupId: string
        :param artifactId: the maven artifact id.
        :type artifactId: string
        :param version: the version of the artifact.
        :type version: string
        :param repo: the maven repository to use.
        :type repo: string
        :param classifier: the classifier of the artifact.
        :type classifier: string
        :param artifact_type: the type of the artifact.
        :type artifact_type: string
        :param packaging: the packaging of the artifact.
        :type packaging: string
        :param filename: filename of the artifact; guessed if not specified.
        :type filename: string
        :param checksum: the sha1 checksum of the file.
        :type checksum: string
        """
        self.groupId = groupId
        self.artifactId = artifactId
        self.version = version
        self.repo = repo
        self.classifier = classifier
        self.type = artifact_type
        self.packaging = packaging
        self._filename = filename
        self.wanted_checksum = checksum

    @property
    def filename(self):
        """
        The full absolute path to this artifact.

        :return: path to artifact
        :rtype: string
        """
        cp = get_classpath().split(":")

        for artifact in cp:
            if self._filename:
                if os.path.basename(artifact) == self._filename:
                    return artifact
            else:
                if os.path.basename(artifact).startswith("-".join((
                    self.artifactId, self.version))):
                    return artifact

        if not self._filename:
            log.error("Please specify the filename as argument to %s." % self)
        else:
            log.error("Incorrect artifact filename for %s." % self)

        raise LookupError('Artifact filename could not be determined!')

    @property
    @memoized
    def actual_checksum(self):
        """
        The actual checksum of this artifact.
        """
        return sha1sum(self.filename)

    def check_checksum(self):
        """
        Checks if the checksum is correct.
        Raises an :class:`IntegrityError` if not.
        """
        if not self.wanted_checksum:
            return

        if not self.wanted_checksum == self.actual_checksum:
            raise IntegrityError(
                    "Checksums don't match! Actual %s; Wanted %s" % \
                    (self.actual_checksum, self.wanted_checksum))

    def __eq__(self, other):
        return self.__dict__ == other.__dict__

    def __repr__(self):
        return "<%s: %s>" % (self.__class__.__name__,
                dict2string(self.__dict__, MavenDependency.POM_ATTRIBS))

class POM(object):
    """
    This class represents a basic Maven POM.

    Duplicates are discarded, so no repository or dependency will
    be defined twice in the POM.

    Keywords are directly translated into children of the <project>
    node::

        POM(groupId='de.tu_darmstadt.penchy').write('pom.xml')

    would result in something like::

        <project>
            <groupId>de.tu_darmstadt.penchy</groupId>
        </project>
    """

    ATTRIBS = {
            'modelVersion': '4.0.0',
    }

    def __init__(self, **kwargs):
        self.repository_list = set()
        self.dependency_list = set()

        self.root = Element('project')
        self.tree = ElementTree(self.root)
        self.dependency_tree = SubElement(self.root, 'dependencies')
        self.repository_tree = SubElement(self.root, 'repositories')

        attribs = POM.ATTRIBS.copy()
        attribs.update(kwargs)
        dict2tree(self.root, attribs)

    def add_dependency(self, dep):
        """
        Adds a given dependency to the POM.

        :param dep: the dependency
        :type dep: :class:`MavenDependency`
        """
        if dep in self.dependency_list:
            return

        if dep.repo:
            self.add_repository(dep.repo)

        clean_dep = dict((k, v) for k, v in dep.__dict__.items() if k in
                MavenDependency.POM_ATTRIBS and v)

        e = SubElement(self.dependency_tree, 'dependency')
        dict2tree(e, clean_dep)

        self.dependency_list.add(dep)

    def add_repository(self, url, identifier=None):
        """
        Adds a repository to the POM.

        The identifier of the repository will be equal to
        the url by default.

        :param url: the URL of the repository
        :type url: string
        """
        if url in self.repository_list:
            return

        if not identifier:
            identifier = url

        e = SubElement(self.repository_tree, 'repository')
        dict2tree(e, {'url': url, 'id': identifier})

        self.repository_list.add(url)

    def write(self, filename='pom.xml', pretty=True):
        """
        Writes the POM to a file.

        :param filename: the filename to write to
        :type filename: string
        :param pretty: pretty-print resulting file
        :type pretty: bool
        """
        if pretty:
            tree_pp(self.root)

        self.tree.write(filename)

class BootstrapPOM(POM):
    """
    This class represents a bootstrap POM which is used to deploy
    PenchY and its dependencies.
    """

    def __init__(self):
        POM.__init__(self,
                groupId='de.tu_darmstadt.penchy',
                artifactId='penchy-bootstrap',
                name='penchy-bootstrap',
                url='http://www.tu-darmstadt.de',
                version=penchy_version,
                packaging='jar',  # won't work with pom
                )

        self.add_dependency(MavenDependency(
            groupId='de.tu_darmstadt.penchy',
            artifactId='penchy',
            version=penchy_version,
            classifier='py',
            repo='http://mvn.0x0b.de',
            artifact_type='zip'))
<commit_msg>removed blank lines<commit_after>#!/usr/bin/env python

import logging
import os
from subprocess import Popen, PIPE
from xml.etree.ElementTree import Element, SubElement, ElementTree

from penchy import __version__ as penchy_version
from penchy.util import memoized, tree_pp, dict2tree, dict2string, sha1sum

log = logging.getLogger("maven")

@memoized
def get_classpath():
    """
    Returns the Java classpath using Maven.

    This method expects a Maven POM (pom.xml) in the current
    working directory. A POM can be generated using the
    :class:`BootstrapPOM` or :class:`POM` class::

        >>> from penchy.maven import BootstrapPOM, get_classpath
        >>> from penchy.jobs.workloads import ScalaBench
        >>> pom = BootstrapPOM()
        >>> for dep in ScalaBench.DEPENDENCIES:
        ...     pom.add_dependency(dep)
        ...
        >>> pom.write()
        >>> get_classpath()
        '/home/fabian/.m2/repository/de/tu_darmstadt/penchy/penchy/0.1/penchy-0.1-py.zip:/home/fabian/.m2/repository/org/scalabench/benchmarks/scala-benchmark-suite/0.1.0-SNAPSHOT/scala-benchmark-suite-0.1.0-SNAPSHOT.jar'

    :returns: java classpath
    :rtype: string
    """
    if not os.path.exists('pom.xml'):
        raise OSError("No pom.xml found in the current directory")

    proc = Popen(['mvn', 'dependency:build-classpath'], stdout=PIPE)
    stdout, _ = proc.communicate()

    if proc.returncode is not 0:
        log.error(stdout)
        raise MavenError("The classpath could not be determined")

    for line in stdout.split("\n"):
        if not line.startswith("["):
            return line

    raise MavenError("The classpath was not in maven's output")

class MavenError(Exception):
    pass

class IntegrityError(Exception):
    pass

class MavenDependency(object):
    """
    This class represents a Maven Dependency.

    A sample Maven Dependency might look like::

        dep = MavenDependency('de.tu_darmstadt.penchy',
                              'pia', '2.0.0.0', 'http://mvn.0x0b.de')
    """
    POM_ATTRIBS = ('version', 'groupId', 'artifactId', 'version',
            'classifier', 'packaging', 'type')

    def __init__(self, groupId, artifactId, version, repo=None,
            classifier=None, artifact_type=None, packaging=None,
            filename=None, checksum=None):
        """
        :param groupId: the maven group id.
        :type groupId: string
        :param artifactId: the maven artifact id.
        :type artifactId: string
        :param version: the version of the artifact.
        :type version: string
        :param repo: the maven repository to use.
        :type repo: string
        :param classifier: the classifier of the artifact.
        :type classifier: string
        :param artifact_type: the type of the artifact.
        :type artifact_type: string
        :param packaging: the packaging of the artifact.
        :type packaging: string
        :param filename: filename of the artifact; guessed if not specified.
        :type filename: string
        :param checksum: the sha1 checksum of the file.
        :type checksum: string
        """
        self.groupId = groupId
        self.artifactId = artifactId
        self.version = version
        self.repo = repo
        self.classifier = classifier
        self.type = artifact_type
        self.packaging = packaging
        self._filename = filename
        self.wanted_checksum = checksum

    @property
    def filename(self):
        """
        The full absolute path to this artifact.

        :return: path to artifact
        :rtype: string
        """
        cp = get_classpath().split(":")

        for artifact in cp:
            if self._filename:
                if os.path.basename(artifact) == self._filename:
                    return artifact
            else:
                if os.path.basename(artifact).startswith("-".join((
                    self.artifactId, self.version))):
                    return artifact

        if not self._filename:
            log.error("Please specify the filename as argument to %s." % self)
        else:
            log.error("Incorrect artifact filename for %s." % self)

        raise LookupError('Artifact filename could not be determined!')

    @property
    @memoized
    def actual_checksum(self):
        """
        The actual checksum of this artifact.
        """
        return sha1sum(self.filename)

    def check_checksum(self):
        """
        Checks if the checksum is correct.
        Raises an :class:`IntegrityError` if not.
        """
        if not self.wanted_checksum:
            return

        if not self.wanted_checksum == self.actual_checksum:
            raise IntegrityError(
                    "Checksums don't match! Actual %s; Wanted %s" % \
                    (self.actual_checksum, self.wanted_checksum))

    def __eq__(self, other):
        return self.__dict__ == other.__dict__

    def __repr__(self):
        return "<%s: %s>" % (self.__class__.__name__,
                dict2string(self.__dict__, MavenDependency.POM_ATTRIBS))

class POM(object):
    """
    This class represents a basic Maven POM.

    Duplicates are discarded, so no repository or dependency will
    be defined twice in the POM.

    Keywords are directly translated into children of the <project>
    node::

        POM(groupId='de.tu_darmstadt.penchy').write('pom.xml')

    would result in something like::

        <project>
            <groupId>de.tu_darmstadt.penchy</groupId>
        </project>
    """

    ATTRIBS = {
            'modelVersion': '4.0.0',
    }

    def __init__(self, **kwargs):
        self.repository_list = set()
        self.dependency_list = set()

        self.root = Element('project')
        self.tree = ElementTree(self.root)
        self.dependency_tree = SubElement(self.root, 'dependencies')
        self.repository_tree = SubElement(self.root, 'repositories')

        attribs = POM.ATTRIBS.copy()
        attribs.update(kwargs)
        dict2tree(self.root, attribs)

    def add_dependency(self, dep):
        """
        Adds a given dependency to the POM.

        :param dep: the dependency
        :type dep: :class:`MavenDependency`
        """
        if dep in self.dependency_list:
            return

        if dep.repo:
            self.add_repository(dep.repo)

        clean_dep = dict((k, v) for k, v in dep.__dict__.items() if k in
                MavenDependency.POM_ATTRIBS and v)

        e = SubElement(self.dependency_tree, 'dependency')
        dict2tree(e, clean_dep)

        self.dependency_list.add(dep)

    def add_repository(self, url, identifier=None):
        """
        Adds a repository to the POM.

        The identifier of the repository will be equal to
        the url by default.

        :param url: the URL of the repository
        :type url: string
        """
        if url in self.repository_list:
            return

        if not identifier:
            identifier = url

        e = SubElement(self.repository_tree, 'repository')
        dict2tree(e, {'url': url, 'id': identifier})

        self.repository_list.add(url)

    def write(self, filename='pom.xml', pretty=True):
        """
        Writes the POM to a file.

        :param filename: the filename to write to
        :type filename: string
        :param pretty: pretty-print resulting file
        :type pretty: bool
        """
        if pretty:
            tree_pp(self.root)

        self.tree.write(filename)

class BootstrapPOM(POM):
    """
    This class represents a bootstrap POM which is used to deploy
    PenchY and its dependencies.
    """

    def __init__(self):
        POM.__init__(self,
                groupId='de.tu_darmstadt.penchy',
                artifactId='penchy-bootstrap',
                name='penchy-bootstrap',
                url='http://www.tu-darmstadt.de',
                version=penchy_version,
                packaging='jar',  # won't work with pom
                )

        self.add_dependency(MavenDependency(
            groupId='de.tu_darmstadt.penchy',
            artifactId='penchy',
            version=penchy_version,
            classifier='py',
            repo='http://mvn.0x0b.de',
            artifact_type='zip'))
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

import asyncio
import logging
import sys
from concurrent.futures import CancelledError

import aiohttp
import async_timeout

from . import data_processing, exceptions, utils
from .exceptions import StreamLimit
from .general import rate_limit_notices

ClientPayloadError = aiohttp.ClientPayloadError
ClientConnectionError = aiohttp.ClientConnectionError

RECONNECTION_TIMEOUT = 5
MAX_RECONNECTION_TIMEOUT = 320
DISCONNECTION_TIMEOUT = 0.25
ERROR_TIMEOUT = DISCONNECTION_TIMEOUT
MAX_DISCONNECTION_TIMEOUT = 16
ENHANCE_YOUR_CALM_TIMEOUT = 60

NORMAL = 0
DISCONNECTION = 1
ERROR = DISCONNECTION
RECONNECTION = 2
ENHANCE_YOUR_CALM = 3
EOF = 4

HandledErrors = asyncio.TimeoutError, ClientPayloadError, TimeoutError

logger = logging.getLogger(__name__)

class StreamResponse:
    """
        Asynchronous iterator for streams

    Parameters
    ----------
    *args : list, optional
        Positional arguments of the request
    client : .client.BasePeonyClient
        client used to make the request
    session : aiohttp.ClientSession, optional
        Session used by the request
    loads : function, optional
        function used to decode the JSON data received
    timeout : int, optional
        Timeout on connection
    kwargs : dict, optional
        Keyword parameters of the request
    """

    def __init__(self,
                 client,
                 session=None,
                 loads=data_processing.loads,
                 timeout=10,
                 **kwargs):

        self.client = client
        self.session = session
        self.loads = loads
        self.timeout = timeout
        self.kwargs = kwargs

        self.response = None
        self._reconnecting = False
        self._state = NORMAL
        self._error_timeout = 0

    async def _connect(self):
        """
            Connect to the stream

        Returns
        -------
        asyncio.coroutine
            The streaming response
        """
        logger.debug("connecting to the stream")
        await self.client.setup
        if self.session is None:
            self.session = self.client._session
        kwargs = await self.client.headers.prepare_request(**self.kwargs)
        request = self.client.error_handler(self.session.request)

        return await request(timeout=0, **kwargs)

    async def connect(self):
        """
            Create the connection

        Returns
        -------
        self

        Raises
        ------
        exception.PeonyException
            On a response status in 4xx that are not status 420 or 429
            Also on statuses in 1xx or 3xx since this should not be the status
            received here
        """
        with async_timeout.timeout(self.timeout):
            self.response = await self._connect()

        if self.response.status in range(200, 300):
            self._error_timeout = 0
            self.state = NORMAL
        elif self.response.status == 500:
            self.state = DISCONNECTION
        elif self.response.status in range(501, 600):
            self.state = RECONNECTION
        elif self.response.status in (420, 429):
            self.state = ENHANCE_YOUR_CALM
        else:
            logger.debug("raising error during stream connection")
            raise await exceptions.throw(self.response,
                                         loads=self.client._loads,
                                         url=self.kwargs['url'])

        logger.debug("stream state: %d" % self.state)

    def __aiter__(self):
        return self

    if sys.version_info < (3, 5, 2):  # pragma: no cover
        __aiter__ = asyncio.coroutine(__aiter__)

    async def __anext__(self):
        """
            Decode each line using json

        Returns
        -------
        dict
            Decoded JSON data
        """
        if self.response is None:
            logger.info("first connection to the stream")
            await self.connect()
            return {'connected': True}

        line = b''
        try:
            if self.state != NORMAL:
                if self._reconnecting:
                    return await self.restart_stream()
                else:
                    return await self.init_restart()

            while not line:
                if self.response.content.at_eof():
                    logger.debug("Received EOF")
                    self.state = EOF
                    return await self.init_restart()

                with async_timeout.timeout(90):
                    line = await self.response.content.readline()
                    line = line.strip(b'\r\n')
                    logger.debug("received data: %s" % line)

            if line in rate_limit_notices:
                logger.debug("raising StreamLimit")
                raise StreamLimit(line)

            logger.debug("decoding data")
            return self.loads(line)

        except HandledErrors as e:
            logger.debug("handling error %s: %s" % (e.__class__.__name__, e))
            self.state = ERROR
            return await self.init_restart()

        except ClientConnectionError:
            logger.debug("Disconnected from stream")
            self.state = DISCONNECTION
            return await self.init_restart()

        except CancelledError:
            logger.debug("Stopping stream")
            raise

        except Exception as e:
            self.state = ERROR
            return await self.init_restart(error=e)

    @property
    def state(self):
        return self._state

    @state.setter
    def state(self, value):
        if value == NORMAL or self.state < value:
            self._state = value

    async def init_restart(self, error=None):
        """
            Restart the stream on error

        Parameters
        ----------
        error : bool, optional
            Whether to print the error or not
        """
        if error:
            utils.log_error(logger=logger)

        if self.state == DISCONNECTION:
            if self._error_timeout < MAX_DISCONNECTION_TIMEOUT:
                self._error_timeout += DISCONNECTION_TIMEOUT

            logger.info("The stream was disconnected, will reconnect in %ss"
                        % self._error_timeout)

        elif self.state == RECONNECTION:
            if self._error_timeout < RECONNECTION_TIMEOUT:
                self._error_timeout = RECONNECTION_TIMEOUT
            elif self._error_timeout < MAX_RECONNECTION_TIMEOUT:
                self._error_timeout *= 2

            logger.info("Could not connect to the stream, reconnection in %ss"
                        % self._error_timeout)

        elif self.state == ENHANCE_YOUR_CALM:
            if self._error_timeout < ENHANCE_YOUR_CALM_TIMEOUT:
                self._error_timeout = ENHANCE_YOUR_CALM_TIMEOUT
            else:
                self._error_timeout *= 2

            logger.warning("Enhance Your Calm response received from Twitter. "
                           "If you didn't restart your program frenetically "
                           "then there is probably something wrong with it. "
                           "Make sure you are not opening too many connections"
                           " to the endpoint you are currently using by "
                           "checking out Twitter's Streaming API "
                           "documentation: "
                           "https://dev.twitter.com/streaming/overview\n"
                           "The stream will restart in %ss."
                           % self._error_timeout)
        elif self.state == EOF:
            pass  # no timeout
        else:
            raise RuntimeError("Incorrect state: %d" % self.state)

        self._reconnecting = True
        return {'reconnecting_in': self._error_timeout, 'error': error}

    async def restart_stream(self):
        """
            Restart the stream on error
        """
        await self.response.release()
        await asyncio.sleep(self._error_timeout)
        await self.connect()

        logger.info("Reconnected to the stream")
        self._reconnecting = False
        return {'stream_restart': True}

    def __enter__(self):
        """
            Prepare the stream

        Returns
        -------
        StreamResponse
            The stream iterator
        """
        return self

    async def __aenter__(self):
        """
            Prepare the stream

        Returns
        -------
        StreamResponse
            The stream iterator
        """
        await self.client.setup
        return self

    def __exit__(self, *args):
        """ Close the response on error """
        if getattr(self, 'response', None) is not None:
            if not self.response.closed:
                logger.debug("Closing the stream")
                self.response.close()

    async def __aexit__(self, *args):
        """ Close the response on error """
        self.__exit__(*args)
<commit_msg>stream: fix CancelledError import for python 3.8+<commit_after># -*- coding: utf-8 -*-

import asyncio
import logging
import sys

try:
    from asyncio import CancelledError
except ImportError:
    from concurrent.futures import CancelledError

import aiohttp
import async_timeout

from . import data_processing, exceptions, utils
from .exceptions import StreamLimit
from .general import rate_limit_notices

ClientPayloadError = aiohttp.ClientPayloadError
ClientConnectionError = aiohttp.ClientConnectionError

RECONNECTION_TIMEOUT = 5
MAX_RECONNECTION_TIMEOUT = 320
DISCONNECTION_TIMEOUT = 0.25
ERROR_TIMEOUT = DISCONNECTION_TIMEOUT
MAX_DISCONNECTION_TIMEOUT = 16
ENHANCE_YOUR_CALM_TIMEOUT = 60

NORMAL = 0
DISCONNECTION = 1
ERROR = DISCONNECTION
RECONNECTION = 2
ENHANCE_YOUR_CALM = 3
EOF = 4

HandledErrors = asyncio.TimeoutError, ClientPayloadError, TimeoutError

logger = logging.getLogger(__name__)

class StreamResponse:
    """
        Asynchronous iterator for streams

    Parameters
    ----------
    *args : list, optional
        Positional arguments of the request
    client : .client.BasePeonyClient
        client used to make the request
    session : aiohttp.ClientSession, optional
        Session used by the request
    loads : function, optional
        function used to decode the JSON data received
    timeout : int, optional
        Timeout on connection
    kwargs : dict, optional
        Keyword parameters of the request
    """

    def __init__(self,
                 client,
                 session=None,
                 loads=data_processing.loads,
                 timeout=10,
                 **kwargs):

        self.client = client
        self.session = session
        self.loads = loads
        self.timeout = timeout
        self.kwargs = kwargs

        self.response = None
        self._reconnecting = False
        self._state = NORMAL
        self._error_timeout = 0

    async def _connect(self):
        """
            Connect to the stream

        Returns
        -------
        asyncio.coroutine
            The streaming response
        """
        logger.debug("connecting to the stream")
        await self.client.setup
        if self.session is None:
            self.session = self.client._session
        kwargs = await self.client.headers.prepare_request(**self.kwargs)
        request = self.client.error_handler(self.session.request)

        return await request(timeout=0, **kwargs)

    async def connect(self):
        """
            Create the connection

        Returns
        -------
        self

        Raises
        ------
        exception.PeonyException
            On a response status in 4xx that are not status 420 or 429
            Also on statuses in 1xx or 3xx since this should not be the status
            received here
        """
        with async_timeout.timeout(self.timeout):
            self.response = await self._connect()

        if self.response.status in range(200, 300):
            self._error_timeout = 0
            self.state = NORMAL
        elif self.response.status == 500:
            self.state = DISCONNECTION
        elif self.response.status in range(501, 600):
            self.state = RECONNECTION
        elif self.response.status in (420, 429):
            self.state = ENHANCE_YOUR_CALM
        else:
            logger.debug("raising error during stream connection")
            raise await exceptions.throw(self.response,
                                         loads=self.client._loads,
                                         url=self.kwargs['url'])

        logger.debug("stream state: %d" % self.state)

    def __aiter__(self):
        return self

    if sys.version_info < (3, 5, 2):  # pragma: no cover
        __aiter__ = asyncio.coroutine(__aiter__)

    async def __anext__(self):
        """
            Decode each line using json

        Returns
        -------
        dict
            Decoded JSON data
        """
        if self.response is None:
            logger.info("first connection to the stream")
            await self.connect()
            return {'connected': True}

        line = b''
        try:
            if self.state != NORMAL:
                if self._reconnecting:
                    return await self.restart_stream()
                else:
                    return await self.init_restart()

            while not line:
                if self.response.content.at_eof():
                    logger.debug("Received EOF")
                    self.state = EOF
                    return await self.init_restart()

                with async_timeout.timeout(90):
                    line = await self.response.content.readline()
                    line = line.strip(b'\r\n')
                    logger.debug("received data: %s" % line)

            if line in rate_limit_notices:
                logger.debug("raising StreamLimit")
                raise StreamLimit(line)

            logger.debug("decoding data")
            return self.loads(line)

        except HandledErrors as e:
            logger.debug("handling error %s: %s" % (e.__class__.__name__, e))
            self.state = ERROR
            return await self.init_restart()

        except ClientConnectionError:
            logger.debug("Disconnected from stream")
            self.state = DISCONNECTION
            return await self.init_restart()

        except CancelledError:
            logger.debug("Stopping stream")
            raise

        except Exception as e:
            self.state = ERROR
            return await self.init_restart(error=e)

    @property
    def state(self):
        return self._state

    @state.setter
    def state(self, value):
        if value == NORMAL or self.state < value:
            self._state = value

    async def init_restart(self, error=None):
        """
            Restart the stream on error

        Parameters
        ----------
        error : bool, optional
            Whether to print the error or not
        """
        if error:
            utils.log_error(logger=logger)

        if self.state == DISCONNECTION:
            if self._error_timeout < MAX_DISCONNECTION_TIMEOUT:
                self._error_timeout += DISCONNECTION_TIMEOUT

            logger.info("The stream was disconnected, will reconnect in %ss"
                        % self._error_timeout)

        elif self.state == RECONNECTION:
            if self._error_timeout < RECONNECTION_TIMEOUT:
                self._error_timeout = RECONNECTION_TIMEOUT
            elif self._error_timeout < MAX_RECONNECTION_TIMEOUT:
                self._error_timeout *= 2

            logger.info("Could not connect to the stream, reconnection in %ss"
                        % self._error_timeout)

        elif self.state == ENHANCE_YOUR_CALM:
            if self._error_timeout < ENHANCE_YOUR_CALM_TIMEOUT:
                self._error_timeout = ENHANCE_YOUR_CALM_TIMEOUT
            else:
                self._error_timeout *= 2

            logger.warning("Enhance Your Calm response received from Twitter. "
                           "If you didn't restart your program frenetically "
                           "then there is probably something wrong with it. "
                           "Make sure you are not opening too many connections"
                           " to the endpoint you are currently using by "
                           "checking out Twitter's Streaming API "
                           "documentation: "
                           "https://dev.twitter.com/streaming/overview\n"
                           "The stream will restart in %ss."
                           % self._error_timeout)
        elif self.state == EOF:
            pass  # no timeout
        else:
            raise RuntimeError("Incorrect state: %d" % self.state)

        self._reconnecting = True
        return {'reconnecting_in': self._error_timeout, 'error': error}

    async def restart_stream(self):
        """
            Restart the stream on error
        """
        await self.response.release()
        await asyncio.sleep(self._error_timeout)
        await self.connect()

        logger.info("Reconnected to the stream")
        self._reconnecting = False
        return {'stream_restart': True}

    def __enter__(self):
        """
            Prepare the stream

        Returns
        -------
        StreamResponse
            The stream iterator
        """
        return self

    async def __aenter__(self):
        """
            Prepare the stream

        Returns
        -------
        StreamResponse
            The stream iterator
        """
        await self.client.setup
        return self

    def __exit__(self, *args):
        """ Close the response on error """
        if getattr(self, 'response', None) is not None:
            if not self.response.closed:
                logger.debug("Closing the stream")
                self.response.close()

    async def __aexit__(self, *args):
        """ Close the response on error """
        self.__exit__(*args)
<|endoftext|>


<commit_before>from typing import Iterable, NamedTuple
from re import compile
from collections import namedtuple
from subprocess import getoutput
from sys import exit

import click

PREFIX = 'test'
SUFFIX = "g2sd"

NAME_RE = compile("menuentry '(?P<name>[\w\d\W\D]*)' -")
KERNEL_RE = compile("linux(?:[\t ]*)(?P<kernel>.*) root=(?P<root>[\w\d\-=\/]*)")
INIT_RE = compile("initrd(?:[\t ])(?P<initrd>.*)")

#MenuEntry = namedtuple('MenuEntry', 'name kernel root initrd')
class MenuEntry(NamedTuple):
    name: str
    kernel: str
    root: str
    initrd: str

def gen_menu_entries(input: Iterable[str]) -> Iterable[MenuEntry]:
    args = []

    for num, line in enumerate(input):
        try:
            line = line.strip()

            if line.startswith('menuentry'):
                if args:
                    args = []

                name = NAME_RE.findall(line)

                args.extend(name)

            elif line.startswith("linux"):
                all = KERNEL_RE.findall(line)
                args.extend(all[0])

            elif line.startswith("initrd"):
                init = INIT_RE.findall(line)
                args.extend(init)

                yield MenuEntry(*args)

                args = []

        except Exception as ex:
            print(args, ex)
            exit(1)

def convert_root_entry(root_str: str) -> str:
    if root_str.startswith('UUID'):
        _, uuid = root_str.split('=')
        cmd = "blkid -t %s" % root_str

    elif root_str.startswith("PARTUUID"):
        return root_str

    else:
        cmd = "blkid %s" % root_str

    blkid_out = getoutput(cmd)
    partuuid_str = blkid_out.split(' ')[-1]
    partuuid_str = partuuid_str.replace('"', '')

    return partuuid_str

def parse_options(options_str: str) -> str:
    options = options_str.split(' ')

    return ' '.join(option for option in options
                    if not option.startswith('$'))

def menuentry_to_systemd(me: MenuEntry) -> str:
    partuuid = convert_root_entry(me.root)
    options = ' '.join((partuuid, parse_options(me.options)))

    return "title %s\nlinux %s\ninitrd %s\noptions %s" % (me.name, me.kernel, me.initrd, options)

@click.command(help="Convert your grub.cfg bootloader entries into systemd-boot loaders. GRUB_FILE is usually located in /boot/grub and your ESP_PATH is usually /boot.")
@click.argument("grub_file", type=click.Path(dir_okay=False, exists=True, readable=True))
@click.argument("esp_path", type=click.Path(dir_okay=True, exists=True, writable=True))
def cmd(grub_file: str, esp_path: str):
    with open(grub_file, "r") as file:
        grub = file.read().splitlines()

    for index, me in enumerate(gen_menu_entries(grub)):
        with open(esp_path + f'/loader/entries/{index}_{SUFFIX}.conf', 'w+') as file:
            file.write(menuentry_to_systemd(me))
            print("Wrote %s to %s" % (me.name, file.name))

if __name__ == "__main__":
    cmd()
<commit_msg>Add options to MenuEntry<commit_after>from typing import Iterable, NamedTuple
from re import compile
from collections import namedtuple
from subprocess import getoutput
from sys import exit

import click

PREFIX = 'test'
SUFFIX = "g2sd"

NAME_RE = compile("menuentry '(?P<name>[\w\d\W\D]*)' -")
KERNEL_RE = compile("linux(?:[\t ]*)(?P<kernel>.*) root=(?P<root>[\w\d\-=\/]*)")
INIT_RE = compile("initrd(?:[\t ])(?P<initrd>.*)")

#MenuEntry = namedtuple('MenuEntry', 'name kernel root initrd')
class MenuEntry(NamedTuple):
    name: str
    kernel: str
    root: str
    options: str
    initrd: str

def gen_menu_entries(input: Iterable[str]) -> Iterable[MenuEntry]:
    args = []

    for num, line in enumerate(input):
        try:
            line = line.strip()

            if line.startswith('menuentry'):
                if args:
                    args = []

                name = NAME_RE.findall(line)

                args.extend(name)

            elif line.startswith("linux"):
                all = KERNEL_RE.findall(line)
                args.extend(all[0])

            elif line.startswith("initrd"):
                init = INIT_RE.findall(line)
                args.extend(init)

                yield MenuEntry(*args)

                args = []

        except Exception as ex:
            print(args, ex)
            exit(1)

def convert_root_entry(root_str: str) -> str:
    if root_str.startswith('UUID'):
        _, uuid = root_str.split('=')
        cmd = "blkid -t %s" % root_str

    elif root_str.startswith("PARTUUID"):
        return root_str

    else:
        cmd = "blkid %s" % root_str

    blkid_out = getoutput(cmd)
    partuuid_str = blkid_out.split(' ')[-1]
    partuuid_str = partuuid_str.replace('"', '')

    return partuuid_str

def parse_options(options_str: str) -> str:
    options = options_str.split(' ')

    return ' '.join(option for option in options
                    if not option.startswith('$'))

def menuentry_to_systemd(me: MenuEntry) -> str:
    partuuid = convert_root_entry(me.root)
    options = ' '.join((partuuid, parse_options(me.options)))

    return "title %s\nlinux %s\ninitrd %s\noptions %s" % (me.name, me.kernel, me.initrd, options)

@click.command(help="Convert your grub.cfg bootloader entries into systemd-boot loaders. GRUB_FILE is usually located in /boot/grub and your ESP_PATH is usually /boot.")
@click.argument("grub_file", type=click.Path(dir_okay=False, exists=True, readable=True))
@click.argument("esp_path", type=click.Path(dir_okay=True, exists=True, writable=True))
def cmd(grub_file: str, esp_path: str):
    with open(grub_file, "r") as file:
        grub = file.read().splitlines()

    for index, me in enumerate(gen_menu_entries(grub)):
        with open(esp_path + f'/loader/entries/{index}_{SUFFIX}.conf', 'w+') as file:
            file.write(menuentry_to_systemd(me))
            print("Wrote %s to %s" % (me.name, file.name))

if __name__ == "__main__":
    cmd()
<|endoftext|>


<commit_before>###########################################################################
#Copyright [2016] [Anna Levin, Lyran Shour - IBM]
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
############################################################################

import uuid
import os
import logging
from netfa.fa_sdn_controller import FaSdnController
from netfa.fa_sdn_controller import EventRegisterVNIDReq
from ryu.controller.handler import MAIN_DISPATCHER
from ryu.controller.handler import set_ev_cls
import ryu.lib.ovs.vsctl as ovs_vsctl
from ryu import cfg

class FaBridge(FaSdnController):
    def initialize(self):
        return

    def __init__(self, *args, **kwargs):
        super(FaBridge, self).__init__(*args, **kwargs)
        self.vsctl = ovs_vsctl.VSCtl('unix:/usr/local/var/run/openvswitch/db.sock')

    def get_module_name(self):
        return 'FaBridge'

    def register_vnid(self, req):

        # add patch port on OVN bridge
        vnid_ctl_port = self._add_patch_port(self.CONF.netfa.controller_br_name, req.vNID, 'fa-br')

        vnid_fa_port = self._add_patch_port(self.CONF.netfa.fa_br_name, 'fa-br', req.vNID)

        logging.info('Created FA<-->Bridge peer ports %s<-->%s',
                     vnid_ctl_port, vnid_fa_port)

        return vnid_fa_port

    def _add_patch_port(self, bridge, base, peer):
        port_name = base + "-" + peer
        peer_name = peer + "-" + base

        command1 = ovs_vsctl.VSCtlCommand('add-port', (bridge, port_name), options=['--may_exist'])
        options = 'peer=%s' % peer_name
        command2 = ovs_vsctl.VSCtlCommand('set', ('Interface', port_name, 'type=patch',  'options=%s' % options))

        self.vsctl.run_command([command1, command2])

        return port_name
<commit_msg>Update fa_bridge.py<commit_after>###########################################################################
#Copyright  2016 Anna Levin, Liran Shour - IBM
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
############################################################################

import uuid
import os
import logging
from netfa.fa_sdn_controller import FaSdnController
from netfa.fa_sdn_controller import EventRegisterVNIDReq
from ryu.controller.handler import MAIN_DISPATCHER
from ryu.controller.handler import set_ev_cls
import ryu.lib.ovs.vsctl as ovs_vsctl
from ryu import cfg

class FaBridge(FaSdnController):
    def initialize(self):
        return

    def __init__(self, *args, **kwargs):
        super(FaBridge, self).__init__(*args, **kwargs)
        self.vsctl = ovs_vsctl.VSCtl('unix:/usr/local/var/run/openvswitch/db.sock')

    def get_module_name(self):
        return 'FaBridge'

    def register_vnid(self, req):

        # add patch port on OVN bridge
        vnid_ctl_port = self._add_patch_port(self.CONF.netfa.controller_br_name, req.vNID, 'fa-br')

        vnid_fa_port = self._add_patch_port(self.CONF.netfa.fa_br_name, 'fa-br', req.vNID)

        logging.info('Created FA<-->Bridge peer ports %s<-->%s',
                     vnid_ctl_port, vnid_fa_port)

        return vnid_fa_port

    def _add_patch_port(self, bridge, base, peer):
        port_name = base + "-" + peer
        peer_name = peer + "-" + base

        command1 = ovs_vsctl.VSCtlCommand('add-port', (bridge, port_name), options=['--may_exist'])
        options = 'peer=%s' % peer_name
        command2 = ovs_vsctl.VSCtlCommand('set', ('Interface', port_name, 'type=patch',  'options=%s' % options))

        self.vsctl.run_command([command1, command2])

        return port_name
<|endoftext|>


<commit_before>from django.core.urlresolvers import reverse
from django.core.mail import send_mail
from django.template.loader import render_to_string

from django.contrib.auth.tokens import default_token_generator
from django.utils.http import int_to_base36

from ifresnoy import settings

def send_activation_email(request, user):

    # Create activation token URL
    uidb36 = int_to_base36(user.id)
    token = default_token_generator.make_token(user)
    url = reverse('user-activate', kwargs={
        'uidb36': uidb36,
        'token': token,
    })
    absolute_url = request.build_absolute_uri(url)
    # Send email
    msg_plain = render_to_string('emails/send_activation_link.txt', {'url': absolute_url})
    msg_html = render_to_string('emails/send_activation_link.html', {'url': absolute_url})

    mail_sent = send_mail('Le Fresnoy - Activation du compte',
                          msg_plain,
                          'pedagogie@lefresnoy.net',
                          [user.email],
                          html_message=msg_html,
                          )
    return mail_sent

def send_account_information_email(user):

    reset_password_url = settings.authfront_reset_password_url

    # Send email
    msg_plain = render_to_string('emails/account_infos.txt', {'user': user, 'reset_password_url': reset_password_url})
    msg_html = render_to_string('emails/account_infos.html', {'user': user, 'reset_password_url': reset_password_url})

    mail_sent = send_mail('Le Fresnoy - Activation du compte',
                          msg_plain,
                          'poleweb@lefresnoy.net',
                          [user.email],
                          html_message=msg_html,
                          )
    return mail_sent
<commit_msg>pep8 fix<commit_after>from django.core.urlresolvers import reverse
from django.core.mail import send_mail
from django.template.loader import render_to_string

from django.contrib.auth.tokens import default_token_generator
from django.utils.http import int_to_base36

from ifresnoy import settings

def send_activation_email(request, user):

    # Create activation token URL
    uidb36 = int_to_base36(user.id)
    token = default_token_generator.make_token(user)
    url = reverse('user-activate', kwargs={
        'uidb36': uidb36,
        'token': token,
    })
    absolute_url = request.build_absolute_uri(url)
    # Send email
    msg_plain = render_to_string('emails/send_activation_link.txt', {'url': absolute_url})
    msg_html = render_to_string('emails/send_activation_link.html', {'url': absolute_url})

    mail_sent = send_mail('Le Fresnoy - Activation du compte',
                          msg_plain,
                          'pedagogie@lefresnoy.net',
                          [user.email],
                          html_message=msg_html,
                          )
    return mail_sent

def send_account_information_email(user):

    reset_password_url = settings.authfront_reset_password_url

    # Send email
    msg_plain = render_to_string('emails/account_infos.txt', {'user': user, 'reset_password_url': reset_password_url})
    msg_html = render_to_string('emails/account_infos.html', {'user': user, 'reset_password_url': reset_password_url})

    mail_sent = send_mail('Le Fresnoy - Activation du compte',
                          msg_plain,
                          'poleweb@lefresnoy.net',
                          [user.email],
                          html_message=msg_html,
                          )
    return mail_sent
<|endoftext|>