Exemplo n.º 1
0
def test_dotted_name():
    assert utils.get_dotted_name(
        FooBar()) == 'guillotina.tests.test_utils.FooBar'
    assert utils.get_dotted_name(
        FooBar) == 'guillotina.tests.test_utils.FooBar'
    assert utils.get_module_dotted_name(
        FooBar()) == 'guillotina.tests.test_utils'
    assert utils.get_module_dotted_name(
        FooBar) == 'guillotina.tests.test_utils'
    assert utils.get_dotted_name(
        IResource) == 'guillotina.interfaces.content.IResource'
Exemplo n.º 2
0
def test_dotted_name():
    assert utils.get_dotted_name(
        FooBar()) == 'guillotina.tests.test_utils.FooBar'
    assert utils.get_dotted_name(
        FooBar) == 'guillotina.tests.test_utils.FooBar'
    assert utils.get_module_dotted_name(
        FooBar()) == 'guillotina.tests.test_utils'
    assert utils.get_module_dotted_name(
        FooBar) == 'guillotina.tests.test_utils'
    assert utils.get_dotted_name(
        IResource) == 'guillotina.interfaces.content.IResource'
Exemplo n.º 3
0
async def get_all_subscribers(context, request):
    subscribers = {}
    sm = component.get_global_components()
    for registration in sm.registeredHandlers():
        if len(registration.required) != 2:
            continue
        handler = get_dotted_name(registration.handler)
        event = get_dotted_name(registration.required[1])
        resource = get_dotted_name(registration.required[0])
        if resource not in subscribers:
            subscribers[resource] = {}
        if event not in subscribers[resource]:
            subscribers[resource][event] = []
        subscribers[resource][event].append(handler)
    return subscribers
Exemplo n.º 4
0
async def get_all_subscribers(context, request):
    subscribers = {}
    sm = component.get_global_components()
    for registration in sm.registeredHandlers():
        if len(registration.required) != 2:
            continue
        handler = get_dotted_name(registration.handler)
        event = get_dotted_name(registration.required[1])
        resource = get_dotted_name(registration.required[0])
        if resource not in subscribers:
            subscribers[resource] = {}
        if event not in subscribers[resource]:
            subscribers[resource][event] = []
        subscribers[resource][event].append(handler)
    return subscribers
Exemplo n.º 5
0
def includeme(root):
    configure.scan("guillotina_elasticsearch.utility")
    configure.scan("guillotina_elasticsearch.manager")
    configure.scan("guillotina_elasticsearch.parser")

    # add store true to guillotina indexes
    for name, utility in get_utilities_for(IResourceFactory):
        if not get_dotted_name(utility._callable).startswith("guillotina."):
            continue
        for field_name, catalog_info in get_index_fields(name).items():
            if field_name in (
                    "id",
                    "path",
                    "uuid",
                    "type_name",
                    "tid",
                    "creators",
                    "contributors",
                    "access_roles",
                    "access_users",
                    "parent_uuid",
                    "title",
                    "creation_date",
                    "modification_date",
                    "tags",
            ):
                catalog_info["store"] = True
Exemplo n.º 6
0
 def get_service_def(self, path, method=None, type_name=None):
     base_path, subpath, path_type_name = self.get_service_type_name(path)
     if type_name is not None:
         services = self.get_type_services(type_name)
     else:
         services = self.get_type_services(path_type_name)
     try:
         if '@' in path:
             return services['endpoints']['@' + subpath][method.upper()]
         else:
             return services[method]
     except (KeyError, TypeError):
         if type_name is not None:
             raise
         # this shouldn't happen, so we lookup other interfaces that this inherits
         # from to find service we're looking for
         iface = resolve_dotted_name(path_type_name)
         service = None
         for other_iface in iface.__bases__:
             try:
                 service = self.get_service_def(
                     path, method, get_dotted_name(other_iface))
             except (KeyError, TypeError):
                 pass
             if service is not None:
                 return service
