Giter VIP home page Giter VIP logo

Comments (11)

rmorshea avatar rmorshea commented on June 20, 2024

I may be wrong, but I have a feeling this isn't likely to be something that would be included in vanilla Traitlets. However, #131 concerns generating a docstring in __init__ about the traits on the instance. The information is simply ordered alphabetically, but maybe it helps with readability at least.

from traitlets.

ssanderson avatar ssanderson commented on June 20, 2024

This could be done very easily in Python 3 by implementing a prepare on MetaHasTraits that returns an OrderedDict. In Python 2 I don't think there's a straightforward way to do this.

On Dec 16, 2015, at 2:42 PM, perrygreenfield [email protected] wrote:

For our application, it would be extremely useful to retain the order of the traits as defined internally. I.e., we would like to determine the order the traits were defined in the class. Any way of supporting this other than our making our own modified copy of traitlets? (The motivation for this is so that tools that can print out or otherwise save this information in a readable state can retain logical groupings of traits as defined in the class).


Reply to this email directly or view it on GitHub.

from traitlets.

perrygreenfield avatar perrygreenfield commented on June 20, 2024

At the moment we are trying to support both 2 and 3 so that may be an issue, at least for a couple years. Alphabetical is easy to do, but isn't usually what the user wants. They usually want to see related parameters close together, and typically more frequently changed parameters higher in the list. All this relates to our need to serialize and de-serialize the parameter information to and from files that users want to view and edit (this is a very common interface in astronomy for running applications).

from traitlets.

ssanderson avatar ssanderson commented on June 20, 2024

If you want to support Py2 then you'd have to construct your traitlets ahead of time and then dynamically add them to the body of the class, ala:

_myclass_traits = [('dict_trait', Dict(...)), ('list_trait', List(...))]

class MyTraitedClass(HasTraits):
    _trait_order = []
    ls = locals()  # fun Python trivia: locals() is mutable in the body of a class.
    for name, value in _myclass_traits:
        ls[name] = value
        _trait_order.append(value)

# MyTraitedClass now has all the desired traits, plus a list of them in order as a class-level attribute named _trait_order.

This might be a reasonable thing to do if you're defining all your traited classes ahead of time, and you don't expect users to have to extend your traited classes.

If you're expecting your users to be participants in the class hierarchy I expect that it wouldn't be with the added confusion and complexity.

from traitlets.

rmorshea avatar rmorshea commented on June 20, 2024

How do you plan on controlling order with traits inherited from other classes? It seems like you need a system of priority and grouping that is independent of the defined order of traits on any particular class to resolve that. I think your best bet is to just tag the trait with some metadata doc_order=<n>. Then you can just run through the mro, group traits with the same doc_order on a class together, and then order those groups.

from traitlets.

perrygreenfield avatar perrygreenfield commented on June 20, 2024

Adding a ordering keyword is pretty clumsy and I don't think it would be acceptable. Well, there's always the source code to self analyze :-)

from traitlets.

rmorshea avatar rmorshea commented on June 20, 2024

It could also be a dictionary defined on the class which is keyed on trait names, and whose values are their order. Then you could run through that dictionary and tag them in the metaclass instead of doing so in the class definition.

from traitlets.

perrygreenfield avatar perrygreenfield commented on June 20, 2024

Any idea of how much work to add an alternate class HasOrderedTraits?

from traitlets.

ssanderson avatar ssanderson commented on June 20, 2024

@perrygreenfield in Python 3, it's pretty trivial. As an example, here's an implementation that provides an ordered_traits attribute on subclasses of OrderedHasTraits, and a trait_values property on instances of those subclasses, both of which contain OrderedDicts mapping names to trait instances, and trait values, respectively:

from collections import OrderedDict
from traitlets import MetaHasTraits, HasTraits, List, Dict, is_trait

from ipython_genutils.py3compat import iteritems, with_metaclass


class OrderedMetaHasTraits(MetaHasTraits):

    def __prepare__(name, bases, **kwds):
        return OrderedDict()

    def __init__(cls, name, bases, classdict):
        """Set up the `ordered_traits` attribute on subtypes of OrderedHasTraits."""
        super(OrderedMetaHasTraits, cls).__init__(name, bases, classdict)
        cls.ordered_traits = OrderedDict(
            (k, v) for k, v in iteritems(classdict)
            if is_trait(v)
        )


class OrderedHasTraits(with_metaclass(OrderedMetaHasTraits, HasTraits)):

    @property
    def trait_values(self):
        return OrderedDict((key, getattr(self, key)) for key in type(self).ordered_traits)


if __name__ == '__main__':
    class MyType(OrderedHasTraits):
        x = List()
        y = Dict()

    print(MyType.ordered_traits)
    print(MyType(x=[], y={}).trait_values)

Running that script produces this as output:

python scratch.py
OrderedDict([('x', <traitlets.traitlets.List object at 0x7f4a2f11a908>), ('y', <traitlets.traitlets.Dict object at 0x7f4a2f127208>)])
OrderedDict([('x', []), ('y', {})])

The only thing that would probably still need some fleshing out here would be merging these attributes in subclasses.

In Python 2, there's no way to accomplish this that I'm aware of, because by the time our metaclass gets access to the class body, it's already a dict with no implied order. If you wanted to replicate this behavior in Python 2, you'd have to require to user to supply an ordering, which seems like the whole thing you're trying to avoid here.

from traitlets.

perrygreenfield avatar perrygreenfield commented on June 20, 2024

Thanks for taking the time to explain. It saved me quite a bit of time trying to distill that aspect.

from traitlets.

rmorshea avatar rmorshea commented on June 20, 2024

Closing given that support for Python 2 ends in 2020, the solution proposed by @ssanderson for Python<3.6, and that this is no longer an issue in Python>=3.6 due to PEP-520.

from traitlets.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.