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
1=== modified file 'MANIFEST.in'
2--- MANIFEST.in 2010-08-02 13:45:54 +0000
3+++ MANIFEST.in 2010-11-30 19:41:01 +0000
4@@ -1,4 +1,4 @@
5 include MANIFEST.in
6-include COPYING pylintrc
7+include COPYING pylintrc run-tests
8 recursive-include data *.conf
9 recursive-include man *.1
10
11=== modified file 'PKG-INFO'
12--- PKG-INFO 2010-08-02 13:45:54 +0000
13+++ PKG-INFO 2010-11-30 19:41:01 +0000
14@@ -1,6 +1,6 @@
15 Metadata-Version: 1.0
16 Name: ubuntuone-dev-tools
17-Version: 0.1.1
18+Version: 0.1.2
19 Summary: Ubuntu One development tools and utilities
20 Home-page: http://launchpad.net/ubuntuone-dev-tools
21 Author: UNKNOWN
22
23=== modified file 'bin/u1lint'
24--- bin/u1lint 2010-08-02 13:45:54 +0000
25+++ bin/u1lint 2010-11-30 19:41:01 +0000
26@@ -6,18 +6,19 @@
27 #
28 # Copyright 2009-2010 Canonical Ltd.
29 #
30-# This program is free software: you can redistribute it and/or modify it
31-# under the terms of the GNU General Public License version 3, as published
32+# This program is free software: you can redistribute it and/or modify it
33+# under the terms of the GNU General Public License version 3, as published
34 # by the Free Software Foundation.
35 #
36-# This program is distributed in the hope that it will be useful, but
37-# WITHOUT ANY WARRANTY; without even the implied warranties of
38-# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
39+# This program is distributed in the hope that it will be useful, but
40+# WITHOUT ANY WARRANTY; without even the implied warranties of
41+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
42 # PURPOSE. See the GNU General Public License for more details.
43 #
44-# You should have received a copy of the GNU General Public License along
45+# You should have received a copy of the GNU General Public License along
46 # with this program. If not, see <http://www.gnu.org/licenses/>.
47-"""Wrapper script for pylint command"""
48+
49+"""Wrapper script for pylint command."""
50
51 import ConfigParser
52 import os
53@@ -104,45 +105,51 @@
54 return pyfiles
55
56
57-failed = False
58-
59-ignored = _read_pylintrc_ignored()
60-
61-# So that we can match the path correctly
62-if ignored:
63- moreignores = [os.path.join(SRCDIR, item) for item in ignored]
64- ignored.extend(moreignores)
65-else:
66- ignored = []
67-
68-if os.environ.get('USE_PYFLAKES'):
69- pylint_args = ["pyflakes"]
70-else:
71- pylint_args = ["pylint",
72- "--output-format=parseable",
73- "--include-ids=yes",]
74- if PYLINTRC:
75- pylint_args.append("--rcfile=" + PYLINTRC)
76-
77-for path in _find_files():
78- if path not in ignored and not path.startswith(os.path.join(SRCDIR,
79- "_build")):
80- pylint_args.append(path)
81-
82-p = subprocess.Popen(pylint_args,
83- bufsize=4096, stdout=subprocess.PIPE)
84-notices = p.stdout
85-
86-output = "".join(notices.readlines())
87-if output != "":
88- print "== Python Lint Notices =="
89- (failed, grouped) = _group_lines_by_file(output)
90- print grouped
91- print ""
92-
93-returncode = p.wait()
94-if returncode != 0:
95- exit(returncode)
96-
97-if failed:
98- exit(1)
99+def main():
100+ """Do the deed."""
101+ failed = False
102+ ignored = _read_pylintrc_ignored()
103+
104+ # So that we can match the path correctly
105+ if ignored:
106+ moreignores = [os.path.join(SRCDIR, item) for item in ignored]
107+ ignored.extend(moreignores)
108+ else:
109+ ignored = []
110+
111+ if os.environ.get('USE_PYFLAKES'):
112+ pylint_args = ["pyflakes"]
113+ else:
114+ pylint_args = ["pylint",
115+ "--output-format=parseable",
116+ "--include-ids=yes",]
117+ if PYLINTRC:
118+ pylint_args.append("--rcfile=" + PYLINTRC)
119+
120+ for path in _find_files():
121+ is_build = path.startswith(os.path.join(SRCDIR, "_build"))
122+ if path not in ignored and not is_build:
123+ pylint_args.append(path)
124+
125+ sp = subprocess.Popen(pylint_args,
126+ bufsize=4096, stdout=subprocess.PIPE)
127+ notices = sp.stdout
128+
129+ output = "".join(notices.readlines())
130+ if output != "":
131+ print "== Python Lint Notices =="
132+ (failed, grouped) = _group_lines_by_file(output)
133+ print grouped
134+ print ""
135+
136+ returncode = sp.wait()
137+ # XXX Testing that W0511 does not cause a failure
138+ if failed:
139+ if returncode != 0:
140+ exit(returncode)
141+ else:
142+ exit(1)
143+
144+
145+if __name__ == '__main__':
146+ main()
147
148=== modified file 'bin/u1trial'
149--- bin/u1trial 2010-08-02 13:45:54 +0000
150+++ bin/u1trial 2010-11-30 19:41:01 +0000
151@@ -6,38 +6,78 @@
152 #
153 # Copyright 2009-2010 Canonical Ltd.
154 #
155-# This program is free software: you can redistribute it and/or modify it
156-# under the terms of the GNU General Public License version 3, as published
157+# This program is free software: you can redistribute it and/or modify it
158+# under the terms of the GNU General Public License version 3, as published
159 # by the Free Software Foundation.
160 #
161-# This program is distributed in the hope that it will be useful, but
162-# WITHOUT ANY WARRANTY; without even the implied warranties of
163-# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
164+# This program is distributed in the hope that it will be useful, but
165+# WITHOUT ANY WARRANTY; without even the implied warranties of
166+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
167 # PURPOSE. See the GNU General Public License for more details.
168 #
169-# You should have received a copy of the GNU General Public License along
170+# You should have received a copy of the GNU General Public License along
171 # with this program. If not, see <http://www.gnu.org/licenses/>.
172+
173 """Test runner that uses a private dbus session and glib main loop."""
174
175+import coverage
176+import gc
177+import inspect
178 import os
179 import re
180 import sys
181 import unittest
182
183+from twisted.trial.runner import TrialRunner
184+
185 sys.path.insert(0, os.path.abspath("."))
186
187-# pylint: disable=W0212
188
189-class TestRunner(object):
190+class TestRunner(TrialRunner):
191 """The test runner implementation."""
192
193+ def __init__(self):
194+ # install the glib2reactor before any import of the reactor to avoid
195+ # using the default SelectReactor and be able to run the dbus tests
196+ from twisted.internet import glib2reactor
197+ glib2reactor.install()
198+ from twisted.trial.reporter import TreeReporter
199+
200+ # setup a custom XDG_CACHE_HOME and create the logs directory
201+ xdg_cache = os.path.join(os.getcwd(), "_trial_temp", "xdg_cache")
202+ os.environ["XDG_CACHE_HOME"] = xdg_cache
203+ # setup the ROOTDIR env var
204+ os.environ['ROOTDIR'] = os.getcwd()
205+ if not os.path.exists(xdg_cache):
206+ os.makedirs(xdg_cache)
207+
208+ self.tempdir = os.path.join(os.getcwd(), "_trial_temp")
209+ working_dir = os.path.join(self.tempdir, 'tmp')
210+ super(TestRunner, self).__init__(reporterFactory=TreeReporter,
211+ realTimeErrors=True,
212+ workingDirectory=working_dir,
213+ forceGarbageCollection=True)
214+ self.required_services = []
215+ self.source_files = []
216+
217 def _load_unittest(self, relpath):
218- """Load unit tests from a Python module with the given relative path."""
219+ """Load unit tests from a Python module with the given 'relpath'."""
220 assert relpath.endswith(".py"), (
221 "%s does not appear to be a Python module" % relpath)
222+ if not os.path.basename(relpath).startswith('test_'):
223+ return
224 modpath = relpath.replace(os.path.sep, ".")[:-3]
225 module = __import__(modpath, None, None, [""])
226
227+ # If the module specifies required_services, make sure we get them
228+ members = [x[1] for x in inspect.getmembers(module, inspect.isclass)]
229+ for member_type in members:
230+ if hasattr(member_type, 'required_services'):
231+ member = member_type()
232+ self.required_services.extend(member.required_services())
233+ del member
234+ gc.collect()
235+
236 # If the module has a 'suite' or 'test_suite' function, use that
237 # to load the tests.
238 if hasattr(module, "suite"):
239@@ -53,8 +93,11 @@
240 if test_pattern:
241 pattern = re.compile('.*%s.*' % test_pattern)
242 else:
243- pattern = None
244+ pattern = None
245
246+ # Disable this lint warning as we need to access _tests in the
247+ # test suites, to collect the tests
248+ # pylint: disable=W0212
249 if path:
250 try:
251 module_suite = self._load_unittest(path)
252@@ -69,83 +112,92 @@
253 except AssertionError:
254 pass
255 else:
256- parser.print_help()
257+ print 'Path should be defined.'
258 exit(1)
259
260 # We don't use the dirs variable, so ignore the warning
261 # pylint: disable=W0612
262 for root, dirs, files in os.walk(path):
263 for test in files:
264- path = os.path.join(root, test)
265- if test.endswith(".py") and test.startswith("test_"):
266- module_suite = self._load_unittest(path)
267- if pattern:
268- for inner_suite in module_suite._tests:
269- for test in inner_suite._tests:
270- if pattern.match(test.id()):
271- suite.addTest(test)
272- else:
273- suite.addTests(module_suite)
274+ filepath = os.path.join(root, test)
275+ if test.endswith(".py"):
276+ self.source_files.append(filepath)
277+ if test.startswith("test_"):
278+ module_suite = self._load_unittest(filepath)
279+ if pattern:
280+ for inner_suite in module_suite._tests:
281+ for test in inner_suite._tests:
282+ if pattern.match(test.id()):
283+ suite.addTest(test)
284+ else:
285+ suite.addTests(module_suite)
286 return suite
287
288- def run(self, path, test_pattern=None, loops=None):
289- """run the tests. """
290- # install the glib2reactor before any import of the reactor to avoid
291- # using the default SelectReactor and be able to run the dbus tests
292- from twisted.internet import glib2reactor
293- glib2reactor.install()
294- from twisted.trial.reporter import TreeReporter
295- from twisted.trial.runner import TrialRunner
296-
297- from ubuntuone.devtools.dbus_util import DBusRunner
298- dbus_runner = DBusRunner()
299- dbus_runner.startDBus()
300-
301- working_dir = os.path.join(os.getcwd(), "_trial_temp", "tmp")
302- runner = TrialRunner(reporterFactory=TreeReporter, realTimeErrors=True,
303- workingDirectory=working_dir)
304-
305- # setup a custom XDG_CACHE_HOME and create the logs directory
306- xdg_cache = os.path.join(os.getcwd(), "_trial_temp", "xdg_cache")
307- os.environ["XDG_CACHE_HOME"] = xdg_cache
308- # setup the ROOTDIR env var
309- os.environ['ROOTDIR'] = os.getcwd()
310- if not os.path.exists(xdg_cache):
311- os.makedirs(xdg_cache)
312+ # pylint: disable=E0202
313+ def run(self, path, options=None):
314+ """run the tests."""
315 success = 0
316+ running_services = []
317+ if options.coverage:
318+ coverage.erase()
319+ coverage.start()
320+
321 try:
322- suite = self._collect_tests(path, test_pattern)
323- if loops:
324+ suite = self._collect_tests(path, options.test)
325+ if options.loops:
326 old_suite = suite
327 suite = unittest.TestSuite()
328- for _ in xrange(loops):
329+ for _ in xrange(options.loops):
330 suite.addTest(old_suite)
331- result = runner.run(suite)
332+
333+ # Start any required services
334+ for service in self.required_services:
335+ runner = service()
336+ runner.start_service(tempdir=self.tempdir)
337+ running_services.append(runner)
338+
339+ result = super(TestRunner, self).run(suite)
340 success = result.wasSuccessful()
341 finally:
342- dbus_runner.stopDBus()
343+ # Stop all the running services
344+ for runner in running_services:
345+ runner.stop_service()
346+
347+ if options.coverage:
348+ coverage.stop()
349+ coverage.report(self.source_files, ignore_errors=True,
350+ show_missing=False)
351+
352 if not success:
353 sys.exit(1)
354 else:
355 sys.exit(0)
356
357
358-if __name__ == '__main__':
359+def main():
360+ """Do the deed."""
361 from optparse import OptionParser
362 usage = '%prog [options] path'
363 parser = OptionParser(usage=usage)
364 parser.add_option("-t", "--test", dest="test",
365 help = "run specific tests, e.g: className.methodName")
366 parser.add_option("-l", "--loop", dest="loops", type="int", default=1,
367- help = "loop selected tests LOOPS number of times",
368+ help = "loop selected tests LOOPS number of times",
369 metavar="LOOPS")
370+ parser.add_option("-c", "--coverage", action="store_true", dest="coverage",
371+ help="print a coverage report when finished")
372
373 (options, args) = parser.parse_args()
374 if args:
375 testpath = args[0]
376 if not os.path.exists(testpath):
377 print "the path to test does not exists!"
378- sys.exit()
379+ sys.exit(1)
380 else:
381- testpath = None
382- TestRunner().run(testpath, options.test, options.loops)
383+ parser.print_help()
384+ sys.exit(2)
385+
386+ TestRunner().run(testpath, options)
387+
388+if __name__ == '__main__':
389+ main()
390
391=== modified file 'debian/changelog'
392--- debian/changelog 2010-08-02 13:45:54 +0000
393+++ debian/changelog 2010-11-30 19:41:01 +0000
394@@ -1,3 +1,14 @@
395+ubuntuone-dev-tools (0.1.2-0ubuntu1) natty; urgency=low
396+
397+ * New upstream release.
398+ * Fix debian/watch to use the right file extension.
399+ * Remove python-oauth as a dependency.
400+ * Update build and runtime dependencies.
401+ * Require pep8 to run tests during build.
402+ * Use ./run-tests during the build instead of setup.py lint to run tests.
403+
404+ -- Rodney Dawes <rodney.dawes@ubuntu.com> Mon, 29 Nov 2010 13:43:06 -0500
405+
406 ubuntuone-dev-tools (0.1.1-0ubuntu1) maverick; urgency=low
407
408 * Initial packaging for ubuntuone-dev-tools. (LP:#610576)
409
410=== modified file 'debian/control'
411--- debian/control 2010-08-02 13:45:54 +0000
412+++ debian/control 2010-11-30 19:41:01 +0000
413@@ -5,20 +5,23 @@
414 Priority: optional
415 Standards-Version: 3.9.1
416 Build-Depends-Indep:
417+ dbus,
418+ pep8,
419+ pylint (>= 0.21.0),
420+ python-coverage,
421+ python-dbus,
422+ python-gobject,
423 python-setuptools,
424 python-support,
425- python-xdg,
426 python-twisted-core,
427- python-dbus,
428- python-oauth,
429- pylint (>= 0.21.0)
430+ python-xdg
431 Build-Depends: cdbs (>= 0.4.43), debhelper (>= 7.0.17), python-all
432 Homepage: http://launchpad.net/ubuntuone-dev-tools
433
434 Package: python-ubuntuone-devtools
435 Architecture: all
436 Depends: ${python:Depends}, ${misc:Depends},
437- python-oauth,
438+ dbus,
439 python-dbus
440 Description: Ubuntu One development tools - Python modules
441 Ubuntu One development tools provides scripts, test cases, and other
442@@ -29,8 +32,11 @@
443 Package: ubuntuone-dev-tools
444 Architecture: all
445 Depends: ${python:Depends}, ${misc:Depends}, python,
446+ pylint (>= 0.21.0) | pyflakes,
447+ python-coverage,
448+ python-gobject,
449+ python-twisted-core,
450 python-ubuntuone-devtools (= ${binary:Version}),
451- python-twisted-core,
452 python-xdg
453 Description: Ubuntu One development tools
454 Ubuntu One development tools provides scripts, test cases, and other
455
456=== modified file 'debian/rules'
457--- debian/rules 2010-08-02 13:45:54 +0000
458+++ debian/rules 2010-11-30 19:41:01 +0000
459@@ -6,7 +6,7 @@
460
461 common-build-arch common-build-indep:: debian/stamp-check
462 debian/stamp-check:
463- cd $(DEB_SRCDIR) && $(call cdbs_python_binary,python$(cdbs_python_compile_version)) $(DEB_PYTHON_SETUP_CMD) lint
464+ cd $(DEB_SRCDIR) && ./run-tests
465 touch $@
466
467 makefile-clean::
468
469=== modified file 'debian/watch'
470--- debian/watch 2010-08-02 13:45:54 +0000
471+++ debian/watch 2010-11-30 19:41:01 +0000
472@@ -1,3 +1,3 @@
473 version=3
474-http://launchpad.net/ubuntuone-dev-tools/+download .*/ubuntuone-dev-tools-([0-9.]+)\.tar\.bz2
475+http://launchpad.net/ubuntuone-dev-tools/+download .*/ubuntuone-dev-tools-([0-9.]+)\.tar\.gz
476
477
478=== modified file 'pylintrc'
479--- pylintrc 2010-08-02 13:45:54 +0000
480+++ pylintrc 2010-11-30 19:41:01 +0000
481@@ -1,39 +1,137 @@
482 # lint Python modules using external checkers.
483 #
484-# This is the main checker controling the other ones and the reports
485+# This is the main checker controlling the other ones and the reports
486 # generation. It is itself both a raw checker and an astng checker in order
487 # to:
488 # * handle message activation / deactivation at the module level
489-# * handle some basic but necessary stats data (number of classes, methods...)
490+# * handle some basic but necessary stats'data (number of classes, methods...)
491 #
492 [MASTER]
493-# Set the cache size for astng objects.
494-cache-size=500
495+
496+# Specify a configuration file.
497+#rcfile=
498+
499+# Python code to execute, usually for sys.path manipulation such as
500+# pygtk.require().
501+#init-hook=
502+
503+# Profiled execution.
504+profile=no
505+
506+# Add <file or directory> to the black list. It should be a base name, not a
507+# path. You may set this option multiple times.
508+#ignore=<somedir>
509+
510+# Pickle collected data for later comparisons.
511+persistent=no
512+
513+# List of plugins (as comma separated values of python modules names) to load,
514+# usually to register additional checkers.
515+load-plugins=
516+
517
518 [MESSAGES CONTROL]
519-# Disable some checkers
520+
521+# Enable only checker(s) with the given id(s). This option conflicts with the
522+# disable-checker option
523+#enable-checker=
524+
525+# Enable all checker(s) except those with the given id(s). This option
526+# conflicts with the enable-checker option
527+#disable-checker=
528+
529+# Enable all messages in the listed categories.
530+#enable-cat=
531+
532 # Disable all messages in the listed categories.
533-# Disable the message(s) with the given id(s).
534-# :E0101: *Explicit return in __init__*
535-# :E0202: An attribute inherited from %s hide this method
536-# :W0142: *Used * or ** magic*
537-# :W0201: Attribute '%s' defined outside __init__
538-# :W0221: *Arguments number differs from %s method* (pylint is confused by * and **)
539-# :W0613: *Unused argument %r* (We get lots of these from interfaces)
540-# :W0621: *Redefining name %r from outer scope (line %s)* (pylint does a poor evaluation)
541-# :W0622: *Redefining built-in '%r'
542-disable=typecheck,design,similarities,R,I,E0101,E0202,W0142,W0201,W0221,W0613,W0621,W0622,C0322
543+#disable-cat=
544+
545+# Disable the message(s) with the given id(s) or categories
546+# W0142: Used * or ** magic
547+# W0221: Arguments number differs from %s method (pylint is confused by * and **)
548+# W0613: Unused argument %r (We get lots of these from interfaces)
549+disable=R,I,W0142,W0221,W0613
550
551
552 [REPORTS]
553-# Tells wether to display a full report or only the messages
554+
555+# Set the output format. Available formats are text, parseable, colorized, msvs
556+# (visual studio) and html
557+output-format=colorized
558+
559+# Include message's id in output
560+include-ids=yes
561+
562+# Put messages in a separate file for each module / package specified on the
563+# command line instead of printing them on stdout. Reports (if any) will be
564+# written in a file name "pylint_global.[txt|html]".
565+files-output=no
566+
567+# Tells whether to display a full report or only the messages
568 reports=no
569
570+# Python expression which should return a note less than 10 (10 is the highest
571+# note). You have access to the variables errors warning, statement which
572+# respectively contain the number of errors / warnings messages and the total
573+# number of statements analyzed. This is used by the global evaluation report
574+# (R0004).
575+evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
576+
577+# Add a comment according to your evaluation note. This is used by the global
578+# evaluation report (R0004).
579+comment=no
580+
581+# Enable the report(s) with the given id(s).
582+#enable-report=
583+
584+# Disable the report(s) with the given id(s).
585+#disable-report=
586+
587+
588+# try to find bugs in the code using type inference
589+#
590+[TYPECHECK]
591+
592+# Tells whether missing members accessed in mixin class should be ignored. A
593+# mixin class is detected if its name ends with "mixin" (case insensitive).
594+ignore-mixin-members=yes
595+
596+# List of classes names for which member attributes should not be checked
597+# (useful for classes with attributes dynamically set).
598+ignored-classes=
599+
600+# When zope mode is activated, add a predefined set of Zope acquired attributes
601+# to generated-members.
602+zope=no
603+
604+# List of members which are set dynamically and missed by pylint inference
605+# system, and so shouldn't trigger E0201 when accessed.
606+generated-members=REQUEST,acl_users,aq_parent
607+
608+
609+# checks for
610+# * unused variables / imports
611+# * undefined variables
612+# * redefinition of variable from builtins or from an outer scope
613+# * use of variable before assignment
614+#
615+[VARIABLES]
616+
617+# Tells whether we should check for unused import in __init__ files.
618+init-import=yes
619+
620+# A regular expression matching names used for dummy variables (i.e. not used).
621+dummy-variables-rgx=_|dummy
622+
623+# List of additional names supposed to be defined in builtins. Remember that
624+# you should avoid to define new builtins when possible.
625+additional-builtins=
626+
627
628 # checks for :
629 # * doc strings
630 # * modules / classes / functions / methods / arguments / variables name
631-# * number of arguments, local variables, branchs, returns and statements in
632+# * number of arguments, local variables, branches, returns and statements in
633 # functions, methods
634 # * required module attributes
635 # * dangerous default values as arguments
636@@ -41,7 +139,6 @@
637 # * uses of the global statement
638 #
639 [BASIC]
640-enable-basic=yes
641
642 # Required attributes for module, separated by a comma
643 required-attributes=
644@@ -54,34 +151,32 @@
645 module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
646
647 # Regular expression which should only match correct module level names
648-const-rgx=([a-z_][a-z0-9_]*|[A-Z_][A-Z0-9_]*)$
649+const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
650
651 # Regular expression which should only match correct class names
652 class-rgx=[A-Z_][a-zA-Z0-9]+$
653
654 # Regular expression which should only match correct function names
655-function-rgx=[a-z_][a-zA-Z0-9_]*$
656+function-rgx=[a-z_][a-z0-9_]{2,79}$
657
658 # Regular expression which should only match correct method names
659-method-rgx=[a-z_][a-zA-Z0-9_]*$
660+method-rgx=([a-z_][a-z0-9_]{2,79}$|setUp|tearDown)
661
662 # Regular expression which should only match correct instance attribute names
663-attr-rgx=[a-z_][a-zA-Z0-9_]*$
664+attr-rgx=[a-z_][a-z0-9_]{1,30}$
665
666 # Regular expression which should only match correct argument names
667-argument-rgx=[a-z_][a-zA-Z0-9_]{1,30}$
668+argument-rgx=[a-z_][a-z0-9_]{1,30}$
669
670 # Regular expression which should only match correct variable names
671-# They are normally all lowercase, but when a constant, they are all uppercase.
672-variable-rgx=([a-z_][a-z0-9_]*|[A-Z_][A-Z0-9_]*)$
673+variable-rgx=[a-z_][a-z0-9_]{1,30}$
674
675 # Regular expression which should only match correct list comprehension /
676 # generator expression variable names
677 inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
678
679 # Good variable names which should always be accepted, separated by a comma
680-# Update this to supress warnings about inherrited names (C0103)
681-good-names=_,a,b,c,i,j,k,v,d,f,s,t,l,ex,_,orderBy,getByName,clauseTables
682+good-names=d,e,f,g,i,j,k,ex,logger,Run,_
683
684 # Bad variable names which should always be refused, separated by a comma
685 bad-names=foo,bar,baz,toto,tutu,tata
686@@ -90,13 +185,80 @@
687 bad-functions=apply,input,reduce
688
689
690-# checks for:
691-# * warning notes in the code like FIXME, XXX
692-# * PEP 263: source code with non ascii character but no encoding declaration
693-#
694-[MISCELLANEOUS]
695-# List of note tags to take in consideration, separated by a comma.
696-notes=FIXME,XXX,TODO,fixme,todo
697+# checks for sign of poor/misdesign:
698+# * number of methods, attributes, local variables...
699+# * size, complexity of functions, methods
700+#
701+[DESIGN]
702+
703+# Maximum number of arguments for function / method
704+max-args=5
705+
706+# Maximum number of locals for function / method body
707+max-locals=15
708+
709+# Maximum number of return / yield for function / method body
710+max-returns=6
711+
712+# Maximum number of branch for function / method body
713+max-branchs=12
714+
715+# Maximum number of statements in function / method body
716+max-statements=50
717+
718+# Maximum number of parents for a class (see R0901).
719+max-parents=7
720+
721+# Maximum number of attributes for a class (see R0902).
722+max-attributes=7
723+
724+# Minimum number of public methods for a class (see R0903).
725+min-public-methods=2
726+
727+# Maximum number of public methods for a class (see R0904).
728+max-public-methods=20
729+
730+
731+# checks for :
732+# * methods without self as first argument
733+# * overridden methods signature
734+# * access only to existent members via self
735+# * attributes not defined in the __init__ method
736+# * supported interfaces implementation
737+# * unreachable code
738+#
739+[CLASSES]
740+
741+# List of interface methods to ignore, separated by a comma. This is used for
742+# instance to not check methods defines in Zopes Interface base class.
743+#ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by,providedBy
744+
745+# List of method names used to declare (i.e. assign) instance attributes.
746+defining-attr-methods=__init__,__new__,setUp
747+
748+
749+# checks for
750+# * external modules dependencies
751+# * relative / wildcard imports
752+# * cyclic imports
753+# * uses of deprecated modules
754+#
755+[IMPORTS]
756+
757+# Deprecated modules which should not be used, separated by a comma
758+deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
759+
760+# Create a graph of every (i.e. internal and external) dependencies in the
761+# given file (report RP0402 must not be disabled)
762+import-graph=
763+
764+# Create a graph of external dependencies in the given file (report RP0402 must
765+# not be disabled)
766+ext-import-graph=
767+
768+# Create a graph of internal dependencies in the given file (report RP0402 must
769+# not be disabled)
770+int-import-graph=
771
772
773 # checks for :
774@@ -106,10 +268,9 @@
775 # * use of <> instead of !=
776 #
777 [FORMAT]
778-enable-format=yes
779
780 # Maximum number of characters on a single line.
781-max-line-length=80
782+max-line-length=79
783
784 # Maximum number of lines in a module
785 max-module-lines=2000
786@@ -117,3 +278,29 @@
787 # String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
788 # tab).
789 indent-string=' '
790+
791+
792+# checks for similarities and duplicated code. This computation may be
793+# memory / CPU intensive, so you should disable it if you experiments some
794+# problems.
795+#
796+[SIMILARITIES]
797+
798+# Minimum lines number of a similarity.
799+min-similarity-lines=4
800+
801+# Ignore comments when computing similarities.
802+ignore-comments=yes
803+
804+# Ignore docstrings when computing similarities.
805+ignore-docstrings=yes
806+
807+
808+# checks for:
809+# * warning notes in the code like FIXME, XXX
810+# * PEP 263: source code with non ascii character but no encoding declaration
811+#
812+[MISCELLANEOUS]
813+
814+# List of note tags to take in consideration, separated by a comma.
815+notes=FIXME,XXX,TODO,fixme,xxx,todo
816
817=== added file 'run-tests'
818--- run-tests 1970-01-01 00:00:00 +0000
819+++ run-tests 2010-11-30 19:41:01 +0000
820@@ -0,0 +1,23 @@
821+#!/bin/bash
822+# Author: Natalia Bidart <natalia.bidart@canonical.com>
823+#
824+# Copyright 2010 Canonical Ltd.
825+#
826+# This program is free software: you can redistribute it and/or modify it
827+# under the terms of the GNU General Public License version 3, as published
828+# by the Free Software Foundation.
829+#
830+# This program is distributed in the hope that it will be useful, but
831+# WITHOUT ANY WARRANTY; without even the implied warranties of
832+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
833+# PURPOSE. See the GNU General Public License for more details.
834+#
835+# You should have received a copy of the GNU General Public License along
836+# with this program. If not, see <http://www.gnu.org/licenses/>.
837+set -e
838+
839+bin/u1trial -c ubuntuone
840+bin/u1lint
841+pep8 --repeat .
842+rm -rf _trial_temp
843+rm -rf .coverage
844
845=== modified file 'setup.py'
846--- setup.py 2010-08-02 13:45:54 +0000
847+++ setup.py 2010-11-30 19:41:01 +0000
848@@ -21,10 +21,11 @@
849 from distutils.core import setup, Command
850
851 PACKAGE = 'ubuntuone-dev-tools'
852-VERSION = '0.1.1'
853+VERSION = '0.1.2'
854
855 U1LINT = 'bin/u1lint'
856
857+
858 class Lint(Command):
859 """Command to run the lint checks."""
860 description = 'run python lint checks'
861@@ -37,7 +38,7 @@
862 def finalize_options(self):
863 pass
864
865- def run (self):
866+ def run(self):
867 """Run u1lint to check the code."""
868 retcode = subprocess.call([U1LINT])
869 if retcode != 0:
870@@ -48,21 +49,20 @@
871 description='Ubuntu One development tools and utilities',
872 url='http://launchpad.net/ubuntuone-dev-tools',
873 packages=['ubuntuone',
874- 'ubuntuone.devtools'],
875+ 'ubuntuone.devtools',
876+ 'ubuntuone.devtools.services'],
877 scripts=['bin/u1lint',
878 'bin/u1trial',
879 ],
880 data_files=[('share/%s' % PACKAGE,
881 ['pylintrc',
882- 'data/dbus-session.conf']
883- ),
884+ 'data/dbus-session.conf']),
885 ('share/man/man1',
886 ['man/u1lint.1',
887- 'man/u1trial.1',]
888- ),
889+ 'man/u1trial.1']),
890 ],
891
892- cmdclass = {
893- 'lint' : Lint,
894+ cmdclass={
895+ 'lint': Lint,
896 },
897 )
898
899=== modified file 'ubuntuone/devtools/__init__.py'
900--- ubuntuone/devtools/__init__.py 2010-08-02 13:45:54 +0000
901+++ ubuntuone/devtools/__init__.py 2010-11-30 19:41:01 +0000
902@@ -1,2 +1,1 @@
903 """Testing utilities for Ubuntu One client code."""
904-
905
906=== removed file 'ubuntuone/devtools/dbus_util.py'
907--- ubuntuone/devtools/dbus_util.py 2010-08-02 13:45:54 +0000
908+++ ubuntuone/devtools/dbus_util.py 1970-01-01 00:00:00 +0000
909@@ -1,89 +0,0 @@
910-#
911-# Author: Guillermo Gonzalez <guillermo.gonzalez@canonical.com>
912-#
913-# Copyright 2009-2010 Canonical Ltd.
914-#
915-# This program is free software: you can redistribute it and/or modify it
916-# under the terms of the GNU General Public License version 3, as published
917-# by the Free Software Foundation.
918-#
919-# This program is distributed in the hope that it will be useful, but
920-# WITHOUT ANY WARRANTY; without even the implied warranties of
921-# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
922-# PURPOSE. See the GNU General Public License for more details.
923-#
924-# You should have received a copy of the GNU General Public License along
925-# with this program. If not, see <http://www.gnu.org/licenses/>.
926-"""Utilities for finding and running a dbus session bus for testing."""
927-
928-import os
929-import signal
930-import subprocess
931-
932-from distutils.spawn import find_executable
933-from xdg.BaseDirectory import load_data_paths
934-
935-
936-class DBusLaunchError(Exception):
937- """Error while launching dbus-daemon"""
938- pass
939-
940-class NotFoundError(Exception):
941- """Not found error"""
942- pass
943-
944-
945-class DBusRunner(object):
946- """Class for running dbus-daemon with a private session."""
947-
948- def __init__(self):
949- self.dbus_address = None
950- self.dbus_pid = None
951- self.running = False
952-
953- def _find_config_file(self):
954- """Find the first appropriate dbus-session.conf to use."""
955- # In case we're running from within the source tree
956- path = os.path.join(os.path.dirname(__file__), "..", "..",
957- "data", "dbus-session.conf")
958- if os.path.exists(path):
959- return path
960-
961- # Use the installed file in $pkgdatadir
962- for i in load_data_paths("ubuntuone-dev-tools", "dbus-session.conf"):
963- if os.path.exists(i):
964- return i
965-
966-
967- def startDBus(self):
968- """Start our own session bus daemon for testing."""
969- dbus = find_executable("dbus-daemon")
970- if not dbus:
971- raise NotFoundError("dbus-daemon was not found.")
972-
973- config_file = self._find_config_file()
974-
975- dbus_args = ["--fork",
976- "--config-file=" + config_file,
977- "--print-address=1",
978- "--print-pid=2"]
979- p = subprocess.Popen([dbus] + dbus_args,
980- bufsize=4096, stdout=subprocess.PIPE,
981- stderr=subprocess.PIPE)
982-
983- self.dbus_address = "".join(p.stdout.readlines()).strip()
984- self.dbus_pid = int("".join(p.stderr.readlines()).strip())
985-
986- if self.dbus_address != "":
987- os.environ["DBUS_SESSION_BUS_ADDRESS"] = self.dbus_address
988- else:
989- os.kill(self.dbus_pid, signal.SIGKILL)
990- raise DBusLaunchError("There was a problem launching dbus-daemon.")
991- self.running = True
992-
993- def stopDBus(self):
994- """Stop our DBus session bus daemon."""
995- del os.environ["DBUS_SESSION_BUS_ADDRESS"]
996- os.kill(self.dbus_pid, signal.SIGKILL)
997- self.running = False
998-
999
1000=== added file 'ubuntuone/devtools/handlers.py'
1001--- ubuntuone/devtools/handlers.py 1970-01-01 00:00:00 +0000
1002+++ ubuntuone/devtools/handlers.py 2010-11-30 19:41:01 +0000
1003@@ -0,0 +1,64 @@
1004+# -*- coding: utf-8 -*-
1005+
1006+# Author: Guillermo Gonzalez <guillermo.gonzalez@canonical.com>
1007+# Author: Facundo Batista <facundo@canonical.com>
1008+#
1009+# Copyright 2009-2010 Canonical Ltd.
1010+#
1011+# This program is free software: you can redistribute it and/or modify it
1012+# under the terms of the GNU General Public License version 3, as published
1013+# by the Free Software Foundation.
1014+#
1015+# This program is distributed in the hope that it will be useful, but
1016+# WITHOUT ANY WARRANTY; without even the implied warranties of
1017+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1018+# PURPOSE. See the GNU General Public License for more details.
1019+#
1020+# You should have received a copy of the GNU General Public License along
1021+# with this program. If not, see <http://www.gnu.org/licenses/>.
1022+
1023+"""Set of helpers handlers."""
1024+
1025+import logging
1026+
1027+
1028+class MementoHandler(logging.Handler):
1029+ """ A handler class which store logging records in a list """
1030+
1031+ def __init__(self, *args, **kwargs):
1032+ """ Create the instance, and add a records attribute. """
1033+ logging.Handler.__init__(self, *args, **kwargs)
1034+ self.records = []
1035+ self.debug = False
1036+
1037+ def emit(self, record):
1038+ """ Just add the record to self.records. """
1039+ self.format(record)
1040+ self.records.append(record)
1041+
1042+ def check(self, level, *msgs):
1043+ """Verifies that the msgs are logged in the specified level."""
1044+ for rec in self.records:
1045+ if rec.levelno == level and all(m in rec.message for m in msgs):
1046+ return True
1047+ if self.debug:
1048+ recorded = [(logging.getLevelName(r.levelno), r.message)
1049+ for r in self.records]
1050+ print "Memento messages:", recorded
1051+ return False
1052+
1053+ def check_debug(self, *msgs):
1054+ """Shortcut for checking in DEBUG."""
1055+ return self.check(logging.DEBUG, *msgs)
1056+
1057+ def check_info(self, *msgs):
1058+ """Shortcut for checking in INFO."""
1059+ return self.check(logging.INFO, *msgs)
1060+
1061+ def check_warning(self, *msgs):
1062+ """Shortcut for checking in WARNING."""
1063+ return self.check(logging.WARNING, *msgs)
1064+
1065+ def check_error(self, *msgs):
1066+ """Shortcut for checking in ERROR."""
1067+ return self.check(logging.ERROR, *msgs)
1068
1069=== added directory 'ubuntuone/devtools/services'
1070=== added file 'ubuntuone/devtools/services/__init__.py'
1071--- ubuntuone/devtools/services/__init__.py 1970-01-01 00:00:00 +0000
1072+++ ubuntuone/devtools/services/__init__.py 2010-11-30 19:41:01 +0000
1073@@ -0,0 +1,1 @@
1074+"""Service runners for testing."""
1075
1076=== added file 'ubuntuone/devtools/services/dbus.py'
1077--- ubuntuone/devtools/services/dbus.py 1970-01-01 00:00:00 +0000
1078+++ ubuntuone/devtools/services/dbus.py 2010-11-30 19:41:01 +0000
1079@@ -0,0 +1,94 @@
1080+#
1081+# Author: Guillermo Gonzalez <guillermo.gonzalez@canonical.com>
1082+#
1083+# Copyright 2009-2010 Canonical Ltd.
1084+#
1085+# This program is free software: you can redistribute it and/or modify it
1086+# under the terms of the GNU General Public License version 3, as published
1087+# by the Free Software Foundation.
1088+#
1089+# This program is distributed in the hope that it will be useful, but
1090+# WITHOUT ANY WARRANTY; without even the implied warranties of
1091+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1092+# PURPOSE. See the GNU General Public License for more details.
1093+#
1094+# You should have received a copy of the GNU General Public License along
1095+# with this program. If not, see <http://www.gnu.org/licenses/>.
1096+"""Utilities for finding and running a dbus session bus for testing."""
1097+
1098+import os
1099+import signal
1100+import subprocess
1101+
1102+from distutils.spawn import find_executable
1103+from xdg.BaseDirectory import load_data_paths
1104+
1105+
1106+class DBusLaunchError(Exception):
1107+ """Error while launching dbus-daemon"""
1108+ pass
1109+
1110+
1111+class NotFoundError(Exception):
1112+ """Not found error"""
1113+ pass
1114+
1115+
1116+class DBusRunner(object):
1117+ """Class for running dbus-daemon with a private session."""
1118+
1119+ def __init__(self):
1120+ self.dbus_address = None
1121+ self.dbus_pid = None
1122+ self.running = False
1123+
1124+ def _find_config_file(self):
1125+ """Find the first appropriate dbus-session.conf to use."""
1126+ # In case we're running from within the source tree
1127+ path = os.path.join(os.path.dirname(__file__), "..", "..", ".."
1128+ "data", "dbus-session.conf")
1129+ if os.path.exists(path):
1130+ return path
1131+
1132+ # Use the installed file in $pkgdatadir
1133+ for i in load_data_paths("ubuntuone-dev-tools", "dbus-session.conf"):
1134+ if os.path.exists(i):
1135+ return i
1136+
1137+ def start_service(self, tempdir=None):
1138+ """Start our own session bus daemon for testing."""
1139+ if not tempdir:
1140+ tempdir = os.path.join(os.getcwd(), '_trial_temp')
1141+ dbus = find_executable("dbus-daemon")
1142+ if not dbus:
1143+ raise NotFoundError("dbus-daemon was not found.")
1144+
1145+ config_file = self._find_config_file()
1146+
1147+ dbus_args = ["--fork",
1148+ "--config-file=" + config_file,
1149+ "--print-address=1",
1150+ "--print-pid=2",
1151+ "--address=unix:tmpdir=%s" % tempdir]
1152+ sp = subprocess.Popen([dbus] + dbus_args,
1153+ bufsize=4096, stdout=subprocess.PIPE,
1154+ stderr=subprocess.PIPE)
1155+
1156+ self.dbus_address = "".join(sp.stdout.readlines()).strip()
1157+ self.dbus_pid = int("".join(sp.stderr.readlines()).strip())
1158+
1159+ if self.dbus_address != "":
1160+ os.environ["DBUS_SESSION_BUS_ADDRESS"] = self.dbus_address
1161+ else:
1162+ os.kill(self.dbus_pid, signal.SIGKILL)
1163+ raise DBusLaunchError("There was a problem launching dbus-daemon.")
1164+ self.running = True
1165+
1166+ def stop_service(self):
1167+ """Stop our DBus session bus daemon."""
1168+ try:
1169+ del os.environ["DBUS_SESSION_BUS_ADDRESS"]
1170+ except KeyError:
1171+ pass
1172+ os.kill(self.dbus_pid, signal.SIGKILL)
1173+ self.running = False
1174
1175=== modified file 'ubuntuone/devtools/testcase.py'
1176--- ubuntuone/devtools/testcase.py 2010-08-02 13:45:54 +0000
1177+++ ubuntuone/devtools/testcase.py 2010-11-30 19:41:01 +0000
1178@@ -1,4 +1,5 @@
1179-#
1180+# -*- coding: utf-8 -*-
1181+
1182 # Author: Guillermo Gonzalez <guillermo.gonzalez@canonical.com>
1183 #
1184 # Copyright 2009-2010 Canonical Ltd.
1185@@ -14,19 +15,26 @@
1186 #
1187 # You should have received a copy of the GNU General Public License along
1188 # with this program. If not, see <http://www.gnu.org/licenses/>.
1189-""" Base tests cases and test utilities """
1190+
1191+"""Base tests cases and test utilities."""
1192+
1193 from __future__ import with_statement
1194
1195-import dbus
1196-from dbus.mainloop.glib import DBusGMainLoop
1197 import contextlib
1198 import os
1199 import shutil
1200
1201+import dbus
1202+import dbus.service
1203+
1204+from dbus.mainloop.glib import DBusGMainLoop
1205+
1206 from twisted.internet import defer
1207 from twisted.python import failure
1208-from unittest import TestCase
1209-from oauth import oauth
1210+from twisted.trial.unittest import TestCase
1211+
1212+# DBusRunner for DBusTestCase using tests
1213+from ubuntuone.devtools.services.dbus import DBusRunner
1214
1215
1216 @contextlib.contextmanager
1217@@ -41,21 +49,9 @@
1218 os.environ[env_var] = old_value
1219
1220
1221-class FakeOAuthClient(object):
1222- """ Fake OAuthClient"""
1223-
1224- def __init__(self, realm):
1225- """ create the instance. """
1226- self.realm = realm
1227- self.consumer = oauth.OAuthConsumer('ubuntuone', 'hammertime')
1228-
1229- def get_access_token(self):
1230- """ returns a Token"""
1231- return 'a token'
1232-
1233-
1234 class FakeDBusInterface(object):
1235 """A fake DBusInterface..."""
1236+
1237 def shutdown(self, with_restart=False):
1238 """...that only knows how to go away"""
1239
1240@@ -67,10 +63,15 @@
1241 mktemp(name): helper to create temporary dirs
1242 rmtree(path): support read-only shares
1243 makedirs(path): support read-only shares
1244+
1245 """
1246
1247+ def required_services(self):
1248+ """Return the list of required services for DBusTestCase."""
1249+ return []
1250+
1251 def mktemp(self, name='temp'):
1252- """ Customized mktemp that accepts an optional name argument. """
1253+ """Customized mktemp that accepts an optional name argument."""
1254 tempdir = os.path.join(self.tmpdir, name)
1255 if os.path.exists(tempdir):
1256 self.rmtree(tempdir)
1257@@ -84,10 +85,10 @@
1258 root_dir = getattr(self, '__root', None)
1259 if root_dir:
1260 return root_dir
1261- MAX_FILENAME = 32 # some platforms limit lengths of filenames
1262- base = os.path.join(self.__class__.__module__[:MAX_FILENAME],
1263- self.__class__.__name__[:MAX_FILENAME],
1264- self._testMethodName[:MAX_FILENAME])
1265+ max_filename = 32 # some platforms limit lengths of filenames
1266+ base = os.path.join(self.__class__.__module__[:max_filename],
1267+ self.__class__.__name__[:max_filename],
1268+ self._testMethodName[:max_filename])
1269 # use _trial_temp dir, it should be os.gwtcwd()
1270 # define the root temp dir of the testcase, pylint: disable=W0201
1271 self.__root = os.path.join(os.getcwd(), base)
1272@@ -116,19 +117,20 @@
1273 os.chmod(parent, 0755)
1274 os.makedirs(path)
1275
1276- def setUp(self):
1277- TestCase.setUp(self)
1278-
1279- def tearDown(self):
1280- """ cleanup the temp dir. """
1281- return TestCase.tearDown(self)
1282-
1283
1284 class DBusTestCase(BaseTestCase):
1285- """ Test the DBus event handling """
1286+ """Test the DBus event handling."""
1287+
1288+ def required_services(self):
1289+ """Return the list of required services for DBusTestCase."""
1290+ services = super(DBusTestCase, self).required_services()
1291+ services.extend([DBusRunner])
1292+ return services
1293
1294 def setUp(self):
1295- """ Setup the infrastructure fo the test (dbus service). """
1296+ """Setup the infrastructure fo the test (dbus service)."""
1297+ # Class 'BaseTestCase' has no 'setUp' member
1298+ # pylint: disable=E1101
1299 BaseTestCase.setUp(self)
1300 self.loop = DBusGMainLoop(set_as_default=True)
1301 self.bus = dbus.bus.BusConnection(mainloop=self.loop)
1302@@ -139,29 +141,32 @@
1303 self.signal_receivers = set()
1304
1305 def tearDown(self):
1306- """ Cleanup the test. """
1307+ """Cleanup the test."""
1308+ # Class 'BaseTestCase' has no 'tearDown' member
1309+ # pylint: disable=E1101
1310 d = self.cleanup_signal_receivers(self.signal_receivers)
1311- d.addBoth(self._tearDown)
1312+ d.addBoth(self._tear_down)
1313 d.addBoth(lambda _: BaseTestCase.tearDown(self))
1314 return d
1315
1316- def _tearDown(self):
1317- """ shutdown """
1318+ def _tear_down(self):
1319+ """Shutdown."""
1320 self.bus.flush()
1321 self.bus.close()
1322
1323 def error_handler(self, error):
1324- """ default error handler for DBus calls. """
1325+ """Default error handler for DBus calls."""
1326 if isinstance(error, failure.Failure):
1327 self.fail(error.getErrorMessage())
1328
1329 def cleanup_signal_receivers(self, signal_receivers):
1330- """ cleanup self.signal_receivers and returns a deferred """
1331+ """Cleanup self.signal_receivers and returns a deferred."""
1332 deferreds = []
1333 for match in signal_receivers:
1334 d = defer.Deferred()
1335+
1336 def callback(*args):
1337- """ callback that accepts *args. """
1338+ """Callback that accepts *args."""
1339 if not d.called:
1340 d.callback(args)
1341 self.bus.call_async(dbus.bus.BUS_DAEMON_NAME,
1342@@ -173,4 +178,3 @@
1343 return defer.DeferredList(deferreds)
1344 else:
1345 return defer.succeed(True)
1346-

Subscribers

People subscribed via source and target branches

to all changes: