From 1799d33ded956bb99d14c37d84e3c608cafd1f7e Mon Sep 17 00:00:00 2001 From: Midhun PM Date: Mon, 9 Mar 2020 14:32:14 -0500 Subject: [PATCH 1/6] Allow mutable values in Constant trait, add tests --- traits/tests/test_constant.py | 54 +++++++++++++++++++++++++++++++++++ traits/trait_types.py | 8 ------ 2 files changed, 54 insertions(+), 8 deletions(-) create mode 100644 traits/tests/test_constant.py diff --git a/traits/tests/test_constant.py b/traits/tests/test_constant.py new file mode 100644 index 000000000..7b6bb205f --- /dev/null +++ b/traits/tests/test_constant.py @@ -0,0 +1,54 @@ +# (C) Copyright 2005-2020 Enthought, Inc., Austin, TX +# All rights reserved. +# +# This software is provided without warranty under the terms of the BSD +# license included in LICENSE.txt and may be redistributed only under +# the conditions described in the aforementioned license. The license +# is also available online at http://www.enthought.com/licenses/BSD.txt +# +# Thanks for using Enthought open source! + + +import unittest + +from traits.api import Constant, HasTraits, TraitError + + +class TestConstantTrait(unittest.TestCase): + + def test_initial_value(self): + class TestClass(HasTraits): + c_atr = Constant(5) + + self.assertEqual(5, TestClass().c_atr) + + def test_mutable_initial_value(self): + class TestClass(HasTraits): + c_atr_1 = Constant([1, 2, 3, 4, 5]) + c_atr_2 = Constant({"a": 1, "b": 2}) + + obj = TestClass() + + self.assertEqual([1, 2, 3, 4, 5], obj.c_atr_1) + self.assertEqual({"a": 1, "b": 2}, obj.c_atr_2) + + def test_assign_fails(self): + class TestClass(HasTraits): + c_atr = Constant(5) + + with self.assertRaises(TraitError): + TestClass(c_atr=5) + with self.assertRaises(TraitError): + del TestClass().c_atr + + def test_mutate_succeeds(self): + class TestClass(HasTraits): + c_atr_1 = Constant([1, 2, 3, 4, 5]) + c_atr_2 = Constant({"a": 1, "b": 2}) + + obj = TestClass() + obj.c_atr_1.append(6) + obj.c_atr_2["c"] = 3 + + self.assertEqual([1, 2, 3, 4, 5, 6], obj.c_atr_1) + self.assertEqual({"a": 1, "b": 2, "c": 3}, obj.c_atr_2) diff --git a/traits/trait_types.py b/traits/trait_types.py index b8b33a155..b66a557f8 100644 --- a/traits/trait_types.py +++ b/traits/trait_types.py @@ -1029,14 +1029,6 @@ class Constant(TraitType): #: The standard metadata for the trait: metadata = {"type": "constant", "transient": True} - def __init__(self, value, **metadata): - if type(value) in MutableTypes: - raise TraitError( - "Cannot define a constant using a mutable list or dictionary" - ) - - super(Constant, self).__init__(value, **metadata) - class Delegate(TraitType): """ A trait type whose value is delegated to a trait on another object. From 0cf0bdb809f4dd5eb5f2c3acbc1fb7531835b389 Mon Sep 17 00:00:00 2001 From: Midhun PM Date: Mon, 9 Mar 2020 15:37:52 -0500 Subject: [PATCH 2/6] Remove constant MutableTypes --- traits/trait_types.py | 1 - 1 file changed, 1 deletion(-) diff --git a/traits/trait_types.py b/traits/trait_types.py index b66a557f8..dfef8ff6d 100644 --- a/traits/trait_types.py +++ b/traits/trait_types.py @@ -69,7 +69,6 @@ # Constants -MutableTypes = (list, dict) SetTypes = SequenceTypes + (set,) # Numeric type fast validator definitions From e4d4dde1413c9e53a9b7c19619162a96a6daac1e Mon Sep 17 00:00:00 2001 From: Midhun PM Date: Wed, 11 Mar 2020 14:40:28 -0500 Subject: [PATCH 3/6] Update docstring --- traits/trait_types.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/traits/trait_types.py b/traits/trait_types.py index dfef8ff6d..9dc05fcce 100644 --- a/traits/trait_types.py +++ b/traits/trait_types.py @@ -1011,12 +1011,11 @@ class Constant(TraitType): Traits of this type are very space efficient (and fast) because *value* is not stored in each instance using the trait, but only in - the trait object itself. The *value* cannot be a list or dictionary, - because those types have mutable values. + the trait object itself. Parameters ---------- - value : any type other than list or dict + value : Any The constant value for the trait. **metadata Trait metadata for the trait. From 7fbc99aabb2c0e69f69fef3a4062a2682cb1e7b7 Mon Sep 17 00:00:00 2001 From: Midhun PM Date: Mon, 16 Mar 2020 17:47:28 -0500 Subject: [PATCH 4/6] Remove 'MutableTypes' from traits-stubs --- traits-stubs/traits-stubs/trait_types.pyi | 1 - 1 file changed, 1 deletion(-) diff --git a/traits-stubs/traits-stubs/trait_types.pyi b/traits-stubs/traits-stubs/trait_types.pyi index 46d9543b3..00bdef73e 100644 --- a/traits-stubs/traits-stubs/trait_types.pyi +++ b/traits-stubs/traits-stubs/trait_types.pyi @@ -27,7 +27,6 @@ from uuid import UUID as _UUID from .trait_type import _TraitType -MutableTypes: _Any SetTypes: _Any int_fast_validate: _Any float_fast_validate: _Any From 099080ecbf540eb4deedff9b9fa7409da3bb47e8 Mon Sep 17 00:00:00 2001 From: Midhun PM Date: Mon, 16 Mar 2020 17:49:27 -0500 Subject: [PATCH 5/6] Docstring fix --- traits/trait_types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/traits/trait_types.py b/traits/trait_types.py index 9dc05fcce..b2f8bbb8b 100644 --- a/traits/trait_types.py +++ b/traits/trait_types.py @@ -1015,7 +1015,7 @@ class Constant(TraitType): Parameters ---------- - value : Any + value : any The constant value for the trait. **metadata Trait metadata for the trait. From 0ba35e2ac38633a5751a9b2f74303b7c59985aa6 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Tue, 17 Mar 2020 08:22:16 +0000 Subject: [PATCH 6/6] Change assertEqual parameter order to the prevailing order --- traits/tests/test_constant.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/traits/tests/test_constant.py b/traits/tests/test_constant.py index 7b6bb205f..5ad091947 100644 --- a/traits/tests/test_constant.py +++ b/traits/tests/test_constant.py @@ -20,7 +20,7 @@ def test_initial_value(self): class TestClass(HasTraits): c_atr = Constant(5) - self.assertEqual(5, TestClass().c_atr) + self.assertEqual(TestClass().c_atr, 5) def test_mutable_initial_value(self): class TestClass(HasTraits): @@ -29,8 +29,8 @@ class TestClass(HasTraits): obj = TestClass() - self.assertEqual([1, 2, 3, 4, 5], obj.c_atr_1) - self.assertEqual({"a": 1, "b": 2}, obj.c_atr_2) + self.assertEqual(obj.c_atr_1, [1, 2, 3, 4, 5]) + self.assertEqual(obj.c_atr_2, {"a": 1, "b": 2}) def test_assign_fails(self): class TestClass(HasTraits): @@ -50,5 +50,5 @@ class TestClass(HasTraits): obj.c_atr_1.append(6) obj.c_atr_2["c"] = 3 - self.assertEqual([1, 2, 3, 4, 5, 6], obj.c_atr_1) - self.assertEqual({"a": 1, "b": 2, "c": 3}, obj.c_atr_2) + self.assertEqual(obj.c_atr_1, [1, 2, 3, 4, 5, 6]) + self.assertEqual(obj.c_atr_2, {"a": 1, "b": 2, "c": 3})