Merge lp:~dobey/ubuntu/natty/ubuntuone-dev-tools/devtools-012 into lp:ubuntu/natty/ubuntuone-dev-tools

Proposed by dobey
Status: Merged
Merged at revision: 3
Proposed branch: lp:~dobey/ubuntu/natty/ubuntuone-dev-tools/devtools-012
Merge into: lp:ubuntu/natty/ubuntuone-dev-tools
Diff against target: 1346 lines (+649/-290)
17 files modified
MANIFEST.in (+1/-1)
PKG-INFO (+1/-1)
bin/u1lint (+56/-49)
bin/u1trial (+107/-55)
debian/changelog (+11/-0)
debian/control (+12/-6)
debian/rules (+1/-1)
debian/watch (+1/-1)
pylintrc (+223/-36)
run-tests (+23/-0)
setup.py (+9/-9)
ubuntuone/devtools/__init__.py (+0/-1)
ubuntuone/devtools/dbus_util.py (+0/-89)
ubuntuone/devtools/handlers.py (+64/-0)
ubuntuone/devtools/services/__init__.py (+1/-0)
ubuntuone/devtools/services/dbus.py (+94/-0)
ubuntuone/devtools/testcase.py (+45/-41)
To merge this branch: bzr merge lp:~dobey/ubuntu/natty/ubuntuone-dev-tools/devtools-012
Reviewer Review Type Date Requested Status
Daniel Holbach (community) Approve
Ubuntu branches Pending
Review via email: mp+42295@code.launchpad.net

Description of the change

* New upstream release.
* Fix debian/watch to use the right file extension.
* Remove python-oauth as a dependency.
* Update build and runtime dependencies.
* Require pep8 to run tests during build.
* Use ./run-tests during the build instead of setup.py lint to run tests.

To post a comment you must log in.
Revision history for this message
Daniel Holbach (dholbach) wrote :