Exemplo n.º 7
0
    def run_command(self):
        settings = get_settings(self.arguments.configuration)
        app = self.make_app(settings)

        if self.arguments.line_profiler:
            if not HAS_LINE_PROFILER:
                sys.stderr.write(
                    'You must first install line_profiler for the --line-profiler option to work.\n'
                    'Use `pip install line_profiler` to install line_profiler.\n'
                )
                return 1
            self.line_profiler = line_profiler.LineProfiler()
            for func in profile.get_profilable_functions():
                if fnmatch(get_dotted_name(func),
                           self.arguments.line_profiler_matcher or '*'):
                    self.line_profiler.add_function(func)
            self.line_profiler.enable_by_count()

        run_func = self.__run
        if self.arguments.monitor:
            if not HAS_AIOMONITOR:
                sys.stderr.write(
                    'You must install aiomonitor for the '
                    '--monitor option to work.\n'
                    'Use `pip install aiomonitor` to install aiomonitor.\n')
                return 1
            run_func = self.__run_with_monitor

        if self.arguments.profile:
            self.profiler = cProfile.Profile()
            self.profiler.runcall(run_func, app, settings)
        else:
            run_func(app, settings)
Exemplo n.º 8
0
def convert_interfaces_to_schema(interfaces):
    properties = {}
    for iface in interfaces:
        properties[get_dotted_name(iface)] = {
            "type": "object",
            "properties": convert_interface_to_schema(iface)
        }
    return properties
Exemplo n.º 9
0
async def test_job_function_name():
    data = {
        "func": get_dotted_name(_run_object_task),
        "args": ["my.func.foobar"]
    }
    job = Job(None, data, None, None)
    assert job.function_name == "run_object_task/my.func.foobar"

    data = {
        "func": get_dotted_name(_yield_object_task),
        "args": ["my.func.foobar"]
    }
    job = Job(None, data, None, None)
    assert job.function_name == "yield_object_task/my.func.foobar"

    data = {"func": get_dotted_name(_test_func), "args": []}
    job = Job(None, data, None, None)
    assert job.function_name == "guillotina_amqp.tests.utils._test_func"
Exemplo n.º 10
0
    def run_command(self, settings=None, loop=None):
        if loop is not None:
            self.loop = loop
        if settings is None:
            settings = get_settings(self.arguments.configuration,
                                    self.arguments.override)
        if settings.get("loop_policy"):
            loop_policy = resolve_dotted_name(settings["loop_policy"])
            asyncio.set_event_loop_policy(loop_policy())

        app = self.make_app(settings)

        if self.arguments.line_profiler:
            if not HAS_LINE_PROFILER:
                sys.stderr.write(
                    "You must first install line_profiler for the --line-profiler option to work.\n"
                    "Use `pip install line_profiler` to install line_profiler.\n"
                )
                return 1
            self.line_profiler = line_profiler.LineProfiler()
            for func in profile.get_profilable_functions():
                if fnmatch(get_dotted_name(func),
                           self.arguments.line_profiler_matcher or "*"):
                    self.line_profiler.add_function(func)
            self.line_profiler.enable_by_count()

        run_func = self.__run
        if self.arguments.monitor:
            if not HAS_AIOMONITOR:
                sys.stderr.write(
                    "You must install aiomonitor for the "
                    "--monitor option to work.\n"
                    "Use `pip install aiomonitor` to install aiomonitor.\n")
                return 1
            run_func = self.__run_with_monitor

        if self.arguments.profile:
            self.profiler = cProfile.Profile()
            self.profiler.runcall(run_func, app, settings)
            if self.arguments.profile_output:
                self.profiler.dump_stats(self.arguments.profile_output)
            else:
                # dump to screen
                self.profiler.print_stats(-1)
        else:
            run_func(app, settings)

        if self.line_profiler is not None:
            self.line_profiler.disable_by_count()
            if self.arguments.line_profiler_output:
                self.line_profiler.dump_stats(
                    self.arguments.line_profiler_output)
            else:
                self.line_profiler.print_stats()
Exemplo n.º 11
0
def convert_interface_to_schema(iface):
    properties = {}
    for name in iface.names():
        field = iface[name]
        try:
            props = convert_field_to_schema(field)
        except Exception:
            logger.warning('Error converting {} of {} into json schema'.format(
                name, get_dotted_name(iface)))
        if props is not None:
            properties[name] = props
    return properties
Exemplo n.º 12
0
 def get_task_payload(self):
     name = self.__parent__.__name__
     function = app_settings['hive_tasks'][name]
     if isinstance(function, dict) and 'klass' in function:
         function = get_dotted_name(function['klass'])
     return {
         'name': name,
         'task_uri': IAbsoluteURL(self)(relative=True),
         'function': function,
         'args': self.params,
         'persistent': True
     }
