aboutsummaryrefslogtreecommitdiffstats
path: root/pygithub3/requests/base.py
diff options
context:
space:
mode:
Diffstat (limited to 'pygithub3/requests/base.py')
-rw-r--r--pygithub3/requests/base.py137
1 files changed, 137 insertions, 0 deletions
diff --git a/pygithub3/requests/base.py b/pygithub3/requests/base.py
new file mode 100644
index 0000000..4b1aa9b
--- /dev/null
+++ b/pygithub3/requests/base.py
@@ -0,0 +1,137 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+import re
+from importlib import import_module
+try:
+ import simplejson as json
+except ImportError:
+ import json
+
+from pygithub3.exceptions import (DoesNotExists, UriInvalid, ValidationError,
+ InvalidBodySchema)
+from pygithub3.resources.base import Raw
+
+ABS_IMPORT_PREFIX = 'pygithub3.requests'
+
+
+class Body(object):
+
+ def __init__(self, content, schema, required):
+ self.content = content
+ self.schema = schema
+ self.required = required
+
+ def dumps(self):
+ if not self.schema:
+ return self.content or None
+ return json.dumps(self.parse())
+
+ def parse(self):
+ if not hasattr(self.content, 'items'):
+ raise ValidationError("'%s' needs a content dictionary"
+ % self.__class__.__name__)
+ parsed = {key: self.content[key] for key in self.schema
+ if key in self.content}
+ for attr_required in self.required:
+ if attr_required not in parsed:
+ raise ValidationError("'%s' attribute is required" %
+ attr_required)
+ if not parsed[attr_required]:
+ raise ValidationError("'%s' attribute can't be empty" %
+ attr_required)
+ return parsed
+
+
+class Request(object):
+ """ """
+
+ uri = ''
+ resource = Raw
+ body_schema = {}
+
+ def __init__(self, **kwargs):
+ """ """
+ self.body = kwargs.pop('body', None)
+ self.args = kwargs
+ self.clean()
+
+ def clean(self):
+ self.uri = self.clean_uri() or self.uri
+ self.body = Body(self.clean_body(), **self.clean_valid_body())
+
+ def clean_body(self):
+ return self.body
+
+ def clean_uri(self):
+ return None
+
+ def clean_valid_body(self):
+ schema = set(self.body_schema.get('schema', ()))
+ required = set(self.body_schema.get('required', ()))
+ if not required.issubset(schema):
+ raise InvalidBodySchema(
+ "'%s:valid_body' attribute is invalid. "
+ "'%s required' isn't a subset of '%s schema'" % (
+ self.__class__.__name__, required, schema))
+ return dict(schema=schema, required=required)
+
+ def __getattr__(self, name):
+ return self.args.get(name)
+
+ def __str__(self):
+ return self.populate_uri()
+
+ def populate_uri(self):
+ try:
+ populated_uri = self.uri.format(**self.args)
+ except KeyError:
+ raise ValidationError(
+ "'%s' request wasn't be able to populate the uri '%s' with "
+ "'%s' args" % (self.__class__.__name__, self.uri, self.args))
+ return str(populated_uri).strip('/')
+
+ def get_body(self):
+ return self.body.dumps()
+
+
+class Factory(object):
+ """ """
+
+ import_pattern = re.compile(r'^(\w+\.)+\w+$')
+
+ def validate(func):
+ """ """
+
+ def wrapper(self, request_uri, **kwargs):
+ if not Factory.import_pattern.match(request_uri):
+ raise UriInvalid("'%s' isn't valid form" % request_uri)
+ return func(self, request_uri.lower(), **kwargs)
+ return wrapper
+
+ def dispatch(func):
+ """ """
+
+ def wrapper(self, request_uri, **kwargs):
+ module_chunk, s, request_chunk = request_uri.rpartition('.')
+ try:
+ # TODO: CamelCase and under_score support, now only Class Name
+ module = import_module('%s.%s'
+ % (ABS_IMPORT_PREFIX, module_chunk))
+ request = getattr(module, request_chunk.capitalize())
+ except ImportError:
+ raise DoesNotExists("'%s' module does not exists"
+ % module_chunk)
+ except AttributeError:
+ raise DoesNotExists(
+ "'%s' request doesn't exists into '%s' module"
+ % (request_chunk.capitalize(), module_chunk))
+ return func(self, request, **kwargs)
+ return wrapper
+
+ @validate
+ @dispatch
+ def __call__(self, request='', **kwargs):
+ request = request(**kwargs)
+ assert isinstance(request, Request)
+ return request