Skip to content

Use traitlets for our configuration. #16476

Open

Description

@nstarman

What is the problem this feature will solve?

We currently bundle configobj with Astropy and use it to do our configuration. It's old, not well supported / actively developed, and doesn't do nice things like load configurations from JSON files.

Describe the desired outcome

We replace configobj with traitlets, which is the IPython and Jupyter configuration system (but that depends on neither). It's stable, well-supported, actively developed, supports a lot of modern conveniences, and has 0 dependencies.

Additional context

See the Design Requirements!
I wish our config system supported this.

Here are the main requirements we wanted our configuration system to have:

  • Support for hierarchical configuration information.

  • Full integration with command line option parsers. Often, you want to read
    a configuration file, but then override some of the values with command line
    options. Our configuration system automates this process and allows each
    command line option to be linked to a particular attribute in the
    configuration hierarchy that it will override.

  • Configuration files that are themselves valid Python code. This accomplishes
    many things. First, it becomes possible to put logic in your configuration
    files that sets attributes based on your operating system, network setup,
    Python version, etc. Second, Python has a super simple syntax for accessing
    hierarchical data structures, namely regular attribute access
    (Foo.Bar.Bam.name). Third, using Python makes it easy for users to
    import configuration attributes from one configuration file to another.
    Fourth, even though Python is dynamically typed, it does have types that can
    be checked at runtime. Thus, a 1 in a config file is the integer '1',
    while a '1' is a string.

  • A fully automated method for getting the configuration information to the
    classes that need it at runtime. Writing code that walks a configuration
    hierarchy to extract a particular attribute is painful. When you have
    complex configuration information with hundreds of attributes, this makes
    you want to cry.

  • Type checking and validation that doesn't require the entire configuration
    hierarchy to be specified statically before runtime. Python is a very
    dynamic language and you don't always know everything that needs to be
    configured when a program starts.

Activity

  1. neutrinoceros commented on May 21, 2024

    @neutrinoceros
    Contributor

    Vendoring something that isn't actively developed indeed sounds worse than adding a dependency on a package that doesn't have any.
    Are you proposing to vendor traitlets or to add it as a dependency ? If we vendor it, could it create incompatibilities with IPython/Jupyter at runtime (I assume not) ? If we depend on it, how likely is it that future versions might break astropy in a significant way ?

  2. nstarman commented on May 21, 2024

    @nstarman
    MemberAuthor

    Are you proposing to vendor traitlets or to add it as a dependency ?

    Dependency.

    If we depend on it, how likely is it that future versions might break astropy in a significant way ?

    Nothing can be promised, but it's been stable. And the config system in particular is stable because it's isolated: we would only use it for our config.

  3. eerovaher commented on May 21, 2024

    @eerovaher
    Member

    Could switching to traitlets help with #9893?

  4. added
    externalPRs and issues related to external packages vendored with Astropy (astropy.extern)
    on May 21, 2024
  5. pllim commented on May 21, 2024

    @pllim
    Member

    I think you are talking about gutting out something fundamental in astropy.config. I see your point but the impact is very high, as the configuration system is also widely used downstream. I wonder if this warrants an APE.

  6. nstarman commented on May 21, 2024

    @nstarman
    MemberAuthor

    @eerovaher.

    Could switching to traitlets help with #9893?

    Yes! Traitlets supports custom types. It's quite easy to do (https://traitlets.readthedocs.io/en/stable/defining_traits.html)

    @pllim

    I think you are talking about gutting out something fundamental in astropy.config.

    Yes.

    I see your point but the impact is very high.

    🎉

    as the configuration system is also widely used downstream.

    There's two different uses:

    1. configuring Astropy itself. This is a breaking change in Astropy so downstream libraries would have to modify their code.

    2. Downstream libraries building their own config by inheriting from astropy.config. The current config in extern has seen very little change so it would be relatively easy to spin it out into a standalone legacy library that we basically don't touch except to add a deprecation warning. Then libraries that are building their own config on top of astropy.config would just have a trivial change to their import, e.g. legacy_astropy_config_system (or whatever we name it).

    I wonder if this warrants an APE.

    Sadly, probably.

  7. jdavies-st commented on Oct 1, 2026

    @jdavies-st
    Contributor

    Agree that traitlets is very nice.

    Several years ago @eslavich wrote up a nice issue showing how the JWST science calibration pipeline could move from configobj to traitlets, showing how you got the CLI for free, and how validation worked.

    spacetelescope/stpipe#10

    We ran out of steam and never got further. But it was a nice idea.

  8. astrofrog commented on Oct 1, 2026

    @astrofrog
    Member

    I'm a bit confused, I thought we mainly used configobj to deal with I/O to .cfg files? I don't think traitlets does I/O so even if we used traitlets for in-memory validation we would still need ConfigObj for I/O?

  9. nstarman commented on Oct 1, 2026

    @nstarman
    MemberAuthor

    Traitlets does not natively write read/cfg files, in part for the same reasons Python switched from setup.cfg to a more structured format. Traitlets uses JSON.
    Our non-mutually exclusive options are:

    1. Support JSON as the config file format
    2. Use stdlib configparser to continue to support cfg files, reading the file into a dict, then feed it to traitlets as its Config object.

    IMO we should do both, setting a long horizon on deprecating cfg.

  10. neutrinoceros commented on Oct 1, 2026

    @neutrinoceros
    Contributor

    if we're planning to sunset cfg support why go with json now that we have widely available toml support ?

  11. saimn commented on Oct 1, 2026

    @saimn
    Contributor

    Independently from the config file format (json is not the greatest for a config file) and from the library we use to read/write config files, the problem is that our configuration system is a complicated custom beast, supporting some weird features (e.g. hot reloading or temporarily modifying config items). And iirc config items are stored deep into the ConfigObj instances... (which has some performance impact: #12504).
    I learned that painfully when #17461 was reverted because of one of those features (#18138).
    So I think the discussion needs to start with questioning the usefulness of those features, otherwise good luck with changing anything here.

  12. pllim commented on Oct 1, 2026

    @pllim
    Member

    I don't see the point of breaking so many things for no apparent benefit now that we no longer bundle configobj. I think the existing config system will die when we archive this repo. Can I close this as won't fix?

  13. nstarman commented on Oct 1, 2026

    @nstarman
    MemberAuthor

    Not bundling configobj is better than bundling, but see the release cadence. If we're ever interested in supporting IMO near-tablestakes features for 2020+ (see Additional context in #16476 (comment)) this is a must fix.

    Image

    hot reloading or temporarily modifying config items

    traitlets supports this relatively easily.
    See how I do it in https://unxt.readthedocs.io/en/stable/guides/configuration.html#temporary-configuration-with-context-manager

    json now that we have widely available toml support ?

    We can do that easily too! Anything that can be mapped to a dict is supported by traitlets, which ingests dicts. (That's why JSON is the easiest format, it basically is a dict.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Feature RequestRefactoringconfigexternalPRs and issues related to external packages vendored with Astropy (astropy.extern)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions