--- /dev/null
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+\f
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+\f
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+\f
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+\f
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+\f
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
--- /dev/null
+PROJECT_NAME=
+SOURCE_PATH=src
+SOURCE=$(shell find $(SOURCE_PATH) -iname "*.py")
+PROGRAM=$(SOURCE_PATH)/$(PROJECT_NAME).py
+DATA_TYPES=*.ini *.map *.glade *.png
+DATA=$(foreach type, $(DATA_TYPES), $(shell find $(SOURCE_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).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/icons/hicolor/26x26/hildon/$(PROJECT_NAME).png $(BUILD_PATH)/generic/26x26-$(PROJECT_NAME).png
+ cp support/icons/hicolor/64x64/hildon/$(PROJECT_NAME).png $(BUILD_PATH)/generic/64x64-$(PROJECT_NAME).png
+ cp support/icons/hicolor/scalable/hildon/$(PROJECT_NAME).png $(BUILD_PATH)/generic/scale-$(PROJECT_NAME).png
+ cp support/builddeb.py $(BUILD_PATH)/generic
+ cp support/py2deb.py $(BUILD_PATH)/generic
+ cp support/fake_py2deb.py $(BUILD_PATH)/generic
+
+ 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)/debian
+ cp -R $(BUILD_PATH)/generic/* $(BUILD_PATH)/debian
+ cd $(BUILD_PATH)/debian ; python builddeb.py debian
+
+upload:
+ dput fremantle-extras-builder $(BUILD_PATH)/fremantle/$(PROJECT_NAME)*.changes
+ dput diablo-extras-builder $(BUILD_PATH)/diablo/$(PROJECT_NAME)*.changes
+ cp $(BUILD_PATH)/debian/*.deb ./www/$(PROJECT_NAME).deb
+
+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 $*)))
--- /dev/null
+Building a package
+===================
+Run
+ make package
--- /dev/null
+#!/usr/bin/env python
--- /dev/null
+import os
+
+__pretty_app_name__ = ""
+__app_name__ = ""
+__version__ = "0.1.0"
+__build__ = 0
+__app_magic__ = 0xdeadbeef
+_data_path_ = os.path.join(os.path.expanduser("~"), ".%s" % __app_name__)
+_user_settings_ = "%s/settings.ini" % _data_path_
+_user_logpath_ = "%s/%s.log" % (_data_path_, __app_name__)
--- /dev/null
+#!/usr/bin/env python
+
+"""
+Open Issues
+ @bug not all of a message is shown
+ @bug Buttons are too small
+"""
+
+
+import gobject
+import gtk
+import dbus
+
+
+class _NullHildonModule(object):
+ pass
+
+
+try:
+ import hildon as _hildon
+ hildon = _hildon # Dumb but gets around pyflakiness
+except (ImportError, OSError):
+ hildon = _NullHildonModule
+
+
+IS_HILDON_SUPPORTED = hildon is not _NullHildonModule
+
+
+class _NullHildonProgram(object):
+
+ def add_window(self, window):
+ pass
+
+
+def _hildon_get_app_class():
+ return hildon.Program
+
+
+def _null_get_app_class():
+ return _NullHildonProgram
+
+
+try:
+ hildon.Program
+ get_app_class = _hildon_get_app_class
+except AttributeError:
+ get_app_class = _null_get_app_class
+
+
+def _hildon_set_application_title(window, title):
+ pass
+
+
+def _null_set_application_title(window, title):
+ window.set_title(title)
+
+
+if IS_HILDON_SUPPORTED:
+ set_application_title = _hildon_set_application_title
+else:
+ set_application_title = _null_set_application_title
+
+
+def _fremantle_hildonize_window(app, window):
+ oldWindow = window
+ newWindow = hildon.StackableWindow()
+ oldWindow.get_child().reparent(newWindow)
+ app.add_window(newWindow)
+ return newWindow
+
+
+def _hildon_hildonize_window(app, window):
+ oldWindow = window
+ newWindow = hildon.Window()
+ oldWindow.get_child().reparent(newWindow)
+ app.add_window(newWindow)
+ return newWindow
+
+
+def _null_hildonize_window(app, window):
+ return window
+
+
+try:
+ hildon.StackableWindow
+ hildonize_window = _fremantle_hildonize_window
+except AttributeError:
+ try:
+ hildon.Window
+ hildonize_window = _hildon_hildonize_window
+ except AttributeError:
+ hildonize_window = _null_hildonize_window
+
+
+def _fremantle_hildonize_menu(window, gtkMenu):
+ appMenu = hildon.AppMenu()
+ window.set_app_menu(appMenu)
+ gtkMenu.get_parent().remove(gtkMenu)
+ return appMenu
+
+
+def _hildon_hildonize_menu(window, gtkMenu):
+ hildonMenu = gtk.Menu()
+ for child in gtkMenu.get_children():
+ child.reparent(hildonMenu)
+ window.set_menu(hildonMenu)
+ gtkMenu.destroy()
+ return hildonMenu
+
+
+def _null_hildonize_menu(window, gtkMenu):
+ return gtkMenu
+
+
+try:
+ hildon.AppMenu
+ GTK_MENU_USED = False
+ IS_FREMANTLE_SUPPORTED = True
+ hildonize_menu = _fremantle_hildonize_menu
+except AttributeError:
+ GTK_MENU_USED = True
+ IS_FREMANTLE_SUPPORTED = False
+ if IS_HILDON_SUPPORTED:
+ hildonize_menu = _hildon_hildonize_menu
+ else:
+ hildonize_menu = _null_hildonize_menu
+
+
+def _hildon_set_button_auto_selectable(button):
+ button.set_theme_size(hildon.HILDON_SIZE_AUTO_HEIGHT)
+
+
+def _null_set_button_auto_selectable(button):
+ pass
+
+
+try:
+ hildon.HILDON_SIZE_AUTO_HEIGHT
+ gtk.Button.set_theme_size
+ set_button_auto_selectable = _hildon_set_button_auto_selectable
+except AttributeError:
+ set_button_auto_selectable = _null_set_button_auto_selectable
+
+
+def _hildon_set_button_finger_selectable(button):
+ button.set_theme_size(hildon.HILDON_SIZE_FINGER_HEIGHT)
+
+
+def _null_set_button_finger_selectable(button):
+ pass
+
+
+try:
+ hildon.HILDON_SIZE_FINGER_HEIGHT
+ gtk.Button.set_theme_size
+ set_button_finger_selectable = _hildon_set_button_finger_selectable
+except AttributeError:
+ set_button_finger_selectable = _null_set_button_finger_selectable
+
+
+def _hildon_set_button_thumb_selectable(button):
+ button.set_theme_size(hildon.HILDON_SIZE_THUMB_HEIGHT)
+
+
+def _null_set_button_thumb_selectable(button):
+ pass
+
+
+try:
+ hildon.HILDON_SIZE_THUMB_HEIGHT
+ gtk.Button.set_theme_size
+ set_button_thumb_selectable = _hildon_set_button_thumb_selectable
+except AttributeError:
+ set_button_thumb_selectable = _null_set_button_thumb_selectable
+
+
+def _hildon_set_cell_thumb_selectable(renderer):
+ renderer.set_property("scale", 1.5)
+
+
+def _null_set_cell_thumb_selectable(renderer):
+ pass
+
+
+if IS_HILDON_SUPPORTED:
+ set_cell_thumb_selectable = _hildon_set_cell_thumb_selectable
+else:
+ set_cell_thumb_selectable = _null_set_cell_thumb_selectable
+
+
+def _hildon_set_pix_cell_thumb_selectable(renderer):
+ renderer.set_property("stock-size", 48)
+
+
+def _null_set_pix_cell_thumb_selectable(renderer):
+ pass
+
+
+if IS_HILDON_SUPPORTED:
+ set_pix_cell_thumb_selectable = _hildon_set_pix_cell_thumb_selectable
+else:
+ set_pix_cell_thumb_selectable = _null_set_pix_cell_thumb_selectable
+
+
+def _fremantle_show_information_banner(parent, message):
+ hildon.hildon_banner_show_information(parent, "", message)
+
+
+def _hildon_show_information_banner(parent, message):
+ hildon.hildon_banner_show_information(parent, None, message)
+
+
+def _null_show_information_banner(parent, message):
+ pass
+
+
+if IS_FREMANTLE_SUPPORTED:
+ show_information_banner = _fremantle_show_information_banner
+else:
+ try:
+ hildon.hildon_banner_show_information
+ show_information_banner = _hildon_show_information_banner
+ except AttributeError:
+ show_information_banner = _null_show_information_banner
+
+
+def _fremantle_show_busy_banner_start(parent, message):
+ hildon.hildon_gtk_window_set_progress_indicator(parent, True)
+ return parent
+
+
+def _fremantle_show_busy_banner_end(banner):
+ hildon.hildon_gtk_window_set_progress_indicator(banner, False)
+
+
+def _hildon_show_busy_banner_start(parent, message):
+ return hildon.hildon_banner_show_animation(parent, None, message)
+
+
+def _hildon_show_busy_banner_end(banner):
+ banner.destroy()
+
+
+def _null_show_busy_banner_start(parent, message):
+ return None
+
+
+def _null_show_busy_banner_end(banner):
+ assert banner is None
+
+
+try:
+ hildon.hildon_gtk_window_set_progress_indicator
+ show_busy_banner_start = _fremantle_show_busy_banner_start
+ show_busy_banner_end = _fremantle_show_busy_banner_end
+except AttributeError:
+ try:
+ hildon.hildon_banner_show_animation
+ show_busy_banner_start = _hildon_show_busy_banner_start
+ show_busy_banner_end = _hildon_show_busy_banner_end
+ except AttributeError:
+ show_busy_banner_start = _null_show_busy_banner_start
+ show_busy_banner_end = _null_show_busy_banner_end
+
+
+def _hildon_hildonize_text_entry(textEntry):
+ textEntry.set_property('hildon-input-mode', 7)
+
+
+def _null_hildonize_text_entry(textEntry):
+ pass
+
+
+if IS_HILDON_SUPPORTED:
+ hildonize_text_entry = _hildon_hildonize_text_entry
+else:
+ hildonize_text_entry = _null_hildonize_text_entry
+
+
+def _hildon_window_to_portrait(window):
+ # gtk documentation is unclear whether this does a "=" or a "|="
+ flags = hildon.PORTRAIT_MODE_SUPPORT | hildon.PORTRAIT_MODE_REQUEST
+ hildon.hildon_gtk_window_set_portrait_flags(window, flags)
+
+
+def _hildon_window_to_landscape(window):
+ # gtk documentation is unclear whether this does a "=" or a "&= ~"
+ flags = hildon.PORTRAIT_MODE_SUPPORT
+ hildon.hildon_gtk_window_set_portrait_flags(window, flags)
+
+
+def _null_window_to_portrait(window):
+ pass
+
+
+def _null_window_to_landscape(window):
+ pass
+
+
+try:
+ hildon.PORTRAIT_MODE_SUPPORT
+ hildon.PORTRAIT_MODE_REQUEST
+ hildon.hildon_gtk_window_set_portrait_flags
+
+ window_to_portrait = _hildon_window_to_portrait
+ window_to_landscape = _hildon_window_to_landscape
+except AttributeError:
+ window_to_portrait = _null_window_to_portrait
+ window_to_landscape = _null_window_to_landscape
+
+
+def get_device_orientation():
+ bus = dbus.SystemBus()
+ try:
+ rawMceRequest = bus.get_object("com.nokia.mce", "/com/nokia/mce/request")
+ mceRequest = dbus.Interface(rawMceRequest, dbus_interface="com.nokia.mce.request")
+ orientation, standState, faceState, xAxis, yAxis, zAxis = mceRequest.get_device_orientation()
+ except dbus.exception.DBusException:
+ # catching for documentation purposes that when a system doesn't
+ # support this, this is what to expect
+ raise
+
+ if orientation == "":
+ return gtk.ORIENTATION_HORIZONTAL
+ elif orientation == "":
+ return gtk.ORIENTATION_VERTICAL
+ else:
+ raise RuntimeError("Unknown orientation: %s" % orientation)
+
+
+def _hildon_hildonize_password_entry(textEntry):
+ textEntry.set_property('hildon-input-mode', 7 | (1 << 29))
+
+
+def _null_hildonize_password_entry(textEntry):
+ pass
+
+
+if IS_HILDON_SUPPORTED:
+ hildonize_password_entry = _hildon_hildonize_password_entry
+else:
+ hildonize_password_entry = _null_hildonize_password_entry
+
+
+def _hildon_hildonize_combo_entry(comboEntry):
+ comboEntry.set_property('hildon-input-mode', 1 << 4)
+
+
+def _null_hildonize_combo_entry(textEntry):
+ pass
+
+
+if IS_HILDON_SUPPORTED:
+ hildonize_combo_entry = _hildon_hildonize_combo_entry
+else:
+ hildonize_combo_entry = _null_hildonize_combo_entry
+
+
+def _fremantle_hildonize_scrollwindow(scrolledWindow):
+ pannableWindow = hildon.PannableArea()
+
+ child = scrolledWindow.get_child()
+ scrolledWindow.remove(child)
+ pannableWindow.add(child)
+
+ parent = scrolledWindow.get_parent()
+ if parent is not None:
+ parent.remove(scrolledWindow)
+ parent.add(pannableWindow)
+
+ return pannableWindow
+
+
+def _hildon_hildonize_scrollwindow(scrolledWindow):
+ hildon.hildon_helper_set_thumb_scrollbar(scrolledWindow, True)
+ return scrolledWindow
+
+
+def _null_hildonize_scrollwindow(scrolledWindow):
+ return scrolledWindow
+
+
+try:
+ hildon.PannableArea
+ hildonize_scrollwindow = _fremantle_hildonize_scrollwindow
+ hildonize_scrollwindow_with_viewport = _hildon_hildonize_scrollwindow
+except AttributeError:
+ try:
+ hildon.hildon_helper_set_thumb_scrollbar
+ hildonize_scrollwindow = _hildon_hildonize_scrollwindow
+ hildonize_scrollwindow_with_viewport = _hildon_hildonize_scrollwindow
+ except AttributeError:
+ hildonize_scrollwindow = _null_hildonize_scrollwindow
+ hildonize_scrollwindow_with_viewport = _null_hildonize_scrollwindow
+
+
+def _hildon_request_number(parent, title, range, default):
+ spinner = hildon.NumberEditor(*range)
+ spinner.set_value(default)
+
+ dialog = gtk.Dialog(
+ title,
+ parent,
+ gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
+ (gtk.STOCK_OK, gtk.RESPONSE_OK, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
+ )
+ dialog.set_default_response(gtk.RESPONSE_CANCEL)
+ dialog.get_child().add(spinner)
+
+ try:
+ dialog.show_all()
+ response = dialog.run()
+
+ if response == gtk.RESPONSE_OK:
+ return spinner.get_value()
+ elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
+ raise RuntimeError("User cancelled request")
+ else:
+ raise RuntimeError("Unrecognized response %r", response)
+ finally:
+ dialog.hide()
+ dialog.destroy()
+
+
+def _null_request_number(parent, title, range, default):
+ adjustment = gtk.Adjustment(default, range[0], range[1], 1, 5, 0)
+ spinner = gtk.SpinButton(adjustment, 0, 0)
+ spinner.set_wrap(False)
+
+ dialog = gtk.Dialog(
+ title,
+ parent,
+ gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
+ (gtk.STOCK_OK, gtk.RESPONSE_OK, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
+ )
+ dialog.set_default_response(gtk.RESPONSE_CANCEL)
+ dialog.get_child().add(spinner)
+
+ try:
+ dialog.show_all()
+ response = dialog.run()
+
+ if response == gtk.RESPONSE_OK:
+ return spinner.get_value_as_int()
+ elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
+ raise RuntimeError("User cancelled request")
+ else:
+ raise RuntimeError("Unrecognized response %r", response)
+ finally:
+ dialog.hide()
+ dialog.destroy()
+
+
+try:
+ hildon.NumberEditor # TODO deprecated in fremantle
+ request_number = _hildon_request_number
+except AttributeError:
+ request_number = _null_request_number
+
+
+def _hildon_touch_selector(parent, title, items, defaultIndex):
+ model = gtk.ListStore(gobject.TYPE_STRING)
+ for item in items:
+ model.append((item, ))
+
+ selector = hildon.TouchSelector()
+ selector.append_text_column(model, True)
+ selector.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
+ selector.set_active(0, defaultIndex)
+
+ dialog = hildon.PickerDialog(parent)
+ dialog.set_selector(selector)
+
+ try:
+ dialog.show_all()
+ response = dialog.run()
+
+ if response == gtk.RESPONSE_OK:
+ return selector.get_active(0)
+ elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
+ raise RuntimeError("User cancelled request")
+ else:
+ raise RuntimeError("Unrecognized response %r", response)
+ finally:
+ dialog.hide()
+ dialog.destroy()
+
+
+def _on_null_touch_selector_activated(treeView, path, column, dialog, pathData):
+ dialog.response(gtk.RESPONSE_OK)
+ pathData[0] = path
+
+
+def _null_touch_selector(parent, title, items, defaultIndex = -1):
+ parentSize = parent.get_size()
+
+ model = gtk.ListStore(gobject.TYPE_STRING)
+ for item in items:
+ model.append((item, ))
+
+ cell = gtk.CellRendererText()
+ set_cell_thumb_selectable(cell)
+ column = gtk.TreeViewColumn(title)
+ column.pack_start(cell, expand=True)
+ column.add_attribute(cell, "text", 0)
+
+ treeView = gtk.TreeView()
+ treeView.set_model(model)
+ treeView.append_column(column)
+ selection = treeView.get_selection()
+ selection.set_mode(gtk.SELECTION_SINGLE)
+ if 0 < defaultIndex:
+ selection.select_path((defaultIndex, ))
+
+ scrolledWin = gtk.ScrolledWindow()
+ scrolledWin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ scrolledWin.add(treeView)
+
+ dialog = gtk.Dialog(
+ title,
+ parent,
+ gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
+ (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
+ )
+ dialog.set_default_response(gtk.RESPONSE_CANCEL)
+ dialog.get_child().add(scrolledWin)
+ dialog.resize(parentSize[0], max(parentSize[1]-100, 100))
+
+ scrolledWin = hildonize_scrollwindow(scrolledWin)
+ pathData = [None]
+ treeView.connect("row-activated", _on_null_touch_selector_activated, dialog, pathData)
+
+ try:
+ dialog.show_all()
+ response = dialog.run()
+
+ if response == gtk.RESPONSE_OK:
+ if pathData[0] is None:
+ raise RuntimeError("No selection made")
+ return pathData[0][0]
+ elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
+ raise RuntimeError("User cancelled request")
+ else:
+ raise RuntimeError("Unrecognized response %r", response)
+ finally:
+ dialog.hide()
+ dialog.destroy()
+
+
+try:
+ hildon.PickerDialog
+ hildon.TouchSelector
+ touch_selector = _hildon_touch_selector
+except AttributeError:
+ touch_selector = _null_touch_selector
+
+
+def _hildon_touch_selector_entry(parent, title, items, defaultItem):
+ # Got a segfault when using append_text_column with TouchSelectorEntry, so using this way
+ try:
+ selector = hildon.TouchSelectorEntry(text=True)
+ except TypeError:
+ selector = hildon.hildon_touch_selector_entry_new_text()
+ defaultIndex = -1
+ for i, item in enumerate(items):
+ selector.append_text(item)
+ if item == defaultItem:
+ defaultIndex = i
+
+ dialog = hildon.PickerDialog(parent)
+ dialog.set_selector(selector)
+
+ if 0 < defaultIndex:
+ selector.set_active(0, defaultIndex)
+ else:
+ selector.get_entry().set_text(defaultItem)
+
+ try:
+ dialog.show_all()
+ response = dialog.run()
+ finally:
+ dialog.hide()
+
+ if response == gtk.RESPONSE_OK:
+ return selector.get_entry().get_text()
+ elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
+ raise RuntimeError("User cancelled request")
+ else:
+ raise RuntimeError("Unrecognized response %r", response)
+
+
+def _on_null_touch_selector_entry_entry_changed(entry, result, selection, defaultIndex):
+ custom = entry.get_text().strip()
+ if custom:
+ result[0] = custom
+ selection.unselect_all()
+ else:
+ result[0] = None
+ selection.select_path((defaultIndex, ))
+
+
+def _on_null_touch_selector_entry_entry_activated(customEntry, dialog, result):
+ dialog.response(gtk.RESPONSE_OK)
+ result[0] = customEntry.get_text()
+
+
+def _on_null_touch_selector_entry_tree_activated(treeView, path, column, dialog, result):
+ dialog.response(gtk.RESPONSE_OK)
+ model = treeView.get_model()
+ itr = model.get_iter(path)
+ if itr is not None:
+ result[0] = model.get_value(itr, 0)
+
+
+def _null_touch_selector_entry(parent, title, items, defaultItem):
+ parentSize = parent.get_size()
+
+ model = gtk.ListStore(gobject.TYPE_STRING)
+ defaultIndex = -1
+ for i, item in enumerate(items):
+ model.append((item, ))
+ if item == defaultItem:
+ defaultIndex = i
+
+ cell = gtk.CellRendererText()
+ set_cell_thumb_selectable(cell)
+ column = gtk.TreeViewColumn(title)
+ column.pack_start(cell, expand=True)
+ column.add_attribute(cell, "text", 0)
+
+ treeView = gtk.TreeView()
+ treeView.set_model(model)
+ treeView.append_column(column)
+ selection = treeView.get_selection()
+ selection.set_mode(gtk.SELECTION_SINGLE)
+
+ scrolledWin = gtk.ScrolledWindow()
+ scrolledWin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ scrolledWin.add(treeView)
+
+ customEntry = gtk.Entry()
+
+ layout = gtk.VBox()
+ layout.pack_start(customEntry, expand=False)
+ layout.pack_start(scrolledWin)
+
+ dialog = gtk.Dialog(
+ title,
+ parent,
+ gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
+ (gtk.STOCK_OK, gtk.RESPONSE_OK, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
+ )
+ dialog.set_default_response(gtk.RESPONSE_CANCEL)
+ dialog.get_child().add(layout)
+ dialog.resize(parentSize[0], max(parentSize[1]-100, 100))
+
+ scrolledWin = hildonize_scrollwindow(scrolledWin)
+
+ result = [None]
+ if 0 < defaultIndex:
+ selection.select_path((defaultIndex, ))
+ result[0] = defaultItem
+ else:
+ customEntry.set_text(defaultItem)
+
+ customEntry.connect("activate", _on_null_touch_selector_entry_entry_activated, dialog, result)
+ customEntry.connect("changed", _on_null_touch_selector_entry_entry_changed, result, selection, defaultIndex)
+ treeView.connect("row-activated", _on_null_touch_selector_entry_tree_activated, dialog, result)
+
+ try:
+ dialog.show_all()
+ response = dialog.run()
+
+ if response == gtk.RESPONSE_OK:
+ _, itr = selection.get_selected()
+ if itr is not None:
+ return model.get_value(itr, 0)
+ else:
+ enteredText = customEntry.get_text().strip()
+ if enteredText:
+ return enteredText
+ elif result[0] is not None:
+ return result[0]
+ else:
+ raise RuntimeError("No selection made")
+ elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
+ raise RuntimeError("User cancelled request")
+ else:
+ raise RuntimeError("Unrecognized response %r", response)
+ finally:
+ dialog.hide()
+ dialog.destroy()
+
+
+try:
+ hildon.PickerDialog
+ hildon.TouchSelectorEntry
+ touch_selector_entry = _hildon_touch_selector_entry
+except AttributeError:
+ touch_selector_entry = _null_touch_selector_entry
+
+
+if __name__ == "__main__":
+ app = get_app_class()()
+
+ label = gtk.Label("Hello World from a Label!")
+
+ win = gtk.Window()
+ win.add(label)
+ win = hildonize_window(app, win)
+ if False and IS_FREMANTLE_SUPPORTED:
+ appMenu = hildon.AppMenu()
+ for i in xrange(5):
+ b = gtk.Button(str(i))
+ appMenu.append(b)
+ win.set_app_menu(appMenu)
+ win.show_all()
+ appMenu.show_all()
+ gtk.main()
+ elif False:
+ print touch_selector(win, "Test", ["A", "B", "C", "D"], 2)
+ elif False:
+ print touch_selector_entry(win, "Test", ["A", "B", "C", "D"], "C")
+ print touch_selector_entry(win, "Test", ["A", "B", "C", "D"], "Blah")
+ elif False:
+ import pprint
+ name, value = "", ""
+ goodLocals = [
+ (name, value) for (name, value) in locals().iteritems()
+ if not name.startswith("_")
+ ]
+ pprint.pprint(goodLocals)
+ elif False:
+ import time
+ show_information_banner(win, "Hello World")
+ time.sleep(5)
+ elif False:
+ import time
+ banner = show_busy_banner_start(win, "Hello World")
+ time.sleep(5)
+ show_busy_banner_end(banner)
--- /dev/null
+#!/usr/bin/python2.5
+
+import os
+import sys
+
+try:
+ import py2deb
+except ImportError:
+ import fake_py2deb as py2deb
+
+import constants
+
+
+__appname__ = constants.__app_name__
+__description__ = """
+.
+Homepage:
+"""
+__author__ = "Ed Page"
+__email__ = "eopage@byu.net"
+__version__ = constants.__version__
+__build__ = constants.__build__
+__changelog__ = """
+"""
+
+
+__postinstall__ = """#!/bin/sh -e
+
+gtk-update-icon-cache -f /usr/share/icons/hicolor
+"""
+
+
+def find_files(path):
+ for root, dirs, files in os.walk(path):
+ for file in files:
+ if file.startswith("src-"):
+ fileParts = file.split("-")
+ unused, relPathParts, newName = fileParts[0], fileParts[1:-1], fileParts[-1]
+ assert unused == "src"
+ 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",
+ "diablo": maemoSpecificDepends + ", python2.5-conic",
+ "fremantle": maemoSpecificDepends + ", python-glade2, python-alarm",
+ }[distribution]
+ p.recommends = ", ".join([
+ ])
+ p.section = {
+ "debian": "",
+ "diablo": "",
+ "fremantle": "",
+ }[distribution]
+ p.arch = "all"
+ p.urgency = "low"
+ p.distribution = "diablo fremantle debian"
+ p.repository = "extras"
+ p.changelog = __changelog__
+ p.postinstall = __postinstall__
+ p.icon = {
+ "debian": "",
+ "diablo": "",
+ "fremantle": "", # Fremantle natively uses 48x48
+ }[distribution]
+ p["/usr/bin"] = [ "" ]
+ for relPath, files in unflatten_files(find_files(".")).iteritems():
+ fullPath = ""
+ if relPath:
+ fullPath += os.sep+relPath
+ p[fullPath] = list(
+ "|".join((oldName, newName))
+ for (oldName, newName) in files
+ )
+ p["/usr/share/applications/hildon"] = [""]
+ p["/usr/share/icons/hicolor/26x26/hildon"] = [""]
+ p["/usr/share/icons/hicolor/64x64/hildon"] = [""]
+ p["/usr/share/icons/hicolor/scalable/hildon"] = [""]
+
+ if distribution == "debian":
+ print p
+ print p.generate(
+ version="%s-%s" % (__version__, __build__),
+ changelog=__changelog__,
+ build=True,
+ tar=False,
+ changes=False,
+ dsc=False,
+ )
+ print "Building for %s finished" % distribution
+ else:
+ 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])
--- /dev/null
+import pprint
+
+
+class Py2deb(object):
+
+ def __init__(self, appName):
+ self._appName = appName
+ self.description = ""
+ self.author = ""
+ self.mail = ""
+ self.license = ""
+ self.depends = ""
+ self.section = ""
+ self.arch = ""
+ self.ugency = ""
+ self.distribution = ""
+ self.repository = ""
+ self.changelog = ""
+ self.postinstall = ""
+ self.icon = ""
+ self._install = {}
+
+ def generate(self, appVersion, appBuild, changelog, tar, dsc, changes, build, src):
+ return """
+Package: %s
+version: %s-%s
+Changes:
+%s
+
+Build Options:
+ Tar: %s
+ Dsc: %s
+ Changes: %s
+ Build: %s
+ Src: %s
+ """ % (
+ self._appName, appVersion, appBuild, changelog, tar, dsc, changes, build, src
+ )
+
+ def __str__(self):
+ parts = []
+ parts.append("%s Package Settings:" % (self._appName, ))
+ for settingName in dir(self):
+ if settingName.startswith("_"):
+ continue
+ parts.append("\t%s: %s" % (settingName, getattr(self, settingName)))
+
+ parts.append(pprint.pformat(self._install))
+
+ return "\n".join(parts)
+
+ def __getitem__(self, key):
+ return self._install[key]
+
+ def __setitem__(self, key, item):
+ self._install[key] = item
--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+##
+## Copyright (C) 2009 manatlan manatlan[at]gmail(dot)com
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published
+## by the Free Software Foundation; version 2 only.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+"""
+Known limitations :
+- don't sign package (-us -uc)
+- no distinctions between author and maintainer(packager)
+
+depends on :
+- dpkg-dev (dpkg-buildpackage)
+- alien
+- python
+- fakeroot
+
+changelog
+ - ??? ?/??/20?? (By epage)
+ - PEP8
+ - added recommends
+ - fixed bug where it couldn't handle the contents of the pre/post scripts being specified
+ - Added customization based on the targeted policy for sections (Maemo support)
+ - Added maemo specific tarball, dsc, changes file generation support (including icon support)
+ - Added armel architecture
+ - Reduced the size of params being passed around by reducing the calls to locals()
+ - Added respository, distribution, priority
+ - Made setting control file a bit more flexible
+ - 0.5 05/09/2009
+ - pre/post install/remove scripts enabled
+ - deb package install py2deb in dist-packages for py2.6
+ - 0.4 14/10/2008
+ - use os.environ USERNAME or USER (debian way)
+ - install on py 2.(4,5,6) (*FIX* do better here)
+
+"""
+
+import os
+import hashlib
+import sys
+import shutil
+import time
+import string
+import StringIO
+import stat
+import commands
+import base64
+import tarfile
+from glob import glob
+from datetime import datetime
+import socket # gethostname()
+from subprocess import Popen, PIPE
+
+#~ __version__ = "0.4"
+__version__ = "0.5"
+__author__ = "manatlan"
+__mail__ = "manatlan@gmail.com"
+
+
+PERMS_URW_GRW_OR = stat.S_IRUSR | stat.S_IWUSR | \
+ stat.S_IRGRP | stat.S_IWGRP | \
+ stat.S_IROTH
+
+UID_ROOT = 0
+GID_ROOT = 0
+
+
+def run(cmds):
+ p = Popen(cmds, shell=False, stdout=PIPE, stderr=PIPE)
+ time.sleep(0.01) # to avoid "IOError: [Errno 4] Interrupted system call"
+ out = string.join(p.stdout.readlines()).strip()
+ outerr = string.join(p.stderr.readlines()).strip()
+ return out
+
+
+def deb2rpm(file):
+ txt=run(['alien', '-r', file])
+ return txt.split(" generated")[0]
+
+
+def py2src(TEMP, name):
+ l=glob("%(TEMP)s/%(name)s*.tar.gz" % locals())
+ if len(l) != 1:
+ raise Py2debException("don't find source package tar.gz")
+
+ tar = os.path.basename(l[0])
+ shutil.move(l[0], tar)
+
+ return tar
+
+
+def md5sum(filename):
+ f = open(filename, "r")
+ try:
+ return hashlib.md5(f.read()).hexdigest()
+ finally:
+ f.close()
+
+
+class Py2changes(object):
+
+ def __init__(self, ChangedBy, description, changes, files, category, repository, **kwargs):
+ self.options = kwargs # TODO: Is order important?
+ self.description = description
+ self.changes=changes
+ self.files=files
+ self.category=category
+ self.repository=repository
+ self.ChangedBy=ChangedBy
+
+ def getContent(self):
+ content = ["%s: %s" % (k, v)
+ for k,v in self.options.iteritems()]
+
+ if self.description:
+ description=self.description.replace("\n","\n ")
+ content.append('Description: ')
+ content.append(' %s' % description)
+ if self.changes:
+ changes=self.changes.replace("\n","\n ")
+ content.append('Changes: ')
+ content.append(' %s' % changes)
+ if self.ChangedBy:
+ content.append("Changed-By: %s" % self.ChangedBy)
+
+ content.append('Files:')
+
+ for onefile in self.files:
+ md5 = md5sum(onefile)
+ size = os.stat(onefile).st_size.__str__()
+ content.append(' ' + md5 + ' ' + size + ' ' + self.category +' '+self.repository+' '+os.path.basename(onefile))
+
+ return "\n".join(content) + "\n\n"
+
+
+def py2changes(params):
+ changescontent = Py2changes(
+ "%(author)s <%(mail)s>" % params,
+ "%(description)s" % params,
+ "%(changelog)s" % params,
+ (
+ "%(TEMP)s/%(name)s_%(version)s.tar.gz" % params,
+ "%(TEMP)s/%(name)s_%(version)s.dsc" % params,
+ ),
+ "%(section)s" % params,
+ "%(repository)s" % params,
+ Format='1.7',
+ Date=time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime()),
+ Source="%(name)s" % params,
+ Architecture="%(arch)s" % params,
+ Version="%(version)s" % params,
+ Distribution="%(distribution)s" % params,
+ Urgency="%(urgency)s" % params,
+ Maintainer="%(author)s <%(mail)s>" % params
+ )
+ f = open("%(TEMP)s/%(name)s_%(version)s.changes" % params,"wb")
+ f.write(changescontent.getContent())
+ f.close()
+
+ fileHandle = open('/tmp/py2deb2.tmp', 'w')
+ fileHandle.write('#!/bin/sh\n')
+ fileHandle.write("cd " +os.getcwd()+ "\n")
+ # TODO Renable signing
+ # fileHandle.write("gpg --local-user %(mail)s --clearsign %(TEMP)s/%(name)s_%(version)s.changes\n" % params)
+ fileHandle.write("mv %(TEMP)s/%(name)s_%(version)s.changes.asc %(TEMP)s/%(name)s_%(version)s.changes\n" % params)
+ fileHandle.write('\nexit')
+ fileHandle.close()
+ commands.getoutput("chmod 777 /tmp/py2deb2.tmp")
+ commands.getoutput("/tmp/py2deb2.tmp")
+
+ ret = []
+
+ l=glob("%(TEMP)s/%(name)s*.tar.gz" % params)
+ if len(l)!=1:
+ raise Py2debException("don't find source package tar.gz")
+ tar = os.path.basename(l[0])
+ shutil.move(l[0],tar)
+ ret.append(tar)
+
+ l=glob("%(TEMP)s/%(name)s*.dsc" % params)
+ if len(l)!=1:
+ raise Py2debException("don't find source package dsc")
+ tar = os.path.basename(l[0])
+ shutil.move(l[0],tar)
+ ret.append(tar)
+
+ l = glob("%(TEMP)s/%(name)s*.changes" % params)
+ if len(l)!=1:
+ raise Py2debException("don't find source package changes")
+ tar = os.path.basename(l[0])
+ shutil.move(l[0],tar)
+ ret.append(tar)
+
+ return ret
+
+
+class Py2dsc(object):
+
+ def __init__(self, StandardsVersion, BuildDepends, files, **kwargs):
+ self.options = kwargs # TODO: Is order important?
+ self.StandardsVersion = StandardsVersion
+ self.BuildDepends=BuildDepends
+ self.files=files
+
+ @property
+ def content(self):
+ content = ["%s: %s" % (k, v)
+ for k,v in self.options.iteritems()]
+
+ if self.BuildDepends:
+ content.append("Build-Depends: %s" % self.BuildDepends)
+ if self.StandardsVersion:
+ content.append("Standards-Version: %s" % self.StandardsVersion)
+
+ content.append('Files:')
+
+ for onefile in self.files:
+ print onefile
+ md5 = md5sum(onefile)
+ size = os.stat(onefile).st_size.__str__()
+ content.append(' '+md5 + ' ' + size +' '+os.path.basename(onefile))
+
+ return "\n".join(content)+"\n\n"
+
+
+def py2dsc(TEMP, name, version, depends, author, mail, arch):
+ dsccontent = Py2dsc(
+ "%(version)s" % locals(),
+ "%(depends)s" % locals(),
+ ("%(TEMP)s/%(name)s_%(version)s.tar.gz" % locals(),),
+ Format='1.0',
+ Source="%(name)s" % locals(),
+ Version="%(version)s" % locals(),
+ Maintainer="%(author)s <%(mail)s>" % locals(),
+ Architecture="%(arch)s" % locals(),
+ )
+
+ filename = "%(TEMP)s/%(name)s_%(version)s.dsc" % locals()
+
+ f = open(filename, "wb")
+ try:
+ f.write(dsccontent.content)
+ finally:
+ f.close()
+
+ fileHandle = open('/tmp/py2deb.tmp', 'w')
+ try:
+ fileHandle.write('#!/bin/sh\n')
+ fileHandle.write("cd " + os.getcwd() + "\n")
+ # TODO Renable signing
+ # fileHandle.write("gpg --local-user %(mail)s --clearsign %(TEMP)s/%(name)s_%(version)s.dsc\n" % locals())
+ fileHandle.write("mv %(TEMP)s/%(name)s_%(version)s.dsc.asc %(filename)s\n" % locals())
+ fileHandle.write('\nexit')
+ fileHandle.close()
+ finally:
+ f.close()
+
+ commands.getoutput("chmod 777 /tmp/py2deb.tmp")
+ commands.getoutput("/tmp/py2deb.tmp")
+
+ return filename
+
+
+class Py2tar(object):
+
+ def __init__(self, dataDirectoryPath):
+ self._dataDirectoryPath = dataDirectoryPath
+
+ def packed(self):
+ return self._getSourcesFiles()
+
+ def _getSourcesFiles(self):
+ directoryPath = self._dataDirectoryPath
+
+ outputFileObj = StringIO.StringIO() # TODO: Do more transparently?
+
+ tarOutput = tarfile.TarFile.open('sources',
+ mode = "w:gz",
+ fileobj = outputFileObj)
+
+ # Note: We can't use this because we need to fiddle permissions:
+ # tarOutput.add(directoryPath, arcname = "")
+
+ for root, dirs, files in os.walk(directoryPath):
+ archiveRoot = root[len(directoryPath):]
+
+ tarinfo = tarOutput.gettarinfo(root, archiveRoot)
+ # TODO: Make configurable?
+ tarinfo.uid = UID_ROOT
+ tarinfo.gid = GID_ROOT
+ tarinfo.uname = ""
+ tarinfo.gname = ""
+ tarOutput.addfile(tarinfo)
+
+ for f in files:
+ tarinfo = tarOutput.gettarinfo(os.path.join(root, f),
+ os.path.join(archiveRoot, f))
+ tarinfo.uid = UID_ROOT
+ tarinfo.gid = GID_ROOT
+ tarinfo.uname = ""
+ tarinfo.gname = ""
+ tarOutput.addfile(tarinfo, file(os.path.join(root, f)))
+
+ tarOutput.close()
+
+ data_tar_gz = outputFileObj.getvalue()
+
+ return data_tar_gz
+
+
+def py2tar(DEST, TEMP, name, version):
+ tarcontent = Py2tar("%(DEST)s" % locals())
+ filename = "%(TEMP)s/%(name)s_%(version)s.tar.gz" % locals()
+ f = open(filename, "wb")
+ try:
+ f.write(tarcontent.packed())
+ finally:
+ f.close()
+ return filename
+
+
+class Py2debException(Exception):
+ pass
+
+
+SECTIONS_BY_POLICY = {
+ # http://www.debian.org/doc/debian-policy/ch-archive.html#s-subsections
+ "debian": "admin, base, comm, contrib, devel, doc, editors, electronics, embedded, games, gnome, graphics, hamradio, interpreters, kde, libs, libdevel, mail, math, misc, net, news, non-free, oldlibs, otherosfs, perl, python, science, shells, sound, tex, text, utils, web, x11",
+ # http://maemo.org/forrest-images/pdf/maemo-policy.pdf
+ "chinook": "accessories, communication, games, multimedia, office, other, programming, support, themes, tools",
+ # http://wiki.maemo.org/Task:Package_categories
+ "diablo": "user/desktop, user/development, user/education, user/games, user/graphics, user/multimedia, user/navigation, user/network, user/office, user/science, user/system, user/utilities",
+ # http://wiki.maemo.org/Task:Fremantle_application_categories
+ "mer": "user/desktop, user/development, user/education, user/games, user/graphics, user/multimedia, user/navigation, user/network, user/office, user/science, user/system, user/utilities",
+ # http://wiki.maemo.org/Task:Fremantle_application_categories
+ "fremantle": "user/desktop, user/development, user/education, user/games, user/graphics, user/multimedia, user/navigation, user/network, user/office, user/science, user/system, user/utilities",
+}
+
+
+LICENSE_AGREEMENT = {
+ "gpl": """
+ This package is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This package is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this package; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+On Debian systems, the complete text of the GNU General
+Public License can be found in `/usr/share/common-licenses/GPL'.
+""",
+ "lgpl":"""
+ This package is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This package is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this package; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+On Debian systems, the complete text of the GNU Lesser General
+Public License can be found in `/usr/share/common-licenses/LGPL'.
+""",
+ "bsd": """
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted under the terms of the BSD License.
+
+ THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+
+On Debian systems, the complete text of the BSD License can be
+found in `/usr/share/common-licenses/BSD'.
+""",
+ "artistic": """
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the "Artistic License" which comes with Debian.
+
+ THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES
+ OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+On Debian systems, the complete text of the Artistic License
+can be found in `/usr/share/common-licenses/Artistic'.
+"""
+}
+
+
+class Py2deb(object):
+ """
+ heavily based on technic described here :
+ http://wiki.showmedo.com/index.php?title=LinuxJensMakingDeb
+ """
+ ## STATICS
+ clear = False # clear build folder after py2debianization
+
+ SECTIONS = SECTIONS_BY_POLICY["debian"]
+
+ #http://www.debian.org/doc/debian-policy/footnotes.html#f69
+ ARCHS = "all i386 ia64 alpha amd64 armeb arm hppa m32r m68k mips mipsel powerpc ppc64 s390 s390x sh3 sh3eb sh4 sh4eb sparc darwin-i386 darwin-ia64 darwin-alpha darwin-amd64 darwin-armeb darwin-arm darwin-hppa darwin-m32r darwin-m68k darwin-mips darwin-mipsel darwin-powerpc darwin-ppc64 darwin-s390 darwin-s390x darwin-sh3 darwin-sh3eb darwin-sh4 darwin-sh4eb darwin-sparc freebsd-i386 freebsd-ia64 freebsd-alpha freebsd-amd64 freebsd-armeb freebsd-arm freebsd-hppa freebsd-m32r freebsd-m68k freebsd-mips freebsd-mipsel freebsd-powerpc freebsd-ppc64 freebsd-s390 freebsd-s390x freebsd-sh3 freebsd-sh3eb freebsd-sh4 freebsd-sh4eb freebsd-sparc kfreebsd-i386 kfreebsd-ia64 kfreebsd-alpha kfreebsd-amd64 kfreebsd-armeb kfreebsd-arm kfreebsd-hppa kfreebsd-m32r kfreebsd-m68k kfreebsd-mips kfreebsd-mipsel kfreebsd-powerpc kfreebsd-ppc64 kfreebsd-s390 kfreebsd-s390x kfreebsd-sh3 kfreebsd-sh3eb kfreebsd-sh4 kfreebsd-sh4eb kfreebsd-sparc knetbsd-i386 knetbsd-ia64 knetbsd-alpha knetbsd-amd64 knetbsd-armeb knetbsd-arm knetbsd-hppa knetbsd-m32r knetbsd-m68k knetbsd-mips knetbsd-mipsel knetbsd-powerpc knetbsd-ppc64 knetbsd-s390 knetbsd-s390x knetbsd-sh3 knetbsd-sh3eb knetbsd-sh4 knetbsd-sh4eb knetbsd-sparc netbsd-i386 netbsd-ia64 netbsd-alpha netbsd-amd64 netbsd-armeb netbsd-arm netbsd-hppa netbsd-m32r netbsd-m68k netbsd-mips netbsd-mipsel netbsd-powerpc netbsd-ppc64 netbsd-s390 netbsd-s390x netbsd-sh3 netbsd-sh3eb netbsd-sh4 netbsd-sh4eb netbsd-sparc openbsd-i386 openbsd-ia64 openbsd-alpha openbsd-amd64 openbsd-armeb openbsd-arm openbsd-hppa openbsd-m32r openbsd-m68k openbsd-mips openbsd-mipsel openbsd-powerpc openbsd-ppc64 openbsd-s390 openbsd-s390x openbsd-sh3 openbsd-sh3eb openbsd-sh4 openbsd-sh4eb openbsd-sparc hurd-i386 hurd-ia64 hurd-alpha hurd-amd64 hurd-armeb hurd-arm hurd-hppa hurd-m32r hurd-m68k hurd-mips hurd-mipsel hurd-powerpc hurd-ppc64 hurd-s390 hurd-s390x hurd-sh3 hurd-sh3eb hurd-sh4 hurd-sh4eb hurd-sparc armel".split(" ")
+
+ # license terms taken from dh_make
+ LICENSES = list(LICENSE_AGREEMENT.iterkeys())
+
+ def __setitem__(self, path, files):
+
+ if not type(files)==list:
+ raise Py2debException("value of key path '%s' is not a list"%path)
+ if not files:
+ raise Py2debException("value of key path '%s' should'nt be empty"%path)
+ if not path.startswith("/"):
+ raise Py2debException("key path '%s' malformed (don't start with '/')"%path)
+ if path.endswith("/"):
+ raise Py2debException("key path '%s' malformed (shouldn't ends with '/')"%path)
+
+ nfiles=[]
+ for file in files:
+
+ if ".." in file:
+ raise Py2debException("file '%s' contains '..', please avoid that!"%file)
+
+
+ if "|" in file:
+ if file.count("|")!=1:
+ raise Py2debException("file '%s' is incorrect (more than one pipe)"%file)
+
+ file, nfile = file.split("|")
+ else:
+ nfile=file # same localisation
+
+ if os.path.isdir(file):
+ raise Py2debException("file '%s' is a folder, and py2deb refuse folders !"%file)
+
+ if not os.path.isfile(file):
+ raise Py2debException("file '%s' doesn't exist"%file)
+
+ if file.startswith("/"): # if an absolute file is defined
+ if file==nfile: # and not renamed (pipe trick)
+ nfile=os.path.basename(file) # it's simply copied to 'path'
+
+ nfiles.append((file, nfile))
+
+ nfiles.sort(lambda a, b: cmp(a[1], b[1])) #sort according new name (nfile)
+
+ self.__files[path]=nfiles
+
+ def __delitem__(self, k):
+ del self.__files[k]
+
+ def __init__(self,
+ name,
+ description="no description",
+ license="gpl",
+ depends="",
+ section="utils",
+ arch="all",
+
+ url="",
+ author = None,
+ mail = None,
+
+ preinstall = None,
+ postinstall = None,
+ preremove = None,
+ postremove = None
+ ):
+
+ if author is None:
+ author = ("USERNAME" in os.environ) and os.environ["USERNAME"] or None
+ if author is None:
+ author = ("USER" in os.environ) and os.environ["USER"] or "unknown"
+
+ if mail is None:
+ mail = author+"@"+socket.gethostname()
+
+ self.name = name
+ self.prettyName = ""
+ self.description = description
+ self.upgradeDescription = ""
+ self.bugTracker = ""
+ self.license = license
+ self.depends = depends
+ self.recommends = ""
+ self.section = section
+ self.arch = arch
+ self.url = url
+ self.author = author
+ self.mail = mail
+ self.icon = ""
+ self.distribution = ""
+ self.respository = ""
+ self.urgency = "low"
+
+ self.preinstall = preinstall
+ self.postinstall = postinstall
+ self.preremove = preremove
+ self.postremove = postremove
+
+ self.__files={}
+
+ def __repr__(self):
+ name = self.name
+ license = self.license
+ description = self.description
+ depends = self.depends
+ recommends = self.recommends
+ section = self.section
+ arch = self.arch
+ url = self.url
+ author = self.author
+ mail = self.mail
+
+ preinstall = self.preinstall
+ postinstall = self.postinstall
+ preremove = self.preremove
+ postremove = self.postremove
+
+ paths=self.__files.keys()
+ paths.sort()
+ files=[]
+ for path in paths:
+ for file, nfile in self.__files[path]:
+ #~ rfile=os.path.normpath(os.path.join(path, nfile))
+ rfile=os.path.join(path, nfile)
+ if nfile==file:
+ files.append(rfile)
+ else:
+ files.append(rfile + " (%s)"%file)
+
+ files.sort()
+ files = "\n".join(files)
+
+
+ lscripts = [ preinstall and "preinst",
+ postinstall and "postinst",
+ preremove and "prerm",
+ postremove and "postrm",
+ ]
+ scripts = lscripts and ", ".join([i for i in lscripts if i]) or "None"
+ return """
+----------------------------------------------------------------------
+NAME : %(name)s
+----------------------------------------------------------------------
+LICENSE : %(license)s
+URL : %(url)s
+AUTHOR : %(author)s
+MAIL : %(mail)s
+----------------------------------------------------------------------
+DEPENDS : %(depends)s
+RECOMMENDS : %(recommends)s
+ARCH : %(arch)s
+SECTION : %(section)s
+----------------------------------------------------------------------
+DESCRIPTION :
+%(description)s
+----------------------------------------------------------------------
+SCRIPTS : %(scripts)s
+----------------------------------------------------------------------
+FILES :
+%(files)s
+""" % locals()
+
+ def generate(self, version, changelog="", rpm=False, src=False, build=True, tar=False, changes=False, dsc=False):
+ """ generate a deb of version 'version', with or without 'changelog', with or without a rpm
+ (in the current folder)
+ return a list of generated files
+ """
+ if not sum([len(i) for i in self.__files.values()])>0:
+ raise Py2debException("no files are defined")
+
+ if not changelog:
+ changelog="* no changelog"
+
+ name = self.name
+ description = self.description
+ license = self.license
+ depends = self.depends
+ recommends = self.recommends
+ section = self.section
+ arch = self.arch
+ url = self.url
+ distribution = self.distribution
+ repository = self.repository
+ urgency = self.urgency
+ author = self.author
+ mail = self.mail
+ files = self.__files
+ preinstall = self.preinstall
+ postinstall = self.postinstall
+ preremove = self.preremove
+ postremove = self.postremove
+
+ if section not in Py2deb.SECTIONS:
+ raise Py2debException("section '%s' is unknown (%s)" % (section, str(Py2deb.SECTIONS)))
+
+ if arch not in Py2deb.ARCHS:
+ raise Py2debException("arch '%s' is unknown (%s)"% (arch, str(Py2deb.ARCHS)))
+
+ if license not in Py2deb.LICENSES:
+ raise Py2debException("License '%s' is unknown (%s)" % (license, str(Py2deb.LICENSES)))
+
+ # create dates (buildDate, buildDateYear)
+ d=datetime.now()
+ buildDate=d.strftime("%a, %d %b %Y %H:%M:%S +0000")
+ buildDateYear=str(d.year)
+
+ #clean description (add a space before each next lines)
+ description=description.replace("\r", "").strip()
+ description = "\n ".join(description.split("\n"))
+
+ #clean changelog (add 2 spaces before each next lines)
+ changelog=changelog.replace("\r", "").strip()
+ changelog = "\n ".join(changelog.split("\n"))
+
+ TEMP = ".py2deb_build_folder"
+ DEST = os.path.join(TEMP, name)
+ DEBIAN = os.path.join(DEST, "debian")
+
+ packageContents = locals()
+
+ # let's start the process
+ try:
+ shutil.rmtree(TEMP)
+ except:
+ pass
+
+ os.makedirs(DEBIAN)
+ try:
+ rules=[]
+ dirs=[]
+ for path in files:
+ for ofile, nfile in files[path]:
+ if os.path.isfile(ofile):
+ # it's a file
+
+ if ofile.startswith("/"): # if absolute path
+ # we need to change dest
+ dest=os.path.join(DEST, nfile)
+ else:
+ dest=os.path.join(DEST, ofile)
+
+ # copy file to be packaged
+ destDir = os.path.dirname(dest)
+ if not os.path.isdir(destDir):
+ os.makedirs(destDir)
+
+ shutil.copy2(ofile, dest)
+
+ ndir = os.path.join(path, os.path.dirname(nfile))
+ nname = os.path.basename(nfile)
+
+ # make a line RULES to be sure the destination folder is created
+ # and one for copying the file
+ fpath = "/".join(["$(CURDIR)", "debian", name+ndir])
+ rules.append('mkdir -p "%s"' % fpath)
+ rules.append('cp -a "%s" "%s"' % (ofile, os.path.join(fpath, nname)))
+
+ # append a dir
+ dirs.append(ndir)
+
+ else:
+ raise Py2debException("unknown file '' "%ofile) # shouldn't be raised (because controlled before)
+
+ # make rules right
+ rules= "\n\t".join(rules) + "\n"
+ packageContents["rules"] = rules
+
+ # make dirs right
+ dirs= [i[1:] for i in set(dirs)]
+ dirs.sort()
+
+ #==========================================================================
+ # CREATE debian/dirs
+ #==========================================================================
+ open(os.path.join(DEBIAN, "dirs"), "w").write("\n".join(dirs))
+
+ #==========================================================================
+ # CREATE debian/changelog
+ #==========================================================================
+ clog="""%(name)s (%(version)s) stable; urgency=low
+
+ %(changelog)s
+
+ -- %(author)s <%(mail)s> %(buildDate)s
+""" % packageContents
+
+ open(os.path.join(DEBIAN, "changelog"), "w").write(clog)
+
+ #==========================================================================
+ #Create pre/post install/remove
+ #==========================================================================
+ def mkscript(name, dest):
+ if name and name.strip()!="":
+ if os.path.isfile(name): # it's a file
+ content = file(name).read()
+ else: # it's a script
+ content = name
+ open(os.path.join(DEBIAN, dest), "w").write(content)
+
+ mkscript(preinstall, "preinst")
+ mkscript(postinstall, "postinst")
+ mkscript(preremove, "prerm")
+ mkscript(postremove, "postrm")
+
+
+ #==========================================================================
+ # CREATE debian/compat
+ #==========================================================================
+ open(os.path.join(DEBIAN, "compat"), "w").write("5\n")
+
+ #==========================================================================
+ # CREATE debian/control
+ #==========================================================================
+ generalParagraphFields = [
+ "Source: %(name)s",
+ "Maintainer: %(author)s <%(mail)s>",
+ "Section: %(section)s",
+ "Priority: extra",
+ "Build-Depends: debhelper (>= 5)",
+ "Standards-Version: 3.7.2",
+ ]
+
+ specificParagraphFields = [
+ "Package: %(name)s",
+ "Architecture: %(arch)s",
+ "Depends: %(depends)s",
+ "Recommends: %(recommends)s",
+ "Description: %(description)s",
+ ]
+
+ if self.prettyName:
+ prettyName = "XSBC-Maemo-Display-Name: %s" % self.prettyName.strip()
+ specificParagraphFields.append("\n ".join(prettyName.split("\n")))
+
+ if self.bugTracker:
+ bugTracker = "XSBC-Bugtracker: %s" % self.bugTracker.strip()
+ specificParagraphFields.append("\n ".join(bugTracker.split("\n")))
+
+ if self.upgradeDescription:
+ upgradeDescription = "XSBC-Maemo-Upgrade-Description: %s" % self.upgradeDescription.strip()
+ specificParagraphFields.append("\n ".join(upgradeDescription.split("\n")))
+
+ if self.icon:
+ f = open(self.icon, "rb")
+ try:
+ rawIcon = f.read()
+ finally:
+ f.close()
+ uueIcon = base64.b64encode(rawIcon)
+ uueIconLines = []
+ for i, c in enumerate(uueIcon):
+ if i % 60 == 0:
+ uueIconLines.append("")
+ uueIconLines[-1] += c
+ uueIconLines[0:0] = ("XSBC-Maemo-Icon-26:", )
+ specificParagraphFields.append("\n ".join(uueIconLines))
+
+ generalParagraph = "\n".join(generalParagraphFields)
+ specificParagraph = "\n".join(specificParagraphFields)
+ controlContent = "\n\n".join((generalParagraph, specificParagraph)) % packageContents
+ open(os.path.join(DEBIAN, "control"), "w").write(controlContent)
+
+ #==========================================================================
+ # CREATE debian/copyright
+ #==========================================================================
+ packageContents["txtLicense"] = LICENSE_AGREEMENT[license]
+ packageContents["pv"] =__version__
+ txt="""This package was py2debianized(%(pv)s) by %(author)s <%(mail)s> on
+%(buildDate)s.
+
+It was downloaded from %(url)s
+
+Upstream Author: %(author)s <%(mail)s>
+
+Copyright: %(buildDateYear)s by %(author)s
+
+License:
+
+%(txtLicense)s
+
+The Debian packaging is (C) %(buildDateYear)s, %(author)s <%(mail)s> and
+is licensed under the GPL, see above.
+
+
+# Please also look if there are files or directories which have a
+# different copyright/license attached and list them here.
+""" % packageContents
+ open(os.path.join(DEBIAN, "copyright"), "w").write(txt)
+
+ #==========================================================================
+ # CREATE debian/rules
+ #==========================================================================
+ txt="""#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+
+
+
+CFLAGS = -Wall -g
+
+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+ CFLAGS += -O0
+else
+ CFLAGS += -O2
+endif
+
+configure: configure-stamp
+configure-stamp:
+ dh_testdir
+ # Add here commands to configure the package.
+
+ touch configure-stamp
+
+
+build: build-stamp
+
+build-stamp: configure-stamp
+ dh_testdir
+ touch build-stamp
+
+clean:
+ dh_testdir
+ dh_testroot
+ rm -f build-stamp configure-stamp
+ dh_clean
+
+install: build
+ dh_testdir
+ dh_testroot
+ dh_clean -k
+ dh_installdirs
+
+ # ======================================================
+ #$(MAKE) DESTDIR="$(CURDIR)/debian/%(name)s" install
+ mkdir -p "$(CURDIR)/debian/%(name)s"
+
+ %(rules)s
+ # ======================================================
+
+# Build architecture-independent files here.
+binary-indep: build install
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: build install
+ dh_testdir
+ dh_testroot
+ dh_installchangelogs debian/changelog
+ dh_installdocs
+ dh_installexamples
+# dh_install
+# dh_installmenu
+# dh_installdebconf
+# dh_installlogrotate
+# dh_installemacsen
+# dh_installpam
+# dh_installmime
+# dh_python
+# dh_installinit
+# dh_installcron
+# dh_installinfo
+ dh_installman
+ dh_link
+ dh_strip
+ dh_compress
+ dh_fixperms
+# dh_perl
+# dh_makeshlibs
+ dh_installdeb
+ dh_shlibdeps
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install configure
+""" % packageContents
+ open(os.path.join(DEBIAN, "rules"), "w").write(txt)
+ os.chmod(os.path.join(DEBIAN, "rules"), 0755)
+
+ ###########################################################################
+ ###########################################################################
+ ###########################################################################
+
+ generatedFiles = []
+
+ if build:
+ #http://www.debian.org/doc/manuals/maint-guide/ch-build.fr.html
+ ret = os.system('cd "%(DEST)s"; dpkg-buildpackage -tc -rfakeroot -us -uc' % packageContents)
+ if ret != 0:
+ raise Py2debException("buildpackage failed (see output)")
+
+ l=glob("%(TEMP)s/%(name)s*.deb" % packageContents)
+ if len(l) != 1:
+ raise Py2debException("didn't find builded deb")
+
+ tdeb = l[0]
+ deb = os.path.basename(tdeb)
+ shutil.move(tdeb, deb)
+
+ generatedFiles = [deb, ]
+
+ if rpm:
+ rpmFilename = deb2rpm(deb)
+ generatedFiles.append(rpmFilename)
+
+ if src:
+ tarFilename = py2src(TEMP, name)
+ generatedFiles.append(tarFilename)
+
+ if tar:
+ tarFilename = py2tar(DEST, TEMP, name, version)
+ generatedFiles.append(tarFilename)
+
+ if dsc:
+ dscFilename = py2dsc(TEMP, name, version, depends, author, mail, arch)
+ generatedFiles.append(dscFilename)
+
+ if changes:
+ changesFilenames = py2changes(packageContents)
+ generatedFiles.extend(changesFilenames)
+
+ return generatedFiles
+
+ #~ except Exception,m:
+ #~ raise Py2debException("build error :"+str(m))
+
+ finally:
+ if Py2deb.clear:
+ shutil.rmtree(TEMP)
+
+
+if __name__ == "__main__":
+ try:
+ os.chdir(os.path.dirname(sys.argv[0]))
+ except:
+ pass
+
+ p=Py2deb("python-py2deb")
+ p.description="Generate simple deb(/rpm/tgz) from python (2.4, 2.5 and 2.6)"
+ p.url = "http://www.manatlan.com/page/py2deb"
+ p.author=__author__
+ p.mail=__mail__
+ p.depends = "dpkg-dev, fakeroot, alien, python"
+ p.section="python"
+ p["/usr/lib/python2.6/dist-packages"] = ["py2deb.py", ]
+ p["/usr/lib/python2.5/site-packages"] = ["py2deb.py", ]
+ p["/usr/lib/python2.4/site-packages"] = ["py2deb.py", ]
+ #~ p.postinstall = "s.py"
+ #~ p.preinstall = "s.py"
+ #~ p.postremove = "s.py"
+ #~ p.preremove = "s.py"
+ print p
+ print p.generate(__version__, changelog = __doc__, src=True)
--- /dev/null
+# 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'
--- /dev/null
+#!/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);
--- /dev/null
+#!/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);
--- /dev/null
+#!/usr/bin/env python
+
+
+from __future__ import with_statement
+
+import inspect
+import contextlib
+import functools
+
+
+def TODO(func):
+ """
+ unittest test method decorator that ignores
+ exceptions raised by test
+
+ Used to annotate test methods for code that may
+ not be written yet. Ignores failures in the
+ annotated test method; fails if the text
+ unexpectedly succeeds.
+ !author http://kbyanc.blogspot.com/2007/06/pythons-unittest-module-aint-that-bad.html
+
+ Example:
+ >>> import unittest
+ >>> class ExampleTestCase(unittest.TestCase):
+ ... @TODO
+ ... def testToDo(self):
+ ... MyModule.DoesNotExistYet('boo')
+ ...
+ """
+
+ @functools.wraps(func)
+ def wrapper(*args, **kw):
+ try:
+ func(*args, **kw)
+ succeeded = True
+ except:
+ succeeded = False
+ assert succeeded is False, \
+ "%s marked TODO but passed" % func.__name__
+ return wrapper
+
+
+def PlatformSpecific(platformList):
+ """
+ unittest test method decorator that only
+ runs test method if os.name is in the
+ given list of platforms
+ !author http://kbyanc.blogspot.com/2007/06/pythons-unittest-module-aint-that-bad.html
+ Example:
+ >>> import unittest
+ >>> class ExampleTestCase(unittest.TestCase):
+ ... @PlatformSpecific(('mac', ))
+ ... def testMacOnly(self):
+ ... MyModule.SomeMacSpecificFunction()
+ ...
+ """
+
+ def decorator(func):
+ import os
+
+ @functools.wraps(func)
+ def wrapper(*args, **kw):
+ if os.name in platformList:
+ return func(*args, **kw)
+ return wrapper
+ return decorator
+
+
+def CheckReferences(func):
+ """
+ !author http://kbyanc.blogspot.com/2007/06/pythons-unittest-module-aint-that-bad.html
+ """
+
+ @functools.wraps(func)
+ def wrapper(*args, **kw):
+ refCounts = []
+ for i in range(5):
+ func(*args, **kw)
+ refCounts.append(XXXGetRefCount())
+ assert min(refCounts) != max(refCounts), "Reference counts changed - %r" % refCounts
+
+ return wrapper
+
+
+@contextlib.contextmanager
+def expected(exception):
+ """
+ >>> with expected2(ZeroDivisionError):
+ ... 1 / 0
+ >>> with expected2(AssertionError("expected ZeroDivisionError to have been thrown")):
+ ... with expected(ZeroDivisionError):
+ ... 1 / 2
+ Traceback (most recent call last):
+ File "/usr/lib/python2.5/doctest.py", line 1228, in __run
+ compileflags, 1) in test.globs
+ File "<doctest libraries.recipes.context.expected[1]>", line 3, in <module>
+ 1 / 2
+ File "/media/data/Personal/Development/bzr/Recollection-trunk/src/libraries/recipes/context.py", line 139, in __exit__
+ assert t is not None, ("expected {0:%s} to have been thrown" % (self._t.__name__))
+ AssertionError: expected {0:ZeroDivisionError} to have been thrown
+ >>> with expected2(Exception("foo")):
+ ... raise Exception("foo")
+ >>> with expected2(Exception("bar")):
+ ... with expected(Exception("foo")): # this won't catch it
+ ... raise Exception("bar")
+ ... assert False, "should not see me"
+ >>> with expected2(Exception("can specify")):
+ ... raise Exception("can specify prefixes")
+ >>> with expected2(Exception("Base class fun")):
+ True
+ >>> True
+ False
+ """
+ if isinstance(exception, Exception):
+ excType, excValue = type(exception), str(exception)
+ elif isinstance(exception, type):
+ excType, excValue = exception, ""
+
+ try:
+ yield
+ except Exception, e:
+ if not (excType in inspect.getmro(type(e)) and str(e).startswith(excValue)):
+ raise
+ else:
+ raise AssertionError("expected {0:%s} to have been thrown" % excType.__name__)
+
+
+if __name__ == "__main__":
+ import doctest
+ doctest.testmod()
--- /dev/null
+<html>
+ <head>
+ <title></title>
+ </head>
+ <body>
+ <h1>
+ </h1>
+ <h2></h2>
+ <h3><a href="index.html">[About]</a> <a href="screenshots.html">[Screenshots]</a> <a href="download.html">[Download]</a>
+ <h3>Download</h3>
+
+ <h4>Packages</h4>
+ <p>Maemo 5 and Later: Go to the application installer, enable Extras, and download</p>
+
+ <p>Maemo 4.1 and Earlier: Add the <a href="http://wiki.maemo.org/Extras">Extras Repository</a> and check the App Manager</p>
+
+ <p>Linux: <a href="">.deb files</a></p>
+
+ <h3>Development</h3>
+ <h4>Source</h4>
+ <p>For the most up to date version check out <a href="">git</a>.
+ </p>
+ <p>Requires</p>
+ <ul>
+ <li>PyGTK / Glade</li>
+ <li>Python bindings for hildon, osso, dbus, and conic</li>
+ </ul>
+
+ <h4>Bugs</h4>
+
+ <p>Discuss your issue on <a href="">Maemo.Org Talk</a></p>
+
+ <p>File a <a href="">bug report</a></p>
+ <p>View <a href="">existing bug reports</a></p>
+ </body>
+</html>
--- /dev/null
+<html>
+ <head>
+ <title></title>
+ </head>
+ <body>
+ <h1>
+ </h1>
+ <h2></h2>
+
+ <h3><a href="">[About]</a> <a href="screenshots.html">[Screenshots]</a> <a href="download.html">[Download]</a>
+
+ <h3>About</h3>
+ <p>
+ </p>
+
+
+ <p>This has been tested on Maemo 5, Maemo 4.1, and Ubuntu 9.04. Go check out some <a href="">reviews</a> or join the <a href="">conversation</a></p>
+
+ <p>This is Free Software and available under the <a href="http://www.gnu.org/licenses/lgpl-2.1.html">LGPLv2.1</a>.
+
+ <h4>Features</h4>
+
+ <p>(See <a href="">Maemo.Org Talk</a>)</p>
+
+ <ul>
+ <li></li>
+ </ul>
+
+ </body>
+</html>
--- /dev/null
+<html>
+ <head>
+ <title></title>
+ </head>
+ <body>
+ <h1>
+ </h1>
+ <h2></h2>
+ <h3><a href="index.html">[About]</a> <a href="screenshots.html">[Screenshots]</a> <a href="download.html">[Download]</a>
+
+ <h3>Screen shots</h3>
+
+ </body>
+</html>