From b475cffa77a65b203cbe348f03d2cf81f4471b3f Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Mon, 28 May 2007 23:15:43 +0200 Subject: [PATCH] [svn] added pylint script for jinja and cleaned code up a bit (and importing is faster now) --HG-- branch : trunk --- Makefile | 3 + jinja/_native.py | 17 +- jinja/datastructure.py | 6 - jinja/filters.py | 21 +-- jinja/lexer.py | 6 +- jinja/loaders.py | 19 ++- jinja/parser.py | 9 +- jinja/tests.py | 1 - jinja/translators/python.py | 19 +-- jinja/utils.py | 56 ++++--- scripts/pylintrc | 301 ++++++++++++++++++++++++++++++++++++ 11 files changed, 359 insertions(+), 99 deletions(-) create mode 100644 scripts/pylintrc diff --git a/Makefile b/Makefile index 8f40d47..9b1cd17 100644 --- a/Makefile +++ b/Makefile @@ -20,5 +20,8 @@ documentation: webpage: @(cd ../www; ./generate.py) +pylint: + @pylint --rcfile scripts/pylintrc jinja + release: documentation @(python2.3 setup.py release bdist_egg upload; python2.4 setup.py release bdist_egg upload; python2.5 setup.py release bdist_egg sdist upload) diff --git a/jinja/_native.py b/jinja/_native.py index 9fa723f..1c01fa0 100644 --- a/jinja/_native.py +++ b/jinja/_native.py @@ -13,21 +13,8 @@ :copyright: 2007 by Armin Ronacher. :license: BSD, see LICENSE for more details. """ -from jinja.datastructure import Deferred, Undefined -try: - from collections import deque -except ImportError: - class deque(list): - """ - Minimal subclass of list that provides the deque - interface used by the native `BaseContext`. - """ - - def appendleft(self, item): - list.insert(self, 0, item) - - def popleft(self): - return list.pop(self, 0) +from jinja.datastructure import Deferred +from jinja.utils import deque class BaseContext(object): diff --git a/jinja/datastructure.py b/jinja/datastructure.py index f66e16d..0f5d9e9 100644 --- a/jinja/datastructure.py +++ b/jinja/datastructure.py @@ -9,12 +9,6 @@ :license: BSD, see LICENSE for more details. """ -# sets -try: - set -except NameError: - from sets import Set as set - from jinja.exceptions import TemplateSyntaxError, TemplateRuntimeError diff --git a/jinja/filters.py b/jinja/filters.py index 17c0ce8..1d45fc4 100644 --- a/jinja/filters.py +++ b/jinja/filters.py @@ -11,26 +11,11 @@ import re from random import choice from urllib import urlencode, quote -from jinja.utils import urlize, escape -from jinja.datastructure import Markup, TemplateData +from jinja.utils import urlize, escape, reversed +from jinja.datastructure import TemplateData from jinja.exceptions import FilterArgumentError -try: - _reversed = reversed -except NameError: - # python2.3 compatibility hack for the do_reverse function - def _reversed(seq): - try: - return seq[::-1] - except: - try: - return list(seq)[::-1] - except: - raise TypeError('argument to _reversed must ' - 'be a sequence') - - def stringfilter(f): """ Decorator for filters that just work on unicode objects. @@ -332,7 +317,7 @@ def do_last(): """ def wrapped(env, context, seq): try: - return iter(_reversed(seq)).next() + return iter(reversed(seq)).next() except StopIteration: return env.undefined_singleton return wrapped diff --git a/jinja/lexer.py b/jinja/lexer.py index 7b98a57..825722b 100644 --- a/jinja/lexer.py +++ b/jinja/lexer.py @@ -25,13 +25,9 @@ import re from jinja.datastructure import TokenStream from jinja.exceptions import TemplateSyntaxError +from jinja.utils import set from weakref import WeakValueDictionary -try: - set -except NameError: - from sets import Set as set - __all__ = ['Lexer', 'Failure', 'keywords'] diff --git a/jinja/loaders.py b/jinja/loaders.py index 15d04e6..ae93aaa 100644 --- a/jinja/loaders.py +++ b/jinja/loaders.py @@ -18,11 +18,6 @@ from jinja.parser import Parser from jinja.translators.python import PythonTranslator, Template from jinja.exceptions import TemplateNotFound, TemplateSyntaxError from jinja.utils import CacheDict, raise_syntax_error -try: - from pkg_resources import resource_exists, resource_string, \ - resource_filename -except ImportError: - resource_exists = resource_string = resource_filename = None #: when updating this, update the listing in the jinja package too @@ -131,6 +126,12 @@ class BaseLoader(object): ast = self.parse(environment, name, None) return translator.process(environment, ast) + def get_source(self, environment, name, parent): + """ + Override this method to get the source for a template. + """ + raise TemplateNotFound(name) + class CachedLoaderMixin(object): """ @@ -353,8 +354,10 @@ class PackageLoader(CachedLoaderMixin, BaseLoader): def __init__(self, package_name, package_path, use_memcache=False, memcache_size=40, cache_folder=None, auto_reload=True, cache_salt=None): - if resource_filename is None: - raise ImportError('setuptools not found') + try: + import pkg_resources + except ImportError: + raise RuntimeError('setuptools not installed') self.package_name = package_name self.package_path = package_path if cache_salt is None: @@ -363,6 +366,7 @@ class PackageLoader(CachedLoaderMixin, BaseLoader): cache_folder, auto_reload, cache_salt) def get_source(self, environment, name, parent): + from pkg_resources import resource_exists, resource_string name = '/'.join([self.package_path] + [p for p in name.split('/') if p != '..']) if not resource_exists(self.package_name, name): @@ -371,6 +375,7 @@ class PackageLoader(CachedLoaderMixin, BaseLoader): return contents.decode(environment.template_charset) def check_source_changed(self, environment, name): + from pkg_resources import resource_exists, resource_filename fn = resource_filename(self.package_name, '/'.join([self.package_path] + [p for p in name.split('/') if p and p[0] != '.'])) if resource_exists(self.package_name, fn): diff --git a/jinja/parser.py b/jinja/parser.py index befcbc5..80f4c72 100644 --- a/jinja/parser.py +++ b/jinja/parser.py @@ -14,16 +14,11 @@ :copyright: 2007 by Armin Ronacher. :license: BSD, see LICENSE for more details. """ -import re from compiler import ast, parse -from compiler.misc import set_filename from jinja import nodes -from jinja.datastructure import TokenStream, StateTest +from jinja.datastructure import StateTest from jinja.exceptions import TemplateSyntaxError -try: - set -except NameError: - from sets import Set as set +from jinja.utils import set __all__ = ['Parser'] diff --git a/jinja/tests.py b/jinja/tests.py index 8f0e395..cdef3a3 100644 --- a/jinja/tests.py +++ b/jinja/tests.py @@ -12,7 +12,6 @@ import re number_re = re.compile(r'^-?\d+(\.\d+)?$') - regex_type = type(number_re) diff --git a/jinja/translators/python.py b/jinja/translators/python.py index 12a829a..a26299a 100644 --- a/jinja/translators/python.py +++ b/jinja/translators/python.py @@ -43,7 +43,7 @@ from jinja.parser import Parser from jinja.exceptions import TemplateSyntaxError from jinja.translators import Translator from jinja.datastructure import TemplateStream -from jinja.utils import translate_exception, capture_generator, \ +from jinja.utils import set, translate_exception, capture_generator, \ RUNTIME_EXCEPTION_OFFSET @@ -51,15 +51,9 @@ from jinja.utils import translate_exception, capture_generator, \ _debug_re = re.compile(r'^\s*\# DEBUG\(filename=(?P.*?), ' r'lineno=(?P\d+)\)$') -# For Python2.3 compatibiilty +# For Python versions without generator exit exceptions try: - set -except NameError: - from sets import Set as set - -# For Python 2.3/2.4 compatibility -try: - GeneratorExit + GeneratorExit = GeneratorExit except NameError: class GeneratorExit(Exception): pass @@ -424,7 +418,6 @@ class PythonTranslator(Translator): # handle requirements code if requirements: requirement_lines = ['def bootstrap(context):'] - has_requirements = False for n in requirements: requirement_lines.append(self.handle_node(n)) requirement_lines.append(' if 0: yield None\n') @@ -464,12 +457,6 @@ class PythonTranslator(Translator): self.to_tuple(tmp) )) - # aliases boilerplate - aliases = ['%s = environment.%s' % (item, item) for item in - ['get_attribute', 'perform_test', 'apply_filters', - 'call_function', 'call_function_simple', 'finish_var', - 'undefined_singleton'] if item in self.used_shortcuts] - # bootstrapping code lines = ['# Essential imports', 'from __future__ import division'] if self.used_utils: diff --git a/jinja/utils.py b/jinja/utils.py index 6274983..4102115 100644 --- a/jinja/utils.py +++ b/jinja/utils.py @@ -17,7 +17,6 @@ import string from types import MethodType, FunctionType from compiler.ast import CallFunc, Name, Const from jinja.nodes import Trans -from jinja.datastructure import Context from jinja.exceptions import SecurityException, TemplateNotFound # the python2.4 version of deque is missing the remove method @@ -27,11 +26,34 @@ try: from collections import deque deque.remove except (ImportError, AttributeError): - deque = None + class deque(list): + """ + Minimal subclass of list that provides the deque + interface used by the native `BaseContext` and the + `CacheDict` + """ + def appendleft(self, item): + list.insert(self, 0, item) + def popleft(self): + return list.pop(self, 0) + def clear(self): + del self[:] + +# support for a working reversed() +try: + reversed = reversed +except NameError: + def reversed(iterable): + if hasattr(iterable, '__reversed__'): + return iterable.__reversed__() + try: + return iter(iterable[::-1]) + except TypeError: + return iter(tuple(iterable)[::-1]) # support for python 2.3/2.4 try: - set + set = set except NameError: from sets import Set as set @@ -276,9 +298,7 @@ def buffereater(f): Used by the python translator to capture output of substreams. (macros, filter sections etc) """ - def wrapped(*args, **kwargs): - return capture_generator(f(*args, **kwargs)) - return wrapped + return lambda *a, **kw: capture_generator(f(*a, **kw)) def empty_block(context): @@ -297,6 +317,8 @@ def fake_template_exception(exception, filename, lineno, source, """ # some traceback systems allow to skip frames __traceback_hide__ = True + + from jinja.datastructure import Context if isinstance(context_or_env, Context): env = context_or_env.environment namespace = context_or_env.to_dict() @@ -541,18 +563,10 @@ class CacheDict(object): def __init__(self, capacity): self.capacity = capacity self._mapping = {} - - # use a deque here if possible - if deque is not None: - self._queue = deque() - self._popleft = self._queue.popleft - # python2.3/2.4, just use a list - else: - self._queue = [] - pop = self._queue.pop - self._popleft = lambda: pop(0) + self._queue = deque() # alias all queue methods for faster lookup + self._popleft = self._queue.popleft self._pop = self._queue.pop self._remove = self._queue.remove self._append = self._queue.append @@ -589,10 +603,7 @@ class CacheDict(object): Clear the cache dict. """ self._mapping.clear() - try: - self._queue.clear() - except AttributeError: - del self._queue[:] + self._queue.clear() def __contains__(self, key): """ @@ -650,10 +661,7 @@ class CacheDict(object): Iterate over all values in the cache dict, ordered by the most recent usage. """ - try: - return reversed(self._queue) - except NameError: - return iter(self._queue[::-1]) + return reversed(self._queue) def __reversed__(self): """ diff --git a/scripts/pylintrc b/scripts/pylintrc new file mode 100644 index 0000000..4f85b49 --- /dev/null +++ b/scripts/pylintrc @@ -0,0 +1,301 @@ +# lint Python modules using external checkers. +# +# This is the main checker controling the other ones and the reports +# generation. It is itself both a raw checker and an astng checker in order +# to: +# * handle message activation / deactivation at the module level +# * handle some basic but necessary stats'data (number of classes, methods...) +# +[MASTER] + +# Specify a configuration file. +#rcfile= + +# Profiled execution. +profile=no + +# Add to the black list. It should be a base name, not a +# path. You may set this option multiple times. +ignore=.svn + +# Pickle collected data for later comparisons. +persistent=yes + +# Set the cache size for astng objects. +cache-size=500 + +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins= + + +[MESSAGES CONTROL] + +# Enable only checker(s) with the given id(s). This option conflict with the +# disable-checker option +#enable-checker= + +# Enable all checker(s) except those with the given id(s). This option conflict +# with the disable-checker option +#disable-checker= + +# Enable all messages in the listed categories. +#enable-msg-cat= + +# Disable all messages in the listed categories. +#disable-msg-cat= + +# Enable the message(s) with the given id(s). +#enable-msg= + +# Disable the message(s) with the given id(s). +disable-msg=C0323,W0142,C0301,C0103,C0111,E0213,C0302,C0203,W0703,R0201 + + +[REPORTS] + +# set the output format. Available formats are text, parseable, colorized and +# html +output-format=colorized + +# Include message's id in output +include-ids=yes + +# Put messages in a separate file for each module / package specified on the +# command line instead of printing them on stdout. Reports (if any) will be +# written in a file name "pylint_global.[txt|html]". +files-output=no + +# Tells wether to display a full report or only the messages +reports=yes + +# Python expression which should return a note less than 10 (10 is the highest +# note).You have access to the variables errors warning, statement which +# respectivly contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (R0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Add a comment according to your evaluation note. This is used by the global +# evaluation report (R0004). +comment=no + +# Enable the report(s) with the given id(s). +#enable-report= + +# Disable the report(s) with the given id(s). +#disable-report= + + +# checks for +# * unused variables / imports +# * undefined variables +# * redefinition of variable from builtins or from an outer scope +# * use of variable before assigment +# +[VARIABLES] + +# Tells wether we should check for unused import in __init__ files. +init-import=no + +# A regular expression matching names used for dummy variables (i.e. not used). +dummy-variables-rgx=_|dummy + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + + +# try to find bugs in the code using type inference +# +[TYPECHECK] + +# Tells wether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# When zope mode is activated, consider the acquired-members option to ignore +# access to some undefined attributes. +zope=no + +# List of members which are usually get through zope's acquisition mecanism and +# so shouldn't trigger E0201 when accessed (need zope=yes to be considered). +acquired-members=REQUEST,acl_users,aq_parent + + +# checks for : +# * doc strings +# * modules / classes / functions / methods / arguments / variables name +# * number of arguments, local variables, branchs, returns and statements in +# functions, methods +# * required module attributes +# * dangerous default values as arguments +# * redefinition of function / method / class +# * uses of the global statement +# +[BASIC] + +# Required attributes for module, separated by a comma +required-attributes= + +# Regular expression which should only match functions or classes name which do +# not require a docstring +no-docstring-rgx=__.*__ + +# Regular expression which should only match correct module names +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Regular expression which should only match correct module level names +const-rgx=(([A-Z_][A-Z1-9_]*)|(__.*__))$ + +# Regular expression which should only match correct class names +class-rgx=[A-Z_][a-zA-Z0-9]+$ + +# Regular expression which should only match correct function names +function-rgx=[a-z_][a-z0-9_]*$ + +# Regular expression which should only match correct method names +method-rgx=[a-z_][a-z0-9_]*$ + +# Regular expression which should only match correct instance attribute names +attr-rgx=[a-z_][a-z0-9_]*$ + +# Regular expression which should only match correct argument names +argument-rgx=[a-z_][a-z0-9_]*$ + +# Regular expression which should only match correct variable names +variable-rgx=[a-z_][a-z0-9_]*$ + +# Regular expression which should only match correct list comprehension / +# generator expression variable names +inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ + +# Good variable names which should always be accepted, separated by a comma +good-names=i,j,k,ex,Run,_ + +# Bad variable names which should always be refused, separated by a comma +bad-names=foo,bar,baz,toto,tutu,tata + +# List of builtins function names that should not be used, separated by a comma +bad-functions=apply,input + + +# checks for sign of poor/misdesign: +# * number of methods, attributes, local variables... +# * size, complexity of functions, methods +# +[DESIGN] + +# Maximum number of arguments for function / method +max-args=12 + +# Maximum number of locals for function / method body +max-locals=30 + +# Maximum number of return / yield for function / method body +max-returns=12 + +# Maximum number of branch for function / method body +max-branchs=30 + +# Maximum number of statements in function / method body +max-statements=60 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of attributes for a class (see R0902). +max-attributes=20 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=0 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + + +# checks for +# * external modules dependencies +# * relative / wildcard imports +# * cyclic imports +# * uses of deprecated modules +# +[IMPORTS] + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=regsub,string,TERMIOS,Bastion,rexec + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report R0402 must not be disabled) +import-graph= + +# Create a graph of external dependencies in the given file (report R0402 must +# not be disabled) +ext-import-graph= + +# Create a graph of internal dependencies in the given file (report R0402 must +# not be disabled) +int-import-graph= + + +# checks for : +# * methods without self as first argument +# * overridden methods signature +# * access only to existant members via self +# * attributes not defined in the __init__ method +# * supported interfaces implementation +# * unreachable code +# +[CLASSES] + +# List of interface methods to ignore, separated by a comma. This is used for +# instance to not check methods defines in Zope's Interface base class. +ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__,__new__,setUp + + +# checks for similarities and duplicated code. This computation may be +# memory / CPU intensive, so you should disable it if you experiments some +# problems. +# +[SIMILARITIES] + +# Minimum lines number of a similarity. +min-similarity-lines=10 + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + + +# checks for: +# * warning notes in the code like FIXME, XXX +# * PEP 263: source code with non ascii character but no encoding declaration +# +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=FIXME,XXX,TODO + + +# checks for : +# * unauthorized constructions +# * strict indentation +# * line length +# * use of <> instead of != +# +[FORMAT] + +# Maximum number of characters on a single line. +max-line-length=90 + +# Maximum number of lines in a module +max-module-lines=1000 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' -- 2.26.2