More hildonizing prep
authorEd Page <eopage@byu.net>
Sat, 31 Oct 2009 03:28:25 +0000 (22:28 -0500)
committerEd Page <eopage@byu.net>
Sat, 31 Oct 2009 03:28:25 +0000 (22:28 -0500)
Makefile [new file with mode: 0644]
support/builddeb.py [new file with mode: 0755]
support/pylint.rc [new file with mode: 0644]
support/test_syntax.py [new file with mode: 0755]
support/todo.py [new file with mode: 0755]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..cfefc13
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,101 @@
+PROJECT_NAME=gonvert
+SOURCE_PATH=src
+SOURCE=$(shell find $(SOURCE_PATH) -iname "*.py")
+PROGRAM=$(SOURCE_PATH)/$(PROJECT_NAME).py
+DATA_PATH=data
+DATA_TYPES=*.ini *.map *.glade *.png
+DATA=$(foreach type, $(DATA_TYPES), $(shell find $(DATA_PATH) -iname "$(type)"))
+OBJ=$(SOURCE:.py=.pyc)
+BUILD_PATH=./build
+TAG_FILE=~/.ctags/$(PROJECT_NAME).tags
+TODO_FILE=./TODO
+
+DEBUGGER=winpdb
+UNIT_TEST=nosetests --with-doctest -w .
+SYNTAX_TEST=support/test_syntax.py
+STYLE_TEST=../../Python/tools/pep8.py --ignore=W191,E501
+LINT_RC=./support/pylint.rc
+LINT=pylint --rcfile=$(LINT_RC)
+PROFILE_GEN=python -m cProfile -o .profile
+PROFILE_VIEW=python -m pstats .profile
+TODO_FINDER=support/todo.py
+CTAGS=ctags-exuberant
+
+.PHONY: all run profile debug test build lint tags todo clean distclean
+
+all: test
+
+run: $(OBJ)
+       $(SOURCE_PATH)/$(PROJECT_NAME)_glade.py
+
+profile: $(OBJ)
+       $(PROFILE_GEN) $(PROGRAM)
+       $(PROFILE_VIEW)
+
+debug: $(OBJ)
+       $(DEBUGGER) $(PROGRAM)
+
+test: $(OBJ)
+       $(UNIT_TEST)
+
+package: $(OBJ)
+       rm -Rf $(BUILD_PATH)
+
+       mkdir -p $(BUILD_PATH)/generic
+       cp $(SOURCE_PATH)/constants.py  $(BUILD_PATH)/generic
+       cp $(SOURCE_PATH)/$(PROJECT_NAME).py  $(BUILD_PATH)/generic
+       $(foreach file, $(DATA), cp $(file) $(BUILD_PATH)/generic/$(subst /,-,$(file)) ; )
+       $(foreach file, $(SOURCE), cp $(file) $(BUILD_PATH)/generic/$(subst /,-,$(file)) ; )
+       #$(foreach file, $(OBJ), cp $(file) $(BUILD_PATH)/generic/$(subst /,-,$(file)) ; )
+       cp support/$(PROJECT_NAME).desktop $(BUILD_PATH)/generic
+       cp support/builddeb.py $(BUILD_PATH)/generic
+       cp support/py2deb.py $(BUILD_PATH)/generic
+
+       mkdir -p $(BUILD_PATH)/chinook
+       cp -R $(BUILD_PATH)/generic/* $(BUILD_PATH)/chinook
+       cd $(BUILD_PATH)/chinook ; python builddeb.py chinook
+       mkdir -p $(BUILD_PATH)/diablo
+       cp -R $(BUILD_PATH)/generic/* $(BUILD_PATH)/diablo
+       cd $(BUILD_PATH)/diablo ; python builddeb.py diablo
+       mkdir -p $(BUILD_PATH)/fremantle
+       cp -R $(BUILD_PATH)/generic/* $(BUILD_PATH)/fremantle
+       cd $(BUILD_PATH)/fremantle ; python builddeb.py fremantle
+       mkdir -p $(BUILD_PATH)/mer
+       cp -R $(BUILD_PATH)/generic/* $(BUILD_PATH)/mer
+       cd $(BUILD_PATH)/mer ; python builddeb.py mer
+
+lint: $(OBJ)
+       $(foreach file, $(SOURCE), $(LINT) $(file) ; )
+
+tags: $(TAG_FILE) 
+
+todo: $(TODO_FILE)
+
+clean:
+       rm -Rf $(OBJ)
+       rm -Rf $(BUILD_PATH)
+       rm -Rf $(TODO_FILE)
+
+distclean:
+       rm -Rf $(OBJ)
+       rm -Rf $(BUILD_PATH)
+       rm -Rf $(TAG_FILE)
+       find $(SOURCE_PATH) -name "*.*~" | xargs rm -f
+       find $(SOURCE_PATH) -name "*.swp" | xargs rm -f
+       find $(SOURCE_PATH) -name "*.bak" | xargs rm -f
+       find $(SOURCE_PATH) -name ".*.swp" | xargs rm -f
+
+$(TAG_FILE): $(OBJ)
+       mkdir -p $(dir $(TAG_FILE))
+       $(CTAGS) -o $(TAG_FILE) $(SOURCE)
+
+$(TODO_FILE): $(SOURCE)
+       @- $(TODO_FINDER) $(SOURCE) > $(TODO_FILE)
+
+%.pyc: %.py
+       $(SYNTAX_TEST) $<
+
+#Makefile Debugging
+#Target to print any variable, can be added to the dependencies of any other target
+#Userfule flags for make, -d, -p, -n
+print-%: ; @$(error $* is $($*) ($(value $*)) (from $(origin $*)))
diff --git a/support/builddeb.py b/support/builddeb.py
new file mode 100755 (executable)
index 0000000..8685250
--- /dev/null
@@ -0,0 +1,259 @@
+#!/usr/bin/python2.5
+
+import os
+import sys
+
+import py2deb
+
+import constants
+
+
+__appname__ = constants.__app_name__
+__description__ = """Unit Conversions
+A conversion utility that allows conversion between many units like CGS, Ancient, Imperial with many categories like length, mass, numbers, etc. All units converted values shown at once as you type
+.
+Homepage: http://www.unihedron.com/projects/gonvert/index.php
+"""
+__author__ = "Ed Page (Maemo Porter)"
+__email__ = "eopage@byu.net"
+__version__ = constants.__version__
+__build__ = constants.__build__
+__changelog__ = """
+0.2.24
+* Added shortcuts for fullscreen
+* Switched to Find being brought up by CTRL+F
+* Added Find Previous and Find Next shortcuts (CTRL+P, CTRL+N)
+* Debugging: Added logging support
+* Internal: Massive cleanup of code
+
+0.2.23  - Added UK currency category and other UK measurements thanks to Dale Hair
+0.2.22  - Restore previously used window size
+0.2.21  - Category column widened. Maximize on start.
+0.2.20  - correction in micron pressure conversion
+0.2.19  - viscosity cP conversion correction
+0.2.18 - addition of magnitudes per square arcsecond to Luminance category
+0.2.17 - updated baud definitions
+       - fixed homepath location because new debian version changed
+0.2.16 - fixed icon locating for display in about
+       - added alternate icon gonvert-icon_alernative.png (copy over gonvert.png)
+0.2.15 - updated mainloop to main as discovered by Alexander Skwar
+0.2.14 - added Calgary energy and volume suggestions per Kim Lux
+0.2.13 - new more easily understandable icon
+       - nanotesla definition (nT).
+       - added shortlist feature.
+0.2.12 - removed inoperable books feature.
+       - fixed up acre accuracy.
+0.2.11 - miodified descriprion for silver, newton, sadzhens.
+0.2.10 - \x90 changed to \u00C9 for Emile and similar for Reaumur utf-8 text.
+       - Added translation for "All" book text.
+       - The write units text is translatable.
+       - The pl_messages.po file has been updated
+0.2.09 - Added utf-8 coding to all text strings in preparation for complete language translation.
+0.2.08 - Added language translation for menus and labels.
+0.2.07 - Added language translation changes and messages.pot.
+0.2.06 - Fixed category list size to show preselected categorys on startup,
+         scroll window H&Vpolicy set to always.
+0.2.05 - Spelling of Luminance category fixed.
+0.2.04 - Modified unit clicking to force focus on value entry.
+         Modified Makefile to remove /share/share bug for desktop entry.
+0.2.03 - Modified Makefile to allow better integration on other platforms.
+0.2.01 - Added saved selections feature, creates ~/.gonvert/ and file. 
+0.1.11 - fixed packaging for RPM
+0.1.10 - added Current Loop category for PLCs and 4-20mA instrumentation.
+0.1.9  - added kilobit, and more density units.
+0.1.8  - Added Torque units
+0.1.7  - Added many more pressure units
+       - Added thermal categories
+       - Added fuel consumption category
+       - Program extension to .pyw so that Windows startup without console
+0.1.6  - add more frequency units
+       - fixed computer number bases nums was bad near "h" and "v"
+       - fixed error:
+         "GtkTextBuffer.insert_at_cursor() takes exactly 1 argument (2 given)"
+         thanks to Riccardo Galli
+0.1.5  - put packages into /usr instead of /usr/local
+       - add gnome menu item back in
+0.1.4  - remove dependency on gnome-config from Makefile, RPM, binary.
+0.1.3  - touched up computer numbers units for better sorting
+       - limited up resizing of windows to prevent dissapearing areas
+       - fixed find bug that some users might notice (TreeViewColumn/None)
+0.1.2  - Added description box when writing units
+0.1.1  - Added help/about box
+       - fixed bug that sets focus on line 2480
+       - fixed temperature difference units labels
+       - all scroll bars only show when needed
+       - Added RPM distribution
+0.1.0   - Major modifications for GTK2 (RedHat 8.0)
+       - addition of units column in display
+       - sorting for all units columns with sort pointer
+0.0.15 - added Electromagnetic Radiation category
+0.0.14 - fixed window close bug, attempt to fix libglade XML startup bug for
+          some machines
+0.0.13 - changes for python2.2, had to remove gnome dependencies
+0.0.12 - change contact information address
+0.0.11 - addition of ppm to "find" utility
+0.0.10 - addition of petabyte to computer data
+0.0.9  - addition of cesium atom vibrations to Time category
+0.0.8  - more accurate calculation of degrees F
+0.0.7  - added 'Find unit' feature
+       - changed Category list to clist for ease of moveto (focus) after find
+0.0.6  - added description for Amperes
+       - added DENSITY category
+       - added 4 new categories 101 new units
+       - added shoe size converter
+       - add a function to convert custom formulas (like area from diameter)
+         example: area = pi * (D/2)^2
+         base value = pi* (x/2)^2  #metres in diameter metres, cm, inch, foot.
+0.0.5  - Tool for listing all categories and units to STDOUT.
+       - re-organization of project files.
+       - addition of suffixes between duodecillion and centillion.
+       - addition of Makefile to install onto Gnome based systems.
+       - sort Units or Value columns (ascending or descending)
+         by clicking on column.
+0.0.4  - Prefixes and Suffixes addition of;
+         ppm, %, Marx brothers, various descriptions.
+       - addition of microgram to mass category.
+       - replaced base 63 with 62 from computer numbers since
+         only 62 characters can be represented.
+       - fixed error if second line has nothing it wouldn't get
+         updated.
+0.0.3  - fix bug in labelling of base 36 (was base 37)
+         all numbering systems past 23 were at fault due
+         to improper nums string (fixed).
+0.0.2  - Completion of second row data entry so that changes
+         to text are not cyclicly causing changes to all
+         values.
+0.0.1  - Initial release.
+"""
+
+
+__postinstall__ = """#!/bin/sh -e
+
+gtk-update-icon-cache -f /usr/share/icons/hicolor
+rm -f ~/.gonvert/gonvert.log
+"""
+
+__preremove__ = """#!/bin/sh -e
+"""
+
+
+def find_files(prefix, path):
+       for root, dirs, files in os.walk(path):
+               for file in files:
+                       if file.startswith(prefix+"-"):
+                               fileParts = file.split("-")
+                               unused, relPathParts, newName = fileParts[0], fileParts[1:-1], fileParts[-1]
+                               assert unused == prefix
+                               relPath = os.sep.join(relPathParts)
+                               yield relPath, file, newName
+
+
+def unflatten_files(files):
+       d = {}
+       for relPath, oldName, newName in files:
+               if relPath not in d:
+                       d[relPath] = []
+               d[relPath].append((oldName, newName))
+       return d
+
+
+def build_package(distribution):
+       try:
+               os.chdir(os.path.dirname(sys.argv[0]))
+       except:
+               pass
+
+       py2deb.Py2deb.SECTIONS = py2deb.SECTIONS_BY_POLICY[distribution]
+       p = py2deb.Py2deb(__appname__)
+       p.prettyName = constants.__pretty_app_name__
+       p.description = __description__
+       p.bugTracker = ""
+       p.upgradeDescription = __changelog__.split("\n\n", 1)[0]
+       p.author = __author__
+       p.mail = __email__
+       p.license = "lgpl"
+       p.depends = ", ".join([
+               "python2.6 | python2.5",
+               "python-gtk2 | python2.5-gtk2",
+               "python-xml | python2.5-xml",
+               "python-dbus | python2.5-dbus",
+       ])
+       maemoSpecificDepends = ", python-osso | python2.5-osso, python-hildon | python2.5-hildon"
+       p.depends += {
+               "debian": ", python-glade2",
+               "chinook": maemoSpecificDepends,
+               "diablo": maemoSpecificDepends,
+               "fremantle": maemoSpecificDepends + ", python-glade2",
+               "mer": maemoSpecificDepends + ", python-glade2",
+       }[distribution]
+       p.recommends = ", ".join([
+       ])
+       p.section = {
+               "debian": "science",
+               "chinook": "other",
+               "diablo": "user/science",
+               "fremantle": "user/science",
+               "mer": "user/science",
+       }[distribution]
+       p.arch = "all"
+       p.urgency = "low"
+       p.distribution = "chinook diablo fremantle mer debian"
+       p.repository = "extras"
+       p.changelog = __changelog__
+       p.postinstall = __postinstall__
+       p.preremove = __preremove__
+       p.icon = {
+               "debian": "data-pixmaps-gonvert.png",
+               "chinook": "data-pixmaps-gonvert.png",
+               "diablo": "data-pixmaps-gonvert.png",
+               "fremantle": "data-pixmaps-gonvert.png", # Fremantle natively uses 48x48
+               "mer": "data-pixmaps-gonvert.png",
+       }[distribution]
+       p["/usr/bin"] = [ "gonvert.py" ]
+       for relPath, files in unflatten_files(find_files("src", ".")).iteritems():
+               fullPath = "/usr/lib/gonvert"
+               if relPath:
+                       fullPath += os.sep+relPath
+               p[fullPath] = list(
+                       "|".join((oldName, newName))
+                       for (oldName, newName) in files
+               )
+       for relPath, files in unflatten_files(find_files("data", ".")).iteritems():
+               fullPath = "/usr/lib/gonvert"
+               if relPath:
+                       fullPath += os.sep+relPath
+               p[fullPath] = list(
+                       "|".join((oldName, newName))
+                       for (oldName, newName) in files
+               )
+       p["/usr/share/applications/hildon"] = ["gonvert.desktop"]
+       p["/usr/share/icons/hicolor/26x26/hildon"] = ["data-pixmaps-gonvert.png|gonvert.png"]
+       p["/usr/share/icons/hicolor/64x64/hildon"] = ["data-pixmaps-gonvert.png|gonvert.png"]
+       p["/usr/share/icons/hicolor/scalable/hildon"] = ["data-pixmaps-gonvert.png|gonvert.png"]
+
+       print p
+       print p.generate(
+               version="%s-%s" % (__version__, __build__),
+               changelog=__changelog__,
+               build=False,
+               tar=True,
+               changes=True,
+               dsc=True,
+       )
+       print "Building for %s finished" % distribution
+
+
+if __name__ == "__main__":
+       if len(sys.argv) > 1:
+               try:
+                       import optparse
+               except ImportError:
+                       optparse = None
+
+               if optparse is not None:
+                       parser = optparse.OptionParser()
+                       (commandOptions, commandArgs) = parser.parse_args()
+       else:
+               commandArgs = None
+               commandArgs = ["diablo"]
+       build_package(commandArgs[0])
diff --git a/support/pylint.rc b/support/pylint.rc
new file mode 100644 (file)
index 0000000..2a371a1
--- /dev/null
@@ -0,0 +1,305 @@
+# 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=
+
+# Python code to execute, usually for sys.path manipulation such as
+# pygtk.require().
+#init-hook=
+
+# Profiled execution.
+profile=no
+
+# Add <file or directory> to the black list. It should be a base name, not a
+# path. You may set this option multiple times.
+ignore=CVS
+
+# 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 conflicts with the
+# disable-checker option
+#enable-checker=
+
+# Enable all checker(s) except those with the given id(s). This option
+# conflicts with the enable-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=W0403,W0612,W0613,C0103,C0111,C0301,R0903,W0142,W0603,R0904,R0921,R0201
+
+[REPORTS]
+
+# set the output format. Available formats are text, parseable, colorized, msvs
+# (visual studio) 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=no
+
+# 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=
+
+
+# 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_]{2,30}$
+
+# Regular expression which should only match correct method names
+method-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct instance attribute names
+attr-rgx=[a-z_][a-zA-Z0-9_]{2,30}$
+
+# Regular expression which should only match correct argument names
+argument-rgx=[a-z_][a-zA-Z0-9_]{2,30}$
+
+# Regular expression which should only match correct variable names
+variable-rgx=[a-z_][a-zA-Z0-9_]{2,30}$
+
+# 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=map,filter,apply,input
+
+
+# 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 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=5
+
+# Maximum number of locals for function / method body
+max-locals=15
+
+# Maximum number of return / yield for function / method body
+max-returns=6
+
+# Maximum number of branch for function / method body
+max-branchs=12
+
+# Maximum number of statements in function / method body
+max-statements=50
+
+# Maximum number of parents for a class (see R0901).
+max-parents=7
+
+# Maximum number of attributes for a class (see R0902).
+max-attributes=15
+
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=1
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
+
+
+# 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
+# * 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 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=4
+
+# 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.
+# @note Limiting this to the most extreme cases
+max-line-length=100
+
+# 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='\t'
diff --git a/support/test_syntax.py b/support/test_syntax.py
new file mode 100755 (executable)
index 0000000..65a373c
--- /dev/null
@@ -0,0 +1,45 @@
+#!/usr/bin/env python
+
+import commands
+
+
+verbose = False
+
+
+def syntax_test(file):
+       commandTemplate = """
+       python -t -t -W all -c "import py_compile; py_compile.compile ('%(filename)s', doraise=False)" """
+       compileCommand = commandTemplate % {"filename": file}
+       (status, text) = commands.getstatusoutput (compileCommand)
+       text = text.rstrip()
+       passed = len(text) == 0
+
+       if passed:
+               output = ("Syntax is correct for "+file) if verbose else ""
+       else:
+               output = ("Syntax is invalid for %s\n" % file) if verbose else ""
+               output += text
+       return (passed, output)
+
+
+if __name__ == "__main__":
+       import sys
+       import os
+       import optparse
+
+       opar = optparse.OptionParser()
+       opar.add_option("-v", "--verbose", dest="verbose", help="Toggle verbosity", action="store_true", default=False)
+       options, args = opar.parse_args(sys.argv[1:])
+       verbose = options.verbose
+
+       completeOutput = []
+       allPassed = True
+       for filename in args:
+               passed, output = syntax_test(filename)
+               if not passed:
+                       allPassed = False
+               if output.strip():
+                       completeOutput.append(output)
+       print "\n".join(completeOutput)
+
+       sys.exit(0 if allPassed else 1);
diff --git a/support/todo.py b/support/todo.py
new file mode 100755 (executable)
index 0000000..90cbd04
--- /dev/null
@@ -0,0 +1,104 @@
+#!/usr/bin/env python
+
+from __future__ import with_statement
+import itertools
+
+
+verbose = False
+
+
+def tag_parser(file, tag):
+       """
+       >>> nothing = []
+       >>> for todo in tag_parser(nothing, "@todo"):
+       ...     print todo
+       ...
+       >>> one = ["@todo Help!"]
+       >>> for todo in tag_parser(one, "@todo"):
+       ...     print todo
+       ...
+       1: @todo Help!
+       >>> mixed = ["one", "@todo two", "three"]
+       >>> for todo in tag_parser(mixed, "@todo"):
+       ...     print todo
+       ...
+       2: @todo two
+       >>> embedded = ["one @todo two", "three"]
+       >>> for todo in tag_parser(embedded, "@todo"):
+       ...     print todo
+       ...
+       1: @todo two
+       >>> continuation = ["one", "@todo two", " three"]
+       >>> for todo in tag_parser(continuation, "@todo"):
+       ...     print todo
+       ...
+       2: @todo two three
+       >>> series = ["one", "@todo two", "@todo three"]
+       >>> for todo in tag_parser(series, "@todo"):
+       ...     print todo
+       ...
+       2: @todo two
+       3: @todo three
+       """
+       currentTodo = []
+       prefix = None
+       for lineNumber, line in enumerate(file):
+               column = line.find(tag)
+               if column != -1:
+                       if currentTodo:
+                               yield "\n".join (currentTodo)
+                       prefix = line[0:column]
+                       currentTodo = ["%d: %s" % (lineNumber+1, line[column:].strip())]
+               elif prefix is not None and len(prefix)+1 < len(line) and line.startswith(prefix) and line[len(prefix)].isspace():
+                       currentTodo.append (line[len(prefix):].rstrip())
+               elif currentTodo:
+                       yield "\n".join (currentTodo)
+                       currentTodo = []
+                       prefix = None
+       if currentTodo:
+               yield "\n".join (currentTodo)
+
+
+def tag_finder(filename, tag):
+       todoList = []
+
+       with open(filename) as file:
+               body = "\n".join (tag_parser(file, tag))
+       passed = not body
+       if passed:
+               output = "No %s's for %s" % (tag, filename) if verbose else ""
+       else:
+               header = "%s's for %s:\n" % (tag, filename) if verbose else ""
+               output = header + body
+               output += "\n" if verbose else ""
+
+       return (passed, output)
+
+
+if __name__ == "__main__":
+       import sys
+       import os
+       import optparse
+
+       opar = optparse.OptionParser()
+       opar.add_option("-v", "--verbose", dest="verbose", help="Toggle verbosity", action="store_true", default=False)
+       options, args = opar.parse_args(sys.argv[1:])
+       verbose = options.verbose
+
+       bugsAsError = True
+       todosAsError = False
+
+       completeOutput = []
+       allPassed = True
+       for filename in args:
+               bugPassed, bugOutput = tag_finder(filename, "@bug")
+               todoPassed, todoOutput = tag_finder(filename, "@todo")
+               output = "\n".join ([bugOutput, todoOutput])
+               if (not bugPassed and bugsAsError) or (not todoPassed and todosAsError):
+                       allPassed = False
+               output = output.strip()
+               if output:
+                       completeOutput.append(filename+":\n"+output+"\n\n")
+       print "\n".join(completeOutput)
+       
+       sys.exit(0 if allPassed else 1);