Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion docs/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,10 @@ You can also add callbacks to a trait dynamically:

If a trait attribute with a dynamic default value has another value set
before it is used, the default will not be calculated.
Any callbacks on that trait will will fire, and *old_value* will be ``None``.
Any callbacks on that trait will fire, and *old_value* will be the
trait type's static default (e.g. ``''`` for :class:`Unicode`), or
``traitlets.Undefined`` for trait types whose default can only be
computed dynamically (e.g. containers and :class:`Instance`).

Validating proposed changes
---------------------------
Expand Down
2 changes: 1 addition & 1 deletion docs/source/migration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -270,4 +270,4 @@ which automatically shims the deprecated signature into the new signature:
@observe("path")
@observe_compat # <- this allows super()._path_changed in subclasses to work with the old signature.
def _path_changed(self, change):
self.prefix = os.path.dirname(change["value"])
self.prefix = os.path.dirname(change["new"])
29 changes: 20 additions & 9 deletions docs/source/trait_types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,43 @@ Trait Types
Numbers
-------

.. autoclass:: Integer
.. autoclass:: Int

An integer trait. On Python 2, this automatically uses the ``int`` or
``long`` types as necessary.
An integer trait.


.. class:: Integer

An alias for :class:`Int`

.. class:: Int
.. class:: Long

On Python 2, these are traitlets for values where the ``int`` and ``long``
types are not interchangeable. On Python 3, they are both aliases for
:class:`Integer`.
.. deprecated:: 5.16
Use :class:`Integer` instead.

In almost all situations, you should use :class:`Integer` instead of these.
This (with Int) were values where the Python 2 ``int`` and ``long``
types were not interchangeable. Now Long is a deprecated aliases for
:class:`Int` and emit a :exc:`DeprecationWarning` when used.

.. autoclass:: Float

.. autoclass:: Complex

.. class:: CInt
CLong
CFloat
CComplex

Casting variants of the above. When a value is assigned to the attribute,
these will attempt to convert it by calling e.g. ``value = int(value)``.

.. class:: CLong

.. deprecated:: 5.16
Use :class:`CInt` instead.

A deprecated alias for :class:`CInt`; emits a :exc:`DeprecationWarning`
when used.

Strings
-------

Expand Down
13 changes: 7 additions & 6 deletions examples/myapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@
to set the following options:

* ``config``: set to ``True`` to make the attribute configurable.
* ``shortname``: by default, configurable attributes are set using the syntax
"Classname.attributename". At the command line, this is a bit verbose, so
we allow "shortnames" to be declared. Setting a shortname is optional, but
when you do this, you can set the option at the command line using the
syntax: "shortname=value".
* ``help``: set the help string to display a help message when the ``-h``
option is given at the command line. The help string should be valid ReST.

By default, configurable attributes are set at the command line using the
syntax "--Classname.attributename=value". This is a bit verbose, so an
Application can declare ``aliases``, mapping a short name to a
"Classname.attributename" (see MyApp below); the option can then be set
with "--alias value".

When the config attribute of an Application is updated, it will fire all of
the trait's events for all of the config=True attributes.
"""
Expand All @@ -51,7 +52,7 @@ class Foo(Configurable):

i = Int(0, help="The integer i.").tag(config=True)
j = Int(1, help="The integer j.").tag(config=True)
name = Unicode("Brian", help="First name.").tag(config=True, shortname="B")
name = Unicode("Brian", help="First name.").tag(config=True)
mode = Enum(values=["on", "off", "other"], default_value="on").tag(config=True)

def __init__(self, **kwargs):
Expand Down
14 changes: 12 additions & 2 deletions tests/config/test_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,18 @@

import pytest

from traitlets import Bool, Bytes, Dict, HasTraits, Integer, List, Set, Tuple, Unicode
from traitlets import (
Bool,
Bytes,
Dict,
HasTraits,
Int,
Integer,
List,
Set,
Tuple,
Unicode,
)
from traitlets.config.application import Application
from traitlets.config.configurable import Configurable
from traitlets.config.loader import Config, KVArgParseConfigLoader
Expand Down Expand Up @@ -778,7 +789,6 @@ def test_show_config_json(capsys):


def test_deep_alias():
from traitlets import Int
from traitlets.config import Application, Configurable

class Foo(Configurable):
Expand Down
8 changes: 2 additions & 6 deletions tests/config/test_configurable.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class MyConfigurable(Configurable):

mc_help = """MyConfigurable(Configurable) options
------------------------------------
--MyConfigurable.a=<Integer>
--MyConfigurable.a=<Int>
The integer a.
Default: 1
--MyConfigurable.b=<Float>
Expand All @@ -46,17 +46,13 @@ class MyConfigurable(Configurable):

mc_help_inst = """MyConfigurable(Configurable) options
------------------------------------
--MyConfigurable.a=<Integer>
--MyConfigurable.a=<Int>
The integer a.
Current: 5
--MyConfigurable.b=<Float>
The integer b.
Current: 4.0"""

