class talbased(object): def __init__(self, filename, write=True): ## if not osp.isfile(filepath): ## # print "[tal.py] just for tests..." ## # get parent frame ## directory = osp.abspath(osp.dirname(sys._getframe(1).f_globals['__file__'])) ## filepath = osp.join(directory, filepath) self.filename = filename self.write = write def __call__(self, viewfunc): def wrapped(instance, *args, **kwargs): variables = viewfunc(instance, *args, **kwargs) html = instance.tal_render(self._compiled_template(instance), variables) if self.write: instance.w(html) else: return html return wrapped def _compiled_template(self, instance): for fileordirectory in instance.config.appobjects_path(): filepath = join(fileordirectory, self.filename) if isdir(fileordirectory) and exists(filepath): return compile_template_file(filepath) raise Exception('no such template %s' % self.filename) _compiled_template = cached(_compiled_template, 0)
class Foo(object): @cached def foo(self): """ what's up doc ? """ def bar(self, zogzog): """ what's up doc ? """ bar = cached(bar, 1) @cached def quux(self, zogzog): """ what's up doc ? """
class Function(Statement, Lambda): _astng_fields = ('decorators', 'args', 'body') special_attributes = set(('__name__', '__doc__', '__dict__')) is_function = True # attributes below are set by the builder module or by raw factories blockstart_tolineno = None decorators = None def __init__(self, name, doc): self.locals = {} self.args = [] self.body = [] self.decorators = None self.name = name self.doc = doc self.extra_decorators = [] self.instance_attrs = {} def set_line_info(self, lastchild): self.fromlineno = self.lineno # lineno is the line number of the first decorator, we want the def statement lineno if self.decorators is not None: self.fromlineno += len(self.decorators.nodes) self.tolineno = lastchild.tolineno self.blockstart_tolineno = self.args.tolineno def block_range(self, lineno): """return block line numbers. start from the "def" position whatever the given lineno """ return self.fromlineno, self.tolineno def getattr(self, name, context=None): """this method doesn't look in the instance_attrs dictionary since it's done by an Instance proxy at inference time. """ if name == '__module__': return [cf(self.root().qname())] if name in self.instance_attrs: return self.instance_attrs[name] return std_special_attributes(self, name, False) def is_method(self): """return true if the function node should be considered as a method""" # check we are defined in a Class, because this is usually expected # (e.g. pylint...) when is_method() return True return self.type != 'function' and isinstance(self.parent.frame(), Class) def decoratornames(self): """return a list of decorator qualified names""" result = set() decoratornodes = [] if self.decorators is not None: decoratornodes += self.decorators.nodes decoratornodes += self.extra_decorators for decnode in decoratornodes: for infnode in decnode.infer(): result.add(infnode.qname()) return result decoratornames = cached(decoratornames) def is_bound(self): """return true if the function is bound to an Instance or a class""" return self.type == 'classmethod' def is_abstract(self, pass_is_abstract=True): """return true if the method is abstract It's considered as abstract if the only statement is a raise of NotImplementError, or, if pass_is_abstract, a pass statement """ for child_node in self.body: if isinstance(child_node, Raise): if child_node.raises_not_implemented(): return True if pass_is_abstract and isinstance(child_node, Pass): return True return False # empty function is the same as function with a single "pass" statement if pass_is_abstract: return True def is_generator(self): """return true if this is a generator function""" # XXX should be flagged, not computed try: return self.nodes_of_class(Yield, skip_klass=Function).next() except StopIteration: return False def infer_call_result(self, caller, context=None): """infer what a function is returning when called""" if self.is_generator(): yield Generator(self) return returns = self.nodes_of_class(Return, skip_klass=Function) for returnnode in returns: if returnnode.value is None: yield Const(None) else: try: for infered in returnnode.value.infer(context): yield infered except InferenceError: yield YES
class Function(Statement, Lambda): if PY3K: _astroid_fields = ('decorators', 'args', 'body', 'returns') returns = None else: _astroid_fields = ('decorators', 'args', 'body') special_attributes = set(('__name__', '__doc__', '__dict__')) is_function = True # attributes below are set by the builder module or by raw factories blockstart_tolineno = None decorators = None _type = "function" type = cachedproperty(_function_type) def __init__(self, name, doc): self.locals = {} self.args = [] self.body = [] self.name = name self.doc = doc self.extra_decorators = [] self.instance_attrs = {} @cachedproperty def fromlineno(self): # lineno is the line number of the first decorator, we want the def # statement lineno lineno = self.lineno if self.decorators is not None: lineno += sum(node.tolineno - node.lineno + 1 for node in self.decorators.nodes) return lineno @cachedproperty def blockstart_tolineno(self): return self.args.tolineno def block_range(self, lineno): """return block line numbers. start from the "def" position whatever the given lineno """ return self.fromlineno, self.tolineno def getattr(self, name, context=None): """this method doesn't look in the instance_attrs dictionary since it's done by an Instance proxy at inference time. """ if name == '__module__': return [cf(self.root().qname())] if name in self.instance_attrs: return self.instance_attrs[name] return std_special_attributes(self, name, False) def is_method(self): """return true if the function node should be considered as a method""" # check we are defined in a Class, because this is usually expected # (e.g. pylint...) when is_method() return True return self.type != 'function' and isinstance(self.parent.frame(), Class) def decoratornames(self): """return a list of decorator qualified names""" result = set() decoratornodes = [] if self.decorators is not None: decoratornodes += self.decorators.nodes decoratornodes += self.extra_decorators for decnode in decoratornodes: for infnode in decnode.infer(): result.add(infnode.qname()) return result decoratornames = cached(decoratornames) def is_bound(self): """return true if the function is bound to an Instance or a class""" return self.type == 'classmethod' def is_abstract(self, pass_is_abstract=True): """Returns True if the method is abstract. A method is considered abstract if - the only statement is 'raise NotImplementedError', or - the only statement is 'pass' and pass_is_abstract is True, or - the method is annotated with abc.astractproperty/abc.abstractmethod """ if self.decorators: for node in self.decorators.nodes: try: infered = next(node.infer()) except InferenceError: continue if infered and infered.qname() in ('abc.abstractproperty', 'abc.abstractmethod'): return True for child_node in self.body: if isinstance(child_node, Raise): if child_node.raises_not_implemented(): return True if pass_is_abstract and isinstance(child_node, Pass): return True return False # empty function is the same as function with a single "pass" statement if pass_is_abstract: return True def is_generator(self): """return true if this is a generator function""" # XXX should be flagged, not computed return next(self.nodes_of_class((Yield, YieldFrom), skip_klass=(Function, Lambda)), False) def infer_call_result(self, caller, context=None): """infer what a function is returning when called""" if self.is_generator(): yield Generator() return # This is really a gigantic hack to work around metaclass generators # that return transient class-generating functions. Pylint's AST structure # cannot handle a base class object that is only used for calling __new__, # but does not contribute to the inheritance structure itself. We inject # a fake class into the hierarchy here for several well-known metaclass # generators, and filter it out later. if (self.name == 'with_metaclass' and len(self.args.args) == 1 and self.args.vararg is not None): metaclass = next(caller.args[0].infer(context)) if isinstance(metaclass, Class): c = Class('temporary_class', None) c.hide = True c.parent = self c.bases = [next(b.infer(context)) for b in caller.args[1:]] c._metaclass = metaclass yield c return returns = self.nodes_of_class(Return, skip_klass=Function) for returnnode in returns: if returnnode.value is None: yield Const(None) else: try: for infered in returnnode.value.infer(context): yield infered except InferenceError: yield YES
class CWUser(AnyEntity): __regid__ = 'CWUser' fetch_attrs, cw_fetch_order = fetch_config( ['login', 'firstname', 'surname']) cw_fetch_unrelated_order = cw_fetch_order # used by repository to check if the user can log in or not AUTHENTICABLE_STATES = ('activated', ) # low level utilities ##################################################### @property def groups(self): key = user_session_cache_key(self.eid, 'groups') try: return self._cw.transaction_data[key] except KeyError: with self._cw.security_enabled(read=False): groups = set(group for group, in self._cw.execute( 'Any GN WHERE U in_group G, G name GN, U eid %(userid)s', {'userid': self.eid})) self._cw.transaction_data[key] = groups return groups @property def properties(self): key = user_session_cache_key(self.eid, 'properties') try: return self._cw.transaction_data[key] except KeyError: with self._cw.security_enabled(read=False): properties = dict( self._cw.execute( 'Any K, V WHERE P for_user U, U eid %(userid)s, ' 'P pkey K, P value V', {'userid': self.eid})) self._cw.transaction_data[key] = properties return properties def prefered_language(self, language=None): """return language used by this user, if explicitly defined (eg not using http negociation) """ language = language or self.property_value('ui.language') vreg = self._cw.vreg try: vreg.config.translations[language] except KeyError: language = vreg.property_value('ui.language') assert language in vreg.config.translations[language], language return language def property_value(self, key): try: # properties stored on the user aren't correctly typed # (e.g. all values are unicode string) return self._cw.vreg.typed_value(key, self.properties[key]) except KeyError: pass except ValueError: self.warning('incorrect value for eproperty %s of user %s', key, self.login) return self._cw.vreg.property_value(key) def set_property(self, pkey, value): try: prop = self._cw.execute( 'CWProperty X WHERE X pkey %(k)s, X for_user U, U eid %(u)s', { 'k': pkey, 'u': self.eid }).get_entity(0, 0) except Exception: kwargs = dict(pkey=pkey, value=value) if self.is_in_group('managers'): kwargs['for_user'] = self self._cw.create_entity('CWProperty', **kwargs) else: prop.cw_set(value=value) def matching_groups(self, groups): """return the number of the given group(s) in which the user is :type groups: str or iterable(str) :param groups: a group name or an iterable on group names """ if isinstance(groups, str): groups = frozenset((groups, )) elif isinstance(groups, (tuple, list)): groups = frozenset(groups) return len( groups & self.groups) # XXX return the resulting set instead of its size def is_in_group(self, group): """convience / shortcut method to test if the user belongs to `group` """ return group in self.groups def is_anonymous(self): """ checks if user is an anonymous user""" # FIXME on the web-side anonymous user is detected according to config['anonymous-user'], # we don't have this info on the server side. return self.groups == frozenset(('guests', )) def owns(self, eid): try: return self._cw.execute( 'Any X WHERE X eid %(x)s, X owned_by U, U eid %(u)s', { 'x': eid, 'u': self.eid }) except Unauthorized: return False owns = cached(owns, keyarg=1) # presentation utilities ################################################## def name(self): """construct a name using firstname / surname or login if not defined""" if self.firstname and self.surname: return self._cw._('%(firstname)s %(surname)s') % { 'firstname': self.firstname, 'surname': self.surname } if self.firstname: return self.firstname return self.login def dc_title(self): return self.login dc_long_title = name