Skip to content
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

enable discovery of class source code in IPython interactively defined classes #78007

Closed
t-vi mannequin opened this issue Jun 11, 2018 · 14 comments
Closed

enable discovery of class source code in IPython interactively defined classes #78007

t-vi mannequin opened this issue Jun 11, 2018 · 14 comments
Labels
3.8 only security fixes interpreter-core (Objects, Python, Grammar, and Parser dirs) stdlib Python modules in the Lib dir type-feature A feature request or enhancement

Comments

@t-vi
Copy link
Mannequin

t-vi mannequin commented Jun 11, 2018

BPO 33826
Nosy @taleinat, @native-api, @pablogsal, @tirkarthi
PRs
  • bpo-33826: add __filename__ to Python-defined classes for introspection #13894
  • Files
  • class-filename.diff
  • 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:

    assignee = None
    closed_at = <Date 2019-06-07.14:54:24.087>
    created_at = <Date 2018-06-11.06:16:36.774>
    labels = ['interpreter-core', '3.8', 'type-feature', 'library']
    title = 'enable discovery of class source code in IPython interactively defined classes'
    updated_at = <Date 2019-06-07.14:54:24.086>
    user = 'https://github.com/t-vi'

    bugs.python.org fields:

    activity = <Date 2019-06-07.14:54:24.086>
    actor = 't-vi'
    assignee = 'none'
    closed = True
    closed_date = <Date 2019-06-07.14:54:24.087>
    closer = 't-vi'
    components = ['Interpreter Core', 'Library (Lib)']
    creation = <Date 2018-06-11.06:16:36.774>
    creator = 't-vi'
    dependencies = []
    files = ['47638']
    hgrepos = []
    issue_num = 33826
    keywords = ['patch']
    message_count = 14.0
    messages = ['319274', '319650', '319654', '319659', '319660', '319664', '319692', '328813', '328815', '328822', '328824', '328831', '344945', '344947']
    nosy_count = 4.0
    nosy_names = ['taleinat', 'Ivan.Pozdeev', 'pablogsal', 'xtreak']
    pr_nums = ['13894']
    priority = 'normal'
    resolution = 'rejected'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'enhancement'
    url = 'https://bugs.python.org/issue33826'
    versions = ['Python 3.8']

    @t-vi
    Copy link
    Mannequin Author

    t-vi mannequin commented Jun 11, 2018

    Hello,

    thank you for Python!
    In IPython (or Jupyter), inspect.getsource is able to retrieve the source code for functions but not classes.
    The fundamental reason is that for functions, a "filename" (input reference rather) is available via fn.code.co_filename, while for classes, there is no equivalent (and module is main, so no "filename" there).
    This could be helped by providing a "filename" (or however named) attribute in classes.
    Some digging in the Python code suggests that Python/bltinmodule.c might be a good place to resolve this, namely in function builtin___build_class__. In there, there is the func object and so ((PyCodeObject*) PyFunction_GET_CODE(func))->co_filename has the filename.
    Then one would copy that to an appropriate item in the namespace ns.

    I do have a patch (against python 3.6), but as this is my first attempt at digging in the internals, it is probably more than just a bit raw (I see test failures in test_dbm test_lib2to3 test_pydoc test_site, at least test_pydoc is due to the patch).

    Best regards

    Thomas

    @t-vi t-vi mannequin added 3.8 only security fixes interpreter-core (Objects, Python, Grammar, and Parser dirs) stdlib Python modules in the Lib dir type-feature A feature request or enhancement labels Jun 11, 2018
    @native-api
    Copy link
    Mannequin

    native-api mannequin commented Jun 15, 2018

    In [1]: import logging

    In [2]: logging.Logger.__module__
    Out[2]: 'logging'

    In [4]: import sys

    In [6]: sys.modules[logging.Logger.__module__].__file__
    Out[6]: 'C:\\Program Files\\Python36\\lib\\logging\\init.py'

    @native-api
    Copy link
    Mannequin

    native-api mannequin commented Jun 15, 2018

    What do you mean by "class source code" anyway? A class doesn't actually contain any executable code (and there's no code object associated with it).

    @t-vi
    Copy link
    Mannequin Author

    t-vi mannequin commented Jun 15, 2018

    Apologies for not being clear.
    So I wrote:

    In IPython (or Jupyter), inspect.getsource is able to retrieve the source code for functions but not classes.

    By this I mean:

    import inspect
    
    class X:
      pass
    
    inspect.getsource(X)

    Note that:

    • it won't work in the vanilla python interpreter,
    • it does work for functions in Jupyter/IPython currently,
    • it works for classes (and functions) in modules.
      What I would like is to have it work for classes in Jupyter/IPython.

    By the way: Would a PR be more convenient than a patch?

    @native-api
    Copy link
    Mannequin

    native-api mannequin commented Jun 15, 2018

    I got that part, thank you.

    I can't get 1)what you're expecting as an output and 2)why this should work the way you're suggesting 'cuz functions and classes are very different.

    In particular, classes can be modified dynamically, unlike functions. So if you just print out the lines from the file with the definition (which is what getsource() does), it may not be what the interpreter is actually using.

    @t-vi
    Copy link
    Mannequin Author

    t-vi mannequin commented Jun 15, 2018

    So I want "inspect.showsource" to have the same output whether my class has been defined in a .py or in my Jupyter notebook.

    I appreciate there are limitations to what "inspect.showsource" can do, but I am not so sure how that creates uncertainty my expectation of the output when it should just be the same as the current behaviour when the class is defined in a .py module.

    @native-api
    Copy link
    Mannequin

    native-api mannequin commented Jun 15, 2018

    Oh, I see, you want to be able to get the source for code entered into the interactive session.

    IPython does this by creating a separate fake "file name" for every input and adding corresponding entries for them into `linecache.cache'. This doesn't work for classes 'cuz for them, inspect.getfile() rather looks at __module__.__file__ , and there's no single __file__ for __main__.

    Now, there are two concerns here:

    • This will lead to linecache being polluted with old input, effectively a memory leak. Unlike vanilla's readline cache which has a maximum length. Not much concern for IPython which only needs to be good enough for its target audience and can be dropped if it doesn't work for a specific scenario. But not for vanilla which needs to work reliably in all cases.

    • There indeed is a discrepancy between functions that link to source directly and classes that rely on heuristics for that (inspect.findsource() searches the file with a regex for the class' definition, how absurd is that?). Adding __file__ and __firstlineno__ _could_ help here, the `class' directive will need to add them.

      • In any case, the returned source is prone to "not necessarily what the interpreter uses", but that's the problem with how the returned source is generated, not where it's taken from.

    @tirkarthi
    Copy link
    Member

    This seems to be a duplicate of bpo-12920. bpo-24491 was also a related issue closed as a duplicate of bpo-12920. So I propose closing this to continue the discussion in bpo-12920. Feel free to add in if I am missing something.

    @t-vi
    Copy link
    Mannequin Author

    t-vi mannequin commented Oct 29, 2018

    Yeah, it's a shame no-one looked at the patch that seems to fix the underlying cause and now it's just a duplicate of a bug to improve error messages.
    On the up side, closing this bug will stop me from getting reminders about it.

    @t-vi t-vi mannequin closed this as completed Oct 29, 2018
    @native-api
    Copy link
    Mannequin

    native-api mannequin commented Oct 29, 2018

    @thomas Viehmann , as it's currently formulated, this is a duplicate because it strives to allow getting class source from past interactive input -- which, as I explained, is already possible without the patch and seems to be inappropriate for vanilla console anyway.

    Your patch is rather a new class feature that provides a more robust link to its source, wherever it's located. If you reformulate your ticket to propose that instead, it will no longer be a duplicate. I'm not sure if the UI allows that, it may be better to create a new ticket.

    @native-api
    Copy link
    Mannequin

    native-api mannequin commented Oct 29, 2018

    which, as I explained, is already possible without the patch

    Sorry, I myself explained in https://bugs.python.org/msg319692 that it's not possible. The rest still stands though.

    @tirkarthi
    Copy link
    Member

    Sorry about that I thought to redirect the discussion to the linked issue since it had a lot of people who might provide a better discussion about it. Feel free to reopen this if needed.

    @tirkarthi tirkarthi reopened this Nov 10, 2018
    @taleinat
    Copy link
    Contributor

    taleinat commented Jun 7, 2019

    Given that classes already have a '__module__' attribute, using which it is rather easy to find the filename, I don't see a good reason to add such an attribute to classes.

    IMO it would be more appropriate to directly create enhancement proposal for IPython/Jupyter to enhance the capabilities of their source code retrieval.

    I suggest rejecting this enhancement.

    @t-vi
    Copy link
    Mannequin Author

    t-vi mannequin commented Jun 7, 2019

    Note that the module is less granular than the filename in IPython - i.e. it's useless for within notebooks.

    @t-vi t-vi mannequin closed this as completed Jun 7, 2019
    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    3.8 only security fixes interpreter-core (Objects, Python, Grammar, and Parser dirs) stdlib Python modules in the Lib dir type-feature A feature request or enhancement
    Projects
    None yet
    Development

    No branches or pull requests

    2 participants