functions: revert the function init order to make pylint happy again. See #217
[pygobject.git] / tests / test_glib.py
blob565a87226ea2ab75c28612b5eda1341c926bddca
1 # -*- Mode: Python -*-
2 # encoding: UTF-8
4 from __future__ import absolute_import
6 import os
7 import sys
8 import unittest
9 import os.path
10 import warnings
11 import subprocess
13 import pytest
14 from gi.repository import GLib
15 from gi import PyGIDeprecationWarning
16 from gi._compat import PY3
19 class TestGLib(unittest.TestCase):
21 @pytest.mark.xfail(strict=True)
22 def test_pytest_capture_error_in_closure(self):
23 # this test is supposed to fail
24 ml = GLib.MainLoop()
26 def callback():
27 ml.quit()
28 raise Exception("expected")
30 GLib.idle_add(callback)
31 ml.run()
33 @unittest.skipIf(os.name == "nt", "no bash on Windows")
34 def test_find_program_in_path(self):
35 bash_path = GLib.find_program_in_path('bash')
36 self.assertTrue(bash_path.endswith(os.path.sep + 'bash'))
37 self.assertTrue(os.path.exists(bash_path))
39 self.assertEqual(GLib.find_program_in_path('non existing'), None)
41 def test_markup_escape_text(self):
42 self.assertEqual(GLib.markup_escape_text(u'a&bä'), 'a&bä')
43 self.assertEqual(GLib.markup_escape_text(b'a&b\x05'), 'a&b')
45 # with explicit length argument
46 self.assertEqual(GLib.markup_escape_text(b'a\x05\x01\x02', 2), 'a')
48 def test_progname(self):
49 GLib.set_prgname('moo')
50 self.assertEqual(GLib.get_prgname(), 'moo')
52 def test_appname(self):
53 GLib.set_application_name('moo')
54 self.assertEqual(GLib.get_application_name(), 'moo')
56 def test_xdg_dirs(self):
57 d = GLib.get_user_data_dir()
58 self.assertTrue(os.path.sep in d, d)
59 d = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP)
60 self.assertTrue(os.path.sep in d, d)
61 with warnings.catch_warnings():
62 warnings.simplefilter('ignore', PyGIDeprecationWarning)
64 # also works with backwards compatible enum names
65 self.assertEqual(GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_MUSIC),
66 GLib.get_user_special_dir(GLib.USER_DIRECTORY_MUSIC))
68 for d in GLib.get_system_config_dirs():
69 self.assertTrue(os.path.sep in d, d)
70 for d in GLib.get_system_data_dirs():
71 self.assertTrue(isinstance(d, str), d)
73 def test_main_depth(self):
74 self.assertEqual(GLib.main_depth(), 0)
76 def test_filenames(self):
77 self.assertEqual(GLib.filename_display_name('foo'), 'foo')
78 self.assertEqual(GLib.filename_display_basename('bar/foo'), 'foo')
80 def glibfsencode(f):
81 # the annotations of filename_from_utf8() was changed in
82 # https://bugzilla.gnome.org/show_bug.cgi?id=756128
83 if isinstance(f, bytes):
84 return f
85 if os.name == "nt":
86 if PY3:
87 return f.encode("utf-8", "surrogatepass")
88 else:
89 return f.encode("utf-8")
90 else:
91 assert PY3
92 return os.fsencode(f)
94 # this is locale dependent, so we cannot completely verify the result
95 res = GLib.filename_from_utf8(u'aäb')
96 res = glibfsencode(res)
97 self.assertTrue(isinstance(res, bytes))
98 self.assertGreaterEqual(len(res), 3)
100 # with explicit length argument
101 res = GLib.filename_from_utf8(u'aäb', 1)
102 res = glibfsencode(res)
103 self.assertEqual(res, b'a')
105 def test_uri_extract(self):
106 res = GLib.uri_list_extract_uris('''# some comment
107 http://example.com
108 https://my.org/q?x=1&y=2
109 http://gnome.org/new''')
110 self.assertEqual(res, ['http://example.com',
111 'https://my.org/q?x=1&y=2',
112 'http://gnome.org/new'])
114 def test_current_time(self):
115 with warnings.catch_warnings(record=True) as warn:
116 warnings.simplefilter('always')
117 tm = GLib.get_current_time()
118 self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning))
120 self.assertTrue(isinstance(tm, float))
121 self.assertGreater(tm, 1350000000.0)
123 @unittest.skipIf(sys.platform == "darwin", "fails on OSX")
124 def test_main_loop(self):
125 # note we do not test run() here, as we use this in countless other
126 # tests
127 ml = GLib.MainLoop()
128 self.assertFalse(ml.is_running())
130 context = ml.get_context()
131 self.assertEqual(context, GLib.MainContext.default())
132 self.assertTrue(context.is_owner() in [True, False])
133 self.assertTrue(context.pending() in [True, False])
134 self.assertFalse(context.iteration(False))
136 def test_main_loop_with_context(self):
137 context = GLib.MainContext()
138 ml = GLib.MainLoop(context)
139 self.assertFalse(ml.is_running())
140 self.assertEqual(ml.get_context(), context)
142 def test_main_context(self):
143 # constructor
144 context = GLib.MainContext()
145 self.assertTrue(context.is_owner() in [True, False])
146 self.assertFalse(context.pending())
147 self.assertFalse(context.iteration(False))
149 # GLib API
150 context = GLib.MainContext.default()
151 self.assertTrue(context.is_owner() in [True, False])
152 self.assertTrue(context.pending() in [True, False])
153 self.assertTrue(context.iteration(False) in [True, False])
155 # backwards compatible API
156 context = GLib.main_context_default()
157 self.assertTrue(context.is_owner() in [True, False])
158 self.assertTrue(context.pending() in [True, False])
159 self.assertTrue(context.iteration(False) in [True, False])
161 @unittest.skipIf(os.name == "nt", "hangs")
162 def test_io_add_watch_no_data(self):
163 (r, w) = os.pipe()
164 call_data = []
166 def cb(fd, condition):
167 call_data.append((fd, condition, os.read(fd, 1)))
168 if len(call_data) == 2:
169 ml.quit()
170 return True
172 # io_add_watch() takes an IOChannel, calling with an fd is deprecated
173 with warnings.catch_warnings(record=True) as warn:
174 warnings.simplefilter('always')
175 GLib.io_add_watch(r, GLib.IOCondition.IN, cb,
176 priority=GLib.PRIORITY_HIGH)
177 self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning))
179 def write():
180 os.write(w, b'a')
181 GLib.idle_add(lambda: os.write(w, b'b') and False)
183 ml = GLib.MainLoop()
184 GLib.idle_add(write)
185 GLib.timeout_add(2000, ml.quit)
186 ml.run()
188 self.assertEqual(call_data, [(r, GLib.IOCondition.IN, b'a'),
189 (r, GLib.IOCondition.IN, b'b')])
191 @unittest.skipIf(os.name == "nt", "hangs")
192 def test_io_add_watch_with_data(self):
193 (r, w) = os.pipe()
194 call_data = []
196 def cb(fd, condition, data):
197 call_data.append((fd, condition, os.read(fd, 1), data))
198 if len(call_data) == 2:
199 ml.quit()
200 return True
202 # io_add_watch() takes an IOChannel, calling with an fd is deprecated
203 with warnings.catch_warnings(record=True) as warn:
204 warnings.simplefilter('always')
205 GLib.io_add_watch(r, GLib.IOCondition.IN, cb, 'moo',
206 priority=GLib.PRIORITY_HIGH)
207 self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning))
209 def write():
210 os.write(w, b'a')
211 GLib.idle_add(lambda: os.write(w, b'b') and False)
213 ml = GLib.MainLoop()
214 GLib.idle_add(write)
215 GLib.timeout_add(2000, ml.quit)
216 ml.run()
218 self.assertEqual(call_data, [(r, GLib.IOCondition.IN, b'a', 'moo'),
219 (r, GLib.IOCondition.IN, b'b', 'moo')])
221 @unittest.skipIf(os.name == "nt", "hangs")
222 def test_io_add_watch_with_multiple_data(self):
223 (r, w) = os.pipe()
224 call_data = []
226 def cb(fd, condition, *user_data):
227 call_data.append((fd, condition, os.read(fd, 1), user_data))
228 ml.quit()
229 return True
231 # io_add_watch() takes an IOChannel, calling with an fd is deprecated
232 with warnings.catch_warnings(record=True) as warn:
233 warnings.simplefilter('always')
234 GLib.io_add_watch(r, GLib.IOCondition.IN, cb, 'moo', 'foo')
235 self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning))
237 ml = GLib.MainLoop()
238 GLib.idle_add(lambda: os.write(w, b'a') and False)
239 GLib.timeout_add(2000, ml.quit)
240 ml.run()
242 self.assertEqual(call_data, [(r, GLib.IOCondition.IN, b'a', ('moo', 'foo'))])
244 @unittest.skipIf(sys.platform == "darwin", "fails")
245 @unittest.skipIf(os.name == "nt", "no shell on Windows")
246 def test_io_add_watch_pyfile(self):
247 call_data = []
249 cmd = subprocess.Popen('echo hello; echo world',
250 shell=True, bufsize=0, stdout=subprocess.PIPE)
252 def cb(file, condition):
253 call_data.append((file, condition, file.readline()))
254 if len(call_data) == 2:
255 # avoid having to wait for the full timeout
256 ml.quit()
257 return True
259 # io_add_watch() takes an IOChannel, calling with a Python file is deprecated
260 with warnings.catch_warnings(record=True) as warn:
261 warnings.simplefilter('always')
262 GLib.io_add_watch(cmd.stdout, GLib.IOCondition.IN, cb)
263 self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning))
265 ml = GLib.MainLoop()
266 GLib.timeout_add(2000, ml.quit)
267 ml.run()
269 cmd.wait()
271 self.assertEqual(call_data, [(cmd.stdout, GLib.IOCondition.IN, b'hello\n'),
272 (cmd.stdout, GLib.IOCondition.IN, b'world\n')])
274 def test_glib_version(self):
275 with warnings.catch_warnings():
276 warnings.simplefilter('ignore', PyGIDeprecationWarning)
278 (major, minor, micro) = GLib.glib_version
279 self.assertGreaterEqual(major, 2)
280 self.assertGreaterEqual(minor, 0)
281 self.assertGreaterEqual(micro, 0)
283 def test_pyglib_version(self):
284 with warnings.catch_warnings():
285 warnings.simplefilter('ignore', PyGIDeprecationWarning)
287 (major, minor, micro) = GLib.pyglib_version
288 self.assertGreaterEqual(major, 3)
289 self.assertGreaterEqual(minor, 0)
290 self.assertGreaterEqual(micro, 0)
292 def test_timezone_constructor(self):
293 timezone = GLib.TimeZone("+05:21")
294 self.assertEqual(timezone.get_offset(0), ((5 * 60) + 21) * 60)
296 def test_source_attach_implicit_context(self):
297 context = GLib.MainContext.default()
298 source = GLib.Idle()
299 source_id = source.attach()
300 self.assertEqual(context, source.get_context())
301 self.assertTrue(GLib.Source.remove(source_id))