# On Python 3, the Integer trait is a synonym for Int
mc_help = mc_help.replace("<Integer>", "<Int>")
mc_help_inst = mc_help_inst.replace("<Integer>", "<Int>")


class Foo(Configurable):
a = Integer(0, help="The integer a.").tag(config=True)
Expand Down
12 changes: 12 additions & 0 deletions tests/test_traitlets.py
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,18 @@ def test_trait_types_dict_deprecated(self):
class C(HasTraits):
t = Dict(Int)

def test_long_deprecated_aliases(self):
for cls, replacement in [(Long, "Integer"), (CLong, "CInt")]:
with expected_warnings([f"`{cls.__name__}` trait is deprecated"]):
trait = cls(3)
# deprecated aliases still behave like their replacement
assert isinstance(trait, Integer)

class C(HasTraits):
x = trait

assert C().x == 3


class TestHasDescriptorsMeta(TestCase):
def test_metaclass(self):
Expand Down
5 changes: 0 additions & 5 deletions traitlets/config/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -823,11 +823,6 @@ def __init__(
Dict of flags to full traitlets names for CLI parsing
log
Passed to `ConfigLoader`

Returns
-------
config : Config
The resulting Config object.
"""
classes = classes or []
super(CommandLineConfigLoader, self).__init__(log=log)
Expand Down
44 changes: 38 additions & 6 deletions traitlets/traitlets.py
Original file line number Diff line number Diff line change
Expand Up @@ -1057,7 +1057,7 @@ def setup_class(cls: MetaHasTraits, classdict: dict[str, t.Any]) -> None:
# for instance ipywidgets.
none_ok = trait.default_value is None and trait.allow_none
if (
type(trait) in [CInt, Int]
type(trait) in [CInt, Int, Long, CLong]
and trait.min is None # type: ignore[attr-defined]
and trait.max is None # type: ignore[attr-defined]
and (isinstance(trait.default_value, int) or none_ok)
Expand Down Expand Up @@ -2592,7 +2592,7 @@ def _validate_bounds(


class Int(TraitType[G, S]):
"""An int trait."""
"""An integer trait."""

default_value = 0
info_text = "an int"
Expand Down Expand Up @@ -2712,10 +2712,43 @@ def validate(self, obj: t.Any, value: t.Any) -> G:
return _validate_bounds(self, obj, value) # type:ignore[no-any-return]


Long, CLong = Int, CInt
Integer = Int


class Long(Int[G, S]):
"""A deprecated alias for :class:`Integer`.

.. deprecated:: 5.16
Use :class:`Integer` instead. ``Int`` and ``Long`` used to be distinct
traits back when Python 2 had separate ``int`` and ``long`` types; they
are now both just integers.
"""

def __init__(self, *args: t.Any, **kwargs: t.Any) -> None:
warn(
"The `Long` trait is deprecated since traitlets 5.16, use `Integer` instead.",
DeprecationWarning,
stacklevel=2,
)
super().__init__(*args, **kwargs) # type:ignore[misc]


class CLong(CInt[G, S]):
"""A deprecated alias for :class:`CInt`.

.. deprecated:: 5.16
Use :class:`CInt` instead.
"""

def __init__(self, *args: t.Any, **kwargs: t.Any) -> None:
warn(
"The `CLong` trait is deprecated since traitlets 5.16, use `CInt` instead.",
DeprecationWarning,
stacklevel=2,
)
super().__init__(*args, **kwargs) # type:ignore[misc]


class Float(TraitType[G, S]):
"""A float trait."""

Expand Down Expand Up @@ -3910,11 +3943,11 @@ def __init__(

d2['n'] must be an integer
d2['s'] must be text
>>> d2 = Dict(per_key_traits={"n": Integer(), "s": Unicode()})
>>> d2 = Dict(per_key_traits={"n": Int(), "s": Unicode()})

d3's keys must be text
d3's values must be integers
>>> d3 = Dict(value_trait=Integer(), key_trait=Unicode())
>>> d3 = Dict(value_trait=Int(), key_trait=Unicode())

"""

Expand Down Expand Up @@ -4235,7 +4268,6 @@ class UseEnum(TraitType[t.Any, t.Any]):

.. sourcecode:: python

# -- SINCE: Python 3.4 (or install backport: pip install enum34)
import enum
from traitlets import HasTraits, UseEnum

Expand Down
6 changes: 4 additions & 2 deletions traitlets/utils/importstring.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ def import_item(name: str) -> Any:

Returns
-------
mod : module object
The module that was imported.
mod : object
The imported object: for a dotted name ``foo.bar``, the ``bar``
attribute of module ``foo`` (which may be any object); for an
un-dotted name, the module itself.
"""
if not isinstance(name, str):
raise TypeError("import_item accepts strings, not '%s'." % type(name))
Expand Down
Loading