Merge lp:~barry/window-mocker/py3qt5 into lp:window-mocker

Proposed by Barry Warsaw
Status: Merged
Approved by: Thomi Richards
Approved revision: 42
Merged at revision: 25
Proposed branch: lp:~barry/window-mocker/py3qt5
Merge into: lp:window-mocker
Diff against target: 663 lines (+148/-90)
17 files modified
.bzrignore (+2/-0)
MANIFEST.in (+2/-0)
bin/window-mocker (+6/-4)
debian/changelog (+17/-0)
debian/control (+6/-4)
debian/copyright (+1/-1)
debian/rules (+1/-0)
setup.py (+3/-3)
tests/__init__.py (+1/-1)
tests/test_app_functional.py (+26/-22)
tests/test_plugins.py (+19/-9)
tests/test_testapp_module_functions.py (+30/-16)
windowmocker/__init__.py (+13/-11)
windowmocker/plugins/__init__.py (+3/-3)
windowmocker/plugins/base.py (+9/-6)
windowmocker/plugins/qt4.py (+4/-5)
windowmocker/plugins/qt5.py (+5/-5)
To merge this branch: bzr merge lp:~barry/window-mocker/py3qt5
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve
Thomi Richards (community) Approve
Review via email: mp+204990@code.launchpad.net

This proposal supersedes a proposal from 2014-01-31.

Description of the change

Now with cgoldberg's branch landed, this is rebased on trunk, and cleans up a few ancillary things.

window-mocker (1.4-0ubuntu1) UNRELEASED; urgency=medium

  * Bump revision to 1.4.
  * Add MANIFEST.in to prune build artifacts from tarball.
  * Clean ups:
    + White space.
    + Use of insecure tempfile.mktemp()
    + Use of non-temporary file names.
    + Use of mutable default arguments.
    + Improve Python 2/3 compatibility.
  * d/control:
    + Add dependency on python{,3}-six for Python 3 compatibility fix.
    + Remove dependency on python3-mock (use unittest.mock instead in Py3).
    + Bump Standards-Version to 3.9.5 with no other changes necessary.

 -- Barry Warsaw <email address hidden> Thu, 30 Jan 2014 13:48:47 +0000

To post a comment you must log in.
Revision history for this message
Corey Goldberg (coreygoldberg) wrote : Posted in a previous version of this proposal

Hi Barry,
I have a pending py3 branch also. Mine is Python 2/3 compatible and can select PyQt4 or PyQt5 in the python3 version.
The reason it has yet to be merged is because of a bug in PyQt5 causing a segfault:

the bug is here:
https://bugs.launchpad.net/window-mocker/+bug/1273306

my branch is here:
https://code.launchpad.net/~coreygoldberg/window-mocker/py3

-Corey

Revision history for this message
Barry Warsaw (barry) wrote : Posted in a previous version of this proposal

Oops, sorry, that is the wrong branch. Let me try again.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Barry Warsaw (barry) wrote : Posted in a previous version of this proposal

Thanks Corey. Sorry for not seeing your mp first. I left a comment on yours:

https://code.launchpad.net/~coreygoldberg/window-mocker/py3/+merge/196978/comments/476977

tl;dr: window-mocker should be Python 3 only to eliminate the Python 2 dependencies. I'll leave the PyQt4/5 decisions to you guys, but it's pretty easy to switch between the two (I could make it easier yet by fiddling with the imports), as long as you don't need to speak both versions. Maybe supporting both makes transition easier?

Revision history for this message
Barry Warsaw (barry) wrote : Posted in a previous version of this proposal

FWIW, I think this is blocking my autopilot reexec branch:

https://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-trusty/2434/console

so it would be good to resolve the issue and get this landed asap. Is there anything I can do to help move it along?

Revision history for this message
Barry Warsaw (barry) wrote : Posted in a previous version of this proposal

