diff options
Diffstat (limited to 'test')
-rwxr-xr-x | test/all_benchmarks.py | 56 | ||||
-rwxr-xr-x[-rw-r--r--] | test/all_tests.py (renamed from test/test.py) | 27 | ||||
-rw-r--r-- | test/bm_human_readable.py | 51 | ||||
-rw-r--r-- | test/bm_loader.py | 8 | ||||
-rw-r--r-- | test/tc_bookmarks.py | 6 | ||||
-rw-r--r-- | test/tc_colorscheme.py | 6 | ||||
-rw-r--r-- | test/tc_direction.py | 6 | ||||
-rw-r--r-- | test/tc_directory.py | 7 | ||||
-rw-r--r-- | test/tc_displayable.py | 8 | ||||
-rw-r--r-- | test/tc_ext.py | 7 | ||||
-rw-r--r-- | test/tc_history.py | 33 | ||||
-rw-r--r-- | test/tc_human_readable.py | 51 | ||||
-rw-r--r-- | test/tc_keyapi.py | 6 | ||||
-rw-r--r-- | test/tc_loader.py | 8 | ||||
-rw-r--r-- | test/tc_newkeys.py | 13 | ||||
-rw-r--r-- | test/tc_relative_symlink.py | 47 | ||||
-rw-r--r-- | test/tc_signal.py | 7 | ||||
-rw-r--r-- | test/tc_ui.py | 10 | ||||
-rw-r--r-- | test/tc_utfwidth.py | 46 | ||||
-rw-r--r-- | test/testlib.py (renamed from test/__init__.py) | 9 |
20 files changed, 372 insertions, 40 deletions
diff --git a/test/all_benchmarks.py b/test/all_benchmarks.py new file mode 100755 index 00000000..a3612701 --- /dev/null +++ b/test/all_benchmarks.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python +# Copyright (C) 2009, 2010 Roman Zimbelmann <romanz@lavabit.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +""" +Run all the benchmarks inside this directory. +Usage: ./all_benchmarks.py [count] [regexp-filters...] +""" + +import os.path +import sys +rangerpath = os.path.join(os.path.dirname(__file__), '..') +if sys.path[1] != rangerpath: + sys.path[1:1] = [rangerpath] + +import re +import time + +if __name__ == '__main__': + count = int(sys.argv[1]) if len(sys.argv) > 1 else 10 + regexes = [re.compile(fltr) for fltr in sys.argv[2:]] + modules = (fname[:-3] for fname in os.listdir(sys.path[0]) \ + if fname[:3] == 'bm_' and fname[-3:] == '.py') + + def run_benchmark(cls, methodname): + full_method_name = "{0}.{1}".format(cls.__name__, methodname) + if all(re.search(full_method_name) for re in regexes): + method = getattr(cls(), methodname) + t1 = time.time() + try: + method(count) + except: + print("{0} failed!".format(full_method_name)) + raise + else: + t2 = time.time() + print("{0:60}: {1:10}s".format(full_method_name, t2 - t1)) + + for val in [__import__(module) for module in modules]: + for cls in vars(val).values(): + if type(cls) == type: + for methodname in vars(cls): + if methodname.startswith('bm_'): + run_benchmark(cls, methodname) diff --git a/test/test.py b/test/all_tests.py index d0a69e5a..0c184df5 100644..100755 --- a/test/test.py +++ b/test/all_tests.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python # Copyright (C) 2009, 2010 Roman Zimbelmann <romanz@lavabit.com> # # This program is free software: you can redistribute it and/or modify @@ -13,8 +14,24 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -"""Workaround to allow running single test cases directly""" -try: - from __init__ import init, Fake, OK, raise_ok, TODO -except: - from test import init, Fake, OK, raise_ok, TODO +""" +Run all the tests inside this directory as a test suite. +Usage: ./all_tests.py [verbosity] +""" + +import os.path +import sys +rangerpath = os.path.join(os.path.dirname(__file__), '..') +if sys.path[1] != rangerpath: + sys.path[1:1] = [rangerpath] + +import unittest + +if __name__ == '__main__': + verbosity = int(sys.argv[1]) if len(sys.argv) > 1 else 1 + tests = (fname[:-3] for fname in os.listdir(sys.path[0]) \ + if fname[:3] == 'tc_' and fname[-3:] == '.py') + suite = unittest.TestLoader().loadTestsFromNames(tests) + result = unittest.TextTestRunner(verbosity=verbosity).run(suite) + if len(result.errors + result.failures) > 0: + sys.exit(1) diff --git a/test/bm_human_readable.py b/test/bm_human_readable.py new file mode 100644 index 00000000..ef400774 --- /dev/null +++ b/test/bm_human_readable.py @@ -0,0 +1,51 @@ +# Copyright (C) 2009, 2010 Roman Zimbelmann <romanz@lavabit.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import os.path +import sys +rangerpath = os.path.join(os.path.dirname(__file__), '..') +if sys.path[1] != rangerpath: + sys.path[1:1] = [rangerpath] + +from ranger.ext.human_readable import * + +# The version before 2010/06/24: +import math +UNITS = 'BKMGTP' +MAX_EXPONENT = len(UNITS) - 1 +def human_readable_old(byte, seperator=' '): + if not byte: + return '0' + + exponent = int(math.log(byte, 2) / 10) + flt = round(float(byte) / (1 << (10 * exponent)), 2) + + if exponent > MAX_EXPONENT: + return '>9000' # off scale + + if int(flt) == flt: + return '%.0f%s%s' % (flt, seperator, UNITS[exponent]) + + else: + return '%.2f%s%s' % (flt, seperator, UNITS[exponent]) + +class benchmark_human_readable(object): + def bm_current(self, n): + for i in range(n): + human_readable((128 * i) % 2**50) + + def bm_old(self, n): + for i in range(n): + human_readable_old((128 * i) % 2**50) diff --git a/test/bm_loader.py b/test/bm_loader.py index 745e6f3b..552954a7 100644 --- a/test/bm_loader.py +++ b/test/bm_loader.py @@ -13,12 +13,18 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +import os.path +import sys +rangerpath = os.path.join(os.path.dirname(__file__), '..') +if sys.path[1] != rangerpath: + sys.path[1:1] = [rangerpath] + from ranger.core.loader import Loader from ranger.fsobject import Directory, File from ranger.ext.openstruct import OpenStruct import os.path from ranger.shared import FileManagerAware, SettingsAware -from test import Fake +from testlib import Fake from os.path import realpath, join, dirname from subprocess import Popen, PIPE TESTDIR = realpath(join(dirname(__file__), '/usr/include')) diff --git a/test/tc_bookmarks.py b/test/tc_bookmarks.py index f45ba061..59435f06 100644 --- a/test/tc_bookmarks.py +++ b/test/tc_bookmarks.py @@ -13,7 +13,11 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -if __name__ == '__main__': from __init__ import init; init() +import os.path +import sys +rangerpath = os.path.join(os.path.dirname(__file__), '..') +if sys.path[1] != rangerpath: + sys.path[1:1] = [rangerpath] from os.path import realpath, join, dirname import unittest diff --git a/test/tc_colorscheme.py b/test/tc_colorscheme.py index dbaac1f9..eefb1e4f 100644 --- a/test/tc_colorscheme.py +++ b/test/tc_colorscheme.py @@ -13,7 +13,11 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -if __name__ == '__main__': from __init__ import init; init() +import os.path +import sys +rangerpath = os.path.join(os.path.dirname(__file__), '..') +if sys.path[1] != rangerpath: + sys.path[1:1] = [rangerpath] from unittest import TestCase, main import random diff --git a/test/tc_direction.py b/test/tc_direction.py index f45b4b36..16c26dab 100644 --- a/test/tc_direction.py +++ b/test/tc_direction.py @@ -13,7 +13,11 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -if __name__ == '__main__': from __init__ import init; init() +import os.path +import sys +rangerpath = os.path.join(os.path.dirname(__file__), '..') +if sys.path[1] != rangerpath: + sys.path[1:1] = [rangerpath] import unittest from ranger.ext.direction import Direction diff --git a/test/tc_directory.py b/test/tc_directory.py index 024ebc9d..754253b3 100644 --- a/test/tc_directory.py +++ b/test/tc_directory.py @@ -13,9 +13,12 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -if __name__ == '__main__': from __init__ import init; init() - +import os.path import sys +rangerpath = os.path.join(os.path.dirname(__file__), '..') +if sys.path[1] != rangerpath: + sys.path[1:1] = [rangerpath] + from os.path import realpath, join, dirname from ranger import fsobject diff --git a/test/tc_displayable.py b/test/tc_displayable.py index 50f37845..72e0507d 100644 --- a/test/tc_displayable.py +++ b/test/tc_displayable.py @@ -13,14 +13,18 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -if __name__ == '__main__': from __init__ import init; init() +import os.path +import sys +rangerpath = os.path.join(os.path.dirname(__file__), '..') +if sys.path[1] != rangerpath: + sys.path[1:1] = [rangerpath] import unittest import curses from random import randint from ranger.gui.displayable import Displayable, DisplayableContainer -from test import Fake, OK, raise_ok, TODO +from testlib import Fake, OK, raise_ok, TODO class TestWithFakeCurses(unittest.TestCase): def setUp(self): diff --git a/test/tc_ext.py b/test/tc_ext.py index b8094233..495591a1 100644 --- a/test/tc_ext.py +++ b/test/tc_ext.py @@ -13,7 +13,12 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -if __name__ == '__main__': from __init__ import init; init() +import os.path +import sys +rangerpath = os.path.join(os.path.dirname(__file__), '..') +if sys.path[1] != rangerpath: + sys.path[1:1] = [rangerpath] + import unittest from collections import deque diff --git a/test/tc_history.py b/test/tc_history.py index d027231a..02a8bb9f 100644 --- a/test/tc_history.py +++ b/test/tc_history.py @@ -13,7 +13,11 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -if __name__ == '__main__': from __init__ import init; init() +import os.path +import sys +rangerpath = os.path.join(os.path.dirname(__file__), '..') +if sys.path[1] != rangerpath: + sys.path[1:1] = [rangerpath] from ranger.container import History from unittest import TestCase, main @@ -29,13 +33,13 @@ class Test(TestCase): hist.back() self.assertEqual(4, hist.current()) - self.assertEqual([3,4], list(hist)) + self.assertEqual([3,4], list(hist._left())) self.assertEqual(5, hist.top()) hist.back() self.assertEqual(3, hist.current()) - self.assertEqual([3], list(hist)) + self.assertEqual([3], list(hist._left())) # no change if current == bottom self.assertEqual(hist.current(), hist.bottom()) @@ -48,12 +52,31 @@ class Test(TestCase): hist.forward() hist.forward() self.assertEqual(5, hist.current()) - self.assertEqual([3,4,5], list(hist)) + self.assertEqual([3,4,5], list(hist._left())) self.assertEqual(3, hist.bottom()) hist.add(6) self.assertEqual(4, hist.bottom()) - self.assertEqual([4,5,6], list(hist)) + self.assertEqual([4,5,6], list(hist._left())) + + hist.back() + hist.fast_forward() + self.assertEqual([4,5,6], list(hist._left())) + hist.back() + hist.back() + hist.fast_forward() + self.assertEqual([4,5,6], list(hist._left())) + hist.back() + hist.back() + hist.back() + hist.fast_forward() + self.assertEqual([4,5,6], list(hist._left())) + hist.back() + hist.back() + hist.back() + hist.back() + hist.fast_forward() + self.assertEqual([4,5,6], list(hist._left())) if __name__ == '__main__': main() diff --git a/test/tc_human_readable.py b/test/tc_human_readable.py new file mode 100644 index 00000000..493e6d3a --- /dev/null +++ b/test/tc_human_readable.py @@ -0,0 +1,51 @@ +# Copyright (C) 2009, 2010 Roman Zimbelmann <romanz@lavabit.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import os.path +import sys +rangerpath = os.path.join(os.path.dirname(__file__), '..') +if sys.path[1] != rangerpath: + sys.path[1:1] = [rangerpath] + +import unittest +from ranger.ext.human_readable import human_readable as hr + +class HumanReadableTest(unittest.TestCase): + def test_basic(self): + self.assertEqual("0", hr(0)) + self.assertEqual("1 B", hr(1)) + self.assertEqual("1 K", hr(2 ** 10)) + self.assertEqual("1 M", hr(2 ** 20)) + self.assertEqual("1 G", hr(2 ** 30)) + self.assertEqual(">9000", hr(2 ** 100)) + + def test_big(self): + self.assertEqual("1023 G", hr(2 ** 30 * 1023)) + self.assertEqual("1024 G", hr(2 ** 40 - 1)) + self.assertEqual("1 T", hr(2 ** 40)) + + def test_small(self): + self.assertEqual("1000 B", hr(1000)) + self.assertEqual("1.66 M", hr(1.66 * 2 ** 20)) + self.assertEqual("1.46 K", hr(1500)) + self.assertEqual("1.5 K", hr(2 ** 10 + 2 ** 9)) + self.assertEqual("1.5 K", hr(2 ** 10 + 2 ** 9 - 1)) + + def test_no_exponent(self): + for i in range(2 ** 10, 2 ** 20, 512): + self.assertTrue('e' not in hr(i), "%d => %s" % (i, hr(i))) + +if __name__ == '__main__': + unittest.main() diff --git a/test/tc_keyapi.py b/test/tc_keyapi.py index 2f522173..79d89fa5 100644 --- a/test/tc_keyapi.py +++ b/test/tc_keyapi.py @@ -13,7 +13,11 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -if __name__ == '__main__': from __init__ import init; init() +import os.path +import sys +rangerpath = os.path.join(os.path.dirname(__file__), '..') +if sys.path[1] != rangerpath: + sys.path[1:1] = [rangerpath] from unittest import TestCase, main diff --git a/test/tc_loader.py b/test/tc_loader.py index 53ac5617..5a2e5a68 100644 --- a/test/tc_loader.py +++ b/test/tc_loader.py @@ -13,13 +13,17 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -if __name__ == '__main__': from __init__ import init; init() +import os.path +import sys +rangerpath = os.path.join(os.path.dirname(__file__), '..') +if sys.path[1] != rangerpath: + sys.path[1:1] = [rangerpath] import unittest import os from os.path import realpath, join, dirname -from test import Fake +from testlib import Fake from ranger.shared import FileManagerAware, SettingsAware from ranger.core.loader import Loader from ranger.fsobject import Directory, File diff --git a/test/tc_newkeys.py b/test/tc_newkeys.py index c7a33025..c9597201 100644 --- a/test/tc_newkeys.py +++ b/test/tc_newkeys.py @@ -12,19 +12,22 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -if __name__ == '__main__': from __init__ import init; init() +import os.path +import sys +rangerpath = os.path.join(os.path.dirname(__file__), '..') +if sys.path[1] != rangerpath: + sys.path[1:1] = [rangerpath] +sys.path[1:1] = ['..'] + from unittest import TestCase, main -from test import TODO +from testlib import TODO from ranger.ext.tree import Tree from ranger.container.keymap import * from ranger.container.keybuffer import KeyBuffer from ranger.ext.keybinding_parser import parse_keybinding -import sys - def simulate_press(self, string): for char in parse_keybinding(string): self.add(char) diff --git a/test/tc_relative_symlink.py b/test/tc_relative_symlink.py new file mode 100644 index 00000000..a202513d --- /dev/null +++ b/test/tc_relative_symlink.py @@ -0,0 +1,47 @@ +# Copyright (C) 2009, 2010 Roman Zimbelmann <romanz@lavabit.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import os.path +import sys +rangerpath = os.path.join(os.path.dirname(__file__), '..') +if sys.path[1] != rangerpath: + sys.path[1:1] = [rangerpath] + +import unittest +from ranger.ext.relative_symlink import * +rel = get_relative_source_file + +class Test(unittest.TestCase): + def test_foo(self): + self.assertEqual('../foo', rel('/foo', '/x/bar')) + self.assertEqual('../../foo', rel('/foo', '/x/y/bar')) + self.assertEqual('../../a/b/foo', rel('/a/b/foo', '/x/y/bar')) + self.assertEqual('../../x/b/foo', rel('/x/b/foo', '/x/y/bar', + common_base='/')) + self.assertEqual('../b/foo', rel('/x/b/foo', '/x/y/bar')) + self.assertEqual('../b/foo', rel('/x/b/foo', '/x/y/bar')) + + def test_get_common_base(self): + self.assertEqual('/', get_common_base('', '')) + self.assertEqual('/', get_common_base('', '/')) + self.assertEqual('/', get_common_base('/', '')) + self.assertEqual('/', get_common_base('/', '/')) + self.assertEqual('/', get_common_base('/bla/bar/x', '/foo/bar/a')) + self.assertEqual('/foo/bar/', get_common_base('/foo/bar/x', '/foo/bar/a')) + self.assertEqual('/foo/', get_common_base('/foo/bar/x', '/foo/baz/a')) + self.assertEqual('/foo/', get_common_base('/foo/bar/x', '/foo/baz/a')) + self.assertEqual('/', get_common_base('//foo/bar/x', '/foo/baz/a')) + +if __name__ == '__main__': unittest.main() diff --git a/test/tc_signal.py b/test/tc_signal.py index 35b4eebe..3b1bac40 100644 --- a/test/tc_signal.py +++ b/test/tc_signal.py @@ -13,7 +13,12 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -if __name__ == '__main__': from __init__ import init; init() +import os.path +import sys +rangerpath = os.path.join(os.path.dirname(__file__), '..') +if sys.path[1] != rangerpath: + sys.path[1:1] = [rangerpath] + import unittest import gc from ranger.ext.signal_dispatcher import * diff --git a/test/tc_ui.py b/test/tc_ui.py index 3c659459..fa2bdcac 100644 --- a/test/tc_ui.py +++ b/test/tc_ui.py @@ -13,14 +13,18 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -if __name__ == '__main__': from __init__ import init; init() +import os.path +import sys +rangerpath = os.path.join(os.path.dirname(__file__), '..') +if sys.path[1] != rangerpath: + sys.path[1:1] = [rangerpath] import unittest import curses from ranger.gui import ui -from test import Fake, OK, raise_ok +from testlib import Fake, OK, raise_ok ui.curses = Fake() @@ -39,7 +43,7 @@ class Test(unittest.TestCase): def tearDown(self): self.ui.destroy() - + def test_passing(self): # Test whether certain method calls are passed to widgets widget = self.ui.widget diff --git a/test/tc_utfwidth.py b/test/tc_utfwidth.py new file mode 100644 index 00000000..0288c17b --- /dev/null +++ b/test/tc_utfwidth.py @@ -0,0 +1,46 @@ +# -*- encoding: utf8 -*- +# Copyright (C) 2009, 2010 Roman Zimbelmann <romanz@lavabit.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License + +import os.path +import sys +rangerpath = os.path.join(os.path.dirname(__file__), '..') +if sys.path[1] != rangerpath: + sys.path[1:1] = [rangerpath] +sys.path[1:1] = ['..'] + +from unittest import TestCase, main +from ranger.ext.utfwidth import * + +a_ascii = "a" # width = 1, bytes = 1 +a_umlaut = "ä" # width = 1, bytes = 2 +a_katakana = "ア" # width = 2, bytes = 3 +# need one with width = 1 & bytes = 3 + +class Test(TestCase): + def test_utf_byte_length(self): + self.assertEqual(1, utf_byte_length(a_ascii)) + self.assertEqual(2, utf_byte_length(a_umlaut)) + self.assertEqual(3, utf_byte_length(a_katakana)) + + def test_uwid(self): + self.assertEqual(1, uwid(a_ascii)) + self.assertEqual(1, uwid(a_umlaut)) + self.assertEqual(2, uwid(a_katakana)) + self.assertEqual(3, uwid(a_katakana + a_umlaut)) + self.assertEqual(4, uwid("asdf")) + self.assertEqual(5, uwid("löööl")) + self.assertEqual(6, uwid("バババ")) + +if __name__ == '__main__': main() diff --git a/test/__init__.py b/test/testlib.py index d87d1fc2..29dd9e07 100644 --- a/test/__init__.py +++ b/test/testlib.py @@ -13,12 +13,6 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -import os, sys - -__all__ = [ x[0:x.index('.')] \ - for x in os.listdir(os.path.dirname(__file__)) \ - if x.startswith('tc_') or x.startswith('bm_')] - def TODO(fnc): def result(*arg, **kw): try: @@ -27,9 +21,6 @@ def TODO(fnc): pass # failure expected return result -def init(): - sys.path.append(os.path.abspath(os.path.join(sys.path[0], '..'))) - class Fake(object): def __getattr__(self, attrname): val = Fake() |