Exemplo n.º 13
0
def test_job_function_name():
    data = {
        'func': get_dotted_name(_run_object_task),
        'args': ['my.func.foobar'],
    }
    job = Job(None, data, None, None)
    assert job.function_name == 'run_object_task/my.func.foobar'

    data = {
        'func': get_dotted_name(_yield_object_task),
        'args': ['my.func.foobar'],
    }
    job = Job(None, data, None, None)
    assert job.function_name == 'yield_object_task/my.func.foobar'

    data = {
        'func': get_dotted_name(_test_func),
        'args': [],
    }
    job = Job(None, data, None, None)
    assert job.function_name == 'guillotina_amqp.tests.utils._test_func'
Exemplo n.º 14
0
    async def __call__(self, request):
        try:
            try:
                view_name = get_dotted_name(request.found_view.view_func)
            except AttributeError:
                view_name = get_dotted_name(request.found_view)
        except AttributeError:
            view_name = 'unknown'

        resp = await self.handler(request)

        metric = metrics.request_summary.labels(method=request.method,
                                                view=view_name,
                                                response_code=resp.status)

        try:
            metric.observe(request.events['finish'] - request.events['start'])
        except (AttributeError, KeyError):
            pass

        return resp
Exemplo n.º 15
0
def includeme(root):
    configure.scan('guillotina_elasticsearch.utility')
    configure.scan('guillotina_elasticsearch.manager')

    # add store true to guillotina indexes
    for name, utility in get_utilities_for(IResourceFactory):
        if not get_dotted_name(utility._callable).startswith('guillotina.'):
            continue
        for field_name, catalog_info in get_index_fields(name).items():
            if field_name in ('id', 'path', 'uuid', 'type_name', 'tid',
                              'creators', 'contributors', 'access_roles',
                              'access_users', 'parent_uuid', 'title'):
                catalog_info['store'] = True
Exemplo n.º 16
0
    def decorator(original_func):
        key = get_dotted_name(original_func)

        async def func(*args):
            if key in _cache:
                return _cache[key]
            resp = await original_func(*args)
            _cache[key] = resp
            loop = asyncio.get_event_loop()
            loop.call_later(duration, invalidate, key)
            return resp

        return func
Exemplo n.º 17
0
    def function_name(self):
        """
        """
        func = self.get_function_to_run()
        dotted_name = get_dotted_name(func)
        if func in [_run_object_task, _yield_object_task]:
            # Remove guillotina_amqp.utils part
            dotted_name = dotted_name.lstrip("guillotina_amqp.utils")
            # Get actuall callable that is passed as the first parameter
            # of func
            _callable = self.data.get("args", [""])[0]
            dotted_name += f"/{_callable}"

        return dotted_name
Exemplo n.º 18
0
    def get_service_type_name(self, path):
        base_path, _, subpath = path.partition('@')
        if base_path != '/':
            base_path = base_path.rstrip('/')
        subpath = subpath.split('/')[0]  # could be traversing it...

        type_name = self._get_type_name(path)
        if type_name == 'Application':
            iface = 'guillotina.interfaces.content.IApplication'
        elif type_name == 'Database':
            iface = 'guillotina.interfaces.content.IDatabase'
        else:
            type_name = self._get_type_name(path)
            rfactory = getUtility(IResourceFactory, name=type_name)
            iface = get_dotted_name(rfactory.schema)
        return base_path, subpath, iface
Exemplo n.º 19
0
async def add_object_task(callable=None,
                          ob=None,
                          *args,
                          _request=None,
                          _retries=3,
                          **kwargs):
    superfunc = _run_object_task
    if inspect.isasyncgenfunction(callable):
        # async generators need to be yielded from
        superfunc = _yield_object_task
    return await add_task(superfunc,
                          get_dotted_name(callable),
                          get_content_path(ob),
                          *args,
                          _request=_request,
                          _retries=_retries,
                          **kwargs)
Exemplo n.º 20
0
def create_apply_task(name, ob, function, request=None, commit=False,
                      args=None, kwargs=None, task_config=None):
    if task_config is None:
        task_config = {}
    if args is None:
        args = []
    if kwargs is None:
        kwargs = {}
    from guillotina_hive.model.task import Task

    if request is None:
        request = get_current_request()

    user_data = {}
    try:
        participation = request.security.participations[0]
        user = participation.principal
        user_data = {
            'id': user.id,
            'roles': user.roles,
            'groups': user.groups,
            'Authorization': request.headers.get('Authorization'),
            'data': getattr(user, 'data', {})
        }
    except (AttributeError, IndexError):
        pass

    if request.container:
        user_data['container_url'] = IAbsoluteURL(request.container, request)()

    data = {
        "name": name,
        "guillotina": True,
        "args": {
            "path": get_full_content_path(request, ob),
            "function": get_dotted_name(function),
            'commit': commit,
            'args': args,
            'kwargs': kwargs,
            'user_data': user_data
        }
    }
    data.update(task_config)
    task_info = Task(data=data)
    return task_info
Exemplo n.º 21
0
    def run_command(self, settings=None, loop=None):
        if loop is not None:
            self.loop = loop
        if settings is None:
            settings = get_settings(self.arguments.configuration, self.arguments.override)
        if settings.get('loop_policy'):
            loop_policy = resolve_dotted_name(settings['loop_policy'])
            asyncio.set_event_loop_policy(loop_policy())

        app = self.make_app(settings)

        if self.arguments.line_profiler:
            if not HAS_LINE_PROFILER:
                sys.stderr.write(
                    'You must first install line_profiler for the --line-profiler option to work.\n'
                    'Use `pip install line_profiler` to install line_profiler.\n'
                )
                return 1
            self.line_profiler = line_profiler.LineProfiler()
            for func in profile.get_profilable_functions():
                if fnmatch(get_dotted_name(func), self.arguments.line_profiler_matcher or '*'):
                    self.line_profiler.add_function(func)
            self.line_profiler.enable_by_count()

        run_func = self.__run
        if self.arguments.monitor:
            if not HAS_AIOMONITOR:
                sys.stderr.write(
                    'You must install aiomonitor for the '
                    '--monitor option to work.\n'
                    'Use `pip install aiomonitor` to install aiomonitor.\n')
                return 1
            run_func = self.__run_with_monitor

        if self.arguments.profile:
            self.profiler = cProfile.Profile()
            self.profiler.runcall(run_func, app, settings)
        else:
            run_func(app, settings)
Exemplo n.º 22
0
def convert_field_to_schema(field):
    field_type = type(field)

    props = {"required": field.required, "title": field.title}

    if field_type in _array_types:
        props.update({
            "type": "array",
            "items": {
                "type": _type_mappings[type(field.value_type)]
            }
        })
    elif field_type in _type_mappings:
        props.update({"type": _type_mappings[field_type]})
    else:
        logger.warning(
            'Could not convert field {} of {} into json schema'.format(
                field.__name__, get_dotted_name(field.interface)))
        return
    for prop_name, schema_name in _prop_mappings.items():
        val = getattr(field, prop_name, None)
        if val is not None:
            props[schema_name] = val
    return props
Exemplo n.º 23
0
 def _run(self, arguments, settings, app):
     port = arguments.port or settings.get('address', settings.get('port'))
     host = arguments.host or settings.get('host', '0.0.0.0')
     if arguments.line_profiler:
         if not HAS_LINE_PROFILER:
             sys.stderr.write(
                 'You must first install line_profiler for the --line-profiler option to work.\n'
                 'Use `pip install line_profiler` to install line_profiler.\n'
             )
             return 1
         self.line_profiler = line_profiler.LineProfiler()
         for func in profile.get_profilable_functions():
             if fnmatch(get_dotted_name(func),
                        arguments.line_profiler_matcher or '*'):
                 self.line_profiler.add_function(func)
         self.line_profiler.enable_by_count()
     if arguments.profile:
         self.profiler = cProfile.Profile()
         self.profiler.runcall(
             web.run_app,
             app,
             host=host,
             port=port,
             loop=self.get_loop(),
             access_log_format=settings.get('access_log_format'))
     else:
         try:
             web.run_app(
                 app,
                 host=host,
                 port=port,
                 loop=self.get_loop(),
                 access_log_format=settings.get('access_log_format'))
         except asyncio.CancelledError:
             # server shut down, we're good here.
             pass
Exemplo n.º 24
0
 def type(self):
     if hasattr(self._obj, 'type_name'):
         return self._obj.type_name
     else:
         return get_dotted_name(self._obj)
Exemplo n.º 25
0
 def type(self):
     return get_dotted_name(self._obj)
Exemplo n.º 26
0
async def add_task(func,
                   *args,
                   _request=None,
                   _retries=3,
                   _task_id=None,
                   **kwargs):
    """Given a function and its arguments, it adds it as a task to be ran
    by workers.
    """
    # Get the request and prepare request data
    if _request is None:
        _request = get_current_request()

    req_data = {
        'url': str(_request.url),
        'headers': dict(_request.headers),
        'method': _request.method,
        'annotations': getattr(_request, 'annotations', {})
    }
    user = get_authenticated_user()
    if user is not None:
        try:
            req_data['user'] = {
                'id':
                user.id,
                'roles': [
                    name for name, setting in user.roles.items()
                    if setting == Allow
                ],
                'groups':
                user.groups,
                'headers':
                dict(_request.headers),
                'data':
                getattr(user, 'data', {})
            }
        except AttributeError:
            pass

    container = task_vars.container.get()
    if container is not None:
        req_data['container_url'] = IAbsoluteURL(container, _request)()

    if _task_id is None:
        task_id = generate_task_id()
    else:
        task_id = _task_id

    retries = 0
    while True:
        # Get the rabbitmq connection
        channel, transport, protocol = await amqp.get_connection()
        try:
            state = TaskState(task_id)
            dotted_name = get_dotted_name(func)
            db = task_vars.db.get()
            logger.info(f'Scheduling task: {task_id}: {dotted_name}')
            data = json.dumps({
                'func': dotted_name,
                'args': args,
                'kwargs': kwargs,
                'db_id': getattr(db, 'id', None),
                'container_id': getattr(container, 'id', None),
                'req_data': req_data,
                'task_id': task_id
            })
            # Publish task data on rabbitmq
            await channel.publish(
                data,
                exchange_name=app_settings['amqp']['exchange'],
                routing_key=app_settings['amqp']['queue'],
                properties={'delivery_mode': 2})
            # Update tasks's global state
            state_manager = get_state_manager()
            await update_task_scheduled(state_manager,
                                        task_id,
                                        updated=time.time())
            logger.info(f'Scheduled task: {task_id}: {dotted_name}')
            return state
        except (aioamqp.AmqpClosedConnection,
                aioamqp.exceptions.ChannelClosed):
            await amqp.remove_connection()
            if retries >= _retries:
                raise
            retries += 1
Exemplo n.º 27
0
    def run(self):
        server = get_server()
        loop = server['loop']

        headers = {}
        for header in self.options.get('headers', '').split(','):
            if not header:
                continue
            name, value = header.split(':')
            headers[name.strip()] = value.strip()
        if 'Accept' not in headers:
            headers['Accept'] = 'application/json'

        if 'basic_auth' in self.options:
            encoded = b64encode(
                self.options['basic_auth'].encode('utf-8')).decode("ascii")
            headers['Authorization'] = 'Basic {}'.format(encoded)

        path = self.options.get('path') or '/'
        ob, tail = loop.run_until_complete(self.get_content(path))

        resp = loop.run_until_complete(self.handle_request(headers))
        if 'hidden' in self.options:
            return []

        service_definition = {}
        service_definition.setdefault('description', '')
        service_definition.setdefault('summary', '')
        service_definition.setdefault('permission', '')
        service_definition.setdefault('context', '')

        raw_service_definition = self.get_service_definition(ob, tail)
        if raw_service_definition is not None:
            for key, value in raw_service_definition.items():
                if key in ('method', 'permission', 'summary', 'description',
                           'responses', 'parameters'):
                    if callable(value):
                        value = value(ob)
                    service_definition[key] = value
            service_definition['context'] = get_dotted_name(
                raw_service_definition.get('context', Interface))

        resp_body = None
        if resp.headers.get('content-type') == 'application/json':
            resp_body = loop.run_until_complete(resp.json())
            resp_body = _fmt_body(resp_body, 8)
        else:
            resp_body = loop.run_until_complete(resp.text())

        content = {
            'path_spec': (self.options.get('path_spec') or
                          self.options.get('method', 'GET').upper()),
            'request': {
                'method': self.options.get('method', 'GET').upper(),
                'method_lower': self.options.get('method', 'GET').lower(),
                'path': self.options.get('path') or '/',
                'headers': _fmt_headers(_clean_headers(headers), 8),
                'body': _fmt_body(self.options.get('body'), 8)
            },
            'response': {
                'status': resp.status,
                'headers': _fmt_headers(_clean_headers(dict(resp.headers)), 8),
                'body': resp_body
            },
            'service':
            service_definition,
        }
        rst_content = """.. http:{request[method_lower]}:: {path_spec}

    {service[summary]}

    {service[description]}

    - Permission: **{service[permission]}**
    - Context: **{service[context]}**

    .. http:example:: curl httpie

        {request[method]} {request[path]} HTTP/1.1
        {request[headers]}

        {request[body]}


        HTTP/1.1 {response[status]} OK
        {response[headers]}

        {response[body]}

"""
        rst_content = rst_content.format(**content)

        for parameter in service_definition.get('parameters', []):
            if isinstance(parameter, str):
                parameter = {'name': parameter, 'type': 'string'}
            if parameter.get('in', 'query') != 'query':
                continue
            parameter.setdefault('description', '')
            if parameter.get('required'):
                parameter['description'] += ' (required)'
            elif parameter.get('default'):
                parameter['description'] += ' (default: {default})'.format(
                    **parameter)
            rst_content += '\n    :query {type} {name}: {description}'.format(
                **parameter)

        responses = {
            code: info['description']
            for code, info in service_definition.get('responses', {}).items()
        }
        responses.setdefault('401',
                             'You are not authorized to perform the operation')
        responses.setdefault('404', 'The resource does not exist')
        for code in sorted(responses):
            rst_content += ('\n    :statuscode {}: {}'.format(
                code, responses[code]))
        rst_content = rst_content.split("\n")
        view = docutils.statemachine.StringList(rst_content, '<gapi>')

        node = nodes.paragraph()
        self.state.nested_parse(view, 0, node)
        return [node]
