diff options
| author | shadchin <[email protected]> | 2022-02-10 16:44:30 +0300 |
|---|---|---|
| committer | Daniil Cherednik <[email protected]> | 2022-02-10 16:44:30 +0300 |
| commit | 2598ef1d0aee359b4b6d5fdd1758916d5907d04f (patch) | |
| tree | 012bb94d777798f1f56ac1cec429509766d05181 /contrib/python/traitlets/py2 | |
| parent | 6751af0b0c1b952fede40b19b71da8025b5d8bcf (diff) | |
Restoring authorship annotation for <[email protected]>. Commit 1 of 2.
Diffstat (limited to 'contrib/python/traitlets/py2')
14 files changed, 1600 insertions, 1600 deletions
diff --git a/contrib/python/traitlets/py2/.dist-info/METADATA b/contrib/python/traitlets/py2/.dist-info/METADATA index bd031a5c309..d0c20576621 100644 --- a/contrib/python/traitlets/py2/.dist-info/METADATA +++ b/contrib/python/traitlets/py2/.dist-info/METADATA @@ -1,34 +1,34 @@ -Metadata-Version: 2.1 -Name: traitlets -Version: 4.3.3 -Summary: Traitlets Python config system -Home-page: http://ipython.org -Author: IPython Development Team -Author-email: [email protected] -License: BSD -Keywords: Interactive,Interpreter,Shell,Web -Platform: Linux -Platform: Mac OS X -Platform: Windows -Classifier: Intended Audience :: Developers -Classifier: Intended Audience :: System Administrators -Classifier: Intended Audience :: Science/Research -Classifier: License :: OSI Approved :: BSD License -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.3 -Classifier: Programming Language :: Python :: 3.4 -Classifier: Programming Language :: Python :: 3.5 -Requires-Dist: ipython-genutils -Requires-Dist: six -Requires-Dist: decorator -Requires-Dist: enum34 ; python_version=="2.7" -Requires-Dist: enum34 ; python_version=="3.3" -Provides-Extra: test -Requires-Dist: pytest ; extra == 'test' -Requires-Dist: mock ; (python_version=="2.7") and extra == 'test' - -A configuration system for Python applications. - - +Metadata-Version: 2.1 +Name: traitlets +Version: 4.3.3 +Summary: Traitlets Python config system +Home-page: http://ipython.org +Author: IPython Development Team +Author-email: [email protected] +License: BSD +Keywords: Interactive,Interpreter,Shell,Web +Platform: Linux +Platform: Mac OS X +Platform: Windows +Classifier: Intended Audience :: Developers +Classifier: Intended Audience :: System Administrators +Classifier: Intended Audience :: Science/Research +Classifier: License :: OSI Approved :: BSD License +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Requires-Dist: ipython-genutils +Requires-Dist: six +Requires-Dist: decorator +Requires-Dist: enum34 ; python_version=="2.7" +Requires-Dist: enum34 ; python_version=="3.3" +Provides-Extra: test +Requires-Dist: pytest ; extra == 'test' +Requires-Dist: mock ; (python_version=="2.7") and extra == 'test' + +A configuration system for Python applications. + + diff --git a/contrib/python/traitlets/py2/.dist-info/top_level.txt b/contrib/python/traitlets/py2/.dist-info/top_level.txt index adfea9c6eb5..3d938864d21 100644 --- a/contrib/python/traitlets/py2/.dist-info/top_level.txt +++ b/contrib/python/traitlets/py2/.dist-info/top_level.txt @@ -1 +1 @@ -traitlets +traitlets diff --git a/contrib/python/traitlets/py2/README.md b/contrib/python/traitlets/py2/README.md index aa288947efb..436b97c19b2 100644 --- a/contrib/python/traitlets/py2/README.md +++ b/contrib/python/traitlets/py2/README.md @@ -1,143 +1,143 @@ -# Traitlets - -[](https://travis-ci.org/ipython/traitlets) -[](http://traitlets.readthedocs.org/en/latest/?badge=latest) - -Traitlets is a pure Python library enabling: - - - the enforcement of strong typing for attributes of Python objects - (typed attributes are called "traits"), - - notifications on changes of trait attributes, - - automatic validation and coercion of trait attributes when attempting a - change. - -Its implementation relies on the [descriptor](https://docs.python.org/howto/descriptor.html) -pattern. - -Traitlets powers the configuration system of IPython and Jupyter -and the declarative API of IPython interactive widgets. - -## Installation - -For a local installation, make sure you have -[pip installed](https://pip.pypa.io/en/stable/installing/) and run: - -```bash -pip install traitlets -``` - -For a **development installation**, clone this repository, change into the -`traitlets` root directory, and run pip: - -```bash -git clone https://github.com/ipython/traitlets.git -cd traitlets -pip install -e . -``` - -## Running the tests - -```bash -pip install "traitlets[test]" -py.test traitlets -``` - -## Usage - -Any class with trait attributes must inherit from `HasTraits`. -For the list of available trait types and their properties, see the -[Trait Types](https://traitlets.readthedocs.io/en/latest/trait_types.html) -section of the documentation. - -### Dynamic default values - -To calculate a default value dynamically, decorate a method of your class with -`@default({traitname})`. This method will be called on the instance, and -should return the default value. In this example, the `_username_default` -method is decorated with `@default('username')`: - -```Python -import getpass -from traitlets import HasTraits, Unicode, default - -class Identity(HasTraits): - username = Unicode() - - @default('username') - def _username_default(self): - return getpass.getuser() -``` - -### Callbacks when a trait attribute changes - -When a trait changes, an application can follow this trait change with -additional actions. - -To do something when a trait attribute is changed, decorate a method with -[`traitlets.observe()`](https://traitlets.readthedocs.io/en/latest/api.html?highlight=observe#traitlets.observe). -The method will be called with a single argument, a dictionary which contains -an owner, new value, old value, name of the changed trait, and the event type. - -In this example, the `_num_changed` method is decorated with ``@observe(`num`)``: - -```Python -from traitlets import HasTraits, Integer, observe - -class TraitletsExample(HasTraits): - num = Integer(5, help="a number").tag(config=True) - - @observe('num') - def _num_changed(self, change): - print("{name} changed from {old} to {new}".format(**change)) -``` - -and is passed the following dictionary when called: - -```Python -{ - 'owner': object, # The HasTraits instance - 'new': 6, # The new value - 'old': 5, # The old value - 'name': "foo", # The name of the changed trait - 'type': 'change', # The event type of the notification, usually 'change' -} -``` - -### Validation and coercion - -Each trait type (`Int`, `Unicode`, `Dict` etc.) may have its own validation or -coercion logic. In addition, we can register custom cross-validators -that may depend on the state of other attributes. For example: - -```Python -from traitlets import HasTraits, TraitError, Int, Bool, validate - -class Parity(HasTraits): - value = Int() - parity = Int() - - @validate('value') - def _valid_value(self, proposal): - if proposal['value'] % 2 != self.parity: - raise TraitError('value and parity should be consistent') - return proposal['value'] - - @validate('parity') - def _valid_parity(self, proposal): - parity = proposal['value'] - if parity not in [0, 1]: - raise TraitError('parity should be 0 or 1') - if self.value % 2 != parity: - raise TraitError('value and parity should be consistent') - return proposal['value'] - -parity_check = Parity(value=2) - -# Changing required parity and value together while holding cross validation -with parity_check.hold_trait_notifications(): - parity_check.value = 1 - parity_check.parity = 1 -``` - -However, we **recommend** that custom cross-validators don't modify the state -of the HasTraits instance. +# Traitlets + +[](https://travis-ci.org/ipython/traitlets) +[](http://traitlets.readthedocs.org/en/latest/?badge=latest) + +Traitlets is a pure Python library enabling: + + - the enforcement of strong typing for attributes of Python objects + (typed attributes are called "traits"), + - notifications on changes of trait attributes, + - automatic validation and coercion of trait attributes when attempting a + change. + +Its implementation relies on the [descriptor](https://docs.python.org/howto/descriptor.html) +pattern. + +Traitlets powers the configuration system of IPython and Jupyter +and the declarative API of IPython interactive widgets. + +## Installation + +For a local installation, make sure you have +[pip installed](https://pip.pypa.io/en/stable/installing/) and run: + +```bash +pip install traitlets +``` + +For a **development installation**, clone this repository, change into the +`traitlets` root directory, and run pip: + +```bash +git clone https://github.com/ipython/traitlets.git +cd traitlets +pip install -e . +``` + +## Running the tests + +```bash +pip install "traitlets[test]" +py.test traitlets +``` + +## Usage + +Any class with trait attributes must inherit from `HasTraits`. +For the list of available trait types and their properties, see the +[Trait Types](https://traitlets.readthedocs.io/en/latest/trait_types.html) +section of the documentation. + +### Dynamic default values + +To calculate a default value dynamically, decorate a method of your class with +`@default({traitname})`. This method will be called on the instance, and +should return the default value. In this example, the `_username_default` +method is decorated with `@default('username')`: + +```Python +import getpass +from traitlets import HasTraits, Unicode, default + +class Identity(HasTraits): + username = Unicode() + + @default('username') + def _username_default(self): + return getpass.getuser() +``` + +### Callbacks when a trait attribute changes + +When a trait changes, an application can follow this trait change with +additional actions. + +To do something when a trait attribute is changed, decorate a method with +[`traitlets.observe()`](https://traitlets.readthedocs.io/en/latest/api.html?highlight=observe#traitlets.observe). +The method will be called with a single argument, a dictionary which contains +an owner, new value, old value, name of the changed trait, and the event type. + +In this example, the `_num_changed` method is decorated with ``@observe(`num`)``: + +```Python +from traitlets import HasTraits, Integer, observe + +class TraitletsExample(HasTraits): + num = Integer(5, help="a number").tag(config=True) + + @observe('num') + def _num_changed(self, change): + print("{name} changed from {old} to {new}".format(**change)) +``` + +and is passed the following dictionary when called: + +```Python +{ + 'owner': object, # The HasTraits instance + 'new': 6, # The new value + 'old': 5, # The old value + 'name': "foo", # The name of the changed trait + 'type': 'change', # The event type of the notification, usually 'change' +} +``` + +### Validation and coercion + +Each trait type (`Int`, `Unicode`, `Dict` etc.) may have its own validation or +coercion logic. In addition, we can register custom cross-validators +that may depend on the state of other attributes. For example: + +```Python +from traitlets import HasTraits, TraitError, Int, Bool, validate + +class Parity(HasTraits): + value = Int() + parity = Int() + + @validate('value') + def _valid_value(self, proposal): + if proposal['value'] % 2 != self.parity: + raise TraitError('value and parity should be consistent') + return proposal['value'] + + @validate('parity') + def _valid_parity(self, proposal): + parity = proposal['value'] + if parity not in [0, 1]: + raise TraitError('parity should be 0 or 1') + if self.value % 2 != parity: + raise TraitError('value and parity should be consistent') + return proposal['value'] + +parity_check = Parity(value=2) + +# Changing required parity and value together while holding cross validation +with parity_check.hold_trait_notifications(): + parity_check.value = 1 + parity_check.parity = 1 +``` + +However, we **recommend** that custom cross-validators don't modify the state +of the HasTraits instance. diff --git a/contrib/python/traitlets/py2/tests/ya.make b/contrib/python/traitlets/py2/tests/ya.make index d2d3e3b9bf5..087a9ab183a 100644 --- a/contrib/python/traitlets/py2/tests/ya.make +++ b/contrib/python/traitlets/py2/tests/ya.make @@ -6,18 +6,18 @@ PEERDIR( contrib/python/traitlets ) -ENV( - YA_PYTEST_DISABLE_DOCTEST=yes -) - -SRCDIR(contrib/python/traitlets/py2/traitlets) +ENV( + YA_PYTEST_DISABLE_DOCTEST=yes +) -TEST_SRCS( - tests/__init__.py - tests/_warnings.py - tests/test_traitlets.py - tests/test_traitlets_enum.py - tests/utils.py +SRCDIR(contrib/python/traitlets/py2/traitlets) + +TEST_SRCS( + tests/__init__.py + tests/_warnings.py + tests/test_traitlets.py + tests/test_traitlets_enum.py + tests/utils.py ) NO_LINT() diff --git a/contrib/python/traitlets/py2/traitlets/_version.py b/contrib/python/traitlets/py2/traitlets/_version.py index ed16b3c1e12..e9ec9e6da62 100644 --- a/contrib/python/traitlets/py2/traitlets/_version.py +++ b/contrib/python/traitlets/py2/traitlets/_version.py @@ -1,2 +1,2 @@ -version_info = (4, 3, 3) +version_info = (4, 3, 3) __version__ = '.'.join(map(str, version_info)) diff --git a/contrib/python/traitlets/py2/traitlets/config/application.py b/contrib/python/traitlets/py2/traitlets/config/application.py index d3a4c45e774..147dc9f0682 100644 --- a/contrib/python/traitlets/py2/traitlets/config/application.py +++ b/contrib/python/traitlets/py2/traitlets/config/application.py @@ -267,7 +267,7 @@ class Application(SingletonConfigurable): """ ) - _loaded_config_files = List() + _loaded_config_files = List() def __init__(self, **kwargs): SingletonConfigurable.__init__(self, **kwargs) @@ -558,7 +558,7 @@ class Application(SingletonConfigurable): loaded = [] filenames = [] for loader in [pyloader, jsonloader]: - config = None + config = None try: config = loader.load_config() except ConfigFileNotFound: @@ -584,26 +584,26 @@ class Application(SingletonConfigurable): " {1} has higher priority: {2}".format( filename, loader.full_filename, json.dumps(collisions, indent=2), )) - yield (config, loader.full_filename) + yield (config, loader.full_filename) loaded.append(config) filenames.append(loader.full_filename) - @property - def loaded_config_files(self): - """Currently loaded configuration files""" - return self._loaded_config_files[:] + @property + def loaded_config_files(self): + """Currently loaded configuration files""" + return self._loaded_config_files[:] @catch_config_error def load_config_file(self, filename, path=None): """Load config files by filename and path.""" filename, ext = os.path.splitext(filename) new_config = Config() - for (config, filename) in self._load_config_files(filename, path=path, log=self.log, + for (config, filename) in self._load_config_files(filename, path=path, log=self.log, raise_config_file_errors=self.raise_config_file_errors, ): new_config.merge(config) - if filename not in self._loaded_config_files: # only add to list of loaded files if not previously loaded - self._loaded_config_files.append(filename) + if filename not in self._loaded_config_files: # only add to list of loaded files if not previously loaded + self._loaded_config_files.append(filename) # add self.cli_config to preserve CLI config priority new_config.merge(self.cli_config) self.update_config(new_config) diff --git a/contrib/python/traitlets/py2/traitlets/config/tests/test_application.py b/contrib/python/traitlets/py2/traitlets/config/tests/test_application.py index 39bd9b786e8..ede020bc9c4 100644 --- a/contrib/python/traitlets/py2/traitlets/config/tests/test_application.py +++ b/contrib/python/traitlets/py2/traitlets/config/tests/test_application.py @@ -1,421 +1,421 @@ -# coding: utf-8 -""" -Tests for traitlets.config.application.Application -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import json -import logging -import os -from io import StringIO -from unittest import TestCase - -try: - from unittest import mock -except ImportError: - import mock - -pjoin = os.path.join - -from pytest import mark - -from traitlets.config.configurable import Configurable -from traitlets.config.loader import Config -from traitlets.tests.utils import check_help_output, check_help_all_output - -from traitlets.config.application import ( - Application -) - -from ipython_genutils.tempdir import TemporaryDirectory -from traitlets.traitlets import ( - Bool, Unicode, Integer, List, Dict -) - - -class Foo(Configurable): - - i = Integer(0, help="The integer i.").tag(config=True) - j = Integer(1, help="The integer j.").tag(config=True) - name = Unicode(u'Brian', help="First name.").tag(config=True) - - -class Bar(Configurable): - - b = Integer(0, help="The integer b.").tag(config=True) - enabled = Bool(True, help="Enable bar.").tag(config=True) - - -class MyApp(Application): - - name = Unicode(u'myapp') - running = Bool(False, help="Is the app running?").tag(config=True) - classes = List([Bar, Foo]) - config_file = Unicode(u'', help="Load this config file").tag(config=True) - - warn_tpyo = Unicode(u"yes the name is wrong on purpose", config=True, - help="Should print a warning if `MyApp.warn-typo=...` command is passed") - - aliases = Dict({ - 'i' : 'Foo.i', - 'j' : 'Foo.j', - 'name' : 'Foo.name', - 'enabled' : 'Bar.enabled', - 'log-level' : 'Application.log_level', - }) - - flags = Dict(dict(enable=({'Bar': {'enabled' : True}}, "Set Bar.enabled to True"), - disable=({'Bar': {'enabled' : False}}, "Set Bar.enabled to False"), - crit=({'Application' : {'log_level' : logging.CRITICAL}}, - "set level=CRITICAL"), - )) - - def init_foo(self): - self.foo = Foo(parent=self) - - def init_bar(self): - self.bar = Bar(parent=self) - - -class TestApplication(TestCase): - - def test_log(self): - stream = StringIO() - app = MyApp(log_level=logging.INFO) - handler = logging.StreamHandler(stream) - # trigger reconstruction of the log formatter - app.log.handlers = [handler] - app.log_format = "%(message)s" - app.log_datefmt = "%Y-%m-%d %H:%M" - app.log.info("hello") - assert "hello" in stream.getvalue() - - def test_basic(self): - app = MyApp() - self.assertEqual(app.name, u'myapp') - self.assertEqual(app.running, False) - self.assertEqual(app.classes, [MyApp,Bar,Foo]) - self.assertEqual(app.config_file, u'') - - def test_config(self): - app = MyApp() - app.parse_command_line(["--i=10","--Foo.j=10","--enabled=False","--log-level=50"]) - config = app.config - self.assertEqual(config.Foo.i, 10) - self.assertEqual(config.Foo.j, 10) - self.assertEqual(config.Bar.enabled, False) - self.assertEqual(config.MyApp.log_level,50) - - def test_config_propagation(self): - app = MyApp() - app.parse_command_line(["--i=10","--Foo.j=10","--enabled=False","--log-level=50"]) - app.init_foo() - app.init_bar() - self.assertEqual(app.foo.i, 10) - self.assertEqual(app.foo.j, 10) - self.assertEqual(app.bar.enabled, False) - - def test_cli_priority(self): - """Test that loading config files does not override CLI options""" - name = 'config.py' - class TestApp(Application): - value = Unicode().tag(config=True) - config_file_loaded = Bool().tag(config=True) - aliases = {'v': 'TestApp.value'} - app = TestApp() - with TemporaryDirectory() as td: - config_file = pjoin(td, name) - with open(config_file, 'w') as f: - f.writelines([ - "c.TestApp.value = 'config file'\n", - "c.TestApp.config_file_loaded = True\n" - ]) - - app.parse_command_line(['--v=cli']) - assert 'value' in app.config.TestApp - assert app.config.TestApp.value == 'cli' - assert app.value == 'cli' - - app.load_config_file(name, path=[td]) - assert app.config_file_loaded - assert app.config.TestApp.value == 'cli' - assert app.value == 'cli' - - def test_ipython_cli_priority(self): - # this test is almost entirely redundant with above, - # but we can keep it around in case of subtle issues creeping into - # the exact sequence IPython follows. - name = 'config.py' - class TestApp(Application): - value = Unicode().tag(config=True) - config_file_loaded = Bool().tag(config=True) - aliases = {'v': 'TestApp.value'} - app = TestApp() - with TemporaryDirectory() as td: - config_file = pjoin(td, name) - with open(config_file, 'w') as f: - f.writelines([ - "c.TestApp.value = 'config file'\n", - "c.TestApp.config_file_loaded = True\n" - ]) - # follow IPython's config-loading sequence to ensure CLI priority is preserved - app.parse_command_line(['--v=cli']) - # this is where IPython makes a mistake: - # it assumes app.config will not be modified, - # and storing a reference is storing a copy - cli_config = app.config - assert 'value' in app.config.TestApp - assert app.config.TestApp.value == 'cli' - assert app.value == 'cli' - app.load_config_file(name, path=[td]) - assert app.config_file_loaded - # enforce cl-opts override config file opts: - # this is where IPython makes a mistake: it assumes - # that cl_config is a different object, but it isn't. - app.update_config(cli_config) - assert app.config.TestApp.value == 'cli' - assert app.value == 'cli' - - def test_flags(self): - app = MyApp() - app.parse_command_line(["--disable"]) - app.init_bar() - self.assertEqual(app.bar.enabled, False) - app.parse_command_line(["--enable"]) - app.init_bar() - self.assertEqual(app.bar.enabled, True) - - def test_aliases(self): - app = MyApp() - app.parse_command_line(["--i=5", "--j=10"]) - app.init_foo() - self.assertEqual(app.foo.i, 5) - app.init_foo() - self.assertEqual(app.foo.j, 10) - - def test_flag_clobber(self): - """test that setting flags doesn't clobber existing settings""" - app = MyApp() - app.parse_command_line(["--Bar.b=5", "--disable"]) - app.init_bar() - self.assertEqual(app.bar.enabled, False) - self.assertEqual(app.bar.b, 5) - app.parse_command_line(["--enable", "--Bar.b=10"]) - app.init_bar() - self.assertEqual(app.bar.enabled, True) - self.assertEqual(app.bar.b, 10) - - def test_warn_autocorrect(self): - stream = StringIO() - app = MyApp(log_level=logging.INFO) - app.log.handlers = [logging.StreamHandler(stream)] - - cfg = Config() - cfg.MyApp.warn_typo = "WOOOO" - app.config = cfg - - self.assertIn("warn_typo", stream.getvalue()) - self.assertIn("warn_tpyo", stream.getvalue()) - - - def test_flatten_flags(self): - cfg = Config() - cfg.MyApp.log_level = logging.WARN - app = MyApp() - app.update_config(cfg) - self.assertEqual(app.log_level, logging.WARN) - self.assertEqual(app.config.MyApp.log_level, logging.WARN) - app.initialize(["--crit"]) - self.assertEqual(app.log_level, logging.CRITICAL) - # this would be app.config.Application.log_level if it failed: - self.assertEqual(app.config.MyApp.log_level, logging.CRITICAL) - - def test_flatten_aliases(self): - cfg = Config() - cfg.MyApp.log_level = logging.WARN - app = MyApp() - app.update_config(cfg) - self.assertEqual(app.log_level, logging.WARN) - self.assertEqual(app.config.MyApp.log_level, logging.WARN) - app.initialize(["--log-level", "CRITICAL"]) - self.assertEqual(app.log_level, logging.CRITICAL) - # this would be app.config.Application.log_level if it failed: - self.assertEqual(app.config.MyApp.log_level, "CRITICAL") - - def test_extra_args(self): - app = MyApp() - app.parse_command_line(["--Bar.b=5", 'extra', "--disable", 'args']) - app.init_bar() - self.assertEqual(app.bar.enabled, False) - self.assertEqual(app.bar.b, 5) - self.assertEqual(app.extra_args, ['extra', 'args']) - app = MyApp() - app.parse_command_line(["--Bar.b=5", '--', 'extra', "--disable", 'args']) - app.init_bar() - self.assertEqual(app.bar.enabled, True) - self.assertEqual(app.bar.b, 5) - self.assertEqual(app.extra_args, ['extra', '--disable', 'args']) - - def test_unicode_argv(self): - app = MyApp() - app.parse_command_line(['ünîcødé']) - - def test_document_config_option(self): - app = MyApp() - app.document_config_options() - - def test_generate_config_file(self): - app = MyApp() - assert 'The integer b.' in app.generate_config_file() - - def test_generate_config_file_classes_to_include(self): - class NoTraits(Foo, Bar): - pass - - app = MyApp() - app.classes.append(NoTraits) - conf_txt = app.generate_config_file() - self.assertIn('The integer b.', conf_txt) - self.assertIn('# Bar(Configurable)', conf_txt) - self.assertIn('# Foo(Configurable)', conf_txt) - self.assertNotIn('# Configurable', conf_txt) - self.assertIn('# NoTraits(Foo,Bar)', conf_txt) - - def test_multi_file(self): - app = MyApp() - app.log = logging.getLogger() - name = 'config.py' - with TemporaryDirectory('_1') as td1: - with open(pjoin(td1, name), 'w') as f1: - f1.write("get_config().MyApp.Bar.b = 1") - with TemporaryDirectory('_2') as td2: - with open(pjoin(td2, name), 'w') as f2: - f2.write("get_config().MyApp.Bar.b = 2") - app.load_config_file(name, path=[td2, td1]) - app.init_bar() - self.assertEqual(app.bar.b, 2) - app.load_config_file(name, path=[td1, td2]) - app.init_bar() - self.assertEqual(app.bar.b, 1) - - @mark.skipif(not hasattr(TestCase, 'assertLogs'), reason='requires TestCase.assertLogs') - def test_log_collisions(self): - app = MyApp() - app.log = logging.getLogger() - app.log.setLevel(logging.INFO) - name = 'config' - with TemporaryDirectory('_1') as td: - with open(pjoin(td, name + '.py'), 'w') as f: - f.write("get_config().Bar.b = 1") - with open(pjoin(td, name + '.json'), 'w') as f: - json.dump({ - 'Bar': { - 'b': 2 - } - }, f) - with self.assertLogs(app.log, logging.WARNING) as captured: - app.load_config_file(name, path=[td]) - app.init_bar() - assert app.bar.b == 2 - output = '\n'.join(captured.output) - assert 'Collision' in output - assert '1 ignored, using 2' in output - assert pjoin(td, name + '.py') in output - assert pjoin(td, name + '.json') in output - - @mark.skipif(not hasattr(TestCase, 'assertLogs'), reason='requires TestCase.assertLogs') - def test_log_bad_config(self): - app = MyApp() - app.log = logging.getLogger() - name = 'config.py' - with TemporaryDirectory() as td: - with open(pjoin(td, name), 'w') as f: - f.write("syntax error()") - with self.assertLogs(app.log, logging.ERROR) as captured: - app.load_config_file(name, path=[td]) - output = '\n'.join(captured.output) - self.assertIn('SyntaxError', output) - - def test_raise_on_bad_config(self): - app = MyApp() - app.raise_config_file_errors = True - app.log = logging.getLogger() - name = 'config.py' - with TemporaryDirectory() as td: - with open(pjoin(td, name), 'w') as f: - f.write("syntax error()") - with self.assertRaises(SyntaxError): - app.load_config_file(name, path=[td]) - - def test_loaded_config_files(self): - app = MyApp() - app.log = logging.getLogger() - name = 'config.py' - with TemporaryDirectory('_1') as td1: - config_file = pjoin(td1, name) - with open(config_file, 'w') as f: - f.writelines([ - "c.MyApp.running = True\n" - ]) - - app.load_config_file(name, path=[td1]) - self.assertEqual(len(app.loaded_config_files), 1) - self.assertEquals(app.loaded_config_files[0], config_file) - - app.start() - self.assertEqual(app.running, True) - - # emulate an app that allows dynamic updates and update config file - with open(config_file, 'w') as f: - f.writelines([ - "c.MyApp.running = False\n" - ]) - - # reload and verify update, and that loaded_configs was not increased - app.load_config_file(name, path=[td1]) - self.assertEqual(len(app.loaded_config_files), 1) - self.assertEqual(app.running, False) - - # Attempt to update, ensure error... - with self.assertRaises(AttributeError): - app.loaded_config_files = "/foo" - - # ensure it can't be udpated via append - app.loaded_config_files.append("/bar") - self.assertEqual(len(app.loaded_config_files), 1) - - # repeat to ensure no unexpected changes occurred - app.load_config_file(name, path=[td1]) - self.assertEqual(len(app.loaded_config_files), 1) - self.assertEqual(app.running, False) - - -class DeprecatedApp(Application): - override_called = False - parent_called = False - def _config_changed(self, name, old, new): - self.override_called = True - def _capture(*args): - self.parent_called = True - with mock.patch.object(self.log, 'debug', _capture): - super(DeprecatedApp, self)._config_changed(name, old, new) - - -def test_deprecated_notifier(): - app = DeprecatedApp() - assert not app.override_called - assert not app.parent_called - app.config = Config({'A': {'b': 'c'}}) - assert app.override_called - assert app.parent_called - - -def test_help_output(): - check_help_output(__name__) - check_help_all_output(__name__) - -if __name__ == '__main__': - # for test_help_output: - MyApp.launch_instance()
\ No newline at end of file +# coding: utf-8 +""" +Tests for traitlets.config.application.Application +""" + +# Copyright (c) IPython Development Team. +# Distributed under the terms of the Modified BSD License. + +import json +import logging +import os +from io import StringIO +from unittest import TestCase + +try: + from unittest import mock +except ImportError: + import mock + +pjoin = os.path.join + +from pytest import mark + +from traitlets.config.configurable import Configurable +from traitlets.config.loader import Config +from traitlets.tests.utils import check_help_output, check_help_all_output + +from traitlets.config.application import ( + Application +) + +from ipython_genutils.tempdir import TemporaryDirectory +from traitlets.traitlets import ( + Bool, Unicode, Integer, List, Dict +) + + +class Foo(Configurable): + + i = Integer(0, help="The integer i.").tag(config=True) + j = Integer(1, help="The integer j.").tag(config=True) + name = Unicode(u'Brian', help="First name.").tag(config=True) + + +class Bar(Configurable): + + b = Integer(0, help="The integer b.").tag(config=True) + enabled = Bool(True, help="Enable bar.").tag(config=True) + + +class MyApp(Application): + + name = Unicode(u'myapp') + running = Bool(False, help="Is the app running?").tag(config=True) + classes = List([Bar, Foo]) + config_file = Unicode(u'', help="Load this config file").tag(config=True) + + warn_tpyo = Unicode(u"yes the name is wrong on purpose", config=True, + help="Should print a warning if `MyApp.warn-typo=...` command is passed") + + aliases = Dict({ + 'i' : 'Foo.i', + 'j' : 'Foo.j', + 'name' : 'Foo.name', + 'enabled' : 'Bar.enabled', + 'log-level' : 'Application.log_level', + }) + + flags = Dict(dict(enable=({'Bar': {'enabled' : True}}, "Set Bar.enabled to True"), + disable=({'Bar': {'enabled' : False}}, "Set Bar.enabled to False"), + crit=({'Application' : {'log_level' : logging.CRITICAL}}, + "set level=CRITICAL"), + )) + + def init_foo(self): + self.foo = Foo(parent=self) + + def init_bar(self): + self.bar = Bar(parent=self) + + +class TestApplication(TestCase): + + def test_log(self): + stream = StringIO() + app = MyApp(log_level=logging.INFO) + handler = logging.StreamHandler(stream) + # trigger reconstruction of the log formatter + app.log.handlers = [handler] + app.log_format = "%(message)s" + app.log_datefmt = "%Y-%m-%d %H:%M" + app.log.info("hello") + assert "hello" in stream.getvalue() + + def test_basic(self): + app = MyApp() + self.assertEqual(app.name, u'myapp') + self.assertEqual(app.running, False) + self.assertEqual(app.classes, [MyApp,Bar,Foo]) + self.assertEqual(app.config_file, u'') + + def test_config(self): + app = MyApp() + app.parse_command_line(["--i=10","--Foo.j=10","--enabled=False","--log-level=50"]) + config = app.config + self.assertEqual(config.Foo.i, 10) + self.assertEqual(config.Foo.j, 10) + self.assertEqual(config.Bar.enabled, False) + self.assertEqual(config.MyApp.log_level,50) + + def test_config_propagation(self): + app = MyApp() + app.parse_command_line(["--i=10","--Foo.j=10","--enabled=False","--log-level=50"]) + app.init_foo() + app.init_bar() + self.assertEqual(app.foo.i, 10) + self.assertEqual(app.foo.j, 10) + self.assertEqual(app.bar.enabled, False) + + def test_cli_priority(self): + """Test that loading config files does not override CLI options""" + name = 'config.py' + class TestApp(Application): + value = Unicode().tag(config=True) + config_file_loaded = Bool().tag(config=True) + aliases = {'v': 'TestApp.value'} + app = TestApp() + with TemporaryDirectory() as td: + config_file = pjoin(td, name) + with open(config_file, 'w') as f: + f.writelines([ + "c.TestApp.value = 'config file'\n", + "c.TestApp.config_file_loaded = True\n" + ]) + + app.parse_command_line(['--v=cli']) + assert 'value' in app.config.TestApp + assert app.config.TestApp.value == 'cli' + assert app.value == 'cli' + + app.load_config_file(name, path=[td]) + assert app.config_file_loaded + assert app.config.TestApp.value == 'cli' + assert app.value == 'cli' + + def test_ipython_cli_priority(self): + # this test is almost entirely redundant with above, + # but we can keep it around in case of subtle issues creeping into + # the exact sequence IPython follows. + name = 'config.py' + class TestApp(Application): + value = Unicode().tag(config=True) + config_file_loaded = Bool().tag(config=True) + aliases = {'v': 'TestApp.value'} + app = TestApp() + with TemporaryDirectory() as td: + config_file = pjoin(td, name) + with open(config_file, 'w') as f: + f.writelines([ + "c.TestApp.value = 'config file'\n", + "c.TestApp.config_file_loaded = True\n" + ]) + # follow IPython's config-loading sequence to ensure CLI priority is preserved + app.parse_command_line(['--v=cli']) + # this is where IPython makes a mistake: + # it assumes app.config will not be modified, + # and storing a reference is storing a copy + cli_config = app.config + assert 'value' in app.config.TestApp + assert app.config.TestApp.value == 'cli' + assert app.value == 'cli' + app.load_config_file(name, path=[td]) + assert app.config_file_loaded + # enforce cl-opts override config file opts: + # this is where IPython makes a mistake: it assumes + # that cl_config is a different object, but it isn't. + app.update_config(cli_config) + assert app.config.TestApp.value == 'cli' + assert app.value == 'cli' + + def test_flags(self): + app = MyApp() + app.parse_command_line(["--disable"]) + app.init_bar() + self.assertEqual(app.bar.enabled, False) + app.parse_command_line(["--enable"]) + app.init_bar() + self.assertEqual(app.bar.enabled, True) + + def test_aliases(self): + app = MyApp() + app.parse_command_line(["--i=5", "--j=10"]) + app.init_foo() + self.assertEqual(app.foo.i, 5) + app.init_foo() + self.assertEqual(app.foo.j, 10) + + def test_flag_clobber(self): + """test that setting flags doesn't clobber existing settings""" + app = MyApp() + app.parse_command_line(["--Bar.b=5", "--disable"]) + app.init_bar() + self.assertEqual(app.bar.enabled, False) + self.assertEqual(app.bar.b, 5) + app.parse_command_line(["--enable", "--Bar.b=10"]) + app.init_bar() + self.assertEqual(app.bar.enabled, True) + self.assertEqual(app.bar.b, 10) + + def test_warn_autocorrect(self): + stream = StringIO() + app = MyApp(log_level=logging.INFO) + app.log.handlers = [logging.StreamHandler(stream)] + + cfg = Config() + cfg.MyApp.warn_typo = "WOOOO" + app.config = cfg + + self.assertIn("warn_typo", stream.getvalue()) + self.assertIn("warn_tpyo", stream.getvalue()) + + + def test_flatten_flags(self): + cfg = Config() + cfg.MyApp.log_level = logging.WARN + app = MyApp() + app.update_config(cfg) + self.assertEqual(app.log_level, logging.WARN) + self.assertEqual(app.config.MyApp.log_level, logging.WARN) + app.initialize(["--crit"]) + self.assertEqual(app.log_level, logging.CRITICAL) + # this would be app.config.Application.log_level if it failed: + self.assertEqual(app.config.MyApp.log_level, logging.CRITICAL) + + def test_flatten_aliases(self): + cfg = Config() + cfg.MyApp.log_level = logging.WARN + app = MyApp() + app.update_config(cfg) + self.assertEqual(app.log_level, logging.WARN) + self.assertEqual(app.config.MyApp.log_level, logging.WARN) + app.initialize(["--log-level", "CRITICAL"]) + self.assertEqual(app.log_level, logging.CRITICAL) + # this would be app.config.Application.log_level if it failed: + self.assertEqual(app.config.MyApp.log_level, "CRITICAL") + + def test_extra_args(self): + app = MyApp() + app.parse_command_line(["--Bar.b=5", 'extra', "--disable", 'args']) + app.init_bar() + self.assertEqual(app.bar.enabled, False) + self.assertEqual(app.bar.b, 5) + self.assertEqual(app.extra_args, ['extra', 'args']) + app = MyApp() + app.parse_command_line(["--Bar.b=5", '--', 'extra', "--disable", 'args']) + app.init_bar() + self.assertEqual(app.bar.enabled, True) + self.assertEqual(app.bar.b, 5) + self.assertEqual(app.extra_args, ['extra', '--disable', 'args']) + + def test_unicode_argv(self): + app = MyApp() + app.parse_command_line(['ünîcødé']) + + def test_document_config_option(self): + app = MyApp() + app.document_config_options() + + def test_generate_config_file(self): + app = MyApp() + assert 'The integer b.' in app.generate_config_file() + + def test_generate_config_file_classes_to_include(self): + class NoTraits(Foo, Bar): + pass + + app = MyApp() + app.classes.append(NoTraits) + conf_txt = app.generate_config_file() + self.assertIn('The integer b.', conf_txt) + self.assertIn('# Bar(Configurable)', conf_txt) + self.assertIn('# Foo(Configurable)', conf_txt) + self.assertNotIn('# Configurable', conf_txt) + self.assertIn('# NoTraits(Foo,Bar)', conf_txt) + + def test_multi_file(self): + app = MyApp() + app.log = logging.getLogger() + name = 'config.py' + with TemporaryDirectory('_1') as td1: + with open(pjoin(td1, name), 'w') as f1: + f1.write("get_config().MyApp.Bar.b = 1") + with TemporaryDirectory('_2') as td2: + with open(pjoin(td2, name), 'w') as f2: + f2.write("get_config().MyApp.Bar.b = 2") + app.load_config_file(name, path=[td2, td1]) + app.init_bar() + self.assertEqual(app.bar.b, 2) + app.load_config_file(name, path=[td1, td2]) + app.init_bar() + self.assertEqual(app.bar.b, 1) + + @mark.skipif(not hasattr(TestCase, 'assertLogs'), reason='requires TestCase.assertLogs') + def test_log_collisions(self): + app = MyApp() + app.log = logging.getLogger() + app.log.setLevel(logging.INFO) + name = 'config' + with TemporaryDirectory('_1') as td: + with open(pjoin(td, name + '.py'), 'w') as f: + f.write("get_config().Bar.b = 1") + with open(pjoin(td, name + '.json'), 'w') as f: + json.dump({ + 'Bar': { + 'b': 2 + } + }, f) + with self.assertLogs(app.log, logging.WARNING) as captured: + app.load_config_file(name, path=[td]) + app.init_bar() + assert app.bar.b == 2 + output = '\n'.join(captured.output) + assert 'Collision' in output + assert '1 ignored, using 2' in output + assert pjoin(td, name + '.py') in output + assert pjoin(td, name + '.json') in output + + @mark.skipif(not hasattr(TestCase, 'assertLogs'), reason='requires TestCase.assertLogs') + def test_log_bad_config(self): + app = MyApp() + app.log = logging.getLogger() + name = 'config.py' + with TemporaryDirectory() as td: + with open(pjoin(td, name), 'w') as f: + f.write("syntax error()") + with self.assertLogs(app.log, logging.ERROR) as captured: + app.load_config_file(name, path=[td]) + output = '\n'.join(captured.output) + self.assertIn('SyntaxError', output) + + def test_raise_on_bad_config(self): + app = MyApp() + app.raise_config_file_errors = True + app.log = logging.getLogger() + name = 'config.py' + with TemporaryDirectory() as td: + with open(pjoin(td, name), 'w') as f: + f.write("syntax error()") + with self.assertRaises(SyntaxError): + app.load_config_file(name, path=[td]) + + def test_loaded_config_files(self): + app = MyApp() + app.log = logging.getLogger() + name = 'config.py' + with TemporaryDirectory('_1') as td1: + config_file = pjoin(td1, name) + with open(config_file, 'w') as f: + f.writelines([ + "c.MyApp.running = True\n" + ]) + + app.load_config_file(name, path=[td1]) + self.assertEqual(len(app.loaded_config_files), 1) + self.assertEquals(app.loaded_config_files[0], config_file) + + app.start() + self.assertEqual(app.running, True) + + # emulate an app that allows dynamic updates and update config file + with open(config_file, 'w') as f: + f.writelines([ + "c.MyApp.running = False\n" + ]) + + # reload and verify update, and that loaded_configs was not increased + app.load_config_file(name, path=[td1]) + self.assertEqual(len(app.loaded_config_files), 1) + self.assertEqual(app.running, False) + + # Attempt to update, ensure error... + with self.assertRaises(AttributeError): + app.loaded_config_files = "/foo" + + # ensure it can't be udpated via append + app.loaded_config_files.append("/bar") + self.assertEqual(len(app.loaded_config_files), 1) + + # repeat to ensure no unexpected changes occurred + app.load_config_file(name, path=[td1]) + self.assertEqual(len(app.loaded_config_files), 1) + self.assertEqual(app.running, False) + + +class DeprecatedApp(Application): + override_called = False + parent_called = False + def _config_changed(self, name, old, new): + self.override_called = True + def _capture(*args): + self.parent_called = True + with mock.patch.object(self.log, 'debug', _capture): + super(DeprecatedApp, self)._config_changed(name, old, new) + + +def test_deprecated_notifier(): + app = DeprecatedApp() + assert not app.override_called + assert not app.parent_called + app.config = Config({'A': {'b': 'c'}}) + assert app.override_called + assert app.parent_called + + +def test_help_output(): + check_help_output(__name__) + check_help_all_output(__name__) + +if __name__ == '__main__': + # for test_help_output: + MyApp.launch_instance()
\ No newline at end of file diff --git a/contrib/python/traitlets/py2/traitlets/config/tests/test_configurable.py b/contrib/python/traitlets/py2/traitlets/config/tests/test_configurable.py index 9fbdb7209dc..639b65f7293 100644 --- a/contrib/python/traitlets/py2/traitlets/config/tests/test_configurable.py +++ b/contrib/python/traitlets/py2/traitlets/config/tests/test_configurable.py @@ -1,459 +1,459 @@ -# encoding: utf-8 -"""Tests for traitlets.config.configurable""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import logging -from unittest import TestCase - -from pytest import mark - -from traitlets.config.configurable import ( - Configurable, - LoggingConfigurable, - SingletonConfigurable, -) - -from traitlets.traitlets import ( - Integer, Float, Unicode, List, Dict, Set, - _deprecations_shown, -) - -from traitlets.config.loader import Config -from six import PY3 - -from ...tests._warnings import expected_warnings - -class MyConfigurable(Configurable): - a = Integer(1, help="The integer a.").tag(config=True) - b = Float(1.0, help="The integer b.").tag(config=True) - c = Unicode('no config') - - -mc_help=u"""MyConfigurable options ----------------------- ---MyConfigurable.a=<Integer> - Default: 1 - The integer a. ---MyConfigurable.b=<Float> - Default: 1.0 - The integer b.""" - -mc_help_inst=u"""MyConfigurable options ----------------------- ---MyConfigurable.a=<Integer> - Current: 5 - The integer a. ---MyConfigurable.b=<Float> - Current: 4.0 - The integer b.""" - -# On Python 3, the Integer trait is a synonym for Int -if PY3: - mc_help = mc_help.replace(u"<Integer>", u"<Int>") - mc_help_inst = mc_help_inst.replace(u"<Integer>", u"<Int>") - -class Foo(Configurable): - a = Integer(0, help="The integer a.").tag(config=True) - b = Unicode('nope').tag(config=True) - - -class Bar(Foo): - b = Unicode('gotit', help="The string b.").tag(config=False) - c = Float(help="The string c.").tag(config=True) - - -class TestConfigurable(TestCase): - - def test_default(self): - c1 = Configurable() - c2 = Configurable(config=c1.config) - c3 = Configurable(config=c2.config) - self.assertEqual(c1.config, c2.config) - self.assertEqual(c2.config, c3.config) - - def test_custom(self): - config = Config() - config.foo = 'foo' - config.bar = 'bar' - c1 = Configurable(config=config) - c2 = Configurable(config=c1.config) - c3 = Configurable(config=c2.config) - self.assertEqual(c1.config, config) - self.assertEqual(c2.config, config) - self.assertEqual(c3.config, config) - # Test that copies are not made - self.assertTrue(c1.config is config) - self.assertTrue(c2.config is config) - self.assertTrue(c3.config is config) - self.assertTrue(c1.config is c2.config) - self.assertTrue(c2.config is c3.config) - - def test_inheritance(self): - config = Config() - config.MyConfigurable.a = 2 - config.MyConfigurable.b = 2.0 - c1 = MyConfigurable(config=config) - c2 = MyConfigurable(config=c1.config) - self.assertEqual(c1.a, config.MyConfigurable.a) - self.assertEqual(c1.b, config.MyConfigurable.b) - self.assertEqual(c2.a, config.MyConfigurable.a) - self.assertEqual(c2.b, config.MyConfigurable.b) - - def test_parent(self): - config = Config() - config.Foo.a = 10 - config.Foo.b = "wow" - config.Bar.b = 'later' - config.Bar.c = 100.0 - f = Foo(config=config) - with expected_warnings(['`b` not recognized']): - b = Bar(config=f.config) - self.assertEqual(f.a, 10) - self.assertEqual(f.b, 'wow') - self.assertEqual(b.b, 'gotit') - self.assertEqual(b.c, 100.0) - - def test_override1(self): - config = Config() - config.MyConfigurable.a = 2 - config.MyConfigurable.b = 2.0 - c = MyConfigurable(a=3, config=config) - self.assertEqual(c.a, 3) - self.assertEqual(c.b, config.MyConfigurable.b) - self.assertEqual(c.c, 'no config') - - def test_override2(self): - config = Config() - config.Foo.a = 1 - config.Bar.b = 'or' # Up above b is config=False, so this won't do it. - config.Bar.c = 10.0 - with expected_warnings(['`b` not recognized']): - c = Bar(config=config) - self.assertEqual(c.a, config.Foo.a) - self.assertEqual(c.b, 'gotit') - self.assertEqual(c.c, config.Bar.c) - with expected_warnings(['`b` not recognized']): - c = Bar(a=2, b='and', c=20.0, config=config) - self.assertEqual(c.a, 2) - self.assertEqual(c.b, 'and') - self.assertEqual(c.c, 20.0) - - def test_help(self): - self.assertEqual(MyConfigurable.class_get_help(), mc_help) - - def test_help_inst(self): - inst = MyConfigurable(a=5, b=4) - self.assertEqual(MyConfigurable.class_get_help(inst), mc_help_inst) - - -class TestSingletonConfigurable(TestCase): - - def test_instance(self): - class Foo(SingletonConfigurable): pass - self.assertEqual(Foo.initialized(), False) - foo = Foo.instance() - self.assertEqual(Foo.initialized(), True) - self.assertEqual(foo, Foo.instance()) - self.assertEqual(SingletonConfigurable._instance, None) - - def test_inheritance(self): - class Bar(SingletonConfigurable): pass - class Bam(Bar): pass - self.assertEqual(Bar.initialized(), False) - self.assertEqual(Bam.initialized(), False) - bam = Bam.instance() - bam == Bar.instance() - self.assertEqual(Bar.initialized(), True) - self.assertEqual(Bam.initialized(), True) - self.assertEqual(bam, Bam._instance) - self.assertEqual(bam, Bar._instance) - self.assertEqual(SingletonConfigurable._instance, None) - - -class MyParent(Configurable): - pass - -class MyParent2(MyParent): - pass - -class TestParentConfigurable(TestCase): - - def test_parent_config(self): - cfg = Config({ - 'MyParent' : { - 'MyConfigurable' : { - 'b' : 2.0, - } - } - }) - parent = MyParent(config=cfg) - myc = MyConfigurable(parent=parent) - self.assertEqual(myc.b, parent.config.MyParent.MyConfigurable.b) - - def test_parent_inheritance(self): - cfg = Config({ - 'MyParent' : { - 'MyConfigurable' : { - 'b' : 2.0, - } - } - }) - parent = MyParent2(config=cfg) - myc = MyConfigurable(parent=parent) - self.assertEqual(myc.b, parent.config.MyParent.MyConfigurable.b) - - def test_multi_parent(self): - cfg = Config({ - 'MyParent2' : { - 'MyParent' : { - 'MyConfigurable' : { - 'b' : 2.0, - } - }, - # this one shouldn't count - 'MyConfigurable' : { - 'b' : 3.0, - }, - } - }) - parent2 = MyParent2(config=cfg) - parent = MyParent(parent=parent2) - myc = MyConfigurable(parent=parent) - self.assertEqual(myc.b, parent.config.MyParent2.MyParent.MyConfigurable.b) - - def test_parent_priority(self): - cfg = Config({ - 'MyConfigurable' : { - 'b' : 2.0, - }, - 'MyParent' : { - 'MyConfigurable' : { - 'b' : 3.0, - } - }, - 'MyParent2' : { - 'MyConfigurable' : { - 'b' : 4.0, - } - } - }) - parent = MyParent2(config=cfg) - myc = MyConfigurable(parent=parent) - self.assertEqual(myc.b, parent.config.MyParent2.MyConfigurable.b) - - def test_multi_parent_priority(self): - cfg = Config({ - 'MyConfigurable' : { - 'b' : 2.0, - }, - 'MyParent' : { - 'MyConfigurable' : { - 'b' : 3.0, - } - }, - 'MyParent2' : { - 'MyConfigurable' : { - 'b' : 4.0, - } - }, - 'MyParent2' : { - 'MyParent' : { - 'MyConfigurable' : { - 'b' : 5.0, - } - } - } - }) - parent2 = MyParent2(config=cfg) - parent = MyParent2(parent=parent2) - myc = MyConfigurable(parent=parent) - self.assertEqual(myc.b, parent.config.MyParent2.MyParent.MyConfigurable.b) - -class Containers(Configurable): - lis = List().tag(config=True) - def _lis_default(self): - return [-1] - - s = Set().tag(config=True) - def _s_default(self): - return {'a'} - - d = Dict().tag(config=True) - def _d_default(self): - return {'a' : 'b'} - -class TestConfigContainers(TestCase): - def test_extend(self): - c = Config() - c.Containers.lis.extend(list(range(5))) - obj = Containers(config=c) - self.assertEqual(obj.lis, list(range(-1,5))) - - def test_insert(self): - c = Config() - c.Containers.lis.insert(0, 'a') - c.Containers.lis.insert(1, 'b') - obj = Containers(config=c) - self.assertEqual(obj.lis, ['a', 'b', -1]) - - def test_prepend(self): - c = Config() - c.Containers.lis.prepend([1,2]) - c.Containers.lis.prepend([2,3]) - obj = Containers(config=c) - self.assertEqual(obj.lis, [2,3,1,2,-1]) - - def test_prepend_extend(self): - c = Config() - c.Containers.lis.prepend([1,2]) - c.Containers.lis.extend([2,3]) - obj = Containers(config=c) - self.assertEqual(obj.lis, [1,2,-1,2,3]) - - def test_append_extend(self): - c = Config() - c.Containers.lis.append([1,2]) - c.Containers.lis.extend([2,3]) - obj = Containers(config=c) - self.assertEqual(obj.lis, [-1,[1,2],2,3]) - - def test_extend_append(self): - c = Config() - c.Containers.lis.extend([2,3]) - c.Containers.lis.append([1,2]) - obj = Containers(config=c) - self.assertEqual(obj.lis, [-1,2,3,[1,2]]) - - def test_insert_extend(self): - c = Config() - c.Containers.lis.insert(0, 1) - c.Containers.lis.extend([2,3]) - obj = Containers(config=c) - self.assertEqual(obj.lis, [1,-1,2,3]) - - def test_set_update(self): - c = Config() - c.Containers.s.update({0,1,2}) - c.Containers.s.update({3}) - obj = Containers(config=c) - self.assertEqual(obj.s, {'a', 0, 1, 2, 3}) - - def test_dict_update(self): - c = Config() - c.Containers.d.update({'c' : 'd'}) - c.Containers.d.update({'e' : 'f'}) - obj = Containers(config=c) - self.assertEqual(obj.d, {'a':'b', 'c':'d', 'e':'f'}) - - def test_update_twice(self): - c = Config() - c.MyConfigurable.a = 5 - m = MyConfigurable(config=c) - self.assertEqual(m.a, 5) - - c2 = Config() - c2.MyConfigurable.a = 10 - m.update_config(c2) - self.assertEqual(m.a, 10) - - c2.MyConfigurable.a = 15 - m.update_config(c2) - self.assertEqual(m.a, 15) - - def test_update_self(self): - """update_config with same config object still triggers config_changed""" - c = Config() - c.MyConfigurable.a = 5 - m = MyConfigurable(config=c) - self.assertEqual(m.a, 5) - c.MyConfigurable.a = 10 - m.update_config(c) - self.assertEqual(m.a, 10) - - def test_config_default(self): - class SomeSingleton(SingletonConfigurable): - pass - - class DefaultConfigurable(Configurable): - a = Integer().tag(config=True) - def _config_default(self): - if SomeSingleton.initialized(): - return SomeSingleton.instance().config - return Config() - - c = Config() - c.DefaultConfigurable.a = 5 - - d1 = DefaultConfigurable() - self.assertEqual(d1.a, 0) - - single = SomeSingleton.instance(config=c) - - d2 = DefaultConfigurable() - self.assertIs(d2.config, single.config) - self.assertEqual(d2.a, 5) - - def test_config_default_deprecated(self): - """Make sure configurables work even with the deprecations in traitlets""" - class SomeSingleton(SingletonConfigurable): - pass - - # reset deprecation limiter - _deprecations_shown.clear() - with expected_warnings([]): - class DefaultConfigurable(Configurable): - a = Integer(config=True) - def _config_default(self): - if SomeSingleton.initialized(): - return SomeSingleton.instance().config - return Config() - - c = Config() - c.DefaultConfigurable.a = 5 - - d1 = DefaultConfigurable() - self.assertEqual(d1.a, 0) - - single = SomeSingleton.instance(config=c) - - d2 = DefaultConfigurable() - self.assertIs(d2.config, single.config) - self.assertEqual(d2.a, 5) - - -class TestLogger(TestCase): - - class A(LoggingConfigurable): - foo = Integer(config=True) - bar = Integer(config=True) - baz = Integer(config=True) - - @mark.skipif(not hasattr(TestCase, 'assertLogs'), reason='requires TestCase.assertLogs') - def test_warn_match(self): - logger = logging.getLogger('test_warn_match') - cfg = Config({'A': {'bat': 5}}) - with self.assertLogs(logger, logging.WARNING) as captured: - a = TestLogger.A(config=cfg, log=logger) - - output = '\n'.join(captured.output) - self.assertIn('Did you mean one of: `bar, baz`?', output) - self.assertIn('Config option `bat` not recognized by `A`.', output) - - cfg = Config({'A': {'fool': 5}}) - with self.assertLogs(logger, logging.WARNING) as captured: - a = TestLogger.A(config=cfg, log=logger) - - output = '\n'.join(captured.output) - self.assertIn('Config option `fool` not recognized by `A`.', output) - self.assertIn('Did you mean `foo`?', output) - - cfg = Config({'A': {'totally_wrong': 5}}) - with self.assertLogs(logger, logging.WARNING) as captured: - a = TestLogger.A(config=cfg, log=logger) - - output = '\n'.join(captured.output) - self.assertIn('Config option `totally_wrong` not recognized by `A`.', output) - self.assertNotIn('Did you mean', output) - +# encoding: utf-8 +"""Tests for traitlets.config.configurable""" + +# Copyright (c) IPython Development Team. +# Distributed under the terms of the Modified BSD License. + +import logging +from unittest import TestCase + +from pytest import mark + +from traitlets.config.configurable import ( + Configurable, + LoggingConfigurable, + SingletonConfigurable, +) + +from traitlets.traitlets import ( + Integer, Float, Unicode, List, Dict, Set, + _deprecations_shown, +) + +from traitlets.config.loader import Config +from six import PY3 + +from ...tests._warnings import expected_warnings + +class MyConfigurable(Configurable): + a = Integer(1, help="The integer a.").tag(config=True) + b = Float(1.0, help="The integer b.").tag(config=True) + c = Unicode('no config') + + +mc_help=u"""MyConfigurable options +---------------------- +--MyConfigurable.a=<Integer> + Default: 1 + The integer a. +--MyConfigurable.b=<Float> + Default: 1.0 + The integer b.""" + +mc_help_inst=u"""MyConfigurable options +---------------------- +--MyConfigurable.a=<Integer> + Current: 5 + The integer a. +--MyConfigurable.b=<Float> + Current: 4.0 + The integer b.""" + +# On Python 3, the Integer trait is a synonym for Int +if PY3: + mc_help = mc_help.replace(u"<Integer>", u"<Int>") + mc_help_inst = mc_help_inst.replace(u"<Integer>", u"<Int>") + +class Foo(Configurable): + a = Integer(0, help="The integer a.").tag(config=True) + b = Unicode('nope').tag(config=True) + + +class Bar(Foo): + b = Unicode('gotit', help="The string b.").tag(config=False) + c = Float(help="The string c.").tag(config=True) + + +class TestConfigurable(TestCase): + + def test_default(self): + c1 = Configurable() + c2 = Configurable(config=c1.config) + c3 = Configurable(config=c2.config) + self.assertEqual(c1.config, c2.config) + self.assertEqual(c2.config, c3.config) + + def test_custom(self): + config = Config() + config.foo = 'foo' + config.bar = 'bar' + c1 = Configurable(config=config) + c2 = Configurable(config=c1.config) + c3 = Configurable(config=c2.config) + self.assertEqual(c1.config, config) + self.assertEqual(c2.config, config) + self.assertEqual(c3.config, config) + # Test that copies are not made + self.assertTrue(c1.config is config) + self.assertTrue(c2.config is config) + self.assertTrue(c3.config is config) + self.assertTrue(c1.config is c2.config) + self.assertTrue(c2.config is c3.config) + + def test_inheritance(self): + config = Config() + config.MyConfigurable.a = 2 + config.MyConfigurable.b = 2.0 + c1 = MyConfigurable(config=config) + c2 = MyConfigurable(config=c1.config) + self.assertEqual(c1.a, config.MyConfigurable.a) + self.assertEqual(c1.b, config.MyConfigurable.b) + self.assertEqual(c2.a, config.MyConfigurable.a) + self.assertEqual(c2.b, config.MyConfigurable.b) + + def test_parent(self): + config = Config() + config.Foo.a = 10 + config.Foo.b = "wow" + config.Bar.b = 'later' + config.Bar.c = 100.0 + f = Foo(config=config) + with expected_warnings(['`b` not recognized']): + b = Bar(config=f.config) + self.assertEqual(f.a, 10) + self.assertEqual(f.b, 'wow') + self.assertEqual(b.b, 'gotit') + self.assertEqual(b.c, 100.0) + + def test_override1(self): + config = Config() + config.MyConfigurable.a = 2 + config.MyConfigurable.b = 2.0 + c = MyConfigurable(a=3, config=config) + self.assertEqual(c.a, 3) + self.assertEqual(c.b, config.MyConfigurable.b) + self.assertEqual(c.c, 'no config') + + def test_override2(self): + config = Config() + config.Foo.a = 1 + config.Bar.b = 'or' # Up above b is config=False, so this won't do it. + config.Bar.c = 10.0 + with expected_warnings(['`b` not recognized']): + c = Bar(config=config) + self.assertEqual(c.a, config.Foo.a) + self.assertEqual(c.b, 'gotit') + self.assertEqual(c.c, config.Bar.c) + with expected_warnings(['`b` not recognized']): + c = Bar(a=2, b='and', c=20.0, config=config) + self.assertEqual(c.a, 2) + self.assertEqual(c.b, 'and') + self.assertEqual(c.c, 20.0) + + def test_help(self): + self.assertEqual(MyConfigurable.class_get_help(), mc_help) + + def test_help_inst(self): + inst = MyConfigurable(a=5, b=4) + self.assertEqual(MyConfigurable.class_get_help(inst), mc_help_inst) + + +class TestSingletonConfigurable(TestCase): + + def test_instance(self): + class Foo(SingletonConfigurable): pass + self.assertEqual(Foo.initialized(), False) + foo = Foo.instance() + self.assertEqual(Foo.initialized(), True) + self.assertEqual(foo, Foo.instance()) + self.assertEqual(SingletonConfigurable._instance, None) + + def test_inheritance(self): + class Bar(SingletonConfigurable): pass + class Bam(Bar): pass + self.assertEqual(Bar.initialized(), False) + self.assertEqual(Bam.initialized(), False) + bam = Bam.instance() + bam == Bar.instance() + self.assertEqual(Bar.initialized(), True) + self.assertEqual(Bam.initialized(), True) + self.assertEqual(bam, Bam._instance) + self.assertEqual(bam, Bar._instance) + self.assertEqual(SingletonConfigurable._instance, None) + + +class MyParent(Configurable): + pass + +class MyParent2(MyParent): + pass + +class TestParentConfigurable(TestCase): + + def test_parent_config(self): + cfg = Config({ + 'MyParent' : { + 'MyConfigurable' : { + 'b' : 2.0, + } + } + }) + parent = MyParent(config=cfg) + myc = MyConfigurable(parent=parent) + self.assertEqual(myc.b, parent.config.MyParent.MyConfigurable.b) + + def test_parent_inheritance(self): + cfg = Config({ + 'MyParent' : { + 'MyConfigurable' : { + 'b' : 2.0, + } + } + }) + parent = MyParent2(config=cfg) + myc = MyConfigurable(parent=parent) + self.assertEqual(myc.b, parent.config.MyParent.MyConfigurable.b) + + def test_multi_parent(self): + cfg = Config({ + 'MyParent2' : { + 'MyParent' : { + 'MyConfigurable' : { + 'b' : 2.0, + } + }, + # this one shouldn't count + 'MyConfigurable' : { + 'b' : 3.0, + }, + } + }) + parent2 = MyParent2(config=cfg) + parent = MyParent(parent=parent2) + myc = MyConfigurable(parent=parent) + self.assertEqual(myc.b, parent.config.MyParent2.MyParent.MyConfigurable.b) + + def test_parent_priority(self): + cfg = Config({ + 'MyConfigurable' : { + 'b' : 2.0, + }, + 'MyParent' : { + 'MyConfigurable' : { + 'b' : 3.0, + } + }, + 'MyParent2' : { + 'MyConfigurable' : { + 'b' : 4.0, + } + } + }) + parent = MyParent2(config=cfg) + myc = MyConfigurable(parent=parent) + self.assertEqual(myc.b, parent.config.MyParent2.MyConfigurable.b) + + def test_multi_parent_priority(self): + cfg = Config({ + 'MyConfigurable' : { + 'b' : 2.0, + }, + 'MyParent' : { + 'MyConfigurable' : { + 'b' : 3.0, + } + }, + 'MyParent2' : { + 'MyConfigurable' : { + 'b' : 4.0, + } + }, + 'MyParent2' : { + 'MyParent' : { + 'MyConfigurable' : { + 'b' : 5.0, + } + } + } + }) + parent2 = MyParent2(config=cfg) + parent = MyParent2(parent=parent2) + myc = MyConfigurable(parent=parent) + self.assertEqual(myc.b, parent.config.MyParent2.MyParent.MyConfigurable.b) + +class Containers(Configurable): + lis = List().tag(config=True) + def _lis_default(self): + return [-1] + + s = Set().tag(config=True) + def _s_default(self): + return {'a'} + + d = Dict().tag(config=True) + def _d_default(self): + return {'a' : 'b'} + +class TestConfigContainers(TestCase): + def test_extend(self): + c = Config() + c.Containers.lis.extend(list(range(5))) + obj = Containers(config=c) + self.assertEqual(obj.lis, list(range(-1,5))) + + def test_insert(self): + c = Config() + c.Containers.lis.insert(0, 'a') + c.Containers.lis.insert(1, 'b') + obj = Containers(config=c) + self.assertEqual(obj.lis, ['a', 'b', -1]) + + def test_prepend(self): + c = Config() + c.Containers.lis.prepend([1,2]) + c.Containers.lis.prepend([2,3]) + obj = Containers(config=c) + self.assertEqual(obj.lis, [2,3,1,2,-1]) + + def test_prepend_extend(self): + c = Config() + c.Containers.lis.prepend([1,2]) + c.Containers.lis.extend([2,3]) + obj = Containers(config=c) + self.assertEqual(obj.lis, [1,2,-1,2,3]) + + def test_append_extend(self): + c = Config() + c.Containers.lis.append([1,2]) + c.Containers.lis.extend([2,3]) + obj = Containers(config=c) + self.assertEqual(obj.lis, [-1,[1,2],2,3]) + + def test_extend_append(self): + c = Config() + c.Containers.lis.extend([2,3]) + c.Containers.lis.append([1,2]) + obj = Containers(config=c) + self.assertEqual(obj.lis, [-1,2,3,[1,2]]) + + def test_insert_extend(self): + c = Config() + c.Containers.lis.insert(0, 1) + c.Containers.lis.extend([2,3]) + obj = Containers(config=c) + self.assertEqual(obj.lis, [1,-1,2,3]) + + def test_set_update(self): + c = Config() + c.Containers.s.update({0,1,2}) + c.Containers.s.update({3}) + obj = Containers(config=c) + self.assertEqual(obj.s, {'a', 0, 1, 2, 3}) + + def test_dict_update(self): + c = Config() + c.Containers.d.update({'c' : 'd'}) + c.Containers.d.update({'e' : 'f'}) + obj = Containers(config=c) + self.assertEqual(obj.d, {'a':'b', 'c':'d', 'e':'f'}) + + def test_update_twice(self): + c = Config() + c.MyConfigurable.a = 5 + m = MyConfigurable(config=c) + self.assertEqual(m.a, 5) + + c2 = Config() + c2.MyConfigurable.a = 10 + m.update_config(c2) + self.assertEqual(m.a, 10) + + c2.MyConfigurable.a = 15 + m.update_config(c2) + self.assertEqual(m.a, 15) + + def test_update_self(self): + """update_config with same config object still triggers config_changed""" + c = Config() + c.MyConfigurable.a = 5 + m = MyConfigurable(config=c) + self.assertEqual(m.a, 5) + c.MyConfigurable.a = 10 + m.update_config(c) + self.assertEqual(m.a, 10) + + def test_config_default(self): + class SomeSingleton(SingletonConfigurable): + pass + + class DefaultConfigurable(Configurable): + a = Integer().tag(config=True) + def _config_default(self): + if SomeSingleton.initialized(): + return SomeSingleton.instance().config + return Config() + + c = Config() + c.DefaultConfigurable.a = 5 + + d1 = DefaultConfigurable() + self.assertEqual(d1.a, 0) + + single = SomeSingleton.instance(config=c) + + d2 = DefaultConfigurable() + self.assertIs(d2.config, single.config) + self.assertEqual(d2.a, 5) + + def test_config_default_deprecated(self): + """Make sure configurables work even with the deprecations in traitlets""" + class SomeSingleton(SingletonConfigurable): + pass + + # reset deprecation limiter + _deprecations_shown.clear() + with expected_warnings([]): + class DefaultConfigurable(Configurable): + a = Integer(config=True) + def _config_default(self): + if SomeSingleton.initialized(): + return SomeSingleton.instance().config + return Config() + + c = Config() + c.DefaultConfigurable.a = 5 + + d1 = DefaultConfigurable() + self.assertEqual(d1.a, 0) + + single = SomeSingleton.instance(config=c) + + d2 = DefaultConfigurable() + self.assertIs(d2.config, single.config) + self.assertEqual(d2.a, 5) + + +class TestLogger(TestCase): + + class A(LoggingConfigurable): + foo = Integer(config=True) + bar = Integer(config=True) + baz = Integer(config=True) + + @mark.skipif(not hasattr(TestCase, 'assertLogs'), reason='requires TestCase.assertLogs') + def test_warn_match(self): + logger = logging.getLogger('test_warn_match') + cfg = Config({'A': {'bat': 5}}) + with self.assertLogs(logger, logging.WARNING) as captured: + a = TestLogger.A(config=cfg, log=logger) + + output = '\n'.join(captured.output) + self.assertIn('Did you mean one of: `bar, baz`?', output) + self.assertIn('Config option `bat` not recognized by `A`.', output) + + cfg = Config({'A': {'fool': 5}}) + with self.assertLogs(logger, logging.WARNING) as captured: + a = TestLogger.A(config=cfg, log=logger) + + output = '\n'.join(captured.output) + self.assertIn('Config option `fool` not recognized by `A`.', output) + self.assertIn('Did you mean `foo`?', output) + + cfg = Config({'A': {'totally_wrong': 5}}) + with self.assertLogs(logger, logging.WARNING) as captured: + a = TestLogger.A(config=cfg, log=logger) + + output = '\n'.join(captured.output) + self.assertIn('Config option `totally_wrong` not recognized by `A`.', output) + self.assertNotIn('Did you mean', output) + diff --git a/contrib/python/traitlets/py2/traitlets/config/tests/test_loader.py b/contrib/python/traitlets/py2/traitlets/config/tests/test_loader.py index 50c8659f3c6..fc543a535a5 100644 --- a/contrib/python/traitlets/py2/traitlets/config/tests/test_loader.py +++ b/contrib/python/traitlets/py2/traitlets/config/tests/test_loader.py @@ -1,453 +1,453 @@ -# encoding: utf-8 -"""Tests for traitlets.config.loader""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import copy -import logging -import os -import pickle -import sys -from tempfile import mkstemp -from unittest import TestCase - -from pytest import skip - -from traitlets.config.loader import ( - Config, - LazyConfigValue, - PyFileConfigLoader, - JSONFileConfigLoader, - KeyValueConfigLoader, - ArgParseConfigLoader, - KVArgParseConfigLoader, - ConfigError, -) - - -pyfile = """ -c = get_config() -c.a=10 -c.b=20 -c.Foo.Bar.value=10 -c.Foo.Bam.value=list(range(10)) -c.D.C.value='hi there' -""" - -json1file = """ -{ - "version": 1, - "a": 10, - "b": 20, - "Foo": { - "Bam": { - "value": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] - }, - "Bar": { - "value": 10 - } - }, - "D": { - "C": { - "value": "hi there" - } - } -} -""" - -# should not load -json2file = """ -{ - "version": 2 -} -""" - -import logging -log = logging.getLogger('devnull') -log.setLevel(0) - -class TestFileCL(TestCase): - - def _check_conf(self, config): - self.assertEqual(config.a, 10) - self.assertEqual(config.b, 20) - self.assertEqual(config.Foo.Bar.value, 10) - self.assertEqual(config.Foo.Bam.value, list(range(10))) - self.assertEqual(config.D.C.value, 'hi there') - - def test_python(self): - fd, fname = mkstemp('.py') - f = os.fdopen(fd, 'w') - f.write(pyfile) - f.close() - # Unlink the file - cl = PyFileConfigLoader(fname, log=log) - config = cl.load_config() - self._check_conf(config) - - def test_json(self): - fd, fname = mkstemp('.json') - f = os.fdopen(fd, 'w') - f.write(json1file) - f.close() - # Unlink the file - cl = JSONFileConfigLoader(fname, log=log) - config = cl.load_config() - self._check_conf(config) - - def test_context_manager(self): - - fd, fname = mkstemp('.json') - f = os.fdopen(fd, 'w') - f.write('{}') - f.close() - - cl = JSONFileConfigLoader(fname, log=log) - - value = 'context_manager' - - with cl as c: - c.MyAttr.value = value - - self.assertEqual(cl.config.MyAttr.value, value) - - # check that another loader does see the change - cl2 = JSONFileConfigLoader(fname, log=log) - self.assertEqual(cl.config.MyAttr.value, value) - - def test_json_context_bad_write(self): - fd, fname = mkstemp('.json') - f = os.fdopen(fd, 'w') - f.write('{}') - f.close() - - with JSONFileConfigLoader(fname, log=log) as config: - config.A.b = 1 - - with self.assertRaises(TypeError): - with JSONFileConfigLoader(fname, log=log) as config: - config.A.cant_json = lambda x: x - - loader = JSONFileConfigLoader(fname, log=log) - cfg = loader.load_config() - assert cfg.A.b == 1 - assert 'cant_json' not in cfg.A - - def test_collision(self): - a = Config() - b = Config() - self.assertEqual(a.collisions(b), {}) - a.A.trait1 = 1 - b.A.trait2 = 2 - self.assertEqual(a.collisions(b), {}) - b.A.trait1 = 1 - self.assertEqual(a.collisions(b), {}) - b.A.trait1 = 0 - self.assertEqual(a.collisions(b), { - 'A': { - 'trait1': "1 ignored, using 0", - } - }) - self.assertEqual(b.collisions(a), { - 'A': { - 'trait1': "0 ignored, using 1", - } - }) - a.A.trait2 = 3 - self.assertEqual(b.collisions(a), { - 'A': { - 'trait1': "0 ignored, using 1", - 'trait2': "2 ignored, using 3", - } - }) - - def test_v2raise(self): - fd, fname = mkstemp('.json') - f = os.fdopen(fd, 'w') - f.write(json2file) - f.close() - # Unlink the file - cl = JSONFileConfigLoader(fname, log=log) - with self.assertRaises(ValueError): - cl.load_config() - - -class MyLoader1(ArgParseConfigLoader): - def _add_arguments(self, aliases=None, flags=None): - p = self.parser - p.add_argument('-f', '--foo', dest='Global.foo', type=str) - p.add_argument('-b', dest='MyClass.bar', type=int) - p.add_argument('-n', dest='n', action='store_true') - p.add_argument('Global.bam', type=str) - -class MyLoader2(ArgParseConfigLoader): - def _add_arguments(self, aliases=None, flags=None): - subparsers = self.parser.add_subparsers(dest='subparser_name') - subparser1 = subparsers.add_parser('1') - subparser1.add_argument('-x',dest='Global.x') - subparser2 = subparsers.add_parser('2') - subparser2.add_argument('y') - -class TestArgParseCL(TestCase): - - def test_basic(self): - cl = MyLoader1() - config = cl.load_config('-f hi -b 10 -n wow'.split()) - self.assertEqual(config.Global.foo, 'hi') - self.assertEqual(config.MyClass.bar, 10) - self.assertEqual(config.n, True) - self.assertEqual(config.Global.bam, 'wow') - config = cl.load_config(['wow']) - self.assertEqual(list(config.keys()), ['Global']) - self.assertEqual(list(config.Global.keys()), ['bam']) - self.assertEqual(config.Global.bam, 'wow') - - def test_add_arguments(self): - cl = MyLoader2() - config = cl.load_config('2 frobble'.split()) - self.assertEqual(config.subparser_name, '2') - self.assertEqual(config.y, 'frobble') - config = cl.load_config('1 -x frobble'.split()) - self.assertEqual(config.subparser_name, '1') - self.assertEqual(config.Global.x, 'frobble') - - def test_argv(self): - cl = MyLoader1(argv='-f hi -b 10 -n wow'.split()) - config = cl.load_config() - self.assertEqual(config.Global.foo, 'hi') - self.assertEqual(config.MyClass.bar, 10) - self.assertEqual(config.n, True) - self.assertEqual(config.Global.bam, 'wow') - - -class TestKeyValueCL(TestCase): - klass = KeyValueConfigLoader - - def test_eval(self): - cl = self.klass(log=log) - config = cl.load_config('--Class.str_trait=all --Class.int_trait=5 --Class.list_trait=["hello",5]'.split()) - self.assertEqual(config.Class.str_trait, 'all') - self.assertEqual(config.Class.int_trait, 5) - self.assertEqual(config.Class.list_trait, ["hello", 5]) - - def test_basic(self): - cl = self.klass(log=log) - argv = [ '--' + s[2:] for s in pyfile.split('\n') if s.startswith('c.') ] - print(argv) - config = cl.load_config(argv) - self.assertEqual(config.a, 10) - self.assertEqual(config.b, 20) - self.assertEqual(config.Foo.Bar.value, 10) - # non-literal expressions are not evaluated - self.assertEqual(config.Foo.Bam.value, 'list(range(10))') - self.assertEqual(config.D.C.value, 'hi there') - - def test_expanduser(self): - cl = self.klass(log=log) - argv = ['--a=~/1/2/3', '--b=~', '--c=~/', '--d="~/"'] - config = cl.load_config(argv) - self.assertEqual(config.a, os.path.expanduser('~/1/2/3')) - self.assertEqual(config.b, os.path.expanduser('~')) - self.assertEqual(config.c, os.path.expanduser('~/')) - self.assertEqual(config.d, '~/') - - def test_extra_args(self): - cl = self.klass(log=log) - config = cl.load_config(['--a=5', 'b', '--c=10', 'd']) - self.assertEqual(cl.extra_args, ['b', 'd']) - self.assertEqual(config.a, 5) - self.assertEqual(config.c, 10) - config = cl.load_config(['--', '--a=5', '--c=10']) - self.assertEqual(cl.extra_args, ['--a=5', '--c=10']) - - def test_unicode_args(self): - cl = self.klass(log=log) - argv = [u'--a=épsîlön'] - config = cl.load_config(argv) - self.assertEqual(config.a, u'épsîlön') - - def test_unicode_bytes_args(self): - uarg = u'--a=é' - try: - barg = uarg.encode(sys.stdin.encoding) - except (TypeError, UnicodeEncodeError): - raise skip("sys.stdin.encoding can't handle 'é'") - - cl = self.klass(log=log) - config = cl.load_config([barg]) - self.assertEqual(config.a, u'é') - - def test_unicode_alias(self): - cl = self.klass(log=log) - argv = [u'--a=épsîlön'] - config = cl.load_config(argv, aliases=dict(a='A.a')) - self.assertEqual(config.A.a, u'épsîlön') - - -class TestArgParseKVCL(TestKeyValueCL): - klass = KVArgParseConfigLoader - - def test_expanduser2(self): - cl = self.klass(log=log) - argv = ['-a', '~/1/2/3', '--b', "'~/1/2/3'"] - config = cl.load_config(argv, aliases=dict(a='A.a', b='A.b')) - self.assertEqual(config.A.a, os.path.expanduser('~/1/2/3')) - self.assertEqual(config.A.b, '~/1/2/3') - - def test_eval(self): - cl = self.klass(log=log) - argv = ['-c', 'a=5'] - config = cl.load_config(argv, aliases=dict(c='A.c')) - self.assertEqual(config.A.c, u"a=5") - - -class TestConfig(TestCase): - - def test_setget(self): - c = Config() - c.a = 10 - self.assertEqual(c.a, 10) - self.assertEqual('b' in c, False) - - def test_auto_section(self): - c = Config() - self.assertNotIn('A', c) - assert not c._has_section('A') - A = c.A - A.foo = 'hi there' - self.assertIn('A', c) - assert c._has_section('A') - self.assertEqual(c.A.foo, 'hi there') - del c.A - self.assertEqual(c.A, Config()) - - def test_merge_doesnt_exist(self): - c1 = Config() - c2 = Config() - c2.bar = 10 - c2.Foo.bar = 10 - c1.merge(c2) - self.assertEqual(c1.Foo.bar, 10) - self.assertEqual(c1.bar, 10) - c2.Bar.bar = 10 - c1.merge(c2) - self.assertEqual(c1.Bar.bar, 10) - - def test_merge_exists(self): - c1 = Config() - c2 = Config() - c1.Foo.bar = 10 - c1.Foo.bam = 30 - c2.Foo.bar = 20 - c2.Foo.wow = 40 - c1.merge(c2) - self.assertEqual(c1.Foo.bam, 30) - self.assertEqual(c1.Foo.bar, 20) - self.assertEqual(c1.Foo.wow, 40) - c2.Foo.Bam.bam = 10 - c1.merge(c2) - self.assertEqual(c1.Foo.Bam.bam, 10) - - def test_deepcopy(self): - c1 = Config() - c1.Foo.bar = 10 - c1.Foo.bam = 30 - c1.a = 'asdf' - c1.b = range(10) - c1.Test.logger = logging.Logger('test') - c1.Test.get_logger = logging.getLogger('test') - c2 = copy.deepcopy(c1) - self.assertEqual(c1, c2) - self.assertTrue(c1 is not c2) - self.assertTrue(c1.Foo is not c2.Foo) - self.assertTrue(c1.Test is not c2.Test) - self.assertTrue(c1.Test.logger is c2.Test.logger) - self.assertTrue(c1.Test.get_logger is c2.Test.get_logger) - - def test_builtin(self): - c1 = Config() - c1.format = "json" - - def test_fromdict(self): - c1 = Config({'Foo' : {'bar' : 1}}) - self.assertEqual(c1.Foo.__class__, Config) - self.assertEqual(c1.Foo.bar, 1) - - def test_fromdictmerge(self): - c1 = Config() - c2 = Config({'Foo' : {'bar' : 1}}) - c1.merge(c2) - self.assertEqual(c1.Foo.__class__, Config) - self.assertEqual(c1.Foo.bar, 1) - - def test_fromdictmerge2(self): - c1 = Config({'Foo' : {'baz' : 2}}) - c2 = Config({'Foo' : {'bar' : 1}}) - c1.merge(c2) - self.assertEqual(c1.Foo.__class__, Config) - self.assertEqual(c1.Foo.bar, 1) - self.assertEqual(c1.Foo.baz, 2) - self.assertNotIn('baz', c2.Foo) - - def test_contains(self): - c1 = Config({'Foo' : {'baz' : 2}}) - c2 = Config({'Foo' : {'bar' : 1}}) - self.assertIn('Foo', c1) - self.assertIn('Foo.baz', c1) - self.assertIn('Foo.bar', c2) - self.assertNotIn('Foo.bar', c1) - - def test_pickle_config(self): - cfg = Config() - cfg.Foo.bar = 1 - pcfg = pickle.dumps(cfg) - cfg2 = pickle.loads(pcfg) - self.assertEqual(cfg2, cfg) - - def test_getattr_section(self): - cfg = Config() - self.assertNotIn('Foo', cfg) - Foo = cfg.Foo - assert isinstance(Foo, Config) - self.assertIn('Foo', cfg) - - def test_getitem_section(self): - cfg = Config() - self.assertNotIn('Foo', cfg) - Foo = cfg['Foo'] - assert isinstance(Foo, Config) - self.assertIn('Foo', cfg) - - def test_getattr_not_section(self): - cfg = Config() - self.assertNotIn('foo', cfg) - foo = cfg.foo - assert isinstance(foo, LazyConfigValue) - self.assertIn('foo', cfg) - - def test_getattr_private_missing(self): - cfg = Config() - self.assertNotIn('_repr_html_', cfg) - with self.assertRaises(AttributeError): - _ = cfg._repr_html_ - self.assertNotIn('_repr_html_', cfg) - self.assertEqual(len(cfg), 0) - - def test_getitem_not_section(self): - cfg = Config() - self.assertNotIn('foo', cfg) - foo = cfg['foo'] - assert isinstance(foo, LazyConfigValue) - self.assertIn('foo', cfg) - - def test_merge_no_copies(self): - c = Config() - c2 = Config() - c2.Foo.trait = [] - c.merge(c2) - c2.Foo.trait.append(1) - self.assertIs(c.Foo, c2.Foo) - self.assertEqual(c.Foo.trait, [1]) - self.assertEqual(c2.Foo.trait, [1]) - +# encoding: utf-8 +"""Tests for traitlets.config.loader""" + +# Copyright (c) IPython Development Team. +# Distributed under the terms of the Modified BSD License. + +import copy +import logging +import os +import pickle +import sys +from tempfile import mkstemp +from unittest import TestCase + +from pytest import skip + +from traitlets.config.loader import ( + Config, + LazyConfigValue, + PyFileConfigLoader, + JSONFileConfigLoader, + KeyValueConfigLoader, + ArgParseConfigLoader, + KVArgParseConfigLoader, + ConfigError, +) + + +pyfile = """ +c = get_config() +c.a=10 +c.b=20 +c.Foo.Bar.value=10 +c.Foo.Bam.value=list(range(10)) +c.D.C.value='hi there' +""" + +json1file = """ +{ + "version": 1, + "a": 10, + "b": 20, + "Foo": { + "Bam": { + "value": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] + }, + "Bar": { + "value": 10 + } + }, + "D": { + "C": { + "value": "hi there" + } + } +} +""" + +# should not load +json2file = """ +{ + "version": 2 +} +""" + +import logging +log = logging.getLogger('devnull') +log.setLevel(0) + +class TestFileCL(TestCase): + + def _check_conf(self, config): + self.assertEqual(config.a, 10) + self.assertEqual(config.b, 20) + self.assertEqual(config.Foo.Bar.value, 10) + self.assertEqual(config.Foo.Bam.value, list(range(10))) + self.assertEqual(config.D.C.value, 'hi there') + + def test_python(self): + fd, fname = mkstemp('.py') + f = os.fdopen(fd, 'w') + f.write(pyfile) + f.close() + # Unlink the file + cl = PyFileConfigLoader(fname, log=log) + config = cl.load_config() + self._check_conf(config) + + def test_json(self): + fd, fname = mkstemp('.json') + f = os.fdopen(fd, 'w') + f.write(json1file) + f.close() + # Unlink the file + cl = JSONFileConfigLoader(fname, log=log) + config = cl.load_config() + self._check_conf(config) + + def test_context_manager(self): + + fd, fname = mkstemp('.json') + f = os.fdopen(fd, 'w') + f.write('{}') + f.close() + + cl = JSONFileConfigLoader(fname, log=log) + + value = 'context_manager' + + with cl as c: + c.MyAttr.value = value + + self.assertEqual(cl.config.MyAttr.value, value) + + # check that another loader does see the change + cl2 = JSONFileConfigLoader(fname, log=log) + self.assertEqual(cl.config.MyAttr.value, value) + + def test_json_context_bad_write(self): + fd, fname = mkstemp('.json') + f = os.fdopen(fd, 'w') + f.write('{}') + f.close() + + with JSONFileConfigLoader(fname, log=log) as config: + config.A.b = 1 + + with self.assertRaises(TypeError): + with JSONFileConfigLoader(fname, log=log) as config: + config.A.cant_json = lambda x: x + + loader = JSONFileConfigLoader(fname, log=log) + cfg = loader.load_config() + assert cfg.A.b == 1 + assert 'cant_json' not in cfg.A + + def test_collision(self): + a = Config() + b = Config() + self.assertEqual(a.collisions(b), {}) + a.A.trait1 = 1 + b.A.trait2 = 2 + self.assertEqual(a.collisions(b), {}) + b.A.trait1 = 1 + self.assertEqual(a.collisions(b), {}) + b.A.trait1 = 0 + self.assertEqual(a.collisions(b), { + 'A': { + 'trait1': "1 ignored, using 0", + } + }) + self.assertEqual(b.collisions(a), { + 'A': { + 'trait1': "0 ignored, using 1", + } + }) + a.A.trait2 = 3 + self.assertEqual(b.collisions(a), { + 'A': { + 'trait1': "0 ignored, using 1", + 'trait2': "2 ignored, using 3", + } + }) + + def test_v2raise(self): + fd, fname = mkstemp('.json') + f = os.fdopen(fd, 'w') + f.write(json2file) + f.close() + # Unlink the file + cl = JSONFileConfigLoader(fname, log=log) + with self.assertRaises(ValueError): + cl.load_config() + + +class MyLoader1(ArgParseConfigLoader): + def _add_arguments(self, aliases=None, flags=None): + p = self.parser + p.add_argument('-f', '--foo', dest='Global.foo', type=str) + p.add_argument('-b', dest='MyClass.bar', type=int) + p.add_argument('-n', dest='n', action='store_true') + p.add_argument('Global.bam', type=str) + +class MyLoader2(ArgParseConfigLoader): + def _add_arguments(self, aliases=None, flags=None): + subparsers = self.parser.add_subparsers(dest='subparser_name') + subparser1 = subparsers.add_parser('1') + subparser1.add_argument('-x',dest='Global.x') + subparser2 = subparsers.add_parser('2') + subparser2.add_argument('y') + +class TestArgParseCL(TestCase): + + def test_basic(self): + cl = MyLoader1() + config = cl.load_config('-f hi -b 10 -n wow'.split()) + self.assertEqual(config.Global.foo, 'hi') + self.assertEqual(config.MyClass.bar, 10) + self.assertEqual(config.n, True) + self.assertEqual(config.Global.bam, 'wow') + config = cl.load_config(['wow']) + self.assertEqual(list(config.keys()), ['Global']) + self.assertEqual(list(config.Global.keys()), ['bam']) + self.assertEqual(config.Global.bam, 'wow') + + def test_add_arguments(self): + cl = MyLoader2() + config = cl.load_config('2 frobble'.split()) + self.assertEqual(config.subparser_name, '2') + self.assertEqual(config.y, 'frobble') + config = cl.load_config('1 -x frobble'.split()) + self.assertEqual(config.subparser_name, '1') + self.assertEqual(config.Global.x, 'frobble') + + def test_argv(self): + cl = MyLoader1(argv='-f hi -b 10 -n wow'.split()) + config = cl.load_config() + self.assertEqual(config.Global.foo, 'hi') + self.assertEqual(config.MyClass.bar, 10) + self.assertEqual(config.n, True) + self.assertEqual(config.Global.bam, 'wow') + + +class TestKeyValueCL(TestCase): + klass = KeyValueConfigLoader + + def test_eval(self): + cl = self.klass(log=log) + config = cl.load_config('--Class.str_trait=all --Class.int_trait=5 --Class.list_trait=["hello",5]'.split()) + self.assertEqual(config.Class.str_trait, 'all') + self.assertEqual(config.Class.int_trait, 5) + self.assertEqual(config.Class.list_trait, ["hello", 5]) + + def test_basic(self): + cl = self.klass(log=log) + argv = [ '--' + s[2:] for s in pyfile.split('\n') if s.startswith('c.') ] + print(argv) + config = cl.load_config(argv) + self.assertEqual(config.a, 10) + self.assertEqual(config.b, 20) + self.assertEqual(config.Foo.Bar.value, 10) + # non-literal expressions are not evaluated + self.assertEqual(config.Foo.Bam.value, 'list(range(10))') + self.assertEqual(config.D.C.value, 'hi there') + + def test_expanduser(self): + cl = self.klass(log=log) + argv = ['--a=~/1/2/3', '--b=~', '--c=~/', '--d="~/"'] + config = cl.load_config(argv) + self.assertEqual(config.a, os.path.expanduser('~/1/2/3')) + self.assertEqual(config.b, os.path.expanduser('~')) + self.assertEqual(config.c, os.path.expanduser('~/')) + self.assertEqual(config.d, '~/') + + def test_extra_args(self): + cl = self.klass(log=log) + config = cl.load_config(['--a=5', 'b', '--c=10', 'd']) + self.assertEqual(cl.extra_args, ['b', 'd']) + self.assertEqual(config.a, 5) + self.assertEqual(config.c, 10) + config = cl.load_config(['--', '--a=5', '--c=10']) + self.assertEqual(cl.extra_args, ['--a=5', '--c=10']) + + def test_unicode_args(self): + cl = self.klass(log=log) + argv = [u'--a=épsîlön'] + config = cl.load_config(argv) + self.assertEqual(config.a, u'épsîlön') + + def test_unicode_bytes_args(self): + uarg = u'--a=é' + try: + barg = uarg.encode(sys.stdin.encoding) + except (TypeError, UnicodeEncodeError): + raise skip("sys.stdin.encoding can't handle 'é'") + + cl = self.klass(log=log) + config = cl.load_config([barg]) + self.assertEqual(config.a, u'é') + + def test_unicode_alias(self): + cl = self.klass(log=log) + argv = [u'--a=épsîlön'] + config = cl.load_config(argv, aliases=dict(a='A.a')) + self.assertEqual(config.A.a, u'épsîlön') + + +class TestArgParseKVCL(TestKeyValueCL): + klass = KVArgParseConfigLoader + + def test_expanduser2(self): + cl = self.klass(log=log) + argv = ['-a', '~/1/2/3', '--b', "'~/1/2/3'"] + config = cl.load_config(argv, aliases=dict(a='A.a', b='A.b')) + self.assertEqual(config.A.a, os.path.expanduser('~/1/2/3')) + self.assertEqual(config.A.b, '~/1/2/3') + + def test_eval(self): + cl = self.klass(log=log) + argv = ['-c', 'a=5'] + config = cl.load_config(argv, aliases=dict(c='A.c')) + self.assertEqual(config.A.c, u"a=5") + + +class TestConfig(TestCase): + + def test_setget(self): + c = Config() + c.a = 10 + self.assertEqual(c.a, 10) + self.assertEqual('b' in c, False) + + def test_auto_section(self): + c = Config() + self.assertNotIn('A', c) + assert not c._has_section('A') + A = c.A + A.foo = 'hi there' + self.assertIn('A', c) + assert c._has_section('A') + self.assertEqual(c.A.foo, 'hi there') + del c.A + self.assertEqual(c.A, Config()) + + def test_merge_doesnt_exist(self): + c1 = Config() + c2 = Config() + c2.bar = 10 + c2.Foo.bar = 10 + c1.merge(c2) + self.assertEqual(c1.Foo.bar, 10) + self.assertEqual(c1.bar, 10) + c2.Bar.bar = 10 + c1.merge(c2) + self.assertEqual(c1.Bar.bar, 10) + + def test_merge_exists(self): + c1 = Config() + c2 = Config() + c1.Foo.bar = 10 + c1.Foo.bam = 30 + c2.Foo.bar = 20 + c2.Foo.wow = 40 + c1.merge(c2) + self.assertEqual(c1.Foo.bam, 30) + self.assertEqual(c1.Foo.bar, 20) + self.assertEqual(c1.Foo.wow, 40) + c2.Foo.Bam.bam = 10 + c1.merge(c2) + self.assertEqual(c1.Foo.Bam.bam, 10) + + def test_deepcopy(self): + c1 = Config() + c1.Foo.bar = 10 + c1.Foo.bam = 30 + c1.a = 'asdf' + c1.b = range(10) + c1.Test.logger = logging.Logger('test') + c1.Test.get_logger = logging.getLogger('test') + c2 = copy.deepcopy(c1) + self.assertEqual(c1, c2) + self.assertTrue(c1 is not c2) + self.assertTrue(c1.Foo is not c2.Foo) + self.assertTrue(c1.Test is not c2.Test) + self.assertTrue(c1.Test.logger is c2.Test.logger) + self.assertTrue(c1.Test.get_logger is c2.Test.get_logger) + + def test_builtin(self): + c1 = Config() + c1.format = "json" + + def test_fromdict(self): + c1 = Config({'Foo' : {'bar' : 1}}) + self.assertEqual(c1.Foo.__class__, Config) + self.assertEqual(c1.Foo.bar, 1) + + def test_fromdictmerge(self): + c1 = Config() + c2 = Config({'Foo' : {'bar' : 1}}) + c1.merge(c2) + self.assertEqual(c1.Foo.__class__, Config) + self.assertEqual(c1.Foo.bar, 1) + + def test_fromdictmerge2(self): + c1 = Config({'Foo' : {'baz' : 2}}) + c2 = Config({'Foo' : {'bar' : 1}}) + c1.merge(c2) + self.assertEqual(c1.Foo.__class__, Config) + self.assertEqual(c1.Foo.bar, 1) + self.assertEqual(c1.Foo.baz, 2) + self.assertNotIn('baz', c2.Foo) + + def test_contains(self): + c1 = Config({'Foo' : {'baz' : 2}}) + c2 = Config({'Foo' : {'bar' : 1}}) + self.assertIn('Foo', c1) + self.assertIn('Foo.baz', c1) + self.assertIn('Foo.bar', c2) + self.assertNotIn('Foo.bar', c1) + + def test_pickle_config(self): + cfg = Config() + cfg.Foo.bar = 1 + pcfg = pickle.dumps(cfg) + cfg2 = pickle.loads(pcfg) + self.assertEqual(cfg2, cfg) + + def test_getattr_section(self): + cfg = Config() + self.assertNotIn('Foo', cfg) + Foo = cfg.Foo + assert isinstance(Foo, Config) + self.assertIn('Foo', cfg) + + def test_getitem_section(self): + cfg = Config() + self.assertNotIn('Foo', cfg) + Foo = cfg['Foo'] + assert isinstance(Foo, Config) + self.assertIn('Foo', cfg) + + def test_getattr_not_section(self): + cfg = Config() + self.assertNotIn('foo', cfg) + foo = cfg.foo + assert isinstance(foo, LazyConfigValue) + self.assertIn('foo', cfg) + + def test_getattr_private_missing(self): + cfg = Config() + self.assertNotIn('_repr_html_', cfg) + with self.assertRaises(AttributeError): + _ = cfg._repr_html_ + self.assertNotIn('_repr_html_', cfg) + self.assertEqual(len(cfg), 0) + + def test_getitem_not_section(self): + cfg = Config() + self.assertNotIn('foo', cfg) + foo = cfg['foo'] + assert isinstance(foo, LazyConfigValue) + self.assertIn('foo', cfg) + + def test_merge_no_copies(self): + c = Config() + c2 = Config() + c2.Foo.trait = [] + c.merge(c2) + c2.Foo.trait.append(1) + self.assertIs(c.Foo, c2.Foo) + self.assertEqual(c.Foo.trait, [1]) + self.assertEqual(c2.Foo.trait, [1]) + diff --git a/contrib/python/traitlets/py2/traitlets/tests/test_traitlets.py b/contrib/python/traitlets/py2/traitlets/tests/test_traitlets.py index 11b334cb60a..7ec6e37bfb4 100644 --- a/contrib/python/traitlets/py2/traitlets/tests/test_traitlets.py +++ b/contrib/python/traitlets/py2/traitlets/tests/test_traitlets.py @@ -10,7 +10,7 @@ import pickle import re import sys -from ._warnings import expected_warnings +from ._warnings import expected_warnings from unittest import TestCase import pytest diff --git a/contrib/python/traitlets/py2/traitlets/tests/utils.py b/contrib/python/traitlets/py2/traitlets/tests/utils.py index 88845d8519d..25f59b74a0a 100644 --- a/contrib/python/traitlets/py2/traitlets/tests/utils.py +++ b/contrib/python/traitlets/py2/traitlets/tests/utils.py @@ -4,7 +4,7 @@ from subprocess import Popen, PIPE def get_output_error_code(cmd): """Get stdout, stderr, and exit code from running a command""" - p = Popen(cmd, stdout=PIPE, stderr=PIPE) + p = Popen(cmd, stdout=PIPE, stderr=PIPE) out, err = p.communicate() out = out.decode('utf8', 'replace') err = err.decode('utf8', 'replace') diff --git a/contrib/python/traitlets/py2/traitlets/utils/tests/test_bunch.py b/contrib/python/traitlets/py2/traitlets/utils/tests/test_bunch.py index ef5c3c1384f..ca4357c6746 100644 --- a/contrib/python/traitlets/py2/traitlets/utils/tests/test_bunch.py +++ b/contrib/python/traitlets/py2/traitlets/utils/tests/test_bunch.py @@ -1,14 +1,14 @@ -from ..bunch import Bunch - -def test_bunch(): - b = Bunch(x=5, y=10) - assert 'y' in b - assert 'x' in b - assert b.x == 5 - b['a'] = 'hi' - assert b.a == 'hi' - -def test_bunch_dir(): - b = Bunch(x=5, y=10) - assert 'x' in dir(b) - assert 'keys' in dir(b) +from ..bunch import Bunch + +def test_bunch(): + b = Bunch(x=5, y=10) + assert 'y' in b + assert 'x' in b + assert b.x == 5 + b['a'] = 'hi' + assert b.a == 'hi' + +def test_bunch_dir(): + b = Bunch(x=5, y=10) + assert 'x' in dir(b) + assert 'keys' in dir(b) diff --git a/contrib/python/traitlets/py2/traitlets/utils/tests/test_importstring.py b/contrib/python/traitlets/py2/traitlets/utils/tests/test_importstring.py index c86459ff423..13cf43639ba 100644 --- a/contrib/python/traitlets/py2/traitlets/utils/tests/test_importstring.py +++ b/contrib/python/traitlets/py2/traitlets/utils/tests/test_importstring.py @@ -1,30 +1,30 @@ -# encoding: utf-8 -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. -# -# Adapted from enthought.traits, Copyright (c) Enthought, Inc., -# also under the terms of the Modified BSD License. -"""Tests for traitlets.utils.importstring.""" - -import os -from unittest import TestCase - -from ..importstring import import_item - - -class TestImportItem(TestCase): - - def test_import_unicode(self): - self.assertIs(os, import_item(u'os')) - self.assertIs(os.path, import_item(u'os.path')) - self.assertIs(os.path.join, import_item(u'os.path.join')) - - def test_bad_input(self): - class NotAString(object): - pass - msg = ( - "import_item accepts strings, " - "not '%s'." % NotAString - ) - with self.assertRaisesRegexp(TypeError, msg): - import_item(NotAString()) +# encoding: utf-8 +# Copyright (c) IPython Development Team. +# Distributed under the terms of the Modified BSD License. +# +# Adapted from enthought.traits, Copyright (c) Enthought, Inc., +# also under the terms of the Modified BSD License. +"""Tests for traitlets.utils.importstring.""" + +import os +from unittest import TestCase + +from ..importstring import import_item + + +class TestImportItem(TestCase): + + def test_import_unicode(self): + self.assertIs(os, import_item(u'os')) + self.assertIs(os.path, import_item(u'os.path')) + self.assertIs(os.path.join, import_item(u'os.path.join')) + + def test_bad_input(self): + class NotAString(object): + pass + msg = ( + "import_item accepts strings, " + "not '%s'." % NotAString + ) + with self.assertRaisesRegexp(TypeError, msg): + import_item(NotAString()) diff --git a/contrib/python/traitlets/py2/ya.make b/contrib/python/traitlets/py2/ya.make index 4a601071019..c65ddc5b706 100644 --- a/contrib/python/traitlets/py2/ya.make +++ b/contrib/python/traitlets/py2/ya.make @@ -1,24 +1,24 @@ -# Generated by devtools/yamaker (pypi). +# Generated by devtools/yamaker (pypi). + +PY2_LIBRARY() -PY2_LIBRARY() +PROVIDES(python_traitlets) -PROVIDES(python_traitlets) - -OWNER(borman nslus g:python-contrib) - -VERSION(4.3.3) - -LICENSE(BSD-3-Clause) +OWNER(borman nslus g:python-contrib) + +VERSION(4.3.3) +LICENSE(BSD-3-Clause) + PEERDIR( - contrib/python/decorator - contrib/python/enum34 - contrib/python/ipython-genutils + contrib/python/decorator + contrib/python/enum34 + contrib/python/ipython-genutils contrib/python/six ) -NO_LINT() - +NO_LINT() + PY_SRCS( TOP_LEVEL traitlets/__init__.py @@ -37,14 +37,14 @@ PY_SRCS( traitlets/utils/sentinel.py ) -RESOURCE_FILES( - PREFIX contrib/python/traitlets/py2/ - .dist-info/METADATA - .dist-info/top_level.txt -) - +RESOURCE_FILES( + PREFIX contrib/python/traitlets/py2/ + .dist-info/METADATA + .dist-info/top_level.txt +) + END() RECURSE_FOR_TESTS( - tests + tests ) |
