# Path: zoe_api/zapp_shop.py
# ZAPP_MANIFEST_VERSION = 1  # The manifest version this Zoe Shop can understand
# class ZAppParameter:
# class ZApp:
#     def __init__(self, param_manifest):
#     def __init__(self, zapp_id, manifest, manifest_index):
#     def parse_parameters(self, zapp_manifest):
#     def read_description(self):
#     def parse_json_description(self):
# def zshop_list_apps(role):
# def zshop_read_manifest(zapp_id):
# def get_logo(zapp: ZApp):
# 
# Path: zoe_api/web/request_handler.py
# class ZoeWebRequestHandler(ZoeRequestHandler):
#     """RequestHandler class for Zoe Web interface."""
# 
#     def initialize(self, **kwargs):
#         """Initialize the Jinja template system."""
#         super().initialize(**kwargs)
#         if 'jinja_environment' not in self.application.settings:
#             raise RuntimeError("Needs jinja2 Environment. Initialize with JinjaApp.init_app first")
#         else:
#             self._jinja_env = self.application.settings['jinja_environment']
# 
#     def _render(self, template, **kwargs):
#         """ todo: support multiple template preprocessors """
# 
#         ctx = {
#             'request': self.request,
#             'path_args': self.path_args,
#             'path_kwargs': self.path_kwargs,
#             'settings': self.application.settings,
#             'reverse_url': self.application.reverse_url,
#             'static_url': self.static_url,
#             'xsrf_form_html': self.xsrf_form_html,
#             'datetime': datetime,
#             'locale': self.locale,
#             'handler': self,
#             'zoe_version': zoe_lib.version.ZOE_VERSION,
#             'server_address': self.request.host,
#         }
# 
#         try:
#             ctx['user'] = super().get_current_user()
#         except ZoeAuthException:
#             pass
# 
#         ctx.update(kwargs)
#         return template.render(ctx)
# 
#     def render(self, template_name, **kwargs):
#         """ renders a template file. """
#         template = self._jinja_env.get_template(template_name)
#         try:
#             html = self._render(template, **kwargs)
#         except TemplateSyntaxError as e:
#             self.error_page('Template syntax error at {}:{}:<br> {}'.format(e.name, e.lineno, e.message), 500)
#             return
#         except Exception as e:
#             log.exception('Jinja2 exception while rendering the template {}'.format(template_name))
#             self.error_page('Jinja2 template exception: {}'.format(e), 500)
#             return
#         self.finish(html)
# 
#     def render_string(self, source, **kwargs):
#         """ renders a template source string. """
#         template = self._jinja_env.from_string(source)
#         return self._render(template, **kwargs)
# 
#     def get_current_user(self):
#         """In case auth fails, redirect to login page."""
#         try:
#             user = super().get_current_user()
#         except ZoeAuthException as e:
#             with_gitlab_oauth = zoe_lib.config.get_conf().oauth_client_id != ''
#             self.render('login.jinja2', error=e.message, with_gitlab_oauth=with_gitlab_oauth)
#             return None
#         return user
# 
#     def error_page(self, error_message: str, status: int = 400):
#         """Generate an error page."""
#         self.set_status(status)
#         self.render('error.jinja2', error=error_message)
# 
# Path: zoe_api/exceptions.py
# class ZoeException(Exception):
#     """
#     A generic exception.
#     """
#     def __init__(self, message='Something happened'):
#         super().__init__()
#         self.message = message
#         self.status_code = 500
# 
#     def __str__(self):
#         return '{}: {}'.format(self.status_code, self.message)
# 
# Path: zoe_lib/config.py
# def get_conf() -> Namespace:
#     """Returns the conf singleton."""
#     return _CONF


import logging
from tornado.web import MissingArgumentError
from zoe_api import zapp_shop
from zoe_api.web.request_handler import ZoeWebRequestHandler
from zoe_api.exceptions import ZoeException
from zoe_lib.config import get_conf

        manifest_index = int(zapp_id.split('-')[-1])
        zapp_id = "-".join(zapp_id.split('-')[:-1])
        zapps = zapp_shop.zshop_read_manifest(zapp_id)
        zapp = zapps[manifest_index]

        exec_name = self.get_argument('exec_name')

        if self.current_user.role.can_customize_resources:
            app_descr = self._set_parameters(zapp.zoe_description, zapp.parameters)
        else:
            app_descr = zapp.zoe_description

        if len(zapp.labels) > 0:
            for service in app_descr['services']:
                if 'labels' in service:
                    service['labels'].append(zapp.labels)
                else:
                    service['labels'] = zapp.labels

        try:
            self.get_argument('download_json')
            self.set_header('Content-Type', 'application/json')
            self.set_header('Content-Disposition', 'attachment; filename={}.json'.format(zapp_id))
            self.write(app_descr)
            self.finish()
            return
        except MissingArgumentError:
            try:
                new_id = self.api_endpoint.execution_start(self.current_user, exec_name, app_descr)

# Path: zoe_api/zapp_shop.py
# ZAPP_MANIFEST_VERSION = 1  # The manifest version this Zoe Shop can understand
# class ZAppParameter:
# class ZApp:
#     def __init__(self, param_manifest):
#     def __init__(self, zapp_id, manifest, manifest_index):
#     def parse_parameters(self, zapp_manifest):
#     def read_description(self):
#     def parse_json_description(self):
# def zshop_list_apps(role):
# def zshop_read_manifest(zapp_id):
# def get_logo(zapp: ZApp):
# 
# Path: zoe_api/web/request_handler.py
# class ZoeWebRequestHandler(ZoeRequestHandler):
#     """RequestHandler class for Zoe Web interface."""
# 
#     def initialize(self, **kwargs):
#         """Initialize the Jinja template system."""
#         super().initialize(**kwargs)
#         if 'jinja_environment' not in self.application.settings:
#             raise RuntimeError("Needs jinja2 Environment. Initialize with JinjaApp.init_app first")
#         else:
#             self._jinja_env = self.application.settings['jinja_environment']
# 
#     def _render(self, template, **kwargs):
#         """ todo: support multiple template preprocessors """
# 
#         ctx = {
#             'request': self.request,
#             'path_args': self.path_args,
#             'path_kwargs': self.path_kwargs,
#             'settings': self.application.settings,
#             'reverse_url': self.application.reverse_url,
#             'static_url': self.static_url,
#             'xsrf_form_html': self.xsrf_form_html,
#             'datetime': datetime,
#             'locale': self.locale,
#             'handler': self,
#             'zoe_version': zoe_lib.version.ZOE_VERSION,
#             'server_address': self.request.host,
#         }
# 
#         try:
#             ctx['user'] = super().get_current_user()
#         except ZoeAuthException:
#             pass
# 
#         ctx.update(kwargs)
#         return template.render(ctx)
# 
#     def render(self, template_name, **kwargs):
#         """ renders a template file. """
#         template = self._jinja_env.get_template(template_name)
#         try:
#             html = self._render(template, **kwargs)
#         except TemplateSyntaxError as e:
#             self.error_page('Template syntax error at {}:{}:<br> {}'.format(e.name, e.lineno, e.message), 500)
#             return
#         except Exception as e:
#             log.exception('Jinja2 exception while rendering the template {}'.format(template_name))
#             self.error_page('Jinja2 template exception: {}'.format(e), 500)
#             return
#         self.finish(html)
# 
#     def render_string(self, source, **kwargs):
#         """ renders a template source string. """
#         template = self._jinja_env.from_string(source)
#         return self._render(template, **kwargs)
# 
#     def get_current_user(self):
#         """In case auth fails, redirect to login page."""
#         try:
#             user = super().get_current_user()
#         except ZoeAuthException as e:
#             with_gitlab_oauth = zoe_lib.config.get_conf().oauth_client_id != ''
#             self.render('login.jinja2', error=e.message, with_gitlab_oauth=with_gitlab_oauth)
#             return None
#         return user
# 
#     def error_page(self, error_message: str, status: int = 400):
#         """Generate an error page."""
#         self.set_status(status)
#         self.render('error.jinja2', error=error_message)
# 
# Path: zoe_api/exceptions.py
# class ZoeException(Exception):
#     """
#     A generic exception.
#     """
#     def __init__(self, message='Something happened'):
#         super().__init__()
#         self.message = message
#         self.status_code = 500
# 
#     def __str__(self):
#         return '{}: {}'.format(self.status_code, self.message)
# 
# Path: zoe_lib/config.py
# def get_conf() -> Namespace:
#     """Returns the conf singleton."""
#     return _CONF


# Path: zoe_api/web/zapp_shop.py
import logging
from tornado.web import MissingArgumentError
from zoe_api import zapp_shop
from zoe_api.web.request_handler import ZoeWebRequestHandler
from zoe_api.exceptions import ZoeException
from zoe_lib.config import get_conf


        manifest_index = int(zapp_id.split('-')[-1])
        zapp_id = "-".join(zapp_id.split('-')[:-1])
        zapps = zapp_shop.zshop_read_manifest(zapp_id)
        zapp = zapps[manifest_index]

        exec_name = self.get_argument('exec_name')

        if self.current_user.role.can_customize_resources:
            app_descr = self._set_parameters(zapp.zoe_description, zapp.parameters)
        else:
            app_descr = zapp.zoe_description

        if len(zapp.labels) > 0:
            for service in app_descr['services']:
                if 'labels' in service:
                    service['labels'].append(zapp.labels)
                else:
                    service['labels'] = zapp.labels

        try:
            self.get_argument('download_json')
            self.set_header('Content-Type', 'application/json')
            self.set_header('Content-Disposition', 'attachment; filename={}.json'.format(zapp_id))
            self.write(app_descr)
            self.finish()
            return
        except MissingArgumentError:
            try:
                new_id = self.api_endpoint.execution_start(self.current_user, exec_name, app_descr)

            except ZoeException as e: