def parse(self, data): ''' parse: Loops over the data, looking for string values that can be parsed into rich data structures (think 2012-12-24 becomes a `datetime` object). ''' # handle is just a function that is mapped against a list def handle(val): for datatype in self.datatypes: if datatype[0](self, val): return datatype[1](self, val) return val if isinstance(data, list): return list(map(self.parse, data)) elif not isinstance(data, dict): return handle(data) for key, value in data.items(): if isinstance(value, dict): data[key] = self.parse(value) continue if isinstance(value, list): data[key] = map(self.parse, value) if not isstr(value): continue data[key] = handle(value) return data
def detection(cls, response, value): """ Tests if the value matches a format that signifies it is either an absolute or relative path. """ if not isstr(value): return False return value.startswith('/') or \ value.startswith(str(response.__parent__))
def split(cls, path): """ Break the path down into a list of the levels and the query string """ query = None if isstr(path): url_info = urlparse(path) query = cls.translate_query(url_info.query) path = url_info.path.split(cls.PATH_DELIMITER) return list(filter(bool, path)), query
def detection(cls, response, value): """ Goes through registered string format types and provides whether any of them match the provided string value. Keeps track of which format was matched so that it may later be used for conversion. """ for dateset in cls.types: if not isstr(value): continue if dateset.matcher.match(value): cls.current = dateset.parser return True cls.current = None return False
def __get_path__(self, attr): if not isstr(attr): return self._route(attr) path, query = URL.split(attr) # root path and base is not root, normalize path to subset of base if attr.startswith('/') and len(self.__url__.path): for element in self.__url__.path: if element != path[0]: return attr del path[0] return self._route(self.__url__ + path, query)
def detection(cls, response, value): ''' DateHandler.detection: Tests if the value matches a recognized date string format (ISO, IETF, etc) so that it can then be converted into a more usable data structure. ''' for dateset in cls.types: if not isstr(value): continue if re.match(dateset["regex"], value): cls.current = dateset["parse"] return True cls.current = None return False
def __request__(self, method, headers={}, *args, **kwargs): """ Makes a request to the represented URL of the object. The method passed in will be used for the request and the rest of the arguments will be used to attempt to build the request body/data. """ headers = dict(self._default_headers + list(headers.items())) params = dict(list(self._default_params.items()) + list(kwargs.items())) if len(params): default_MIME = "application/x-www-form-urlencoded" if headers.setdefault("Content-type", default_MIME) == \ default_MIME: params = to_urlstr(params) elif headers["Content-type"] == "application/json": params = json.dumps(params) else: pass # No idea what mimetype to encode against else: params = "" if len(args) > 0 and isstr(args[0]): params = args[0] headers.setdefault("Content-type", "text/plain") # Use the query string for GET ? if method.upper() == 'GET' and len(params): request = urllib2.Request( "?".join([str(self), params]), data=bytearray(params, 'utf-8'), headers=headers) else: request = urllib2.Request( str(self), data=bytearray(params, 'utf-8'), headers=headers) request.get_method = lambda: method.upper() if self.__base.__test__: return request try: response = self.__base.__opener__.open(request) return self.__response__(response) except urllib2.URLError: if self.__base__.EXCEPTION_THROWING: raise InvalidURLError(str(self)) else: return (ERRORS["InvalidURL"], None)
def __request__(self, method, headers={}, *args, **kwargs): ''' __request__: Base request method, actually performs the request on the URL with the defined method. ''' headers = dict(self._default_headers + list(headers.items())) params = dict(list(self._default_params.items()) + list(kwargs.items())) if len(params): default_MIME = "application/x-www-form-urlencoded" if headers.setdefault("Content-type", default_MIME) == \ default_MIME: params = to_urlstr(params) elif headers["Content-type"] == "application/json": params = json.dumps(params) else: pass # No idea what mimetype to encode against else: params = "" if len(args) > 0 and isstr(args[0]): params = args[0] headers.setdefault("Content-type", "text/plain") # Use the query string for GET ? if method.upper() == 'GET' and len(params): request = urllib2.Request( "?".join([str(self), params]), data=bytearray(params, 'utf-8'), headers=headers) else: request = urllib2.Request( str(self), data=bytearray(params, 'utf-8'), headers=headers) request.get_method = lambda: method.upper() if self.__base.__test__: return request try: response = self.__base.__opener__.open(request) return self.__response__(response) except urllib2.URLError: if self.__base__.EXCEPTION_THROWING: raise InvalidURLError(str(self)) else: return (ERRORS["InvalidURL"], None)
def parse(self, data): """ Traverses the data structure and converts any data of a base type into a richer form based on registered detection functions and the corresponding handling function. Provided handlers include a URL detector that will convert the URL string into a :class:`Route <Route>` if applicable and a date detector that will convert a string like ``2013-03-12`` into the rich ``datetime`` object. """ # handle is just a function that is mapped against a list def handle(val): for datatype in self.datatypes: if datatype.detector(self, val): return datatype.handler(self, val) return val if isinstance(data, list): return list(map(self.parse, data)) elif not isinstance(data, dict): return handle(data) for key, value in data.items(): if isinstance(value, dict): data[key] = self.parse(value) continue if isinstance(value, list): data[key] = map(self.parse, value) if not isstr(value): continue data[key] = handle(value) return data