Exemplo n.º 28
0
 def __init__(self, view):
     self.__module__ = view.__module__
     self.__qualname__ = get_dotted_name(view).split(".")[-1]
Exemplo n.º 29
0
    def run(self):
        server = get_server()
        loop = server["loop"]

        headers = {}
        for header in self.options.get("headers", "").split(","):
            if not header:
                continue
            name, value = header.split(":")
            headers[name.strip()] = value.strip()
        if "Accept" not in headers:
            headers["Accept"] = "application/json"

        if "basic_auth" in self.options:
            encoded = b64encode(
                self.options["basic_auth"].encode("utf-8")).decode("ascii")
            headers["Authorization"] = "Basic {}".format(encoded)

        path = self.options.get("path") or "/"
        ob, tail = loop.run_until_complete(self.get_content(path))

        resp = loop.run_until_complete(self.handle_request(headers))
        if "hidden" in self.options:
            return []

        service_definition = {}
        service_definition.setdefault("description", "")
        service_definition.setdefault("summary", "")
        service_definition.setdefault("permission", "")
        service_definition.setdefault("context", "")

        raw_service_definition = self.get_service_definition(ob, tail)
        if raw_service_definition is not None:
            for key, value in raw_service_definition.items():
                if key in ("method", "permission", "summary", "description",
                           "responses", "parameters"):
                    if callable(value):
                        value = value(ob)
                    service_definition[key] = value
            service_definition["context"] = get_dotted_name(
                raw_service_definition.get("context", Interface))

        resp_body = None
        if resp.headers.get("content-type") == "application/json":
            resp_body = loop.run_until_complete(resp.json())
            resp_body = _fmt_body(resp_body, 8)
        else:
            resp_body = loop.run_until_complete(resp.text())

        content = {
            "path_spec": (self.options.get("path_spec")
                          or self.options.get("method", "GET").upper()),
            "request": {
                "method": self.options.get("method", "GET").upper(),
                "method_lower": self.options.get("method", "GET").lower(),
                "path": self.options.get("path") or "/",
                "headers": _fmt_headers(_clean_headers(headers), 8),
                "body": _fmt_body(self.options.get("body"), 8),
            },
            "response": {
                "status": resp.status_code,
                "headers": _fmt_headers(_clean_headers(dict(resp.headers)), 8),
                "body": resp_body,
            },
            "service":
            service_definition,
        }
        rst_content = """.. http:{request[method_lower]}:: {path_spec}

    {service[summary]}

    {service[description]}

    - Permission: **{service[permission]}**
    - Context: **{service[context]}**

    .. http:example:: curl httpie

        {request[method]} {request[path]} HTTP/1.1
        {request[headers]}

        {request[body]}


        HTTP/1.1 {response[status]} OK
        {response[headers]}

        {response[body]}

"""
        rst_content = rst_content.format(**content)

        for parameter in service_definition.get("parameters", []):
            if isinstance(parameter, str):
                parameter = {"name": parameter, "type": "string"}
            if parameter.get("in", "query") != "query":
                continue
            parameter.setdefault("description", "")
            if parameter.get("required"):
                parameter["description"] += " (required)"
            elif parameter.get("default"):
                parameter["description"] += " (default: {default})".format(
                    **parameter)
            try:
                if "schema" in parameter:
                    ptype = parameter["schema"]["type"]
                else:
                    ptype = parameter.get("type", "string")
                rst_content += "\n    :query {ptype} {name}: {description}".format(
                    ptype=ptype, **parameter)
            except (KeyError, ValueError):
                logger.warning(f"Could not format paremeter: {parameter}")

        responses = {
            code: info["description"]
            for code, info in service_definition.get("responses", {}).items()
        }
        responses.setdefault(
            "401", "You are not authorized to perform the operation")
        responses.setdefault("404", "The resource does not exist")
        for code in sorted(responses):
            rst_content += "\n    :statuscode {}: {}".format(
                code, responses[code])
        rst_content = rst_content.split("\n")
        view = docutils.statemachine.StringList(rst_content, "<gapi>")

        node = nodes.paragraph()
        self.state.nested_parse(view, 0, node)
        return [node]
Exemplo n.º 30
0
async def add_task(func,
                   *args,
                   _request=None,
                   _retries=3,
                   _task_id=None,
                   **kwargs):
    """Given a function and its arguments, it adds it as a task to be ran
    by workers.
    """
    # Get the request and prepare request data
    if _request is None:
        _request = get_current_request()
    req_data: SerializedRequest = serialize_request(_request)

    if _task_id is None:
        task_id = generate_task_id()
    else:
        task_id = _task_id

    dotted_name = get_dotted_name(func)

    retries = 0
    while True:
        # Get the rabbitmq connection
        try:
            channel, transport, protocol = await amqp.get_connection()
        except AMQPConfigurationNotFoundError:
            logger.warning(
                f"Could not schedule {dotted_name}, AMQP settings not configured"
            )
            return
        try:
            state = TaskState(task_id)
            db = task_vars.db.get()
            container = task_vars.container.get()
            logger.info(f"Scheduling task: {task_id}: {dotted_name}")
            data = json.dumps({
                "func": dotted_name,
                "args": args,
                "kwargs": kwargs,
                "db_id": getattr(db, "id", None),
                "container_id": getattr(container, "id", None),
                "req_data": req_data,
                "task_id": task_id,
            })
            # Publish task data on rabbitmq
            await channel.publish(
                data,
                exchange_name=app_settings["amqp"]["exchange"],
                routing_key=app_settings["amqp"]["queue"],
                properties={"delivery_mode": 2},
            )
            # Update tasks's global state
            state_manager = get_state_manager()
            await update_task_scheduled(state_manager,
                                        task_id,
                                        updated=time.time())
            logger.info(f"Scheduled task: {task_id}: {dotted_name}")
            return state
        except (aioamqp.AmqpClosedConnection,
                aioamqp.exceptions.ChannelClosed):
            await amqp.remove_connection()
            if retries >= _retries:
                raise
            retries += 1
Exemplo n.º 31
0
 def type(self):
     return get_dotted_name(self._obj)
Exemplo n.º 32
0
    def api(self, path, method='get', file_type_name=None, **kwargs):
        if path != '/':
            path = path.rstrip('/')

        print('Getting {} {}'.format(method, path))
        kwargs['auth'] = ('root', 'root')
        kwargs['headers'] = DEFAULT_HEADERS.copy()
        kwargs['headers'].update(kwargs.get('headers', {}))

        url = self._base_url + path
        response = getattr(requests, method)(url, **kwargs)
        self._store_type_name(response, url, kwargs)

        service = self.get_service_def(path, method.upper())
        # path scheme used for things like traversing to registry value...
        name = service.get('name')
        path_scheme = kwargs.pop('path_scheme', name)

        iface = resolve_dotted_name(self.get_service_type_name(path)[-1])
        dotted = get_dotted_name(iface)
        responses = self._function_swagger_param(service.get('responses'), url)
        parameters = self._function_swagger_param(service.get('parameters'),
                                                  url)
        data = {
            'path': path,
            'path_scheme': path_scheme,
            'method': method,
            'options': kwargs,
            'request': self.dump_request(response.request),
            'response': self.dump_response(response),
            'service': {
                'name': service.get('name'),
                'title': service.get('title'),
                'summary': service.get('summary'),
                'parameters': parameters,
                'responses': responses,
                'method': service.get('method', 'GET'),
                'context': get_dotted_name(iface),
                'permission': service.get('permission')
            }
        }

        if file_type_name is None:
            file_type_name = dotted.split('.')[-1][1:].lower()

        filepath = '{}/{}-{}'.format(self._output_dir, file_type_name,
                                     method.lower())

        if path_scheme != name:
            # use special name here...
            name, _, rest = path_scheme.partition('/')
            filepath += '-{}:{}'.format(
                name.replace('@', ''),
                ''.join([l for l in rest.split(':')[0] if l not in '[]():-']))
        elif service.get('name'):
            filepath += '-' + service.get('name').replace('@', '')

        filepath += '.json'
        fi = open(filepath, 'w')
        fi.write(json.dumps(data, indent=4, sort_keys=True))
        fi.close()
Exemplo n.º 33
0
 def type(self):
     if hasattr(self._obj, 'type_name'):
         return self._obj.type_name
     else:
         return get_dotted_name(self._obj)
Exemplo n.º 34
0
    def run(self):
        server = get_server()
        loop = server['loop']

        headers = {}
        for header in self.options.get('headers', '').split(','):
            if not header:
                continue
            name, value = header.split(':')
            headers[name.strip()] = value.strip()
        if 'Accept' not in headers:
            headers['Accept'] = 'application/json'

        if 'basic_auth' in self.options:
            encoded = b64encode(
                self.options['basic_auth'].encode('utf-8')).decode("ascii")
            headers['Authorization'] = 'Basic {}'.format(encoded)

        path = self.options.get('path') or '/'
        ob, tail = loop.run_until_complete(self.get_content(path))

        resp = loop.run_until_complete(self.handle_request(headers))
        if 'hidden' in self.options:
            return []

        service_definition = {}
        service_definition.setdefault('description', '')
        service_definition.setdefault('summary', '')
        service_definition.setdefault('permission', '')
        service_definition.setdefault('context', '')

        raw_service_definition = self.get_service_definition(ob, tail)
        if raw_service_definition is not None:
            for key, value in raw_service_definition.items():
                if key in ('method', 'permission', 'summary', 'description',
                           'responses', 'parameters'):
                    if callable(value):
                        value = value(ob)
                    service_definition[key] = value
            service_definition['context'] = get_dotted_name(
                raw_service_definition.get('context', Interface))

        resp_body = None
        if resp.headers.get('content-type') == 'application/json':
            resp_body = loop.run_until_complete(resp.json())
            resp_body = _fmt_body(resp_body, 8)
        else:
            resp_body = loop.run_until_complete(resp.text())

        content = {
            'path_spec': (self.options.get('path_spec') or
                          self.options.get('method', 'GET').upper()),
            'request': {
                'method': self.options.get('method', 'GET').upper(),
                'method_lower': self.options.get('method', 'GET').lower(),
                'path': self.options.get('path') or '/',
                'headers': _fmt_headers(_clean_headers(headers), 8),
                'body': _fmt_body(self.options.get('body'), 8)
            },
            'response': {
                'status': resp.status,
                'headers': _fmt_headers(_clean_headers(dict(resp.headers)), 8),
                'body': resp_body
            },
            'service':
            service_definition,
        }
        rst_content = """.. http:{request[method_lower]}:: {path_spec}

    {service[summary]}

    {service[description]}

    - Permission: **{service[permission]}**
    - Context: **{service[context]}**

    .. http:example:: curl httpie

        {request[method]} {request[path]} HTTP/1.1
        {request[headers]}

        {request[body]}


        HTTP/1.1 {response[status]} OK
        {response[headers]}

        {response[body]}

"""
        rst_content = rst_content.format(**content)

        for parameter in service_definition.get('parameters', []):
            if isinstance(parameter, str):
                parameter = {'name': parameter, 'type': 'string'}
            if parameter.get('in', 'query') != 'query':
                continue
            parameter.setdefault('description', '')
            if parameter.get('required'):
                parameter['description'] += ' (required)'
            elif parameter.get('default'):
                parameter['description'] += ' (default: {default})'.format(
                    **parameter)
            rst_content += '\n    :query {type} {name}: {description}'.format(
                **parameter)

        responses = {
            code: info['description']
            for code, info in service_definition.get('responses', {}).items()
        }
        responses.setdefault('401',
                             'You are not authorized to perform the operation')
        responses.setdefault('404', 'The resource does not exist')
        for code in sorted(responses):
            rst_content += ('\n    :statuscode {}: {}'.format(
                code, responses[code]))
        rst_content = rst_content.split("\n")
        view = docutils.statemachine.StringList(rst_content, '<gapi>')

        node = nodes.paragraph()
        self.state.nested_parse(view, 0, node)
        return [node]