Skip to content

Implement a help() method for the configuration system - #13499

Merged
pllim merged 2 commits into
astropy:mainfrom
eerovaher:config-help
Oct 6, 2023
Merged

pllim merged 2 commits into
astropy:mainfrom
eerovaher:config-help

Conversation

@eerovaher

Copy link
Copy Markdown
Member

ConfigItem instances have a description attribute, the contents of which are written to the configuration file as comments. However, there is currently no convenient way of accessing the description strings through the configuration system at runtime (see the awkward code examples in the documentation that this pull request replaces). The new ConfigNamespace.help() method provides a user-friendly way of seeing the name, current value, type and description of one or more configuration items.

Checklist for package maintainer(s)

This checklist is meant to remind the package maintainer(s) who will review this pull request of some common things to look for. This list is not exhaustive.

  • Do the proposed changes actually accomplish desired goals?
  • Do the proposed changes follow the Astropy coding guidelines?
  • Are tests added/updated as required? If so, do they follow the Astropy testing guidelines?
  • Are docs added/updated as required? If so, do they follow the Astropy documentation guidelines?
  • Is rebase and/or squash necessary? If so, please provide the author with appropriate instructions. Also see "When to rebase and squash commits".
  • Did the CI pass? If no, are the failures related? If you need to run daily and weekly cron jobs as part of the PR, please apply the Extra CI label.
  • Is a change log needed? If yes, did the change log check pass? If no, add the no-changelog-entry-needed label. If this is a manual backport, use the skip-changelog-checks label unless special changelog handling is necessary.
  • Is this a big PR that makes a "What's new?" entry worthwhile and if so, is (1) a "what's new" entry included in this PR and (2) the "whatsnew-needed" label applied?
  • Is a milestone set? Milestone must be set but astropy-bot check might be missing; do not let the green checkmark fool you.
  • At the time of adding the milestone, if the milestone set requires a backport to release branch(es), apply the appropriate backport-X.Y.x label(s) before merge.

@eerovaher eerovaher added this to the v5.2 milestone Jul 25, 2022
@taldcroft

Copy link
Copy Markdown
Member

I haven't looked at the code in detail but this is an awesome idea. 💯

@mhvk

mhvk commented Jul 29, 2022

Copy link
Copy Markdown
Contributor

I like the idea too, but wonder if a simpler solution to the problem is not to define a __repr__ which essentially includes your help text for all names.

@mhvk

mhvk commented Jul 29, 2022 •

Copy link
Copy Markdown
Contributor

