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

PR: Consistently handle PYTHONPATH and add Import feature to PYTHONPATH Manager #17512

Merged
merged 20 commits into from
Jun 22, 2022

Conversation

mrclary
Copy link
Contributor

@mrclary mrclary commented Mar 19, 2022

Description of Changes

Explicitly excluded system PYTHONPATH paths from Editor completion paths, IPython Console sys.path, and IPython Console os.environ['PYTHONPATH'].
Added feature to import system PYTHONPATH paths into PYTHONPATH Manager.

The "Syncronize..." feature (Windows only) is changed to "Export" to better complement "Import" and comport with what it actually does. This remains a Windows only feature for the time being.

Resolved an issue where a path was added after canceling "Select directory" dialog.

ppm

Issue(s) Resolved

Fixes #17511

Affirmation

By submitting this Pull Request or typing my (user)name below,
I affirm the Developer Certificate of Origin
with respect to all commits and content included in this PR,
and understand I am releasing the same under Spyder's MIT (Expat) license.

I certify the above statement is true and correct:

@pep8speaks
Copy link

pep8speaks commented Mar 19, 2022

Hello @mrclary! Thanks for updating this PR. We checked the lines you've touched for PEP 8 issues, and found:

Line 659:80: E501 line too long (80 > 79 characters)
Line 850:80: E501 line too long (80 > 79 characters)

Line 216:80: E501 line too long (88 > 79 characters)

Comment last updated at 2022-06-21 20:52:46 UTC

@mrclary
Copy link
Contributor Author

mrclary commented Mar 21, 2022

We had been removing PYTHONPATH from env_vars and using SPY_PYTHONPATH instead. This is only used to set the sys.path paths in the IPython Console at launch. Eliminating SPY_PYTHONPATH in favor of PYTHONPATH will produce the same result while also providing os.environ['PYTHONPATH'] in the IPython Console and obviate set_spyder_pythonpath in spyder-kernels. This prevents kernel crashes at startup if PYTHONPATH Manager paths shadow standard libraries.

A companion PR spyder-ide/spyder-kernels#378 accommodates this change and updates IPython Console's os.environ['PYTHONPATH'] along with the sys.path update.

@ccordoba12
Copy link
Member

ccordoba12 commented Mar 22, 2022

Thanks for your work on this @mrclary! I'm leaving it for 5.3.1 because this is an important change and we need to carefully discuss about it.

@ccordoba12 ccordoba12 added this to the v5.3.1 milestone Mar 22, 2022
@mrclary mrclary force-pushed the pypath-manager-import branch 2 times, most recently from 12387d1 to ee653cd Compare March 23, 2022 01:12
@ccordoba12
Copy link
Member

@mrclary, we discussed your PR with @CAM-Gerlach and @isabela-pf this week and we consider it requires some UI/UX improvements, so that users better understand how the PYTHONPATH manager works with the improvements you propose.

@isabela-pf will be posting more details about it soon.

@mrclary
Copy link
Contributor Author

mrclary commented Mar 26, 2022

@mrclary, we discussed your PR with @CAM-Gerlach and @isabela-pf this week and we consider it requires some UI/UX improvements, so that users better understand how the PYTHONPATH manager works with the improvements you propose.

@isabela-pf will be posting more details about it soon.

Thanks, @ccordoba12 @CAM-Gerlach and @isabela-pf .

Another thing to discuss is whether we should intercept PYTHONPATH in Spyder at launch. In this PR I have only ensured that PYTHONPATH is handled consistently between platforms, launch mechanisms, and completions/IPython Console. @ccordoba12 implemented SPY_PYTHONPATH to intercept PYTHONPATH Manager paths and re-inject them into sys.path in IPython Console without crashing the kernel if the user shadowed standard libraries. This was a good idea and I'm wondering if we shouldn't implement something similar for Spyder at launch. Spyder does not need the user's system PYTHONPATH for anything, but it does get injected into Spyder's runtime sys.path, so if it does shadow standard libraries it could cause problems for Spyder. Although I don't think we've seen any issues posted, so maybe it's nothing to be concerned about, it seems a relatively cheap thing to do to ensure Spyder is robust against user settings.

@ccordoba12 ccordoba12 modified the milestones: v5.3.1, v5.3.2 Apr 9, 2022
@mrclary
Copy link
Contributor Author

mrclary commented Apr 18, 2022

@isabela-pf, did you have some feedback on this PR?

@mrclary mrclary self-assigned this Apr 18, 2022
@steff456
Copy link
Member

It looks better!

@ccordoba12
Copy link
Member

Agreed, it looks much nicer.

Copy link
Member

@ccordoba12 ccordoba12 left a comment

Choose a reason for hiding this comment

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

Last minor details @mrclary, then this should be ready.

Also, since I just merged spyder-ide/spyder-kernels#378, please resync the spyder-kernels subrepo with the instructions in our Contributing guide.

spyder/widgets/pathmanager.py Outdated Show resolved Hide resolved
spyder/widgets/pathmanager.py Outdated Show resolved Hide resolved
spyder/widgets/pathmanager.py Outdated Show resolved Hide resolved
mrclary and others added 2 commits June 21, 2022 13:48
Co-authored-by: Carlos Cordoba <ccordoba12@gmail.com>
…der-ide/spyder-kernels.git external-deps/spyder-kernels

subrepo:
  subdir:   "external-deps/spyder-kernels"
  merged:   "4302062d8"
upstream:
  origin:   "https://github.com/spyder-ide/spyder-kernels.git"
  branch:   "2.x"
  commit:   "4302062d8"
git-subrepo:
  version:  "0.4.3"
  origin:   "???"
  commit:   "???"
Copy link
Member

@ccordoba12 ccordoba12 left a comment

Choose a reason for hiding this comment

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

Looks good to me now, thanks @mrclary!

Copy link
Member

@dalthviz dalthviz left a comment

Choose a reason for hiding this comment

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

Thanks @mrclary ! Checking this locally on Windows seems like is working correctly although to import exported paths you need to restart Spyder and/or run it from a new console/cmd. Seems like the changes done to PYTHONPATH are not being taken into account without that (I think that's something that was happening before this PR though, right?). So for example, if I use Add a path, use Export, remove the path from the manager with Remove path and then try to use Import I see the empty PYTHONPATH while in the consoles I can get the PYTHONPATH update:

imagen

If that is expected then this LGTM 👍

@mrclary
Copy link
Contributor Author

mrclary commented Jun 22, 2022

Thanks @mrclary ! Checking this locally on Windows seems like is working correctly although to import exported paths you need to restart Spyder and/or run it from a new console/cmd. Seems like the changes done to PYTHONPATH are not being taken into account without that (I think that's something that was happening before this PR though, right?). So for example, if I use Add a path, use Export, remove the path from the manager with Remove path and then try to use Import I see the empty PYTHONPATH while in the consoles I can get the PYTHONPATH update:

The "import" feature currently uses the existing os.environ['PYTHONPATH'] in Spyder's runtime environment which is established at launch. We could change this with one of the following options:

  • Upon exporting PPM to the system PYTHONPATH (Windows only), we could also appropriately update Spyder's runtime os.environ['PYTHONPATH']. Spyder does not use this internally for any reason, so this should be safe.
  • Rather than relying on os.environ['PYTHONPATH'], we could retrieve the system environment variable directly. This should be straightforward on Windows by querying the registry (I think this is already done for the purpose of exporting anyway). On unix, a login shell subprocess would be needed to extract the environment variable; this would require a little more work to setup properly as it depends on the user's default shell etc., but is certainly feasible.

The second option may be more robust and future-proof. For example, @CAM-Gerlach has alluded to pending updates to Python which may use new -P flags by default which will preclude use of PYTHON* environment variables. If/when this is the case, os.environ['PYTHONPATH'] may no longer be available by default, so a different mechanism may be prudent.

If that is expected then this LGTM 👍

Technically, it is expected. Nevertheless, it may not be desirable. I think I'll include a fix for this in this PR. Unless @ccordoba12, @dalthviz, or @CAM-Gerlach have anything other recommendations, I'll proceed with the second option.

@dalthviz
Copy link
Member

Sounds good to me 👍 Although, since the current behavior is expected maybe a new issue could be open to track the missing improvements (probably using the comment above #17512 (comment) as an starting point). In that way we could check a little bit more ideas and other missing things regarding the PYTHONPATH manager without that being a blocker to merge this

@mrclary
Copy link
Contributor Author

mrclary commented Jun 22, 2022

Sounds good to me 👍 Although, since the current behavior is expected maybe a new issue could be open to track the missing improvements (probably using the comment above #17512 (comment) as an starting point). In that way we could check a little bit more ideas and other missing things regarding the PYTHONPATH manager without that being a blocker to merge this

Good idea. I'll proceed with the second option in another pull request in order to allow more in-depth feedback without blocking this PR.

@mrclary
Copy link
Contributor Author

mrclary commented Jun 22, 2022

I'm glad @CAM-Gerlach was able to clarify! I don't want to block this PR with my limited time, so please don't feel the need to wait for me.

@isabela-pf, based on this comment, I'll remove you from the reviewer list. If you still wish to review, please feel free to add yourself back. Thanks for the previous feedback.

Copy link
Member

@steff456 steff456 left a comment

Choose a reason for hiding this comment

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

Thanks for working on this! I think it is ready to merge 😬

@CAM-Gerlach
Copy link
Member

The second option may be more robust and future-proof. For example, @CAM-Gerlach has alluded to pending updates to Python which may use new -P flags by default which will preclude use of PYTHON* environment variables. If/when this is the case, os.environ['PYTHONPATH'] may no longer be available by default, so a different mechanism may be prudent.

To clarify, all -P does is disable inserting the current working directory (for -c, -m and the interactive interpreter) or the script directory (for scripts) at sys.path[0]. We hope to someday make it the default, but there is no concrete plan and that day would be a ways off if it comes. Therefore, this has no effect on PYTHONPATH. It is -E that ignores all environment variables, including PYTHONPATH, which is in turn implied by -I (along with -s and, crucially, not inserting the cwd/script dir on the path). However, even then, that is only for constructing the initial sys.path for the Python interpreter (which Spyder already ignores with this PR), it certainly doesn't mean that manually running os.environ["PYTHONPATH"] doesn't work.

To the contrary, I would think that relying on Python's mature, battle tested and widely used facilities for OS interaction are much more robust and reliable than anything we try to hack on our own, and if we want to address this here rather than in a separate PR, the first approach would make more sense and be more consistent (as well as much simpler to implement).

Copy link
Member

@CAM-Gerlach CAM-Gerlach left a comment

Choose a reason for hiding this comment

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

I confess I have not done another round of actual testing or detailed code analysis, to which I defer to the others, but I'm ✔️ on the high-level design and UI/UX (pending optional resolution of the concern above). Thanks @mrclary !

@mrclary
Copy link
Contributor Author

mrclary commented Jun 22, 2022

The second option may be more robust and future-proof. For example, @CAM-Gerlach has alluded to pending updates to Python which may use new -P flags by default which will preclude use of PYTHON* environment variables. If/when this is the case, os.environ['PYTHONPATH'] may no longer be available by default, so a different mechanism may be prudent.

To clarify, all -P does is disable inserting the current working directory (for -c, -m and the interactive interpreter) or the script directory (for scripts) at sys.path[0]. We hope to someday make it the default, but there is no concrete plan and that day would be a ways off if it comes. Therefore, this has no effect on PYTHONPATH. It is -E that ignores all environment variables, including PYTHONPATH, which is in turn implied by -I (along with -s and, crucially, not inserting the cwd/script dir on the path). However, even then, that is only for constructing the initial sys.path for the Python interpreter (which Spyder already ignores with this PR), it certainly doesn't mean that manually running os.environ["PYTHONPATH"] doesn't work.

To the contrary, I would think that relying on Python's mature, battle tested and widely used facilities for OS interaction are much more robust and reliable than anything we try to hack on our own, and if we want to address this here rather than in a separate PR, the first approach would make more sense and be more consistent (as well as much simpler to implement).

Thanks for clarifying. I had the mistaken impression that these would affect os.environ and they do not.

Nevertheless, I still recommend addressing this and any other possible issues in #18397, even if they may be trivial, in order to not prolong this PR.

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.

None yet

7 participants