summaryrefslogtreecommitdiffstats
path: root/contrib/python/traitlets/py2
diff options
context:
space:
mode:
authorshadchin <[email protected]>2022-02-10 16:44:39 +0300
committerDaniil Cherednik <[email protected]>2022-02-10 16:44:39 +0300
commite9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (patch)
tree64175d5cadab313b3e7039ebaa06c5bc3295e274 /contrib/python/traitlets/py2
parent2598ef1d0aee359b4b6d5fdd1758916d5907d04f (diff)
Restoring authorship annotation for <[email protected]>. Commit 2 of 2.
Diffstat (limited to 'contrib/python/traitlets/py2')
-rw-r--r--contrib/python/traitlets/py2/.dist-info/METADATA68
-rw-r--r--contrib/python/traitlets/py2/.dist-info/top_level.txt2
-rw-r--r--contrib/python/traitlets/py2/README.md286
-rw-r--r--contrib/python/traitlets/py2/tests/ya.make22
-rw-r--r--contrib/python/traitlets/py2/traitlets/_version.py2
-rw-r--r--contrib/python/traitlets/py2/traitlets/config/application.py20
-rw-r--r--contrib/python/traitlets/py2/traitlets/config/tests/test_application.py842
-rw-r--r--contrib/python/traitlets/py2/traitlets/config/tests/test_configurable.py918
-rw-r--r--contrib/python/traitlets/py2/traitlets/config/tests/test_loader.py906
-rw-r--r--contrib/python/traitlets/py2/traitlets/tests/test_traitlets.py2
-rw-r--r--contrib/python/traitlets/py2/traitlets/tests/utils.py2
-rw-r--r--contrib/python/traitlets/py2/traitlets/utils/tests/test_bunch.py28
-rw-r--r--contrib/python/traitlets/py2/traitlets/utils/tests/test_importstring.py60
-rw-r--r--contrib/python/traitlets/py2/ya.make42
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 d0c20576621..bd031a5c309 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 3d938864d21..adfea9c6eb5 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 436b97c19b2..aa288947efb 100644
--- a/contrib/python/traitlets/py2/README.md
+++ b/contrib/python/traitlets/py2/README.md
@@ -1,143 +1,143 @@
-# Traitlets
-
-[![Build Status](https://travis-ci.org/ipython/traitlets.svg?branch=master)](https://travis-ci.org/ipython/traitlets)
-[![Documentation Status](https://readthedocs.org/projects/traitlets/badge/?version=latest)](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
+
+[![Build Status](https://travis-ci.org/ipython/traitlets.svg?branch=master)](https://travis-ci.org/ipython/traitlets)
+[![Documentation Status](https://readthedocs.org/projects/traitlets/badge/?version=latest)](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 087a9ab183a..d2d3e3b9bf5 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
-)
+ENV(
+ YA_PYTEST_DISABLE_DOCTEST=yes
+)
+
+SRCDIR(contrib/python/traitlets/py2/traitlets)
-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
+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 e9ec9e6da62..ed16b3c1e12 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 147dc9f0682..d3a4c45e774 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 ede020bc9c4..39bd9b786e8 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 639b65f7293..9fbdb7209dc 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 fc543a535a5..50c8659f3c6 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 7ec6e37bfb4..11b334cb60a 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 25f59b74a0a..88845d8519d 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 ca4357c6746..ef5c3c1384f 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 13cf43639ba..c86459ff423 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 c65ddc5b706..4a601071019 100644
--- a/contrib/python/traitlets/py2/ya.make
+++ b/contrib/python/traitlets/py2/ya.make
@@ -1,24 +1,24 @@
-# Generated by devtools/yamaker (pypi).
-
-PY2_LIBRARY()
+# Generated by devtools/yamaker (pypi).
-PROVIDES(python_traitlets)
+PY2_LIBRARY()
-OWNER(borman nslus g:python-contrib)
-
-VERSION(4.3.3)
+PROVIDES(python_traitlets)
+
+OWNER(borman nslus g:python-contrib)
+
+VERSION(4.3.3)
+
+LICENSE(BSD-3-Clause)
-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
)