After chatting w/thomi on IRC, it sounds like cgoldberg's branch is more aligned with the immediate needs, and thomi has reviewed it and says it looks good. WFM! Landing cgoldberg's branch will unblock my autopilot work, so let's do that asap, and if anything more is needed later, we can handle that.

It does mean we'll carry Python 2 stuff around for now, but that's just cruft that will eventually bitrot in the archive or get cleaned up later.

One note: we found one place in the unity7 test suite that imports windowmocker. It does it for silly reasons though afaict (since it only does it to see if window-mocker is available, but that could easily be done in other ways). AFAICT, windowmocker the module is never used outside of /usr/bin/window-mocker*, except for this one case of unity7, which should be easy to fix.

Or do you know of anything else that imports windowmocker?

lp:~barry/window-mocker/py3qt5 updated
42. By Barry Warsaw

Revert a few previous changes. Fix some typos.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Thomi Richards (thomir-deactivatedaccount) wrote :

LGTM

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file '.bzrignore'
2--- .bzrignore 1970-01-01 00:00:00 +0000
3+++ .bzrignore 2014-02-05 16:22:14 +0000
4@@ -0,0 +1,2 @@
5+__pycache__
6+*.egg-info
7
8=== added file 'MANIFEST.in'
9--- MANIFEST.in 1970-01-01 00:00:00 +0000
10+++ MANIFEST.in 2014-02-05 16:22:14 +0000
11@@ -0,0 +1,2 @@
12+prune debian
13+prune dist
14
15=== modified file 'bin/window-mocker'
16--- bin/window-mocker 2014-01-21 20:26:48 +0000
17+++ bin/window-mocker 2014-02-05 16:22:14 +0000
18@@ -1,6 +1,6 @@
19-#!/usr/bin/env python
20+#!/usr/bin/env python3
21 # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
22-# Copyright 2012 Canonical
23+# Copyright 2012-2014 Canonical, Ltd.
24 # Author: Thomi Richards
25 #
26 # This program is free software: you can redistribute it and/or modify it
27@@ -11,8 +11,10 @@
28 import argparse
29 import sys
30
31-from windowmocker import create_application_from_path, create_application_from_data
32-from windowmocker.plugins import get_default_plugin_name, get_registered_plugin_names
33+from windowmocker import (
34+ create_application_from_path, create_application_from_data)
35+from windowmocker.plugins import (
36+ get_default_plugin_name, get_registered_plugin_names)
37
38
39 def main():
40
41=== modified file 'debian/changelog'
42--- debian/changelog 2013-06-05 07:08:45 +0000
43+++ debian/changelog 2014-02-05 16:22:14 +0000
44@@ -1,3 +1,20 @@
45+window-mocker (1.4-0ubuntu1) UNRELEASED; urgency=medium
46+
47+ * Bump revision to 1.4.
48+ * Add MANIFEST.in to prune build artifacts from tarball.
49+ * Clean ups:
50+ + White space.
51+ + Use of insecure tempfile.mktemp()
52+ + Use of non-temporary file names.
53+ + Use of mutable default arguments.
54+ + Improve Python 2/3 compatibility.
55+ * d/control:
56+ + Add dependency on python{,3}-six for Python 3 compatibility fix.
57+ + Remove dependency on python3-mock (use unittest.mock instead in Py3).
58+ + Bump Standards-Version to 3.9.5 with no other changes necessary.
59+
60+ -- Barry Warsaw <barry@ubuntu.com> Thu, 30 Jan 2014 13:48:47 +0000
61+
62 window-mocker (1.3daily13.06.05-0ubuntu1) saucy; urgency=low
63
64 [ Thomi Richards ]
65
66=== modified file 'debian/control'
67--- debian/control 2014-01-09 17:27:37 +0000
68+++ debian/control 2014-02-05 16:22:14 +0000
69@@ -9,15 +9,16 @@
70 python-mock,
71 python-qt4,
72 python-setuptools,
73+ python-six,
74 python-testscenarios,
75- python3,
76+ python3-all,
77 python3-distutils-extra,
78- python3-mock,
79 python3-pyqt4,
80 python3-pyqt5,
81 python3-setuptools,
82+ python3-six,
83 python3-testscenarios,
84-Standards-Version: 3.9.4
85+Standards-Version: 3.9.5
86 # If you aren't a member of ~autopilot but need to upload packaging changes,
87 # just go ahead. ~autopilot will notice and sync up the code again.
88 Vcs-Bzr: http://bazaar.launchpad.net/~autopilot/window-mocker/trunk
89@@ -29,6 +30,7 @@
90 Depends: ${misc:Depends},
91 ${python:Depends},
92 python-qt4,
93+ python-six,
94 Provides: ${python:Provides},
95 Description: create windows and applications from specifications
96 Window Mocker is a simple tool that allows developers to create windows and
97@@ -42,10 +44,10 @@
98 ${python:Depends},
99 python3-pyqt4,
100 python3-pyqt5,
101+ python3-six,
102 Provides: ${python:Provides},
103 Description: create windows and applications from specifications
104 Window Mocker is a simple tool that allows developers to create windows and
105 applications that follow a certain specification. This is especially useful
106 when testing applications that interact with other windows (like a window
107 manager, for example).
108-
109
110=== modified file 'debian/copyright'
111--- debian/copyright 2013-02-07 16:41:10 +0000
112+++ debian/copyright 2014-02-05 16:22:14 +0000
113@@ -2,7 +2,7 @@
114 Source: http://launchpad.net/window-mocker
115
116 Files: *
117-Copyright: 2012 Canonical, Ltd.
118+Copyright: 2012-2014 Canonical, Ltd.
119 License: GPL-3
120
121 License: GPL-3
122
123=== modified file 'debian/rules'
124--- debian/rules 2014-01-17 22:31:40 +0000
125+++ debian/rules 2014-02-05 16:22:14 +0000
126@@ -1,5 +1,6 @@
127 #!/usr/bin/make -f
128
129+#export DH_VERBOSE=1
130 export PYBUILD_NAME=windowmocker
131
132 %:
133
134=== modified file 'setup.py'
135--- setup.py 2014-01-08 20:35:14 +0000
136+++ setup.py 2014-02-05 16:22:14 +0000
137@@ -1,6 +1,6 @@
138-#!/usr/bin/env python
139+#!/usr/bin/env python3
140 # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
141-# Copyright 2012, 2013 Canonical
142+# Copyright 2012-2014 Canonical, Ltd.
143 # Author: Thomi Richards
144 #
145 # This program is free software: you can redistribute it and/or modify it
146@@ -12,7 +12,7 @@
147
148 DistUtilsExtra.auto.setup(
149 name='window-mocker',
150- version='1.3',
151+ version='1.4',
152 description=open('README').read(),
153 author='Thomi Richards',
154 author_email='thomi.richards@canonical.com',
155
156=== modified file 'tests/__init__.py'
157--- tests/__init__.py 2012-09-18 03:20:19 +0000
158+++ tests/__init__.py 2014-02-05 16:22:14 +0000
159@@ -1,5 +1,5 @@
160 # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
161-# Copyright 2012 Canonical
162+# Copyright 2012-2014 Canonical, Ltd.
163 # Author: Thomi Richards
164 #
165 # This program is free software: you can redistribute it and/or modify it
166
167=== modified file 'tests/test_app_functional.py'
168--- tests/test_app_functional.py 2014-01-21 20:56:11 +0000
169+++ tests/test_app_functional.py 2014-02-05 16:22:14 +0000
170@@ -1,5 +1,5 @@
171 # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
172-# Copyright 2012, 2013 Canonical
173+# Copyright 2012-2014 Canonical, Ltd.
174 # Author: Thomi Richards
175 #
176 # This program is free software: you can redistribute it and/or modify it
177@@ -8,10 +8,10 @@
178
179 """Functional tests for the window-mocker application."""
180
181-import os.path
182+import os
183 import subprocess
184-import sys
185 import tempfile
186+
187 from time import sleep
188
189 from testtools import TestCase
190@@ -34,7 +34,8 @@
191 if os.path.exists(source_path):
192 return source_path
193
194- return subprocess.check_output(['which', 'window-mocker'])
195+ return subprocess.check_output(['which', 'window-mocker'],
196+ universal_newlines=True)
197
198
199 def run_app_with_args(*args):
200@@ -51,7 +52,8 @@
201 application,
202 stdout=subprocess.PIPE,
203 stderr=subprocess.PIPE,
204- shell=False
205+ shell=False,
206+ universal_newlines=True,
207 )
208
209 stdout = stderr = ""
210@@ -63,7 +65,7 @@
211 print("Killing process.")
212 process.kill()
213 if i == 8:
214- print ("Terminating process.")
215+ print("Terminating process.")
216 process.terminate()
217 sleep(1)
218 stdout, stderr = process.communicate()
219@@ -75,41 +77,43 @@
220 """Functional tests for the window-mocker application."""
221
222 def run_with_spec_content(self, content_string):
223- temp_filename = tempfile.mktemp()
224+ fd, temp_filename = tempfile.mkstemp()
225+ self.addCleanup(os.remove, temp_filename)
226+ os.close(fd)
227 with open(temp_filename, 'w') as f:
228 f.write(content_string)
229- self.addCleanup(os.remove, temp_filename)
230 return run_app_with_args(temp_filename)
231
232 def test_errors_with_missing_file(self):
233 retcode, stdout, stderr = run_app_with_args("bad_file_name")
234- self.assertThat(stdout, Equals(b''))
235- self.assertThat(stderr, Equals(b'Error: Unable to open file: No such file or directory\n'))
236+ self.assertThat(stdout, Equals(''))
237+ self.assertThat(stderr, Equals('Error: Unable to open file: No such file or directory\n'))
238 self.assertThat(retcode, Equals(1))
239
240 def test_errors_with_inaccessible_file(self):
241- file_name = 'cannot_read'
242- with open(file_name, 'w') as f:
243- os.chmod(file_name, 0)
244- self.addCleanup(os.remove, file_name)
245+ fd, temp_filename = tempfile.mkstemp()
246+ self.addCleanup(os.remove, temp_filename)
247+ os.close(fd)
248+ with open(temp_filename, 'w'):
249+ pass
250+ os.chmod(temp_filename, 0)
251
252- retcode, stdout, stderr = run_app_with_args("cannot_read")
253- self.assertThat(stdout, Equals(b''))
254- self.assertThat(stderr, Equals(b'Error: Unable to open file: Permission denied\n'))
255+ retcode, stdout, stderr = run_app_with_args(temp_filename)
256+ self.assertThat(stdout, Equals(''))
257+ self.assertThat(stderr, Equals('Error: Unable to open file: Permission denied\n'))
258 self.assertThat(retcode, Equals(1))
259
260 def test_errors_on_empty_file(self):
261 retcode, stdout, stderr = self.run_with_spec_content("")
262
263- self.assertThat(stdout, Equals(b''))
264+ self.assertThat(stdout, Equals(''))
265 self.assertThat(retcode, Equals(3))
266- self.assertThat(stderr, Equals(b'Error: Unable to process request: No JSON object could be decoded\n'))
267+ self.assertThat(stderr, Equals('Error: Unable to process request: No JSON object could be decoded\n'))
268
269 def test_accepts_testability_command_line_argument(self):
270 retcode, stdout, stderr = run_app_with_args("--help")
271- self.assertThat(stdout.decode('utf-8'), Contains("-testability"))
272+ self.assertThat(stdout, Contains("-testability"))
273
274 def test_accepts_plugin_type_command_line_argument(self):
275 retcode, stdout, stderr = run_app_with_args("--help")
276- output = stdout.decode('utf-8')
277- self.assertThat(stdout.decode('utf-8'), Contains("Qt4"))
278+ self.assertThat(stdout, Contains("Qt4"))
279
280=== modified file 'tests/test_plugins.py'
281--- tests/test_plugins.py 2014-01-15 20:35:41 +0000
282+++ tests/test_plugins.py 2014-02-05 16:22:14 +0000
283@@ -1,22 +1,26 @@
284 # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
285-# Copyright 2012 Canonical
286+# Copyright 2012-2014 Canonical, Ltd.
287 # Author: Thomi Richards
288 #
289 # This program is free software: you can redistribute it and/or modify it
290 # under the terms of the GNU General Public License version 3, as published
291 # by the Free Software Foundation.
292
293-from mock import patch
294 from testscenarios import TestWithScenarios
295 from testtools import TestCase
296 from testtools.matchers import Contains, Equals, raises
297
298+try:
299+ from unittest.mock import patch
300+except ImportError:
301+ from mock import patch
302+
303 from windowmocker.plugins import (
304 base,
305 get_plugin_by_name,
306 register_plugin,
307 register_named_plugin,
308- unregister_plugin_by_name
309+ unregister_plugin_by_name
310 )
311
312 class DummyAppPlugin(base.ApplicationTypePluginBase):
313@@ -76,14 +80,16 @@
314 DummyAppPlugin({})
315
316 self.assertThat(mock_create_window.call_count, Equals(1))
317- self.assertThat(mock_create_window.call_args[0][0], Equals(DummyAppPlugin._window_default))
318+ self.assertThat(mock_create_window.call_args[0][0],
319+ Equals(DummyAppPlugin._window_default))
320
321 @patch.object(DummyAppPlugin, "create_window")
322 def test_calls_create_window_with_defaults_added(self, mock_create_window):
323 DummyAppPlugin({})
324
325 self.assertThat(mock_create_window.call_count, Equals(1))
326- self.assertThat(mock_create_window.call_args[0][0], Equals(DummyAppPlugin._window_default))
327+ self.assertThat(mock_create_window.call_args[0][0],
328+ Equals(DummyAppPlugin._window_default))
329
330 @patch.object(DummyAppPlugin, "create_window")
331 def test_passes_params_to_create_window(self, mock_create_window):
332@@ -103,8 +109,10 @@
333 ])
334
335 self.assertThat(mock_create_window.call_count, Equals(2))
336- self.assertThat(mock_create_window.call_args_list[0][0][0]["Title"], Equals("Window 1"))
337- self.assertThat(mock_create_window.call_args_list[1][0][0]["Title"], Equals("Window 2"))
338+ self.assertThat(mock_create_window.call_args_list[0][0][0]["Title"],
339+ Equals("Window 1"))
340+ self.assertThat(mock_create_window.call_args_list[1][0][0]["Title"],
341+ Equals("Window 2"))
342
343
344 class PluginWindowDefaultParameterTests(TestWithScenarios, TestCase):
345@@ -112,10 +120,12 @@
346 """Tests for various default values for required parameters."""
347
348 scenarios = [
349- ("Window Title", {'name': 'Title', 'expected': 'Default Window Title'}),
350+ ("Window Title",
351+ {'name': 'Title', 'expected': 'Default Window Title'}),
352 ("Maximised", {'name': 'Maximized', 'expected': False}),
353 ("Minimized", {'name': 'Minimized', 'expected': False}),
354- ("MinimizeImmediatelyAfterShow", {'name': 'MinimizeImmediatelyAfterShow', 'expected': False}),
355+ ("MinimizeImmediatelyAfterShow",
356+ {'name': 'MinimizeImmediatelyAfterShow', 'expected': False}),
357 ("Menus", {'name': 'Menu', 'expected': []}),
358 ]
359
360
361=== renamed file 'tests/test_testapp_modlue_functions.py' => 'tests/test_testapp_module_functions.py'
362--- tests/test_testapp_modlue_functions.py 2013-12-16 17:12:58 +0000
363+++ tests/test_testapp_module_functions.py 2014-02-05 16:22:14 +0000
364@@ -1,5 +1,5 @@
365 # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
366-# Copyright 2012, 2013 Canonical
367+# Copyright 2012-2014 Canonical, Ltd.
368 # Author: Thomi Richards
369 #
370 # This program is free software: you can redistribute it and/or modify it
371@@ -8,9 +8,15 @@
372
373
374 import os
375+import tempfile
376+
377 from io import StringIO
378
379-from mock import patch
380+try:
381+ from unittest.mock import patch
382+except ImportError:
383+ from mock import patch
384+
385 from testtools import TestCase
386 from testtools.matchers import raises
387
388@@ -25,19 +31,21 @@
389 """create_application_from_path function must raise IOError when asked
390 to open a file that does not exist.
391 """
392- self.assertThat(lambda: windowmocker.create_application_from_path("_does_not_exist"),
393- raises(IOError))
394+ self.assertThat(lambda: windowmocker.create_application_from_path("_does_not_exist"), raises(IOError))
395
396- def test_create_application_from_path_raises_IOError_on_bad_perms(self):
397- """create_application_from_path function must raise IOError when asked
398- to open a file that does not exist.
399+ def test_create_application_from_path_raises_PermError_on_bad_perms(self):
400+ """create_application_from_path function must raise PermissionError
401+ when the file's permissions do not allow it to be read.
402 """
403- file_name = '_bad_perms'
404- with open(file_name, 'w') as f:
405- os.chmod(file_name, 0)
406- self.addCleanup(os.remove, file_name)
407+ fd, temp_filename = tempfile.mkstemp()
408+ self.addCleanup(os.remove, temp_filename)
409+ os.close(fd)
410+ with open(temp_filename, 'w'):
411+ pass
412+ os.chmod(temp_filename, 0)
413
414- self.assertThat(lambda: windowmocker.create_application_from_path(file_name),
415+ self.assertThat(
416+ lambda: windowmocker.create_application_from_path(temp_filename),
417 raises(IOError))
418
419
420@@ -66,9 +74,15 @@
421
422 @patch('windowmocker.create_application_from_data')
423 def test_can_load_unicode_json(self, load_mock):
424- windowmocker.create_application_from_file(StringIO(u'["ɥǝןןo", "ʍoɹןp"]'))
425- load_mock.assert_called_once_with([u'\u0265\u01dd\u05df\u05dfo', u'\u028do\u0279\u05dfp'], None)
426+ windowmocker.create_application_from_file(
427+ StringIO(u'["ɥǝןןo", "ʍoɹןp"]'))
428+ load_mock.assert_called_once_with(
429+ [u'\u0265\u01dd\u05df\u05dfo', u'\u028do\u0279\u05dfp'], None)
430
431 def test_raises_runtime_on_empty_file(self):
432- fn = lambda: windowmocker.create_application_from_file(StringIO())
433- self.assertThat(fn, raises(RuntimeError("No JSON object could be decoded")))
434+ # BAW 2014-01-31: We cannot assert on the exact error message
435+ # returned, because it's different between Python 3.3 and 3.4.
436+ # http://bugs.python.org/issue20453
437+ self.assertThat(
438+ lambda: windowmocker.create_application_from_file(StringIO()),
439+ raises(RuntimeError))
440
441=== modified file 'windowmocker/__init__.py'
442--- windowmocker/__init__.py 2014-01-07 20:05:34 +0000
443+++ windowmocker/__init__.py 2014-02-05 16:22:14 +0000
444@@ -1,5 +1,5 @@
445 # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
446-# Copyright 2012 Canonical
447+# Copyright 2012-2014 Canonical, Ltd.
448 # Author: Thomi Richards
449 #
450 # This program is free software: you can redistribute it and/or modify it
451@@ -11,7 +11,7 @@
452 import logging
453 import os
454 import subprocess
455-from tempfile import mktemp
456+import tempfile
457 from threading import Thread
458
459
460@@ -38,8 +38,8 @@
461 not readable.
462
463 """
464-
465- return create_application_from_file(open(path, 'r'), app_type_name)
466+ with open(path, 'r') as fp:
467+ return create_application_from_file(fp, app_type_name)
468
469
470 def create_application_from_file(file_object, app_type_name=None):
471@@ -60,7 +60,7 @@
472 return create_application_from_data(data, app_type_name)
473
474
475-def create_application_from_data(data={}, app_type_name=None):
476+def create_application_from_data(data=None, app_type_name=None):
477 """Create an application object from 'data'.
478
479 If data is None (the default), a default application is constructed.
480@@ -72,7 +72,8 @@
481 expected format.
482
483 """
484-
485+ if data is None:
486+ data = {}
487 if type(data) not in (dict, list):
488 raise RuntimeError(
489 "Top-level data structure must be a dictionary or list, not %r" %
490@@ -111,13 +112,14 @@
491 (type(data).__name__))
492
493 def run_thread():
494- file_path = mktemp()
495- with open(file_path, 'w') as f:
496- json.dump(data, f)
497+ fd, temp_filename = tempfile.mkstemp()
498+ os.close(fd)
499 try:
500- subprocess.check_call(["window-mocker", file_path])
501+ with open(temp_filename, 'w') as f:
502+ json.dump(data, f)
503+ subprocess.check_call(["window-mocker", temp_filename])
504 finally:
505- os.remove(file_path)
506+ os.remove(temp_filename)
507
508 thread = Thread(target=run_thread)
509 thread.start()
510
511=== modified file 'windowmocker/plugins/__init__.py'
512--- windowmocker/plugins/__init__.py 2014-01-21 20:56:11 +0000
513+++ windowmocker/plugins/__init__.py 2014-02-05 16:22:14 +0000
514@@ -1,5 +1,5 @@
515 # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
516-# Copyright 2012 Canonical
517+# Copyright 2012-2014 Canonical, Ltd.
518 # Author: Thomi Richards
519 #
520 # This program is free software: you can redistribute it and/or modify it
521@@ -45,7 +45,7 @@
522 if sys.version_info[0] < 3:
523 del _plugin_registry['Qt5']
524 return _plugin_registry.keys()
525-
526+
527
528 def register_named_plugin(plugin_name, plugin_class):
529 global _plugin_registry
530@@ -59,7 +59,7 @@
531
532 def register_plugin(plugin_class):
533 """Register plugin_class. Probably not ever needed, except by tests.
534-
535+
536 This function is deprecated and may be removed in a future release.
537 Use `register_named_plugin` instead."""
538 global _plugin_registry
539
540=== modified file 'windowmocker/plugins/base.py'
541--- windowmocker/plugins/base.py 2014-01-15 19:17:26 +0000
542+++ windowmocker/plugins/base.py 2014-02-05 16:22:14 +0000
543@@ -1,5 +1,5 @@
544 # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
545-# Copyright 2012 Canonical
546+# Copyright 2012-2014 Canonical, Ltd.
547 # Author: Thomi Richards
548 #
549 # This program is free software: you can redistribute it and/or modify it
550@@ -33,10 +33,10 @@
551 if not spec_dictionary:
552 logger.warning("Specification contains no window specification. Creating a default window.")
553
554- if type(spec_dictionary) is dict:
555+ if isinstance(spec_dictionary, dict):
556 window_spec = self._create_window_spec(spec_dictionary)
557 self.create_window(window_spec)
558- elif type(spec_dictionary) is list:
559+ elif isinstance(spec_dictionary, list):
560 for window in spec_dictionary:
561 window_spec = self._create_window_spec(window)
562 self.create_window(window_spec)
563@@ -52,12 +52,15 @@
564
565 def create_application(self):
566 """Create an application."""
567- raise NotImplementedError("This method must be implemeneted by child classes.")
568+ raise NotImplementedError(
569+ "This method must be implemented by child classes.")
570
571 def create_window(self, window_spec):
572 """Create a window, according to 'window_spec'."""
573- raise NotImplementedError("This method must be implemeneted by child classes.")
574+ raise NotImplementedError(
575+ "This method must be implemented by child classes.")
576
577 def run(self):
578 """Enter the event loop - run the application & windows."""
579- raise NotImplementedError("This method must be implemeneted by child classes.")
580+ raise NotImplementedError(
581+ "This method must be implemented by child classes.")
582
583=== modified file 'windowmocker/plugins/qt4.py'
584--- windowmocker/plugins/qt4.py 2014-01-21 20:26:48 +0000
585+++ windowmocker/plugins/qt4.py 2014-02-05 16:22:14 +0000
586@@ -1,12 +1,11 @@
587 # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
588-# Copyright 2012, 2013 Canonical
589+# Copyright 2012-2014 Canonical, Ltd.
590 # Author: Thomi Richards
591 #
592 # This program is free software: you can redistribute it and/or modify it
593 # under the terms of the GNU General Public License version 3, as published
594 # by the Free Software Foundation.
595
596-from __future__ import print_function
597 import logging
598 from PyQt4 import QtCore, QtGui
599 import sys
600@@ -47,8 +46,8 @@
601 if not window_spec['Maximized'] and not window_spec['Minimized']:
602 win.showNormal()
603
604- # In some cases, it's also needed to have the appliaction start normally
605- # but minimize itself right after starting
606+ # In some cases, it's also needed to have the application start
607+ # normally but minimize itself right after starting
608 if window_spec['MinimizeImmediatelyAfterShow']:
609 win.setWindowState(QtCore.Qt.WindowMinimized)
610
611@@ -63,7 +62,7 @@
612 menu = parent.addMenu(title)
613 if 'Menu' in item:
614 self._create_menus(menu, item['Menu'])
615- elif isinstance(item, basestring):
616+ elif isinstance(item, str):
617 parent.addAction(item)
618 else:
619 logger.error("Invalid menu item - is not a dict or string: %r", item)
620
621=== modified file 'windowmocker/plugins/qt5.py'
622--- windowmocker/plugins/qt5.py 2014-01-21 17:30:10 +0000
623+++ windowmocker/plugins/qt5.py 2014-02-05 16:22:14 +0000
624@@ -1,5 +1,5 @@
625 # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
626-# Copyright 2012, 2013 Canonical
627+# Copyright 2012-2014 Canonical, Ltd.
628 #
629 # This program is free software: you can redistribute it and/or modify it
630 # under the terms of the GNU General Public License version 3, as published
631@@ -8,11 +8,11 @@
632 from __future__ import print_function
633 import logging
634 from PyQt5 import QtCore, QtWidgets
635+import six
636 import sys
637
638 from windowmocker.plugins.base import ApplicationTypePluginBase
639
640-
641 logger = logging.getLogger(__name__)
642
643 class QtPlugin(ApplicationTypePluginBase):
644@@ -46,8 +46,8 @@
645 if not window_spec['Maximized'] and not window_spec['Minimized']:
646 win.showNormal()
647
648- # In some cases, it's also needed to have the appliaction start normally
649- # but minimize itself right after starting
650+ # In some cases, it's also needed to have the application start
651+ # normally but minimize itself right after starting
652 if window_spec['MinimizeImmediatelyAfterShow']:
653 win.setWindowState(QtCore.Qt.WindowMinimized)
654
655@@ -62,7 +62,7 @@
656 menu = parent.addMenu(title)
657 if 'Menu' in item:
658 self._create_menus(menu, item['Menu'])
659- elif isinstance(item, basestring):
660+ elif isinstance(item, six.string_types):
661 parent.addAction(item)
662 else:
663 logger.error("Invalid menu item - is not a dict or string: %r", item)

Subscribers

People subscribed via source and target branches