Actually, just because I (EDIT: thought wouldn't it be nice if one could just do "help(something)" and) wondered what would happen, help(conf) is quite good...

from astropy.utils.iers import conf

help(conf)

Help on Conf in module astropy.utils.iers.iers object:

class Conf(astropy.config.configuration.ConfigNamespace)
 |  Configuration parameters for `astropy.utils.iers`.
 |  
 |  Method resolution order:
 |      Conf
 |      astropy.config.configuration.ConfigNamespace
 |      builtins.object
 |  
 |  Data descriptors defined here:
 |  
 |  auto_download
 |      Enable auto-downloading of the latest IERS data.  If set to False then the local IERS-B file will be used by default (even if the full IERS file with predictions was already downloaded and cached). This parameter also controls whether internet resources will be queried to update the leap second table if the installed version is out of date. Default is True.
 |  
 |  auto_max_age
 |      Maximum age (days) of predictive data before auto-downloading. See "Auto refresh behavior" in astropy.utils.iers documentation for details. Default is 30.
 |  
 |  iers_auto_url
 |      URL for auto-downloading IERS file data.
 |  
 |  iers_auto_url_mirror
 |      Mirror URL for auto-downloading IERS file data.
 |  
 |  iers_degraded_accuracy
 |      IERS behavior if the range of available IERS data does not cover the times when converting time scales, potentially leading to degraded accuracy.
 |  
 |  iers_leap_second_auto_url
 |      URL for auto-downloading leap seconds.
 |  
 |  ietf_leap_second_auto_url
 |      Alternate URL for auto-downloading leap seconds.
 |  
 |  remote_timeout
 |      Remote timeout downloading IERS file data (seconds).
 |  
 |  system_leap_second_file
 |      System file with leap seconds.
 |  

@eerovaher

Copy link
Copy Markdown
Member Author

Actually, just because I (EDIT: thought wouldn't it be nice if one could just do "help(something)" and) wondered what would happen, help(conf) is quite good...

Python's builtin help() function prints quite a lot for the ConfigNamespace, but if help is wanted for a single item then this could be overwhelming. The ConfigNamespace.help() method I am proposing would allow for printing an overview of a single configuration item, and it shows more information per item than the builtin help() does. In particular, if a configuration item accepts only a finite set of values then ConfigNamespace.help() lists all of them.

I like the idea too, but wonder if a simpler solution to the problem is not to define a __repr__

ConfigItem.__str__() already produces an informative string:

def __str__(self):
out = '\n'.join(('{0}: {1}',
' cfgtype={2!r}',
' defaultvalue={3!r}',
' description={4!r}',
' module={5}',
' value={6!r}'))
out = out.format(self.__class__.__name__, self.name, self.cfgtype,
self.defaultvalue, self.description, self.module,
self())
return out

However, thanks to ConfigItem.__get__() accessing the configuration items normally (as attributes of the ConfigNamespace instance) retrieves their value, not the ConfigItem instance, so the ConfigItem.__str__() method is quite difficult to access.

I have updated the pull request so that if help is printed for multiple configuration items then the entries are separated with empty lines, and there is now an example in the docstring.

@mhvk

mhvk commented Jul 29, 2022

Copy link
Copy Markdown
Contributor

I guess we should separate the two concerns, but right now, while the configitems may have a nice __str__ method, the configuration entity does not: print(conf) and repr(conf) are both essentially useless! I think this is partially a question of what users are most likely to discover; I think that starts with just giving something useful for the repr -- most confs do not have that many entries, so generally it will not be overwhelming.

Note that in ipython, conf? is also not very helpful (conf?? is better but less good than help(conf).

All that said, I definitely see your point that just from tab-completion, it is nearly impossible to get useful information; e.g., conf.auto_download? gives information on bools... My main worry is just that it is unlikely any user would guess there would be a .help() method (though presumably they might find it through tab completion); for the somewhat related Table.read.help, the main trick was to put the existence of the .help method high up in the docstring (though I still worry I only know about it because I saw the PR!).

@eerovaher
eerovaher force-pushed the config-help branch 2 times, most recently from a437d54 to cc417bc Compare August 1, 2022 20:18
@eerovaher
eerovaher marked this pull request as draft August 1, 2022 20:20
@eerovaher

Copy link
Copy Markdown
Member Author

I've implemented ConfigNamespace.__str__(). The string representation of a ConfigNamespace contains the string representations of the configuration items within it, and is used in ConfigNamespace.help(). Although calling print(conf) now results in the same message as calling conf.help() without arguments, having the help() method is still useful because it also allows printing the string representation of a single configuration item.

I have converted this pull request to a draft so that we could discuss if the ConfigItem.__str__() should be changed or if we are happy with the way the string representation of a configuration item is currently formatted.

@eerovaher

Copy link
Copy Markdown
Member Author

@mhvk, does the proposed implementation address your remarks?

@astrofrog astrofrog modified the milestones: v5.2, v5.3 Dec 8, 2022
@github-actions

This comment was marked as outdated.

@github-actions github-actions Bot added the Close? Tell stale bot that this issue/PR is stale label Dec 30, 2022
@eerovaher

Copy link
Copy Markdown
Member Author

@mhvk, could you have a look at this? I converted this pull request to a draft in case we want to also change ConfigItem.__str__(), but if we don't then this should be good to merge as is.

@eerovaher eerovaher removed the Close? Tell stale bot that this issue/PR is stale label Feb 7, 2023
@eerovaher
eerovaher requested a review from mhvk March 9, 2023 19:14
@mhvk

mhvk commented Mar 9, 2023

Copy link
Copy Markdown
Contributor

I'm so sorry that this keeps slipping by. The problem is mostly that really all I remember is a feeling of disquiet at this, but I know that I actually have to look at things again, for which I don't really have time right now. It may be more logical is some of the people who wrote the configuration system had a look, so let's ping @eteq, @saimn and @WilliamJamieson .

@saimn saimn modified the milestones: v5.3, v6.0 Apr 21, 2023
@github-actions github-actions Bot added the Close? Tell stale bot that this issue/PR is stale label Jun 5, 2023
@github-actions

This comment was marked as outdated.

@eerovaher eerovaher removed the Close? Tell stale bot that this issue/PR is stale label Jun 7, 2023
@eerovaher
eerovaher marked this pull request as ready for review June 7, 2023 17:01
@pllim

This comment was marked as outdated.

@eerovaher
eerovaher force-pushed the config-help branch 9 times, most recently from 39eea30 to 3603b8d Compare June 7, 2023 18:09
@eerovaher

Copy link
Copy Markdown
Member Author

The pull request now matches my branch, so this is ready for review.

A short summary of this pull request is that it implements ConfigNamespace.__str__() and ConfigNamespace.help(), both of which make it simple to learn about configuration items from within Python. However, both implemented methods make use of ConfigItem.__str__(), which I haven't edited, but perhaps it should be updated so that the output of ConfigNamespace.help() would be more convenient.

@eerovaher

Copy link
Copy Markdown
Member Author

I have updated the example outputs of the code, both in the tests and in the documentation. As they are written now they are closer to the actual outputs users would see. The cost of doing this are a few overlong lines, but I think not having artificial line breaks in the examples is a good enough excuse.

@pllim

This comment was marked as outdated.

@pllim
pllim self-requested a review June 9, 2023 13:30
@eerovaher

Copy link
Copy Markdown
Member Author

I rebased this once more as requested by https://groups.google.com/g/astropy-dev/c/9DO4YkoU44g

The new string representation of a `ConfigNamespace` contains the string
representations of the configuration items stored within it, so passing
a `ConfigNamespace` to Python's built-in `print()` results in an
informative message.
@pllim

pllim commented Oct 6, 2023

Copy link
Copy Markdown
Member

codecov upload failed, so we can ignore the coverage complain.

Comment thread docs/config/index.rst Resolved
@pllim

pllim commented Oct 6, 2023

Copy link
Copy Markdown
Member

Despite using a .help() method, unlike typical Python str or repr, I still think this is an improvement based on the doc updates. Just have a small comment on the example that was removed.

@pllim

pllim commented Oct 6, 2023

Copy link
Copy Markdown
Member

I think this also works for downstream packages that uses the config system (e.g., synphot), so that is nice. 👏

The new `ConfigNamespace.help()` method prints the string representation
of the specified `ConfigItem`, or of the `ConfigNamespace` itself.

@pllim pllim left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry this dragged on so long. Thanks!

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants