def decorator(clazz): assert isclass(clazz), 'Invalid class %s' % clazz properties = extractPropertiesInherited(clazz.__bases__, TypeExtension) log.info('Extracted extension inherited properties %s for class %s', properties, clazz) properties.update(extractProperties(clazz.__dict__)) log.info('Extracted extension properties %s for class %s', properties, clazz) for prop, typ in properties.items(): if not match(RULE_EXTENSION_PROPERTY[0], prop): raise DevelError(RULE_EXTENSION_PROPERTY[1] % prop) if not typ.isPrimitive: raise DevelError( 'Invalid type %s for property \'%s\', only primitives allowed' % (typ, prop)) extensionContainer = Container(properties) extensionType = TypeExtension(clazz, extensionContainer) reference = {} for prop in extensionContainer.properties: propType = TypeProperty(extensionType, prop) reference[prop] = Reference(propType) setattr(clazz, prop, Property(propType)) clazz._ally_type = extensionType # This specified the detected type for the model class by using 'typeFor' clazz._ally_reference = reference # The references to be returned by the properties when used only with class clazz.__new__ = ContainerSupport.__new__ return clazz
def _pullHeaders(self): ''' Pull the multi part headers, it will leave the content stream attached to the header reader at the body begin. @return: dictionary{string, string} The multi part headers. ''' assert self._flag & FLAG_MARK_START, 'Not at a separator mark position, cannot process headers' data = bytearray() while True: data.extend(self._readToHeader(self._data.packageSize)) if self._flag & FLAG_HEADER_END: self._flag ^= FLAG_HEADER_END # Clearing the header flag break if self._flag & FLAG_CONTENT_END: raise DevelError('No empty line after multi part header') reader = codecs.getreader(self._data.charSet)(BytesIO(data)) headers = {} while True: line = reader.readline() if line == '': break hindex = line.find(self._data.separatorHeader) if hindex < 0: raise DevelError('Invalid multi part header \'%s\'' % line) headers[line[:hindex]] = line[hindex + 1:].strip() self._flag ^= FLAG_MARK_START return headers
def invoke(self, *args): ''' @see: Invoker.invoke ''' lenArgs, wargs = len(args), [] for index in self.indexes: if index < lenArgs: value = args[index] else: inp = self.inputs[index] assert isinstance(inp, Input) if not inp.hasDefault: raise DevelError('No value available for \'%s\' for %s' % (inp.name, self)) value = inp.default wargs.append(value) for index, toSet in self.indexesSetValue.items(): obj = wargs[index] for prop, fromIndex in toSet.items(): arg = args[fromIndex] val = getattr(obj, prop) if val is None: setattr(obj, prop, arg) elif val != arg: raise DevelError( 'Cannot set value %s for \'%s\', expected value %s' % (val, prop, arg)) return self.invoker.invoke(*wargs)
def openSession(): ''' Function to provide the session on the current thread, this will automatically create a session based on the current thread session creator if one is not already created. ''' thread = current_thread() try: creators = thread._ally_db_session_create except AttributeError: raise DevelError( 'Invalid call, it seems that the thread is not tagged with an SQL session' ) creator = creators[-1] creatorId = id(creator) try: sessions = thread._ally_db_session except AttributeError: session = creator() thread._ally_db_session = {creatorId: session} assert log.debug('Created SQL Alchemy session %s', session) or True else: session = sessions.get(creatorId) if session is None: session = sessions[creatorId] = creator() assert log.debug('Created SQL Alchemy session %s', session) or True return session
def _toPatternInput(self, match, req): ''' Processes the match as a pattern input. ''' assert isinstance(req, Request) inp = Input() inp.Id = self._inputId self._inputs[self._inputId] = inp self._inputId += 1 inp.Mandatory = True inp.ForRequest = req.Id if isinstance(match, MatchProperty): assert isinstance(match, MatchProperty) assert isinstance(match.node, NodeProperty) typ = next(iter(match.node.typesProperties)) assert isinstance(typ, TypeModelProperty) inp.Description = _('The %(type)s of %(model)s %(description)s') % \ dict(type=_(typ.property), model=_(typ.container.name), description=re.sub('[\s]+', ' ', getdoc(typ.parent.clazz) or '...')) else: raise DevelError('Unknown match %s' % match) return inp
def decorator(clazz): assert isclass(clazz), 'Invalid class %s' % clazz criterias = extractCriteriasInherited(clazz.__bases__) log.info('Extracted inherited criterias %s for query class %s', criterias, clazz) criterias.update(extractCriterias(clazz.__dict__)) log.info('Extracted criterias %s for query class %s', criterias, clazz) for crt in criterias: if not match(RULE_QUERY_CRITERIA[0], crt): raise DevelError(RULE_QUERY_CRITERIA[1] % crt) queryContainer = Query(criterias) queryType = TypeQuery(clazz, queryContainer, queryOwner) for crt in queryContainer.criterias: critType = TypeCriteriaEntry(queryType, crt) setattr(clazz, crt, CriteriaEntry(critType)) clazz._ally_type = queryType # This specified the detected type for the model class by using 'typeFor' clazz.__new__ = QuerySupport.__new__ clazz.__str__ = QuerySupport.__str__ clazz.__contains__ = QuerySupport.__contains__ return clazz
def _populate(self, language, translator): ''' Helper method that populates directly the language with the translation name. @param language: Language The language to be populated with info from the locale. @param translator: Locale The translating locale to populate from. ''' assert isinstance(language, Language), 'Invalid language %s' % language assert isinstance(translator, Locale), 'Invalid translator locale %s' % translator locale = self._localeOf(language.Code) if not locale: raise DevelError('Invalid language code %r' % language.Code) language.Name = translator.languages.get(locale.language) if locale.territory: language.Territory = translator.territories.get(locale.territory) if locale.script: language.Script = translator.scripts.get(locale.script) if locale.variant: language.Variant = translator.variants.get(locale.variant) return language
def authenticate(self, identifier, attributes, arguments): ''' @see: IAuthenticationSupport.authenticate ''' assert isinstance(identifier, str), 'Invalid identifier %s' % identifier assert isinstance(attributes, dict), 'Invalid attributes %s' % attributes assert isinstance(arguments, dict), 'Invalid arguments %s' % arguments olderThan = self.session().query(current_timestamp()).scalar() olderThan -= self.sessionTimeOut sql = self.session().query(LoginMapped) sql = sql.filter(LoginMapped.Session == identifier) sql = sql.filter(LoginMapped.AccessedOn > olderThan) try: login = sql.one() except NoResultFound: return False assert isinstance(login, LoginMapped), 'Invalid login %s' % login login.AccessedOn = current_timestamp() self.session().flush((login, )) self.session().expunge(login) commitNow() # We need to fore the commit because if there is an exception while processing the request we need to make # sure that the last access has been updated. for authType in arguments: assert isinstance(authType, Type), 'Invalid type %s' % authType if authType == typeFor(User.Id): arguments[authType] = login.User else: raise DevelError('Invalid authenticated type %s' % authType) return True
def toPaths(self, converterPath, invalid=None): ''' Converts the matches into path elements. @param converterPath: ConverterPath The converter path to use in constructing the paths elements. @param invalid: callable(Match, ConverterPath)|None The invalid match handling, if a callable is provided then the callable will be used to get a valid string representation for the invalid match, the callable has to take to parameters, first one is the invalid match and the second one is the converter path to be used. If the invalid is None then an exception will be raised in case of invalid matches. @return: list[string] A list of strings representing the paths elements, or None if the path elements cannot be obtained. ''' assert isinstance( converterPath, ConverterPath), 'Invalid converter path %s' % converterPath assert invalid is None or callable( invalid), 'Invalid callable for invalid %s' % invalid paths = [] for isFirst, isLast, match in firstLastCheck(self.matches): assert isinstance(match, Match) if match.isValid(): path = match.toPath(converterPath, isFirst, isLast) elif invalid: path = invalid(match, converterPath) else: raise DevelError('Invalid match %s' % match) if path is not None: if isinstance(path, list): paths.extend(path) paths.append(path) return paths
def decorator(clazz): assert isclass(clazz), 'Invalid class %s' % clazz nonlocal main properties = extractPropertiesInherited(clazz.__bases__, TypeCriteria) log.info('Extracted criteria inherited properties %s for class %s', properties, clazz) properties.update(extractProperties(clazz.__dict__)) log.info('Extracted criteria properties %s for class %s', properties, clazz) for prop, typ in properties.items(): if not match(RULE_CRITERIA_PROPERTY[0], prop): raise DevelError(RULE_CRITERIA_PROPERTY[1] % prop) if not typ.isPrimitive: raise DevelError( 'Invalid type %s for property \'%s\', only primitives allowed' % (typ, prop)) if main is not None: if isinstance(main, str): main = [main] else: inherited = extractContainersFrom(clazz.__bases__, TypeCriteria) for crt in inherited: assert isinstance(crt, Criteria) if crt.main: main = crt.main break else: main = () criteriaContainer = Criteria(properties, main) criteriaType = TypeCriteria(clazz, criteriaContainer) reference = {} for prop in criteriaContainer.properties: propType = TypeProperty(criteriaType, prop) reference[prop] = Reference(propType) setattr(clazz, prop, Property(propType)) clazz._ally_type = criteriaType # This specified the detected type for the model class by using 'typeFor' clazz._ally_reference = reference # The references to be returned by the properties when used only with class clazz.__new__ = CriteriaSupport.__new__ clazz.__str__ = CriteriaSupport.__str__ clazz.__contains__ = CriteriaSupport.__contains__ return clazz
def extractOuputInput(function, types=None, modelToId=False): ''' Extracts the input and output for a call based on the provided function. @param function: function The function to extract the call for @param types: list[Type or Type container]|None The list of types to associate with the function, if they are not provided then the function annotations are considered. @param modelToId: boolean Flag indicating that the extract should convert all inputs that are model types to their actually corresponding property type, used in order not to constantly provide the id property of the model when in fact we can deduce that the API annotation actually refers to the id and not the model. @return: tuple(Type, list[Input]) A tuple containing on the first position the output type of the call and second the list of inputs for the call. ''' assert isfunction(function), 'Invalid function %s' % function assert isinstance(modelToId, bool), 'Invalid model to id flag %s' % modelToId if IS_PY3K: fnArgs = getfullargspec(function) args, varargs, keywords, defaults = fnArgs.args, fnArgs.varargs, fnArgs.varkw, fnArgs.defaults annotations = fnArgs.annotations else: args, varargs, keywords, defaults = getargspec(function) annotations = {} assert varargs is None, 'No variable arguments are allowed' assert keywords is None, 'No keywords arguments are allowed' assert 'self' == args[0], 'The call needs to be tagged in a class definition' if types: assert isinstance(types, (list, tuple)), 'Invalid types list %s' % types assert len(args) == len(types), 'The functions parameters are not equal with the provided input types' assert not annotations, 'The types for the input arguments cannot be declared as annotations %s and call '\ 'arguments %s' % (annotations, types) annotations['return'] = types[0] annotations.update({args[k]:types[k] for k in range(1, len(args))}) mandatory = len(args) - (1 if defaults is None else len(defaults) + 1) typ = fnArgs.annotations.get('return') output, inputs = typeFor(Non if typ is None else typ), [] for k, arg in enumerate(args[1:]): if arg in args: if arg not in annotations: raise DevelError('There is no type for %s' % arg) typ = typeFor(annotations[arg]) assert isinstance(typ, Type), 'Could not obtain a valid type for %s with %s' % (arg, annotations[arg]) if modelToId and isinstance(typ, TypeModel): assert isinstance(typ, TypeModel) typ = typ.propertyTypeId() if k < mandatory: inputs.append(Input(arg, typ)) else: inputs.append(Input(arg, typ, True, defaults[k - mandatory])) return output, inputs
def hasSession(): ''' Function to check if there is a session on the current thread. ''' thread = current_thread() try: creators = thread._ally_db_session_create except AttributeError: raise DevelError( 'Invalid call, it seems that the thread is not tagged with an SQL session' ) creatorId = id(creators[-1]) try: sessions = thread._ally_db_session except AttributeError: return False return creatorId in sessions
def process(self, request:Request, response:Response, **keyargs): ''' @see: HandlerProcessorProceed.process Create the response content encoder. ''' assert isinstance(request, Request), 'Invalid request %s' % request assert isinstance(response, Response), 'Invalid response %s' % response if response.isSuccess is False: return # Skip in case the response is in error if response.encoder: return # There is already an encoder no need to create another one assert isinstance(request.invoker, Invoker), 'Invalid request invoker %s' % request.invoker response.encoder = self.encoderFor(request.invoker.output) if response.encoder is None: raise DevelError('Cannot encode response object \'%s\'' % request.invoker.output) response.encoderData = dict(converterId=response.converterId, converter=response.converter, normalizer=response.normalizer)
def process(self, request: Request, response: Response, **keyargs): ''' @see: HandlerProcessorProceed.process Invoke the request invoker. ''' assert isinstance(request, Request), 'Invalid request %s' % request assert isinstance(response, Response), 'Invalid response %s' % response if response.isSuccess is False: return # Skip in case the response is in error assert isinstance(request.invoker, Invoker), 'Invalid invoker %s' % request.invoker callBack = self.invokeCallBack.get(request.invoker.method) assert callBack is not None, \ 'Method cannot be processed for invoker \'%s\', something is wrong in the setups' % request.invoker.name assert isinstance(request.arguments, dict), 'Invalid arguments %s' % request.arguments arguments = [] for inp in request.invoker.inputs: assert isinstance(inp, Input), 'Invalid input %s' % inp if inp.name in request.arguments: arguments.append(request.arguments[inp.name]) elif inp.hasDefault: arguments.append(inp.default) else: raise DevelError( 'No value for mandatory input \'%s\' for invoker \'%s\'' % (inp.name, request.invoker.name)) try: value = request.invoker.invoke(*arguments) assert log.debug( 'Successful on calling invoker \'%s\' with values %s', request.invoker, tuple(arguments)) or True callBack(request.invoker, value, response) except InputError as e: assert isinstance(e, InputError) response.code, response.isSuccess = INPUT_ERROR response.errorDetails = self.processInputError(e) assert log.debug('User input exception: %s', e, exc_info=True) or True
def decorator(function): assert isfunction(function), 'Invalid function %s' % function nonlocal method name = function.__name__ if method is None: for regex, m in NAME_TO_METHOD.items(): if match(regex, name): method = m break else: raise DevelError( 'Cannot deduce method for function name "%s"' % name) output, inputs = extractOuputInput(function, types, modelToId=method in (GET, DELETE)) function._ally_call = Call(name, method, output, inputs, hints) return abstractmethod(function)
def decorator(clazz): assert isclass(clazz), 'Invalid class %s' % clazz calls = [] for name, function in clazz.__dict__.items(): if isfunction(function): try: calls.append(function._ally_call) except AttributeError: raise DevelError('No call for method at:\n%s' % locationStack(function)) del function._ally_call services = [typeFor(base) for base in clazz.__bases__] services = [ typ.service for typ in services if isinstance(typ, TypeService) ] names = {call.name for call in calls} for srv in services: assert isinstance(srv, Service) for name, call in srv.calls.items(): assert isinstance(call, Call) if name not in names: calls.append(processGenericCall(call, generic)) names.add(name) service = Service(calls) if type(clazz) != ABCMeta: attributes = dict(clazz.__dict__) attributes.pop( '__dict__', None ) # Removing __dict__ since is a reference to the old class dictionary. attributes.pop('__weakref__', None) clazz = ABCMeta(clazz.__name__, clazz.__bases__, attributes) abstract = set(clazz.__abstractmethods__) abstract.update(service.calls) clazz.__abstractmethods__ = frozenset(abstract) clazz._ally_type = TypeService(clazz, service) # This specified the detected type for the model class by using 'typeFor' return clazz
def __new__(cls, *args, **keyargs): ''' Construct the instance of the container. ''' assert isinstance(cls._ally_type, TypeQuery), \ 'Bad query support class %s, no type assigned' % cls._ally_type assert cls._ally_type.isOf( cls), 'Illegal class %s, expected %s' % (cls, cls._ally_type) query = cls._ally_type.query assert isinstance(query, Query) self = object.__new__(cls) self._ally_values = {} for name, value in keyargs.items(): if name not in query.criterias: raise DevelError('Invalid criteria name %r for %r' % (name, self)) setattr(self, name, value) return self
def endCurrent(sessionCloser=None): ''' Ends the transaction for the current thread session creator. @param sessionCloser: Callable|None A Callable that will be invoked for the ended transaction. It will take as a parameter the session to be closed. ''' assert not sessionCloser or callable( sessionCloser), 'Invalid session closer %s' % sessionCloser thread = current_thread() try: creators = thread._ally_db_session_create except AttributeError: raise DevelError( 'Illegal end transaction call, there is no transaction begun') assert isinstance(creators, deque) creator = creators.pop() assert log.debug('End session creator %s', creator) or True if not creators: if not getattr(current_thread(), '_ally_db_session_alive', False): endSessions(sessionCloser) del thread._ally_db_session_create
def decorator(clazz): assert isclass(clazz), 'Invalid class %s' % clazz nonlocal id, name, hints if name is not None: if isclass(name): typ = typeFor(name) assert isinstance( typ, TypeModel ), 'Invalid class %s to extract name, is not a model class' % name name = typ.container.name assert isinstance(name, str), 'Invalid model name %s' % name else: name = clazz.__name__ if not match(RULE_MODEL[0], name): raise DevelError(RULE_MODEL[1] % name) containers = extractContainersFrom(clazz.__bases__, TypeModel) if id is None: for model in containers: assert isinstance(model, Model) if model.propertyId is not None: id = model.propertyId log.info('Inherited id \'%s\' for class %s', id, clazz) break else: log.info('No id to be inherited for class %s', clazz) containers.reverse( ) # We reverse since the priority is from first class to last properties, hintsInherited = {}, {} for model in containers: properties.update(model.properties) hintsInherited.update(model.hints) log.info('Extracted inherited properties %s and hints %s for class %s', properties, hintsInherited, clazz) properties.update(extractProperties(clazz.__dict__)) hintsInherited.update(hints) hints = hintsInherited log.info('Extracted model properties %s and hints %s for class %s', properties, hints, clazz) for prop, typ in properties.items(): if not match(RULE_MODEL_PROPERTY[0], prop): raise DevelError(RULE_MODEL_PROPERTY[1] % prop) if not (isinstance(typ, TypeModel) or typ.isPrimitive): raise DevelError( 'Invalid type %s for property \'%s\', only primitives or models allowed' % (typ, prop)) replace = hints.pop('replace', None) if id is not None: assert isinstance(id, str), 'Invalid property id %s' % id assert id in properties, 'Invalid property id %s is not in model properties' % id if id is not None: if isinstance(properties[id], List): raise DevelError('The id cannot be a List type, got %s' % properties[id]) if isinstance(properties[id], TypeModel): raise DevelError('The id cannot be a model reference, got %s' % properties[id]) modelType = TypeModel(clazz, Model(properties, name, id, hints)) if replace: assert isclass(replace), 'Invalid class %s' % replace typ = typeFor(replace) if not isinstance(typ, TypeModel): raise DevelError( 'Invalid replace class %s, not a model class' % replace) if clazz.__module__ != replace.__module__: raise DevelError( 'Replace is available only for classes in the same API module invalid replace class ' '%s for replaced class' % (replace, clazz)) typ.clazz = clazz typ.container = modelType.container reference = {} for prop, typ in properties.items(): propType = TypeModelProperty(modelType, prop) reference[prop] = Reference(propType) if isinstance(typ, TypeModel): propType = TypeModelProperty( modelType, prop, typ.container.properties[typ.container.propertyId]) setattr(clazz, prop, Property(propType)) clazz._ally_type = modelType # This specified the detected type for the model class by using 'typeFor' clazz._ally_reference = reference # The references to be returned by the properties when used only with class clazz.__new__ = ContainerSupport.__new__ clazz.__str__ = ContainerSupport.__str__ clazz.__contains__ = ContainerSupport.__contains__ return clazz
The component id. @param plugin: string The plugin id. @return: string The file path. ''' assert isinstance(locale, str), 'Invalid locale %s' % locale path = [] if component: path.append('component') path.append(component) elif plugin: path.append('plugin') path.append(plugin) else: path.append('global') path.append(locale) return '%s.po' % '-'.join(path) # -------------------------------------------------------------------- # Raised when there is an invalid PO content InvalidPOFile = lambda poFile: InputError( _('Invalid content for PO file %(file)s') % dict(file=poFile.getName( ) or C_('Unknown file name', 'unknown'))) # Raised if there are to many files provided in content. ToManyFiles = lambda: DevelError('To many PO files, only one accepted')
def process(self, rendering, request: Request, response: Response, responseCnt: ResponseContent, **keyargs): ''' @see: HandlerBranchingProceed.process Create the render for the response object. ''' assert isinstance(rendering, Processing), 'Invalid processing %s' % rendering assert isinstance(request, Request), 'Invalid request %s' % request assert isinstance(response, Response), 'Invalid response %s' % response assert isinstance( responseCnt, ResponseContent), 'Invalid response content %s' % responseCnt # Resolving the character set if responseCnt.charSet: try: codecs.lookup(responseCnt.charSet) except LookupError: responseCnt.charSet = None else: responseCnt.charSet = None if not responseCnt.charSet: if Request.accCharSets in request and request.accCharSets is not None: for charSet in request.accCharSets: try: codecs.lookup(charSet) except LookupError: continue responseCnt.charSet = charSet break if not responseCnt.charSet: responseCnt.charSet = self.charSetDefault resolved = False if responseCnt.type: renderChain = Chain(rendering) renderChain.process(request=request, response=response, responseCnt=responseCnt, **keyargs) if renderChain.doAll().isConsumed(): if response.isSuccess is not False: response.code, response.isSuccess = ENCODING_UNKNOWN response.text = 'Content type \'%s\' not supported for rendering' % responseCnt.type else: resolved = True if not resolved: # Adding None in case some encoder is configured as default. if Request.accTypes in request and request.accTypes is not None: contentTypes = itertools.chain(request.accTypes, self.contentTypeDefaults) else: contentTypes = self.contentTypeDefaults for contentType in contentTypes: responseCnt.type = contentType renderChain = Chain(rendering) renderChain.process(request=request, response=response, responseCnt=responseCnt, **keyargs) if not renderChain.doAll().isConsumed(): break else: raise DevelError( 'There is no renderer available, this is more likely a setup issues since the ' 'default content types should have resolved the renderer')