Good work.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'MANIFEST.in'
--- MANIFEST.in 2010-08-02 13:45:54 +0000
+++ MANIFEST.in 2010-11-30 19:41:01 +0000
@@ -1,4 +1,4 @@
1include MANIFEST.in1include MANIFEST.in
2include COPYING pylintrc2include COPYING pylintrc run-tests
3recursive-include data *.conf3recursive-include data *.conf
4recursive-include man *.14recursive-include man *.1
55
=== modified file 'PKG-INFO'
--- PKG-INFO 2010-08-02 13:45:54 +0000
+++ PKG-INFO 2010-11-30 19:41:01 +0000
@@ -1,6 +1,6 @@
1Metadata-Version: 1.01Metadata-Version: 1.0
2Name: ubuntuone-dev-tools2Name: ubuntuone-dev-tools
3Version: 0.1.13Version: 0.1.2
4Summary: Ubuntu One development tools and utilities4Summary: Ubuntu One development tools and utilities
5Home-page: http://launchpad.net/ubuntuone-dev-tools5Home-page: http://launchpad.net/ubuntuone-dev-tools
6Author: UNKNOWN6Author: UNKNOWN
77
=== modified file 'bin/u1lint'
--- bin/u1lint 2010-08-02 13:45:54 +0000
+++ bin/u1lint 2010-11-30 19:41:01 +0000
@@ -6,18 +6,19 @@
6#6#
7# Copyright 2009-2010 Canonical Ltd.7# Copyright 2009-2010 Canonical Ltd.
8#8#
9# This program is free software: you can redistribute it and/or modify it 9# This program is free software: you can redistribute it and/or modify it
10# under the terms of the GNU General Public License version 3, as published 10# under the terms of the GNU General Public License version 3, as published
11# by the Free Software Foundation.11# by the Free Software Foundation.
12#12#
13# This program is distributed in the hope that it will be useful, but 13# This program is distributed in the hope that it will be useful, but
14# WITHOUT ANY WARRANTY; without even the implied warranties of 14# WITHOUT ANY WARRANTY; without even the implied warranties of
15# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 15# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
16# PURPOSE. See the GNU General Public License for more details.16# PURPOSE. See the GNU General Public License for more details.
17#17#
18# You should have received a copy of the GNU General Public License along 18# You should have received a copy of the GNU General Public License along
19# with this program. If not, see <http://www.gnu.org/licenses/>.19# with this program. If not, see <http://www.gnu.org/licenses/>.
20"""Wrapper script for pylint command"""20
21"""Wrapper script for pylint command."""
2122
22import ConfigParser23import ConfigParser
23import os24import os
@@ -104,45 +105,51 @@
104 return pyfiles105 return pyfiles
105106
106107
107failed = False108def main():
108109 """Do the deed."""
109ignored = _read_pylintrc_ignored()110 failed = False
110111 ignored = _read_pylintrc_ignored()
111# So that we can match the path correctly112
112if ignored:113 # So that we can match the path correctly
113 moreignores = [os.path.join(SRCDIR, item) for item in ignored]114 if ignored:
114 ignored.extend(moreignores)115 moreignores = [os.path.join(SRCDIR, item) for item in ignored]
115else:116 ignored.extend(moreignores)
116 ignored = []117 else:
117118 ignored = []
118if os.environ.get('USE_PYFLAKES'):119
119 pylint_args = ["pyflakes"]120 if os.environ.get('USE_PYFLAKES'):
120else:121 pylint_args = ["pyflakes"]
121 pylint_args = ["pylint",122 else:
122 "--output-format=parseable",123 pylint_args = ["pylint",
123 "--include-ids=yes",]124 "--output-format=parseable",
124 if PYLINTRC:125 "--include-ids=yes",]
125 pylint_args.append("--rcfile=" + PYLINTRC)126 if PYLINTRC:
126 127 pylint_args.append("--rcfile=" + PYLINTRC)
127for path in _find_files():128
128 if path not in ignored and not path.startswith(os.path.join(SRCDIR,129 for path in _find_files():
129 "_build")):130 is_build = path.startswith(os.path.join(SRCDIR, "_build"))
130 pylint_args.append(path)131 if path not in ignored and not is_build:
131132 pylint_args.append(path)
132p = subprocess.Popen(pylint_args,133
133 bufsize=4096, stdout=subprocess.PIPE)134 sp = subprocess.Popen(pylint_args,
134notices = p.stdout135 bufsize=4096, stdout=subprocess.PIPE)
135136 notices = sp.stdout
136output = "".join(notices.readlines())137
137if output != "":138 output = "".join(notices.readlines())
138 print "== Python Lint Notices =="139 if output != "":
139 (failed, grouped) = _group_lines_by_file(output)140 print "== Python Lint Notices =="
140 print grouped141 (failed, grouped) = _group_lines_by_file(output)
141 print ""142 print grouped
142143 print ""
143returncode = p.wait()144
144if returncode != 0:145 returncode = sp.wait()
145 exit(returncode)146 # XXX Testing that W0511 does not cause a failure
146147 if failed:
147if failed:148 if returncode != 0:
148 exit(1)149 exit(returncode)
150 else:
151 exit(1)
152
153
154if __name__ == '__main__':
155 main()
149156
=== modified file 'bin/u1trial'
--- bin/u1trial 2010-08-02 13:45:54 +0000
+++ bin/u1trial 2010-11-30 19:41:01 +0000
@@ -6,38 +6,78 @@
6#6#
7# Copyright 2009-2010 Canonical Ltd.7# Copyright 2009-2010 Canonical Ltd.
8#8#
9# This program is free software: you can redistribute it and/or modify it 9# This program is free software: you can redistribute it and/or modify it
10# under the terms of the GNU General Public License version 3, as published 10# under the terms of the GNU General Public License version 3, as published
11# by the Free Software Foundation.11# by the Free Software Foundation.
12#12#
13# This program is distributed in the hope that it will be useful, but 13# This program is distributed in the hope that it will be useful, but
14# WITHOUT ANY WARRANTY; without even the implied warranties of 14# WITHOUT ANY WARRANTY; without even the implied warranties of
15# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 15# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
16# PURPOSE. See the GNU General Public License for more details.16# PURPOSE. See the GNU General Public License for more details.
17#17#
18# You should have received a copy of the GNU General Public License along 18# You should have received a copy of the GNU General Public License along
19# with this program. If not, see <http://www.gnu.org/licenses/>.19# with this program. If not, see <http://www.gnu.org/licenses/>.
20
20"""Test runner that uses a private dbus session and glib main loop."""21"""Test runner that uses a private dbus session and glib main loop."""
2122
23import coverage
24import gc
25import inspect
22import os26import os
23import re27import re
24import sys28import sys
25import unittest29import unittest
2630
31from twisted.trial.runner import TrialRunner
32
27sys.path.insert(0, os.path.abspath("."))33sys.path.insert(0, os.path.abspath("."))
2834
29# pylint: disable=W0212
3035
31class TestRunner(object):36class TestRunner(TrialRunner):
32 """The test runner implementation."""37 """The test runner implementation."""
3338
39 def __init__(self):
40 # install the glib2reactor before any import of the reactor to avoid
41 # using the default SelectReactor and be able to run the dbus tests
42 from twisted.internet import glib2reactor
43 glib2reactor.install()
44 from twisted.trial.reporter import TreeReporter
45
46 # setup a custom XDG_CACHE_HOME and create the logs directory
47 xdg_cache = os.path.join(os.getcwd(), "_trial_temp", "xdg_cache")
48 os.environ["XDG_CACHE_HOME"] = xdg_cache
49 # setup the ROOTDIR env var
50 os.environ['ROOTDIR'] = os.getcwd()
51 if not os.path.exists(xdg_cache):
52 os.makedirs(xdg_cache)
53
54 self.tempdir = os.path.join(os.getcwd(), "_trial_temp")
55 working_dir = os.path.join(self.tempdir, 'tmp')
56 super(TestRunner, self).__init__(reporterFactory=TreeReporter,
57 realTimeErrors=True,
58 workingDirectory=working_dir,
59 forceGarbageCollection=True)
60 self.required_services = []
61 self.source_files = []
62
34 def _load_unittest(self, relpath):63 def _load_unittest(self, relpath):
35 """Load unit tests from a Python module with the given relative path."""64 """Load unit tests from a Python module with the given 'relpath'."""
36 assert relpath.endswith(".py"), (65 assert relpath.endswith(".py"), (
37 "%s does not appear to be a Python module" % relpath)66 "%s does not appear to be a Python module" % relpath)
67 if not os.path.basename(relpath).startswith('test_'):
68 return
38 modpath = relpath.replace(os.path.sep, ".")[:-3]69 modpath = relpath.replace(os.path.sep, ".")[:-3]
39 module = __import__(modpath, None, None, [""])70 module = __import__(modpath, None, None, [""])
4071
72 # If the module specifies required_services, make sure we get them
73 members = [x[1] for x in inspect.getmembers(module, inspect.isclass)]
74 for member_type in members:
75 if hasattr(member_type, 'required_services'):
76 member = member_type()
77 self.required_services.extend(member.required_services())
78 del member
79 gc.collect()
80
41 # If the module has a 'suite' or 'test_suite' function, use that81 # If the module has a 'suite' or 'test_suite' function, use that
42 # to load the tests.82 # to load the tests.
43 if hasattr(module, "suite"):83 if hasattr(module, "suite"):
@@ -53,8 +93,11 @@
53 if test_pattern:93 if test_pattern:
54 pattern = re.compile('.*%s.*' % test_pattern)94 pattern = re.compile('.*%s.*' % test_pattern)
55 else:95 else:
56 pattern = None 96 pattern = None
5797
98 # Disable this lint warning as we need to access _tests in the
99 # test suites, to collect the tests
100 # pylint: disable=W0212
58 if path:101 if path:
59 try:102 try:
60 module_suite = self._load_unittest(path)103 module_suite = self._load_unittest(path)
@@ -69,83 +112,92 @@
69 except AssertionError:112 except AssertionError:
70 pass113 pass
71 else:114 else:
72 parser.print_help()115 print 'Path should be defined.'
73 exit(1)116 exit(1)
74117
75 # We don't use the dirs variable, so ignore the warning118 # We don't use the dirs variable, so ignore the warning
76 # pylint: disable=W0612119 # pylint: disable=W0612
77 for root, dirs, files in os.walk(path):120 for root, dirs, files in os.walk(path):
78 for test in files:121 for test in files:
79 path = os.path.join(root, test)122 filepath = os.path.join(root, test)
80 if test.endswith(".py") and test.startswith("test_"):123 if test.endswith(".py"):
81 module_suite = self._load_unittest(path)124 self.source_files.append(filepath)
82 if pattern:125 if test.startswith("test_"):
83 for inner_suite in module_suite._tests:126 module_suite = self._load_unittest(filepath)
84 for test in inner_suite._tests:127 if pattern:
85 if pattern.match(test.id()):128 for inner_suite in module_suite._tests:
86 suite.addTest(test)129 for test in inner_suite._tests:
87 else:130 if pattern.match(test.id()):
88 suite.addTests(module_suite)131 suite.addTest(test)
132 else:
133 suite.addTests(module_suite)
89 return suite134 return suite
90135
91 def run(self, path, test_pattern=None, loops=None):136 # pylint: disable=E0202
92 """run the tests. """137 def run(self, path, options=None):
93 # install the glib2reactor before any import of the reactor to avoid138 """run the tests."""
94 # using the default SelectReactor and be able to run the dbus tests
95 from twisted.internet import glib2reactor
96 glib2reactor.install()
97 from twisted.trial.reporter import TreeReporter
98 from twisted.trial.runner import TrialRunner
99
100 from ubuntuone.devtools.dbus_util import DBusRunner
101 dbus_runner = DBusRunner()
102 dbus_runner.startDBus()
103
104 working_dir = os.path.join(os.getcwd(), "_trial_temp", "tmp")
105 runner = TrialRunner(reporterFactory=TreeReporter, realTimeErrors=True,
106 workingDirectory=working_dir)
107
108 # setup a custom XDG_CACHE_HOME and create the logs directory
109 xdg_cache = os.path.join(os.getcwd(), "_trial_temp", "xdg_cache")
110 os.environ["XDG_CACHE_HOME"] = xdg_cache
111 # setup the ROOTDIR env var
112 os.environ['ROOTDIR'] = os.getcwd()
113 if not os.path.exists(xdg_cache):
114 os.makedirs(xdg_cache)
115 success = 0139 success = 0
140 running_services = []
141 if options.coverage:
142 coverage.erase()
143 coverage.start()
144
116 try:145 try:
117 suite = self._collect_tests(path, test_pattern)146 suite = self._collect_tests(path, options.test)
118 if loops:147 if options.loops:
119 old_suite = suite148 old_suite = suite
120 suite = unittest.TestSuite()149 suite = unittest.TestSuite()
121 for _ in xrange(loops):150 for _ in xrange(options.loops):
122 suite.addTest(old_suite)151 suite.addTest(old_suite)
123 result = runner.run(suite)152
153 # Start any required services
154 for service in self.required_services:
155 runner = service()
156 runner.start_service(tempdir=self.tempdir)
157 running_services.append(runner)
158
159 result = super(TestRunner, self).run(suite)
124 success = result.wasSuccessful()160 success = result.wasSuccessful()
125 finally:161 finally:
126 dbus_runner.stopDBus()162 # Stop all the running services
163 for runner in running_services:
164 runner.stop_service()
165
166 if options.coverage:
167 coverage.stop()
168 coverage.report(self.source_files, ignore_errors=True,
169 show_missing=False)
170
127 if not success:171 if not success:
128 sys.exit(1)172 sys.exit(1)
129 else:173 else:
130 sys.exit(0)174 sys.exit(0)
131175
132176
133if __name__ == '__main__':177def main():
178 """Do the deed."""
134 from optparse import OptionParser179 from optparse import OptionParser
135 usage = '%prog [options] path'180 usage = '%prog [options] path'
136 parser = OptionParser(usage=usage)181 parser = OptionParser(usage=usage)
137 parser.add_option("-t", "--test", dest="test",182 parser.add_option("-t", "--test", dest="test",
138 help = "run specific tests, e.g: className.methodName")183 help = "run specific tests, e.g: className.methodName")
139 parser.add_option("-l", "--loop", dest="loops", type="int", default=1,184 parser.add_option("-l", "--loop", dest="loops", type="int", default=1,
140 help = "loop selected tests LOOPS number of times", 185 help = "loop selected tests LOOPS number of times",
141 metavar="LOOPS")186 metavar="LOOPS")
187 parser.add_option("-c", "--coverage", action="store_true", dest="coverage",
188 help="print a coverage report when finished")
142189
143 (options, args) = parser.parse_args()190 (options, args) = parser.parse_args()
144 if args:191 if args:
145 testpath = args[0]192 testpath = args[0]
146 if not os.path.exists(testpath):193 if not os.path.exists(testpath):
147 print "the path to test does not exists!"194 print "the path to test does not exists!"
148 sys.exit()195 sys.exit(1)
149 else:196 else:
150 testpath = None197 parser.print_help()
151 TestRunner().run(testpath, options.test, options.loops) 198 sys.exit(2)
199
200 TestRunner().run(testpath, options)
201
202if __name__ == '__main__':
203 main()
152204
=== modified file 'debian/changelog'
--- debian/changelog 2010-08-02 13:45:54 +0000
+++ debian/changelog 2010-11-30 19:41:01 +0000
@@ -1,3 +1,14 @@
1ubuntuone-dev-tools (0.1.2-0ubuntu1) natty; urgency=low
2
3 * New upstream release.
4 * Fix debian/watch to use the right file extension.
5 * Remove python-oauth as a dependency.
6 * Update build and runtime dependencies.
7 * Require pep8 to run tests during build.
8 * Use ./run-tests during the build instead of setup.py lint to run tests.
9
10 -- Rodney Dawes <rodney.dawes@ubuntu.com> Mon, 29 Nov 2010 13:43:06 -0500
11
1ubuntuone-dev-tools (0.1.1-0ubuntu1) maverick; urgency=low12ubuntuone-dev-tools (0.1.1-0ubuntu1) maverick; urgency=low
213
3 * Initial packaging for ubuntuone-dev-tools. (LP:#610576)14 * Initial packaging for ubuntuone-dev-tools. (LP:#610576)
415
=== modified file 'debian/control'
--- debian/control 2010-08-02 13:45:54 +0000
+++ debian/control 2010-11-30 19:41:01 +0000
@@ -5,20 +5,23 @@
5Priority: optional5Priority: optional
6Standards-Version: 3.9.16Standards-Version: 3.9.1
7Build-Depends-Indep:7Build-Depends-Indep:
8 dbus,
9 pep8,
10 pylint (>= 0.21.0),
11 python-coverage,
12 python-dbus,
13 python-gobject,
8 python-setuptools,14 python-setuptools,
9 python-support,15 python-support,
10 python-xdg,
11 python-twisted-core,16 python-twisted-core,
12 python-dbus,17 python-xdg
13 python-oauth,
14 pylint (>= 0.21.0)
15Build-Depends: cdbs (>= 0.4.43), debhelper (>= 7.0.17), python-all18Build-Depends: cdbs (>= 0.4.43), debhelper (>= 7.0.17), python-all
16Homepage: http://launchpad.net/ubuntuone-dev-tools19Homepage: http://launchpad.net/ubuntuone-dev-tools
1720
18Package: python-ubuntuone-devtools21Package: python-ubuntuone-devtools
19Architecture: all22Architecture: all
20Depends: ${python:Depends}, ${misc:Depends},23Depends: ${python:Depends}, ${misc:Depends},
21 python-oauth,24 dbus,
22 python-dbus25 python-dbus
23Description: Ubuntu One development tools - Python modules26Description: Ubuntu One development tools - Python modules
24 Ubuntu One development tools provides scripts, test cases, and other27 Ubuntu One development tools provides scripts, test cases, and other
@@ -29,8 +32,11 @@
29Package: ubuntuone-dev-tools32Package: ubuntuone-dev-tools
30Architecture: all33Architecture: all
31Depends: ${python:Depends}, ${misc:Depends}, python,34Depends: ${python:Depends}, ${misc:Depends}, python,
35 pylint (>= 0.21.0) | pyflakes,
36 python-coverage,
37 python-gobject,
38 python-twisted-core,
32 python-ubuntuone-devtools (= ${binary:Version}),39 python-ubuntuone-devtools (= ${binary:Version}),
33 python-twisted-core,
34 python-xdg40 python-xdg
35Description: Ubuntu One development tools41Description: Ubuntu One development tools
36 Ubuntu One development tools provides scripts, test cases, and other42 Ubuntu One development tools provides scripts, test cases, and other
3743
=== modified file 'debian/rules'
--- debian/rules 2010-08-02 13:45:54 +0000
+++ debian/rules 2010-11-30 19:41:01 +0000
@@ -6,7 +6,7 @@
66
7common-build-arch common-build-indep:: debian/stamp-check7common-build-arch common-build-indep:: debian/stamp-check
8debian/stamp-check:8debian/stamp-check:
9 cd $(DEB_SRCDIR) && $(call cdbs_python_binary,python$(cdbs_python_compile_version)) $(DEB_PYTHON_SETUP_CMD) lint9 cd $(DEB_SRCDIR) && ./run-tests
10 touch $@10 touch $@
1111
12makefile-clean::12makefile-clean::
1313
=== modified file 'debian/watch'
--- debian/watch 2010-08-02 13:45:54 +0000
+++ debian/watch 2010-11-30 19:41:01 +0000
@@ -1,3 +1,3 @@
1version=31version=3
2http://launchpad.net/ubuntuone-dev-tools/+download .*/ubuntuone-dev-tools-([0-9.]+)\.tar\.bz22http://launchpad.net/ubuntuone-dev-tools/+download .*/ubuntuone-dev-tools-([0-9.]+)\.tar\.gz
33
44
=== modified file 'pylintrc'
--- pylintrc 2010-08-02 13:45:54 +0000
+++ pylintrc 2010-11-30 19:41:01 +0000
@@ -1,39 +1,137 @@
1# lint Python modules using external checkers.1# lint Python modules using external checkers.
2#2#
3# This is the main checker controling the other ones and the reports3# This is the main checker controlling the other ones and the reports
4# generation. It is itself both a raw checker and an astng checker in order4# generation. It is itself both a raw checker and an astng checker in order
5# to:5# to:
6# * handle message activation / deactivation at the module level6# * handle message activation / deactivation at the module level
7# * handle some basic but necessary stats data (number of classes, methods...)7# * handle some basic but necessary stats'data (number of classes, methods...)
8#8#
9[MASTER]9[MASTER]
10# Set the cache size for astng objects.10
11cache-size=50011# Specify a configuration file.
12#rcfile=
13
14# Python code to execute, usually for sys.path manipulation such as
15# pygtk.require().
16#init-hook=
17
18# Profiled execution.
19profile=no
20
21# Add <file or directory> to the black list. It should be a base name, not a
22# path. You may set this option multiple times.
23#ignore=<somedir>
24
25# Pickle collected data for later comparisons.
26persistent=no
27
28# List of plugins (as comma separated values of python modules names) to load,
29# usually to register additional checkers.
30load-plugins=
31
1232
13[MESSAGES CONTROL]33[MESSAGES CONTROL]
14# Disable some checkers34
35# Enable only checker(s) with the given id(s). This option conflicts with the
36# disable-checker option
37#enable-checker=
38
39# Enable all checker(s) except those with the given id(s). This option
40# conflicts with the enable-checker option
41#disable-checker=
42
43# Enable all messages in the listed categories.
44#enable-cat=
45
15# Disable all messages in the listed categories.46# Disable all messages in the listed categories.
16# Disable the message(s) with the given id(s).47#disable-cat=
17# :E0101: *Explicit return in __init__*48
18# :E0202: An attribute inherited from %s hide this method49# Disable the message(s) with the given id(s) or categories
19# :W0142: *Used * or ** magic*50# W0142: Used * or ** magic
20# :W0201: Attribute '%s' defined outside __init__51# W0221: Arguments number differs from %s method (pylint is confused by * and **)
21# :W0221: *Arguments number differs from %s method* (pylint is confused by * and **)52# W0613: Unused argument %r (We get lots of these from interfaces)
22# :W0613: *Unused argument %r* (We get lots of these from interfaces)53disable=R,I,W0142,W0221,W0613
23# :W0621: *Redefining name %r from outer scope (line %s)* (pylint does a poor evaluation)
24# :W0622: *Redefining built-in '%r'
25disable=typecheck,design,similarities,R,I,E0101,E0202,W0142,W0201,W0221,W0613,W0621,W0622,C0322
2654
2755
28[REPORTS]56[REPORTS]
29# Tells wether to display a full report or only the messages57
58# Set the output format. Available formats are text, parseable, colorized, msvs
59# (visual studio) and html
60output-format=colorized
61
62# Include message's id in output
63include-ids=yes
64
65# Put messages in a separate file for each module / package specified on the
66# command line instead of printing them on stdout. Reports (if any) will be
67# written in a file name "pylint_global.[txt|html]".
68files-output=no
69
70# Tells whether to display a full report or only the messages
30reports=no71reports=no
3172
73# Python expression which should return a note less than 10 (10 is the highest
74# note). You have access to the variables errors warning, statement which
75# respectively contain the number of errors / warnings messages and the total
76# number of statements analyzed. This is used by the global evaluation report
77# (R0004).
78evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
79
80# Add a comment according to your evaluation note. This is used by the global
81# evaluation report (R0004).
82comment=no
83
84# Enable the report(s) with the given id(s).
85#enable-report=
86
87# Disable the report(s) with the given id(s).
88#disable-report=
89
90
91# try to find bugs in the code using type inference
92#
93[TYPECHECK]
94
95# Tells whether missing members accessed in mixin class should be ignored. A
96# mixin class is detected if its name ends with "mixin" (case insensitive).
97ignore-mixin-members=yes
98
99# List of classes names for which member attributes should not be checked
100# (useful for classes with attributes dynamically set).
101ignored-classes=
102
103# When zope mode is activated, add a predefined set of Zope acquired attributes
104# to generated-members.
105zope=no
106
107# List of members which are set dynamically and missed by pylint inference
108# system, and so shouldn't trigger E0201 when accessed.
109generated-members=REQUEST,acl_users,aq_parent
110
111
112# checks for
113# * unused variables / imports
114# * undefined variables
115# * redefinition of variable from builtins or from an outer scope
116# * use of variable before assignment
117#
118[VARIABLES]
119
120# Tells whether we should check for unused import in __init__ files.
121init-import=yes
122
123# A regular expression matching names used for dummy variables (i.e. not used).
124dummy-variables-rgx=_|dummy
125
126# List of additional names supposed to be defined in builtins. Remember that
127# you should avoid to define new builtins when possible.
128additional-builtins=
129
32130
33# checks for :131# checks for :
34# * doc strings132# * doc strings
35# * modules / classes / functions / methods / arguments / variables name133# * modules / classes / functions / methods / arguments / variables name
36# * number of arguments, local variables, branchs, returns and statements in134# * number of arguments, local variables, branches, returns and statements in
37# functions, methods135# functions, methods
38# * required module attributes136# * required module attributes
39# * dangerous default values as arguments137# * dangerous default values as arguments
@@ -41,7 +139,6 @@
41# * uses of the global statement139# * uses of the global statement
42#140#
43[BASIC]141[BASIC]
44enable-basic=yes
45142
46# Required attributes for module, separated by a comma143# Required attributes for module, separated by a comma
47required-attributes=144required-attributes=
@@ -54,34 +151,32 @@
54module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$151module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
55152
56# Regular expression which should only match correct module level names153# Regular expression which should only match correct module level names
57const-rgx=([a-z_][a-z0-9_]*|[A-Z_][A-Z0-9_]*)$154const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
58155
59# Regular expression which should only match correct class names156# Regular expression which should only match correct class names
60class-rgx=[A-Z_][a-zA-Z0-9]+$157class-rgx=[A-Z_][a-zA-Z0-9]+$
61158
62# Regular expression which should only match correct function names159# Regular expression which should only match correct function names
63function-rgx=[a-z_][a-zA-Z0-9_]*$160function-rgx=[a-z_][a-z0-9_]{2,79}$
64161
65# Regular expression which should only match correct method names162# Regular expression which should only match correct method names
66method-rgx=[a-z_][a-zA-Z0-9_]*$163method-rgx=([a-z_][a-z0-9_]{2,79}$|setUp|tearDown)
67164
68# Regular expression which should only match correct instance attribute names165# Regular expression which should only match correct instance attribute names
69attr-rgx=[a-z_][a-zA-Z0-9_]*$166attr-rgx=[a-z_][a-z0-9_]{1,30}$
70167
71# Regular expression which should only match correct argument names168# Regular expression which should only match correct argument names
72argument-rgx=[a-z_][a-zA-Z0-9_]{1,30}$169argument-rgx=[a-z_][a-z0-9_]{1,30}$
73170
74# Regular expression which should only match correct variable names171# Regular expression which should only match correct variable names
75# They are normally all lowercase, but when a constant, they are all uppercase.172variable-rgx=[a-z_][a-z0-9_]{1,30}$
76variable-rgx=([a-z_][a-z0-9_]*|[A-Z_][A-Z0-9_]*)$
77173
78# Regular expression which should only match correct list comprehension /174# Regular expression which should only match correct list comprehension /
79# generator expression variable names175# generator expression variable names
80inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$176inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
81177
82# Good variable names which should always be accepted, separated by a comma178# Good variable names which should always be accepted, separated by a comma
83# Update this to supress warnings about inherrited names (C0103)179good-names=d,e,f,g,i,j,k,ex,logger,Run,_
84good-names=_,a,b,c,i,j,k,v,d,f,s,t,l,ex,_,orderBy,getByName,clauseTables
85180
86# Bad variable names which should always be refused, separated by a comma181# Bad variable names which should always be refused, separated by a comma
87bad-names=foo,bar,baz,toto,tutu,tata182bad-names=foo,bar,baz,toto,tutu,tata
@@ -90,13 +185,80 @@
90bad-functions=apply,input,reduce185bad-functions=apply,input,reduce
91186
92187
93# checks for:188# checks for sign of poor/misdesign:
94# * warning notes in the code like FIXME, XXX189# * number of methods, attributes, local variables...
95# * PEP 263: source code with non ascii character but no encoding declaration190# * size, complexity of functions, methods
96#191#
97[MISCELLANEOUS]192[DESIGN]
98# List of note tags to take in consideration, separated by a comma.193
99notes=FIXME,XXX,TODO,fixme,todo194# Maximum number of arguments for function / method
195max-args=5
196
197# Maximum number of locals for function / method body
198max-locals=15
199
200# Maximum number of return / yield for function / method body
201max-returns=6
202
203# Maximum number of branch for function / method body
204max-branchs=12
205
206# Maximum number of statements in function / method body
207max-statements=50
208
209# Maximum number of parents for a class (see R0901).
210max-parents=7
211
212# Maximum number of attributes for a class (see R0902).
213max-attributes=7
214
215# Minimum number of public methods for a class (see R0903).
216min-public-methods=2
217
218# Maximum number of public methods for a class (see R0904).
219max-public-methods=20
220
221
222# checks for :
223# * methods without self as first argument
224# * overridden methods signature
225# * access only to existent members via self
226# * attributes not defined in the __init__ method
227# * supported interfaces implementation
228# * unreachable code
229#
230[CLASSES]
231
232# List of interface methods to ignore, separated by a comma. This is used for
233# instance to not check methods defines in Zopes Interface base class.
234#ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by,providedBy
235
236# List of method names used to declare (i.e. assign) instance attributes.
237defining-attr-methods=__init__,__new__,setUp
238
239
240# checks for
241# * external modules dependencies
242# * relative / wildcard imports
243# * cyclic imports
244# * uses of deprecated modules
245#
246[IMPORTS]
247
248# Deprecated modules which should not be used, separated by a comma
249deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
250
251# Create a graph of every (i.e. internal and external) dependencies in the
252# given file (report RP0402 must not be disabled)
253import-graph=
254
255# Create a graph of external dependencies in the given file (report RP0402 must
256# not be disabled)
257ext-import-graph=
258
259# Create a graph of internal dependencies in the given file (report RP0402 must
260# not be disabled)
261int-import-graph=
100262
101263
102# checks for :264# checks for :
@@ -106,10 +268,9 @@
106# * use of <> instead of !=268# * use of <> instead of !=
107#269#
108[FORMAT]270[FORMAT]
109enable-format=yes
110271
111# Maximum number of characters on a single line.272# Maximum number of characters on a single line.
112max-line-length=80273max-line-length=79
113274
114# Maximum number of lines in a module275# Maximum number of lines in a module
115max-module-lines=2000276max-module-lines=2000
@@ -117,3 +278,29 @@
117# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1278# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
118# tab).279# tab).
119indent-string=' '280indent-string=' '
281
282
283# checks for similarities and duplicated code. This computation may be
284# memory / CPU intensive, so you should disable it if you experiments some
285# problems.
286#
287[SIMILARITIES]
288
289# Minimum lines number of a similarity.
290min-similarity-lines=4
291
292# Ignore comments when computing similarities.
293ignore-comments=yes
294
295# Ignore docstrings when computing similarities.
296ignore-docstrings=yes
297
298
299# checks for:
300# * warning notes in the code like FIXME, XXX
301# * PEP 263: source code with non ascii character but no encoding declaration
302#
303[MISCELLANEOUS]
304
305# List of note tags to take in consideration, separated by a comma.
306notes=FIXME,XXX,TODO,fixme,xxx,todo
120307
=== added file 'run-tests'
--- run-tests 1970-01-01 00:00:00 +0000
+++ run-tests 2010-11-30 19:41:01 +0000
@@ -0,0 +1,23 @@
1#!/bin/bash
2# Author: Natalia Bidart <natalia.bidart@canonical.com>
3#
4# Copyright 2010 Canonical Ltd.
5#
6# This program is free software: you can redistribute it and/or modify it
7# under the terms of the GNU General Public License version 3, as published
8# by the Free Software Foundation.
9#
10# This program is distributed in the hope that it will be useful, but
11# WITHOUT ANY WARRANTY; without even the implied warranties of
12# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
13# PURPOSE. See the GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License along
16# with this program. If not, see <http://www.gnu.org/licenses/>.
17set -e
18
19bin/u1trial -c ubuntuone
20bin/u1lint
21pep8 --repeat .
22rm -rf _trial_temp
23rm -rf .coverage
024
=== modified file 'setup.py'
--- setup.py 2010-08-02 13:45:54 +0000
+++ setup.py 2010-11-30 19:41:01 +0000
@@ -21,10 +21,11 @@
21from distutils.core import setup, Command21from distutils.core import setup, Command
2222
23PACKAGE = 'ubuntuone-dev-tools'23PACKAGE = 'ubuntuone-dev-tools'
24VERSION = '0.1.1'24VERSION = '0.1.2'
2525
26U1LINT = 'bin/u1lint'26U1LINT = 'bin/u1lint'
2727
28
28class Lint(Command):29class Lint(Command):
29 """Command to run the lint checks."""30 """Command to run the lint checks."""
30 description = 'run python lint checks'31 description = 'run python lint checks'
@@ -37,7 +38,7 @@
37 def finalize_options(self):38 def finalize_options(self):
38 pass39 pass
3940
40 def run (self):41 def run(self):
41 """Run u1lint to check the code."""42 """Run u1lint to check the code."""
42 retcode = subprocess.call([U1LINT])43 retcode = subprocess.call([U1LINT])
43 if retcode != 0:44 if retcode != 0:
@@ -48,21 +49,20 @@
48 description='Ubuntu One development tools and utilities',49 description='Ubuntu One development tools and utilities',
49 url='http://launchpad.net/ubuntuone-dev-tools',50 url='http://launchpad.net/ubuntuone-dev-tools',
50 packages=['ubuntuone',51 packages=['ubuntuone',
51 'ubuntuone.devtools'],52 'ubuntuone.devtools',
53 'ubuntuone.devtools.services'],
52 scripts=['bin/u1lint',54 scripts=['bin/u1lint',
53 'bin/u1trial',55 'bin/u1trial',
54 ],56 ],
55 data_files=[('share/%s' % PACKAGE,57 data_files=[('share/%s' % PACKAGE,
56 ['pylintrc',58 ['pylintrc',
57 'data/dbus-session.conf']59 'data/dbus-session.conf']),
58 ),
59 ('share/man/man1',60 ('share/man/man1',
60 ['man/u1lint.1',61 ['man/u1lint.1',
61 'man/u1trial.1',]62 'man/u1trial.1']),
62 ),
63 ],63 ],
6464
65 cmdclass = {65 cmdclass={
66 'lint' : Lint,66 'lint': Lint,
67 },67 },
68 )68 )
6969
=== modified file 'ubuntuone/devtools/__init__.py'
--- ubuntuone/devtools/__init__.py 2010-08-02 13:45:54 +0000
+++ ubuntuone/devtools/__init__.py 2010-11-30 19:41:01 +0000
@@ -1,2 +1,1 @@
1"""Testing utilities for Ubuntu One client code."""1"""Testing utilities for Ubuntu One client code."""
2
32
=== removed file 'ubuntuone/devtools/dbus_util.py'
--- ubuntuone/devtools/dbus_util.py 2010-08-02 13:45:54 +0000
+++ ubuntuone/devtools/dbus_util.py 1970-01-01 00:00:00 +0000
@@ -1,89 +0,0 @@
1#
2# Author: Guillermo Gonzalez <guillermo.gonzalez@canonical.com>
3#
4# Copyright 2009-2010 Canonical Ltd.
5#
6# This program is free software: you can redistribute it and/or modify it
7# under the terms of the GNU General Public License version 3, as published
8# by the Free Software Foundation.
9#
10# This program is distributed in the hope that it will be useful, but
11# WITHOUT ANY WARRANTY; without even the implied warranties of
12# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
13# PURPOSE. See the GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License along
16# with this program. If not, see <http://www.gnu.org/licenses/>.
17"""Utilities for finding and running a dbus session bus for testing."""
18
19import os
20import signal
21import subprocess
22
23from distutils.spawn import find_executable
24from xdg.BaseDirectory import load_data_paths
25
26
27class DBusLaunchError(Exception):
28 """Error while launching dbus-daemon"""
29 pass
30
31class NotFoundError(Exception):
32 """Not found error"""
33 pass
34
35
36class DBusRunner(object):
37 """Class for running dbus-daemon with a private session."""
38
39 def __init__(self):
40 self.dbus_address = None
41 self.dbus_pid = None
42 self.running = False
43
44 def _find_config_file(self):
45 """Find the first appropriate dbus-session.conf to use."""
46 # In case we're running from within the source tree
47 path = os.path.join(os.path.dirname(__file__), "..", "..",
48 "data", "dbus-session.conf")
49 if os.path.exists(path):
50 return path
51
52 # Use the installed file in $pkgdatadir
53 for i in load_data_paths("ubuntuone-dev-tools", "dbus-session.conf"):
54 if os.path.exists(i):
55 return i
56
57
58 def startDBus(self):
59 """Start our own session bus daemon for testing."""
60 dbus = find_executable("dbus-daemon")
61 if not dbus:
62 raise NotFoundError("dbus-daemon was not found.")
63
64 config_file = self._find_config_file()
65
66 dbus_args = ["--fork",
67 "--config-file=" + config_file,
68 "--print-address=1",
69 "--print-pid=2"]
70 p = subprocess.Popen([dbus] + dbus_args,
71 bufsize=4096, stdout=subprocess.PIPE,
72 stderr=subprocess.PIPE)
73
74 self.dbus_address = "".join(p.stdout.readlines()).strip()
75 self.dbus_pid = int("".join(p.stderr.readlines()).strip())
76
77 if self.dbus_address != "":
78 os.environ["DBUS_SESSION_BUS_ADDRESS"] = self.dbus_address
79 else:
80 os.kill(self.dbus_pid, signal.SIGKILL)
81 raise DBusLaunchError("There was a problem launching dbus-daemon.")
82 self.running = True
83
84 def stopDBus(self):
85 """Stop our DBus session bus daemon."""
86 del os.environ["DBUS_SESSION_BUS_ADDRESS"]
87 os.kill(self.dbus_pid, signal.SIGKILL)
88 self.running = False
89
900
=== added file 'ubuntuone/devtools/handlers.py'
--- ubuntuone/devtools/handlers.py 1970-01-01 00:00:00 +0000
+++ ubuntuone/devtools/handlers.py 2010-11-30 19:41:01 +0000
@@ -0,0 +1,64 @@
1# -*- coding: utf-8 -*-
2
3# Author: Guillermo Gonzalez <guillermo.gonzalez@canonical.com>
4# Author: Facundo Batista <facundo@canonical.com>
5#
6# Copyright 2009-2010 Canonical Ltd.
7#
8# This program is free software: you can redistribute it and/or modify it
9# under the terms of the GNU General Public License version 3, as published
10# by the Free Software Foundation.
11#
12# This program is distributed in the hope that it will be useful, but
13# WITHOUT ANY WARRANTY; without even the implied warranties of
14# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
15# PURPOSE. See the GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License along
18# with this program. If not, see <http://www.gnu.org/licenses/>.
19
20"""Set of helpers handlers."""
21
22import logging
23
24
25class MementoHandler(logging.Handler):
26 """ A handler class which store logging records in a list """
27
28 def __init__(self, *args, **kwargs):
29 """ Create the instance, and add a records attribute. """
30 logging.Handler.__init__(self, *args, **kwargs)
31 self.records = []
32 self.debug = False
33
34 def emit(self, record):
35 """ Just add the record to self.records. """
36 self.format(record)
37 self.records.append(record)
38
39 def check(self, level, *msgs):
40 """Verifies that the msgs are logged in the specified level."""
41 for rec in self.records:
42 if rec.levelno == level and all(m in rec.message for m in msgs):
43 return True
44 if self.debug:
45 recorded = [(logging.getLevelName(r.levelno), r.message)
46 for r in self.records]
47 print "Memento messages:", recorded
48 return False
49
50 def check_debug(self, *msgs):
51 """Shortcut for checking in DEBUG."""
52 return self.check(logging.DEBUG, *msgs)
53
54 def check_info(self, *msgs):
55 """Shortcut for checking in INFO."""
56 return self.check(logging.INFO, *msgs)
57
58 def check_warning(self, *msgs):
59 """Shortcut for checking in WARNING."""
60 return self.check(logging.WARNING, *msgs)
61
62 def check_error(self, *msgs):
63 """Shortcut for checking in ERROR."""
64 return self.check(logging.ERROR, *msgs)
065
=== added directory 'ubuntuone/devtools/services'
=== added file 'ubuntuone/devtools/services/__init__.py'
--- ubuntuone/devtools/services/__init__.py 1970-01-01 00:00:00 +0000
+++ ubuntuone/devtools/services/__init__.py 2010-11-30 19:41:01 +0000
@@ -0,0 +1,1 @@
1"""Service runners for testing."""
02
=== added file 'ubuntuone/devtools/services/dbus.py'
--- ubuntuone/devtools/services/dbus.py 1970-01-01 00:00:00 +0000
+++ ubuntuone/devtools/services/dbus.py 2010-11-30 19:41:01 +0000
@@ -0,0 +1,94 @@
1#
2# Author: Guillermo Gonzalez <guillermo.gonzalez@canonical.com>
3#
4# Copyright 2009-2010 Canonical Ltd.
5#
6# This program is free software: you can redistribute it and/or modify it
7# under the terms of the GNU General Public License version 3, as published
8# by the Free Software Foundation.
9#
10# This program is distributed in the hope that it will be useful, but
11# WITHOUT ANY WARRANTY; without even the implied warranties of
12# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
13# PURPOSE. See the GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License along
16# with this program. If not, see <http://www.gnu.org/licenses/>.
17"""Utilities for finding and running a dbus session bus for testing."""
18
19import os
20import signal
21import subprocess
22
23from distutils.spawn import find_executable
24from xdg.BaseDirectory import load_data_paths
25
26
27class DBusLaunchError(Exception):
28 """Error while launching dbus-daemon"""
29 pass
30
31
32class NotFoundError(Exception):
33 """Not found error"""
34 pass
35
36
37class DBusRunner(object):
38 """Class for running dbus-daemon with a private session."""
39
40 def __init__(self):
41 self.dbus_address = None
42 self.dbus_pid = None
43 self.running = False
44
45 def _find_config_file(self):
46 """Find the first appropriate dbus-session.conf to use."""
47 # In case we're running from within the source tree
48 path = os.path.join(os.path.dirname(__file__), "..", "..", ".."
49 "data", "dbus-session.conf")
50 if os.path.exists(path):
51 return path
52
53 # Use the installed file in $pkgdatadir
54 for i in load_data_paths("ubuntuone-dev-tools", "dbus-session.conf"):
55 if os.path.exists(i):
56 return i
57
58 def start_service(self, tempdir=None):
59 """Start our own session bus daemon for testing."""
60 if not tempdir:
61 tempdir = os.path.join(os.getcwd(), '_trial_temp')
62 dbus = find_executable("dbus-daemon")
63 if not dbus:
64 raise NotFoundError("dbus-daemon was not found.")
65
66 config_file = self._find_config_file()
67
68 dbus_args = ["--fork",
69 "--config-file=" + config_file,
70 "--print-address=1",
71 "--print-pid=2",
72 "--address=unix:tmpdir=%s" % tempdir]
73 sp = subprocess.Popen([dbus] + dbus_args,
74 bufsize=4096, stdout=subprocess.PIPE,
75 stderr=subprocess.PIPE)
76
77 self.dbus_address = "".join(sp.stdout.readlines()).strip()
78 self.dbus_pid = int("".join(sp.stderr.readlines()).strip())
79
80 if self.dbus_address != "":
81 os.environ["DBUS_SESSION_BUS_ADDRESS"] = self.dbus_address
82 else:
83 os.kill(self.dbus_pid, signal.SIGKILL)
84 raise DBusLaunchError("There was a problem launching dbus-daemon.")
85 self.running = True
86
87 def stop_service(self):
88 """Stop our DBus session bus daemon."""
89 try:
90 del os.environ["DBUS_SESSION_BUS_ADDRESS"]
91 except KeyError:
92 pass
93 os.kill(self.dbus_pid, signal.SIGKILL)
94 self.running = False
095
=== modified file 'ubuntuone/devtools/testcase.py'
--- ubuntuone/devtools/testcase.py 2010-08-02 13:45:54 +0000
+++ ubuntuone/devtools/testcase.py 2010-11-30 19:41:01 +0000
@@ -1,4 +1,5 @@
1#1# -*- coding: utf-8 -*-
2
2# Author: Guillermo Gonzalez <guillermo.gonzalez@canonical.com>3# Author: Guillermo Gonzalez <guillermo.gonzalez@canonical.com>
3#4#
4# Copyright 2009-2010 Canonical Ltd.5# Copyright 2009-2010 Canonical Ltd.
@@ -14,19 +15,26 @@
14#15#
15# You should have received a copy of the GNU General Public License along16# You should have received a copy of the GNU General Public License along
16# with this program. If not, see <http://www.gnu.org/licenses/>.17# with this program. If not, see <http://www.gnu.org/licenses/>.
17""" Base tests cases and test utilities """18
19"""Base tests cases and test utilities."""
20
18from __future__ import with_statement21from __future__ import with_statement
1922
20import dbus
21from dbus.mainloop.glib import DBusGMainLoop
22import contextlib23import contextlib
23import os24import os
24import shutil25import shutil
2526
27import dbus
28import dbus.service
29
30from dbus.mainloop.glib import DBusGMainLoop
31
26from twisted.internet import defer32from twisted.internet import defer
27from twisted.python import failure33from twisted.python import failure
28from unittest import TestCase34from twisted.trial.unittest import TestCase
29from oauth import oauth35
36# DBusRunner for DBusTestCase using tests
37from ubuntuone.devtools.services.dbus import DBusRunner
3038
3139
32@contextlib.contextmanager40@contextlib.contextmanager
@@ -41,21 +49,9 @@
41 os.environ[env_var] = old_value49 os.environ[env_var] = old_value
4250
4351
44class FakeOAuthClient(object):
45 """ Fake OAuthClient"""
46
47 def __init__(self, realm):
48 """ create the instance. """
49 self.realm = realm
50 self.consumer = oauth.OAuthConsumer('ubuntuone', 'hammertime')
51
52 def get_access_token(self):
53 """ returns a Token"""
54 return 'a token'
55
56
57class FakeDBusInterface(object):52class FakeDBusInterface(object):
58 """A fake DBusInterface..."""53 """A fake DBusInterface..."""
54
59 def shutdown(self, with_restart=False):55 def shutdown(self, with_restart=False):
60 """...that only knows how to go away"""56 """...that only knows how to go away"""
6157
@@ -67,10 +63,15 @@
67 mktemp(name): helper to create temporary dirs63 mktemp(name): helper to create temporary dirs
68 rmtree(path): support read-only shares64 rmtree(path): support read-only shares
69 makedirs(path): support read-only shares65 makedirs(path): support read-only shares
66
70 """67 """
7168
69 def required_services(self):
70 """Return the list of required services for DBusTestCase."""
71 return []
72
72 def mktemp(self, name='temp'):73 def mktemp(self, name='temp'):
73 """ Customized mktemp that accepts an optional name argument. """74 """Customized mktemp that accepts an optional name argument."""
74 tempdir = os.path.join(self.tmpdir, name)75 tempdir = os.path.join(self.tmpdir, name)
75 if os.path.exists(tempdir):76 if os.path.exists(tempdir):
76 self.rmtree(tempdir)77 self.rmtree(tempdir)
@@ -84,10 +85,10 @@
84 root_dir = getattr(self, '__root', None)85 root_dir = getattr(self, '__root', None)
85 if root_dir:86 if root_dir:
86 return root_dir87 return root_dir
87 MAX_FILENAME = 32 # some platforms limit lengths of filenames88 max_filename = 32 # some platforms limit lengths of filenames
88 base = os.path.join(self.__class__.__module__[:MAX_FILENAME],89 base = os.path.join(self.__class__.__module__[:max_filename],
89 self.__class__.__name__[:MAX_FILENAME],90 self.__class__.__name__[:max_filename],
90 self._testMethodName[:MAX_FILENAME])91 self._testMethodName[:max_filename])
91 # use _trial_temp dir, it should be os.gwtcwd()92 # use _trial_temp dir, it should be os.gwtcwd()
92 # define the root temp dir of the testcase, pylint: disable=W020193 # define the root temp dir of the testcase, pylint: disable=W0201
93 self.__root = os.path.join(os.getcwd(), base)94 self.__root = os.path.join(os.getcwd(), base)
@@ -116,19 +117,20 @@
116 os.chmod(parent, 0755)117 os.chmod(parent, 0755)
117 os.makedirs(path)118 os.makedirs(path)
118119
119 def setUp(self):
120 TestCase.setUp(self)
121
122 def tearDown(self):
123 """ cleanup the temp dir. """
124 return TestCase.tearDown(self)
125
126120
127class DBusTestCase(BaseTestCase):121class DBusTestCase(BaseTestCase):
128 """ Test the DBus event handling """122 """Test the DBus event handling."""
123
124 def required_services(self):
125 """Return the list of required services for DBusTestCase."""
126 services = super(DBusTestCase, self).required_services()
127 services.extend([DBusRunner])
128 return services
129129
130 def setUp(self):130 def setUp(self):
131 """ Setup the infrastructure fo the test (dbus service). """131 """Setup the infrastructure fo the test (dbus service)."""
132 # Class 'BaseTestCase' has no 'setUp' member
133 # pylint: disable=E1101
132 BaseTestCase.setUp(self)134 BaseTestCase.setUp(self)
133 self.loop = DBusGMainLoop(set_as_default=True)135 self.loop = DBusGMainLoop(set_as_default=True)
134 self.bus = dbus.bus.BusConnection(mainloop=self.loop)136 self.bus = dbus.bus.BusConnection(mainloop=self.loop)
@@ -139,29 +141,32 @@
139 self.signal_receivers = set()141 self.signal_receivers = set()
140142
141 def tearDown(self):143 def tearDown(self):
142 """ Cleanup the test. """144 """Cleanup the test."""
145 # Class 'BaseTestCase' has no 'tearDown' member
146 # pylint: disable=E1101
143 d = self.cleanup_signal_receivers(self.signal_receivers)147 d = self.cleanup_signal_receivers(self.signal_receivers)
144 d.addBoth(self._tearDown)148 d.addBoth(self._tear_down)
145 d.addBoth(lambda _: BaseTestCase.tearDown(self))149 d.addBoth(lambda _: BaseTestCase.tearDown(self))
146 return d150 return d
147151
148 def _tearDown(self):152 def _tear_down(self):
149 """ shutdown """153 """Shutdown."""
150 self.bus.flush()154 self.bus.flush()
151 self.bus.close()155 self.bus.close()
152156
153 def error_handler(self, error):157 def error_handler(self, error):
154 """ default error handler for DBus calls. """158 """Default error handler for DBus calls."""
155 if isinstance(error, failure.Failure):159 if isinstance(error, failure.Failure):
156 self.fail(error.getErrorMessage())160 self.fail(error.getErrorMessage())
157161
158 def cleanup_signal_receivers(self, signal_receivers):162 def cleanup_signal_receivers(self, signal_receivers):
159 """ cleanup self.signal_receivers and returns a deferred """163 """Cleanup self.signal_receivers and returns a deferred."""
160 deferreds = []164 deferreds = []
161 for match in signal_receivers:165 for match in signal_receivers:
162 d = defer.Deferred()166 d = defer.Deferred()
167
163 def callback(*args):168 def callback(*args):
164 """ callback that accepts *args. """169 """Callback that accepts *args."""
165 if not d.called:170 if not d.called:
166 d.callback(args)171 d.callback(args)
167 self.bus.call_async(dbus.bus.BUS_DAEMON_NAME,172 self.bus.call_async(dbus.bus.BUS_DAEMON_NAME,
@@ -173,4 +178,3 @@
173 return defer.DeferredList(deferreds)178 return defer.DeferredList(deferreds)
174 else:179 else:
175 return defer.succeed(True)180 return defer.succeed(True)
176

Subscribers

People subscribed via source and target branches

to all changes: