New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Display exceptions' subclasses in help() #52771
Comments
help() on an exception class lists the method resolution order, which is in effect the class inheritance hierarchy. E.g. help(ArithmeticError) lists ArithmeticError, StandardError, Exception, BaseException, __builtin__.object. It struck me it would help to find my way around if it also listed the builtin SUBclasses (if any). Something like: |
2.5 is frozen. 2.6 and 3.1 are in bug-fix mode only, and 2.7 is in beta so new features are unlikely there. So I recommend doing a patch against 3.1 or even the 3.2 trunk. And of course, make sure this proposal makes sense for 3.x. |
Thanks for your work, Rob. To get reviews and comments, you’ll need to submit a patch (a diff) instead of the whole file. This makes it easier to see your changes than looking for a special comment :) This short doc should contain all the information you’ll need: http://www.python.org/dev/patches As Terry said, 2.6 and 3.1 only get bug fixes, 2.7 and 3.2 are in beta stage and don’t get new features, so you’ll want to port your changes to the py3k branch (the trunk for the 3.x series). Regards |
Minor correction to the last comment: 3.2 is not in beta nor feature freeze. |
Migrated the patch to the 3.x trunk and added three tests. |
Thank you. I uploaded your patch to Rietveld and reviewed it: http://codereview.appspot.com/3169042/ |
The following passes tests in elp_8525.patch, but is much simpler: =================================================================== --- Lib/pydoc.py (revision 86600)
+++ Lib/pydoc.py (working copy)
@@ -1139,6 +1139,15 @@
push(' ' + makename(base))
push('')
+ # List the built-in subclasses, if any:
+ subclasses = [cls.__name__ for cls in object.__subclasses__()
+ if cls.__module__ == 'builtins']
+ if subclasses:
+ push("Built-in subclasses:")
+ for subclassname in sorted(subclasses):
+ push(' ' + subclassname)
+ push('')
+
# Cute little class to pump out a horizontal rule between sections.
class HorizontalRule:
def __init__(self): |
Thanks for your work. Glad if I have made a contribution to Python, On 22/11/2010 00:26, Éric Araujo wrote:
|
I would not be at all surprised if my patch could be simplified (in fact On 22/11/2010 01:33, Alexander Belopolsky wrote:
|
New features can only go into 3.2, so you have to test with an updated checkout of the Subversion branch named py3k. See the link I have in a previous message. (P.S. Would you be so kind as to edit quoted text out of your replies? It’s unnecessary noise. Thanks in advance.) |
The proposal is to display builtin subclasses as for example: >>> help(ArithmeticError)
class ArithmeticError(Exception)
| Base class for arithmetic errors.
|
| Method resolution order:
| ArithmeticError
| Exception
| BaseException
| object
|
| Built-in subclasses:
| FloatingPointError
| OverflowError
| ZeroDivisionError Note that this really affects only exceptions because no other builtin class has builtin subclasses. (dict has subclasses in collections, but not in builtins.) Exception hierarchy is presented in the reference manual at http://docs.python.org/dev/library/exceptions.html?#exception-hierarchy I wonder if rather than having MRO and subclasses sections, we should just present a portion of the exception hierarchy including the given exception, all its bases and direct subclasses: object |
Didn’t the first message ask for the feature to be extended to non-exceptions classes? “Built-in” subclasses is a red herring, to me the feature is: display subclasses. In the text output you can use the search feature of your pager to jump to a subclass, in the HTML output it would be a helpful link. |
On Thu, Dec 2, 2010 at 9:56 PM, Éric Araujo <report@bugs.python.org> wrote:
If we don't restrict to builtins, then the display will depend on what |
Yes, I imagine the feature to be useful to find subclasses defined in the same module. Rob, am I misunderstanding your original request? |
Originally I only had built-in classes in mind (with Exceptions being |
Hi, It seems that it hasn't been worked upon from quite a long time and the patch would also need changes. May I work on this? |
I've changed the version to 3.7. Not sure if this would need a backport since this is a new feature. So, I'll defer this call to a core developer. I've created a PR for the new feature. |
Reviewing the builtins in 3.7, I get the following results for builtin objects that have defined subclasses immediately after interpreter startup: ============= >>> for name, obj in vars(builtins).items():
... if isinstance(obj, type) and name in str(obj):
... subclasses = type(obj).__subclasses__(obj)
... if subclasses:
... print(f"{obj}: {len(subclasses)}")
...
<class 'classmethod'>: 1
<class 'dict'>: 1
<class 'property'>: 1
<class 'int'>: 1
<class 'object'>: 132
<class 'staticmethod'>: 1
<class 'tuple'>: 16
<class 'type'>: 1
<class 'BaseException'>: 4
<class 'Exception'>: 19
<class 'ImportError'>: 2
<class 'OSError'>: 13
<class 'RuntimeError'>: 3
<class 'NameError'>: 1
<class 'SyntaxError'>: 1
<class 'IndentationError'>: 1
<class 'LookupError'>: 3
<class 'ValueError'>: 2
<class 'UnicodeError'>: 3
<class 'ArithmeticError'>: 3
<class 'SystemError'>: 1
<class 'Warning'>: 10
<class 'ConnectionError'>: 4 ============= So rather than special-casing exceptions or builtins in general, my inclination would be to include a section that lists up to 4 subclasses inline, and then adds a "... and NNN additional subclasses" trailing when there are more than 4 (or when there are less than 4 subclasses with public names, but additional private subclasses). So in a class like "int", for example, we'd see:
While in a class like OSError we'd see:
And in "help(object)" we'd see something like:
The initial list of subclasses to show would be restricted to public builtins: If that gives less then four names, then the list of names would be expanded to subclasses with public names in public modules (i.e. neither __qualname__ nor __module__ starts with "_", neither of those contains "._", and qualname doesn't contain ".<locals>."). The full count of currently imported subclasses would ignore whether the subclass names were public or not. |
On 14/07/2018 13:44, Nick Coghlan wrote:
My 2 cents: I question whether it is really useful to know all subclasses of ANY
|
From that list, the only unhelpful ones with > 4 items, in my opinion, appear to be
I agree with this - most of the value here comes from showing the full set of exceptions. If we don't do that, we should probably point the user to calling |
Hi, My perception with all the discussion and WIP patch is that we can ideally limit the no. of subclasses shown only for object, and not for any other class.
+1
I agree with this. I would propose to only limit to 4 classes for subclasses of How does it sound? |
This is a UX problem folks: dynamic unbounded lists are inherently problematic in a line based information display. For methods on a class, there's the natural constraint that broad class APIs are a problem for a variety of reasons, but there's no such design constraint for exception hierarchies. In a Fedora Python 3.6 shell (with the Fedora abrt exception handling hook loaded), Exception has 31 subclasses, and OSError has 17. In a 3.6 shell venv (with no Fedora abrt hook), those numbers are 20 and 13. But if you import assorted Django modules then the number of Exception subclasses grows significantly, while the number of OSError subclasses grows slightly: >>> import django
>>> len(list(pkgutil.iter_modules(django.__path__)))
17
>>> len(Exception.__subclasses__())
76
>>> len(OSError.__subclasses__())
22 Having "help(Exception)" list 50+ different Django exceptions is unlikely to be informative for anyone. In many ways, Python 2 was actually better in this regard, since you could just do "import exceptions; help(exceptions)" to get a nice overview of the full exception hierarchy using the standard logic for displaying. The closest Python 3 currently gets to that is "import builtins; help(builtins)", which is significantly harder to discover. |
I think the way modules display this information may actually provide a solid precedent that addresses the dynamic state problem I'm concerned about: filter the subclass list to only include subclasses that come from the same module as the object being displayed, and use the existing showtree/getclasstree interfaces to display the nested hierarchy nicely (the same way modules do). Then the "... and NNN other subclasses in other modules" would only be appended when there was cross-module inheritance involved. |
I've merged the version that displays up to 4 builtin subclasses in a flat list when help() is called on a type. Thanks for the patch Sanyam, and for the comments and suggestions everyone else. While I'm closing out this feature request as implemented, if anyone's interested in pursuing the more sophisticated showtree/getclasstree approach that would better show position in the class hierarchy (both parents *and* children), feel free to file a new enhancement issue that refers back to this one. |
This caused a regression. See bpo-35614 for details. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: