python / cpython

The Python programming language
https://www.python.org
Other
63.34k stars 30.32k forks source link

Create PIP gui #71238

Closed c6bec776-4609-40f6-b75b-fd5d2778bdf3 closed 7 years ago

c6bec776-4609-40f6-b75b-fd5d2778bdf3 commented 8 years ago
BPO 27051
Nosy @rhettinger, @terryjreedy, @ncoghlan, @ned-deily, @bitdancer, @dstufft, @ilevkivskyi, @mec-is
Files
  • Design_notes_v1.docx
  • tk_generate_event.py
  • design_flow.pdf: application flowchart
  • welcome_v1.jpg: Welcome page layout
  • select_venv_system.jpg
  • install_pyPI_v1.png
  • install_requirement_v1.jpg
  • install_local_archive_v1.jpg
  • update_package_v1.png
  • pip_gui-master.zip: Master branch of pip_gui
  • 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: ```python assignee = None closed_at = created_at = labels = ['type-feature', 'expert-tkinter'] title = 'Create PIP gui' updated_at = user = 'https://bugs.python.org/upendra-k14' ``` bugs.python.org fields: ```python activity = actor = 'levkivskyi' assignee = 'none' closed = True closed_date = closer = 'ncoghlan' components = ['Tkinter'] creation = creator = 'upendra-k14' dependencies = [] files = ['42927', '42930', '42992', '42993', '42994', '42995', '42996', '42997', '42998', '46500'] hgrepos = [] issue_num = 27051 keywords = [] message_count = 62.0 messages = ['265810', '266006', '266010', '266014', '266015', '266248', '266249', '266250', '266316', '266354', '266827', '266828', '267111', '267147', '268172', '268174', '268175', '268178', '268587', '268604', '268625', '268913', '268935', '268941', '268947', '268949', '268950', '268952', '268953', '268957', '268983', '268986', '269019', '269032', '269038', '269046', '269248', '269259', '269264', '269267', '269268', '269269', '269284', '269285', '269286', '269324', '269325', '269705', '269872', '269901', '273698', '273699', '273710', '273713', '273828', '286555', '286634', '286857', '286894', '286895', '286898', '287137'] nosy_count = 9.0 nosy_names = ['rhettinger', 'terry.reedy', 'ncoghlan', 'ned.deily', 'r.david.murray', 'dstufft', 'levkivskyi', 'upendra-k14', 'lorenzogotuned'] pr_nums = [] priority = 'normal' resolution = 'postponed' stage = 'resolved' status = 'closed' superseder = None type = 'enhancement' url = 'https://bugs.python.org/issue27051' versions = ['Python 3.6'] ```

    c6bec776-4609-40f6-b75b-fd5d2778bdf3 commented 8 years ago

    This is new issue opened for creating a GUI (tkinter) front end for pip. It is in continuation with Issue bpo-23551.

    c6bec776-4609-40f6-b75b-fd5d2778bdf3 commented 8 years ago

    I have uploaded my first iteration of design process for Tkinter. In the uploaded document "Design_notes_v1.docx", we have tried to identify different use cases and tasks to be fulfilled by the PIP GUI.

    If there are any suggestions regarding further changes or possible use cases, please let me know. I will upload design of different page layouts for the GUI soon.

    6f4e2e18-696b-41f4-bfba-c5b5b10f07e8 commented 8 years ago

    Ok Upendra. Nice summary.

    In the next days:

    This will complete the first design iteration.

    After receiving feedback and adjusting the sketches, I think we can dive into tkinter to find the right objects/patterns to start coding.

    terryjreedy commented 8 years ago

    I posted notice of this issue on bpo-23551.

    I did some research on simulating user interaction for testing. The results are exemplified in the attached tk.generate_event.py with test setups and assertions.

    Events are generated, to fire event handlers, with widget.generate_event(event, **kwds) where keywords are used to set event attributes. The uploaded file has examples. The method is briefly described in http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/universal.html This reference has a more extensive coverage of events in a separate chapter.

    The above does not mention the need to update the widget first. I learned this from Stackoverflow answers to 'How to make generate_event work?" questions. The tcl/tk doc, tcl.tk/man/tcl8.6/TkCmd/event.htm, adds the fact that text widgets require focus.

    Even though button commands fire when releasing the 'main' button, event '\<ButtonRelease-1>' does not work to fire commands. Instead, use 'button.invoke()'.

    terryjreedy commented 8 years ago

    My main concern is that the project produce something good enough, even if not 'perfect' and 'complete', to commit before 3.6.0 beta 1, scheduled 09-07 https://www.python.org/dev/peps/pep-0494/. I would actually like to have a preliminary version in alpha 4 (08-08) or even alpha 3 (07-11). It would be good to get user feedback before the summer is over. I will try to document the GUI in such a way that the detailed layout and operation are not locked in, but can be amended and augmented.

    For style, follow PEP-8. Ask any questions about alternatives and ambiguities here.

    c6bec776-4609-40f6-b75b-fd5d2778bdf3 commented 8 years ago

    These are some of the code parts which may be necessary :

    1. Code for identification of OS
    from sys import platform
    
    if platform.startswith("linux"):
        #linux
    elif platform == "darwin":
        #mac os x
    else platform == "win32":
        # Windows
    c6bec776-4609-40f6-b75b-fd5d2778bdf3 commented 8 years ago
    1. Detecting different versions of Python installed :

    For Windows :

    It is explained in PEP-514 by Steve Dower.

    Windows has registry keys which can be accessed by winreg or _winreg module.

    Priority of registry keys : HKEY_CURRENT_USER > HKEY_LOCAL_MACHINE

    On 64 bit Windows there is another registry key for 32 bit programs, HKEY_LOCAL_MACHINE\Software\Wow6432Node

    Therefore using registry keys we can know about Python packages installed by enumerating on :

    1. HKEY_CURRENT_USER\Software\Python\\<Company>\\<Tag>\\<InstallPath>
    2. HKEY_LOCAL_MACHINE\Software\Python\\<Company>\\<Tag>\\<InstallPath>
    3. HKEY_LOCAL_MACHINE\Wow6432Node\Python\\<Company>\\<Tag>\\<InstallPath>

    \<Tag> will tell the version number of Python, and in \<InstallPath> key there are two more subkeys which will tell the location of Python executable :

    1. \<Executable Path>
    2. \<WindowedExecutablePath>

    For Linux :

    We can find Python installations in /usr/bin/pythonXYZ

    For MAC OS :

    It can be searched for in

    /Library/Frameworks/ /System/Library/Frameworks

    If Python was installed by Homebrew :

    Then the location can be in /usr/local

    c6bec776-4609-40f6-b75b-fd5d2778bdf3 commented 8 years ago
    1. Detecting Virtual Environment

    Virtual environment can be detected using pip module :

    from pip.locations import running_under_virtualenv
    
    if running_under_virtualenv():
          #If user provided path for virtual environment, evrything okay
    else:
          #Prompt for error
    6f4e2e18-696b-41f4-bfba-c5b5b10f07e8 commented 8 years ago

    @Terry: Fine, we can do it.

    @Upendra: All the checks you mentioned have to be performed at start-up, so create a script that returns a configuration object for the UI. I think you can try to build a first easy view in which a package is selected (an input form when you can type a package name, with two buttons: 'search', 'install'); when a button is pushed, an the event is generated as Terry suggested.

    c6bec776-4609-40f6-b75b-fd5d2778bdf3 commented 8 years ago

    I am posting flow of logic for application and related page layouts.

    Related layouts are :

    1. welcome_v1
    2. select_venv_system
    3. install_pyPI_v1
    4. install_local_archive_v1
    5. install_pythonlibs_v1
    6. install_requirements_v1
    7. update_package_v1
    8. remove_package_v1
    9. finish_tasks_v1 ( can be decided later depending on further options )

    Here , update_package_v1 and remove_package_v1 will be very similar. Therefore, for now I have made layout for update_package_v1 only.

    c6bec776-4609-40f6-b75b-fd5d2778bdf3 commented 8 years ago

    @Terry, code updates can be followed on https://github.com/upendra-k14/pip_gui/tree/dump_code

    Please review the code in dump_code branch. For now, only pip_gui_v3.py is relevant.

    1. I had doubt about including a private module from pip ( "pip._vendor" ). As this module contains a lot of important utilites I have included it by copying the "_vendor" module in my package and changed all the package references of "pip._vendor" to "pip_tkinter._vendor" to make it work. Since, it was a private module, I included it by copying it.

    One more reason is that pip has mentioned this module has immutable. There are very less chances that further changes in this module will be introduced in future.

    1. Except a few complex commands like install, I have planned to inherit the pip command classes. For example, I have inherited the pip.commands.SearchCommand class from pip and overrided the "run" method. It helped me to give finer control over the search results.

    For example,

    Now we can retrieve all previous versions of a package ( which is not provided by pip ) and search results can be directly obtained in form of tuple lists without parsing the output. But, I think doing something similar for pip.commands.InstallCommand is very difficult. Therefore, for now I have chosen to use "runpip and pip.main" for pip install command.

    c6bec776-4609-40f6-b75b-fd5d2778bdf3 commented 8 years ago

    Actually now we don't need

    "pip list" command to get list of installed distributions.

    We can directly get it :

    from pip_tkinter._vendor import pkg_resources
    installed_packages = [p.project_name for p in pkg_resources.working_set]
    c6bec776-4609-40f6-b75b-fd5d2778bdf3 commented 8 years ago

    @Terry and @Lorenzo,

    As shown in the GUI of "install_pyPI_v1.png", I needed to add some tkinter widget into treeview. For example, adding a checkbox to the treeview so that multiple selections are possible. In figure "install_pyPI_v1.png", a checkbox in each row of treeview is needed. I am not getting idea about how to implement it?

    terryjreedy commented 8 years ago

    There is apparently no way to insert widgets in a Treeview -- text only. See for instance https://stackoverflow.com/questions/16755176/tkinter-insert-a-combobox-inside-a-treeview-widget. I don't know whether clicks on a row can be pinpointed to a specific field (to pop up a widget), but it should certainly be possible to detect a right click to do the same. Or put treeview in frame with button with command that detect highlighted row. For your particular problem, I believe Treeview has a mode that allows multiple selections, with multiple rows highlighted simultaneously. If not, or in addition, replace proposed boxes with a blank column and insert string 'X' to indicate selection and inclusion in 'Install' or any other action.

    c6bec776-4609-40f6-b75b-fd5d2778bdf3 commented 8 years ago

    I am unable to print anything using winreg module. Does it require administrative privileges?

    I am using this code sample :

    import os
    import errno
    import winreg
    
    proc_arch = os.environ['PROCESSOR_ARCHITECTURE'].lower()
    try:
        proc_arch64 = os.environ['PROCESSOR_ARCHITEW6432'].lower()
    except KeyError:
        proc_arch64 = None
        pass
    
    if proc_arch == 'x86' and not proc_arch64:
        arch_keys = {0}
    elif proc_arch == 'x86' or proc_arch == 'amd64':
        arch_keys = {winreg.KEY_WOW64_32KEY, winreg.KEY_WOW64_64KEY}
    else:
        raise Exception("Unhandled arch {}".format(proc_arch))
    
    for arch_key in arch_keys:
        key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\Python", 0, winreg.KEY_READ | arch_key)
        for i in range(0, winreg.QueryInfoKey(key)[0]):
            skey_name = winreg.EnumKey(key, i)
            skey = winreg.OpenKey(key, skey_name)
            try:
                print(winreg.QueryValueEx(skey, 'DisplayName')[0])
            except OSError as e:
                if e.errno == errno.ENOENT:
                    pass
            finally:
                skey.Close()
    terryjreedy commented 8 years ago

    I don't know what you mean by 'print with winreg'. I presume you need admin privilege to alter the registry. But why are you involved with it? I just want you to use the pip interface, and let pip worry about such low level stuff.

    c6bec776-4609-40f6-b75b-fd5d2778bdf3 commented 8 years ago

    I, actually want to make a 'configuration object' before running the 'pip' GUI. Therefore one of the parameters of the configuration object will be to detect the path to installed 'python.exe' in Windows. In order to get executable paths I need to read the Windows registry keys.

    terryjreedy commented 8 years ago

    sys.executable has the path to the current executable. But you don't even need that. When you import pip, it gets that itself to find site-packages.

    You are making this way too complicated and are trying to do what pip can do. I don't see that we need to know the system. Pip does that. You don't need to know all installed pythons, certainly not to begin. The first thing is to install to the current version. Expand on that later. Don't worry about virtual environments. Beginners don't know what they are, and this is aimed at beginners.

    3.6.0a2 will be tagged on Sunday, and I can look at this more after that.

    terryjreedy commented 8 years ago

    install_page.py fails with

    Traceback (most recent call last):
      File "F:\Python\mypy\tem2.py", line 611, in <module>
        install_app = InstallPage(root)
    TypeError: __init__() missing 1 required positional argument: 'controller'

    manage_installed_modules_page.py would have the same failure.

    c6bec776-4609-40f6-b75b-fd5d2778bdf3 commented 8 years ago

    For executing it currently, we need to run it like this:

    python -m pip_tkinter

    Recently, I have changed code. Therefore we can't execute individual pages/layouts by running it with "python -m pip_tkinter.\<name of file>".

    I will change the code in "__main__" section so that they can be executed independently.

    6f4e2e18-696b-41f4-bfba-c5b5b10f07e8 commented 8 years ago

    I made it run from the root directory with:

    python pip_tkinter/main.py

    For sure the right way should be

    python -m pip_tkinter

    The first view works fine for PyPi, the second one is just void. I added a issue for an enhancement at \https://github.com/upendra-k14/pip_gui/issues/2\. We are going to fix what we have this weekend, for the sake of the first deadline.

    c6bec776-4609-40f6-b75b-fd5d2778bdf3 commented 8 years ago

    For blog posts related to this project, here is the blog link :

    https://scorython.wordpress.com

    For now, there are following posts :

    1. Application Screenshots
    2. Design Patterns: How to write reusable and tidy software? ( to be completed)
    3. Menace of Global Variables : Just a light post
    4. Page Layouts and Application Flow of Logic
    5. Ist Design Iteration of ‘pip’ GUI
    6. My First GSoC Post : Notes on process of designing a GUI application
    terryjreedy commented 8 years ago

    Upendra, Lorenzo is doing your midterm evaluation.

    3.6.0a3 is scheduled for 7/11. A week before that, I would like to see a patch posted here that I could potentially commit. Work out the details of what to include with Lorenzo. The patch should include adding yourself alphabetically (currently between Adnan Umer and Roger Upole) to misc.ACKS. It could include a patch for the idlelib section of docs/whatsnew.rst. It should not include the misc.NEWS entry. You could instead post suggested text for both here.

    The patch should include some automated tests, but I know that some will be tricky. A suggested protocol for human testing, posted here, can initially substitute for some automated tests. Start by writing down, if you have not already, an outline of what you do to test your code, and what I might do to verify that it works.

    I am working on an IDLE patch that already includes the sort of end-to-end testing I have talked about: enter data into gui, simulate 'go' click, and then check final result. I will post the new issue number when there is something to look at.

    terryjreedy commented 8 years ago

    I should mention that the reason we have multiple alpha and beta releases for a new version is that new modules such as this are *typically* incomplete, a bit rough in the API, and even buggy, when first committed. We have had the most problems when modules are first committed just before the beta release. Getting in an alpha release gives more time for feedback and polishing before that. As soon as I commit something, I will notify bpo-23551 and ask people nosy there to test and comment.

    ned-deily commented 8 years ago

    Terry et al: is anyone from the Python Packaging Authority (and or distutils-sig) involved in this project? After all, pip is developed and maintained by them, not by python-dev. I don't think we should be committing code to the Python Standard library for an interface they control that does not at least have their blessing. Nick, what do you think?

    https://pip.pypa.io/en/stable/

    ned-deily commented 8 years ago

    Let me just expand on my concerns here. I apologize for not thinking about these earlier: I haven't been paying enough attention to this project. And I certainly do not intend this to be a criticism of anyone's work on this, especially your work, Upendra and your mentoring, Lorenzo and Terry. Thank you! The issues I'm concerned about here are not so much technical but rather related to process and long-term maintenance.

    As is discussed in PEP-453, https://www.python.org/dev/peps/pep-0453/, which describes how pip was made available through the Python Standard Library, there was a clear boundary drawn between pip development and the standard library:

    "This PEP does not propose making pip (or any dependencies) directly available as part of the standard library. Instead, pip will be a bundled application provided along with CPython for the convenience of Python users, but subject to its own development life cycle and able to be upgraded independently of the core interpreter and standard library."

    What the standard library provides are mechanisms to deliver pip in a standard library (for example, via the "ensurepip" module) but there is deliberately almost no documentation in the standard library about the use of pip. Rather there are links to the official Python Packaging Authority pip documentation. This was to ensure that pip development remains decoupled from Python development; both can operate on their own cycles and have different goals and requirements. For example, a given pip release typically supports a broad range of Python releases; pip has intimate dependencies on other resources, like PyPI, ones that Python itself doesn't (or at least as tightly coupled as pip has). Yes, it's not 100% clean but the separation of concerns and design authority was and remains a very important part of the relationship between pip and Python as independent projects. And that independence also means that the details of how users interface with pip in the current command line environment - what commands are available, what options each has, default values, current best practices - are the purview of the Python Packaging Authority and the pip project, not Python development.

    This translates directly into the whole user experience when using a gui instead of a cli. As we all know, user experience and user interface design is *hard*, especially in the multi-platform environment that Python and pip operate in and especially for relatively naive users, presumably the primary audience for such a gui. It's nice to think of having an IDLE gui interface for pip but treating it as an IDLE feature rather than a pip feature violates the intent of PEP-453 (IMO) and jeopardizes the chance for this feature being successful and has the potential to disrupt the success of PEP-453. In the spirit of PEP-453, I think the gui interface (or at least the bulk of it) needs to be design-reviewed and approved by the Python Packaging Authority and somehow be part of the pip development and release process. Python releases would deliver it initially via the current ensurepip and third-party packager mechanisms and the gui would be updated through normal pip mechanisms, asynchronously of Python releases, so that the gui remains synchronized with pip. Ideally, the gui would be not dependent on IDLE at all; IDLE would just provide convenience UI elements to launch the gui.

    Perhaps this has been discussed before and included in the project plans. If not, I think it needs to be now before we commit ourselves to creating a new set of potentially problematic dependencies for the future.

    terryjreedy commented 8 years ago

    Ned, I agree with you in principle, and would have preferred that this had been handled by PPA/distutils/PIP folk. But see at least the first 4 messages on the original issue bpo-23551, Feb 28 2015, where Donald Stufft says he would like to see it happen but would not do it.

    Hightlights of the rest: In the first month of discussion others said yes, great idea. 6 months later, in September, I posted some proof of concept results. About 5 months later, I suggested on core-mentorship that this would be a good GSOC project and a few days later Upendra expressed interest. Another student joined the competition in March.

    March 27, I posted on pydev "Adding a Pip GUI to IDLE and idlelib (GSOC project)" https://mail.python.org/pipermail/python-dev/2016-March/143586.html and said at the top "Before I commit to mentoring a student (sometime in April), I would like to be sure, by addressing any objections now, that I will be able to commit the code when ready (August or before)." I ended the post with two possible objections.

    As it turns out, no one objected. Ethan Furman and Nick Coughlin strongly approved, the latter at https://mail.python.org/pipermail/python-dev/2016-April/143611.html

    terryjreedy commented 8 years ago

    Ned, my response was to your first message. I am just now reading the second.

    ned-deily commented 8 years ago

    One other possibility: decouple the gui from both Python and pip releases by packaging and, at least initially, releasing it through PyPI as an independent project. That is, after all, the preferred mechanism for adding new functionality to the standard library. The only thing that would need to be in the standard library then is an IDLE version of "ensuregui", serving the same purpose as "ensurepip", to provide an easy way for IDLE users to initially install the gui using pip and PyPI. If, down the road, the gui is a success and the long-term support issues can be addressed, bringing the gui directly under the pip project could happen in the future.

    terryjreedy commented 8 years ago

    I seem to have anticipated some of your expansion, but I note this: while Raymond's first post could be interpreted as suggesting a new IDLE feature, with its own PIP menu with multiple options, I immediately said it should be a standalone module that IDLE starts in a separate process, with one menu entry and a few lines of code, just as with turtledemo.

    Putting the module (or package) in idlelib defines it as private and subject to change. I can repeat that in the package itself. The public interface will be "click on menu entry 'Run PIP". If it were moved to pip, the internal IDLE change should just be to change 'idlelib.pipgui' to 'pip.pipgui' (or whatever).

    I have not decided whether test_pipgui should be added to test or subsumed under test_idle by being added to idle_test. Do you or Nick have an opinion?

    c6bec776-4609-40f6-b75b-fd5d2778bdf3 commented 8 years ago

    Hey, can anyone help me with this code :

    ###################################################################

    Python 3.4.3 (default, Oct 14 2015, 20:33:09) 
    [GCC 4.8.4] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import pip
    >>> pip.main(["install","-U","wheel"])
    Requirement already up-to-date: wheel in /usr/local/lib/python3.4/dist-packages
    Cleaning up...
    0
    >>> pip.main(["install","-U","timingwheel"])
    Downloading/unpacking timingwheel
    Downloading/unpacking timingwheel
      Downloading timingwheel-0.4.tar.gz
      Downloading timingwheel-0.4.tar.gz
      Running setup.py (path:/tmp/pip_build_scorpio/timingwheel/setup.py) egg_info for package timingwheel
      Running setup.py (path:/tmp/pip_build_scorpio/timingwheel/setup.py) egg_info for package timingwheel
        Traceback (most recent call last):
        Traceback (most recent call last):
          File "<string>", line 17, in <module>
          File "<string>", line 17, in <module>
          File "/tmp/pip_build_scorpio/timingwheel/setup.py", line 3, in <module>
          File "/tmp/pip_build_scorpio/timingwheel/setup.py", line 3, in <module>
            from timingwheel import version
            from timingwheel import version
          File "/tmp/pip_build_scorpio/timingwheel/timingwheel/__init__.py", line 1, in <module>
          File "/tmp/pip_build_scorpio/timingwheel/timingwheel/__init__.py", line 1, in <module>
            from timingwheel import BaseWheel, TimingWheel
            from timingwheel import BaseWheel, TimingWheel
        ImportError: cannot import name 'BaseWheel'
        ImportError: cannot import name 'BaseWheel'
        Complete output from command python setup.py egg_info:
        Complete output from command python setup.py egg_info:
        Traceback (most recent call last):

    File "\<string>", line 17, in \<module>

    File "/tmp/pip_build_scorpio/timingwheel/setup.py", line 3, in \<module>

        from timingwheel import version

    File "/tmp/pip_build_scorpio/timingwheel/timingwheel/init.py", line 1, in \<module>

        from timingwheel import BaseWheel, TimingWheel

    ImportError: cannot import name 'BaseWheel'

    ----------------------------------------

        Traceback (most recent call last):

    File "\<string>", line 17, in \<module>

    File "/tmp/pip_build_scorpio/timingwheel/setup.py", line 3, in \<module>

        from timingwheel import version

    File "/tmp/pip_build_scorpio/timingwheel/timingwheel/init.py", line 1, in \<module>

        from timingwheel import BaseWheel, TimingWheel

    ImportError: cannot import name 'BaseWheel'

    ---------------------------------------- Cleaning up... Cleaning up... Command python setup.py egg_info failed with error code 1 in /tmp/pip_build_scorpio/timingwheel Command python setup.py egg_info failed with error code 1 in /tmp/pip_build_scorpio/timingwheel Storing debug log for failure in /home/scorpio/.pip/pip.log Storing debug log for failure in /home/scorpio/.pip/pip.log 1

    ############################################################### ###############################################################

    In the above failure, pip install functionality fails. I don't know why. Other functionalities like "search" and "list" works perfectly. But, when I tried to connect this pip install command with my GUI button, I got the above error.

    c6bec776-4609-40f6-b75b-fd5d2778bdf3 commented 8 years ago

    Sorry for trouble. I think I messed up with my Python installation. I reinstalled Python and pip. The "pip install command issue" is fixed.

    ncoghlan commented 8 years ago

    Unfortunately, Ned's right in highlighting a potential pip integration problem here: pip DOES NOT expose a supported Python API, but pip_tkinter currently imports APIs from within the pip package.

    This means that somebody doing "pip install --upgrade pip" may break a version of the GUI that is implemented this way, contradicting our promise that a post-install "pip install --upgrade pip" is a fully supported operation that won't break anything else in CPython.

    That's 100% fine for a proof of concept that demonstrates the general principle of a Tkinter based package management GUI and it's integration into IDLE (and Upendra's work on that front looks excellent to me), but isn't reasonable for a version that actually lands in CPython as a supported component.

    Where this work could really help move the "Stable Python API for package management" discussion forward is by providing a clear set of use cases, as well as spelling out the internal pip APIs used to implement that feature in the proof-of-concept,

    The reason I believe that will be helpful is that one of the big problems in this area to date has been the lack of a clear statement of the problem that a stable Python API would be aimed at solving - "provide a stable API that meets the needs of the default package management GUI shipped with IDLE" is a far more tractable problem than "provide a stable API for pip".

    terryjreedy commented 8 years ago

    I rechecked bpo-23351 and in msg249924 Donald did disclaim any guarantee that using main() would work forever. He suggested instead using subprocess and the command line interface as presumably more stable.

    In tem_pip_v3.py Upendra switched to using subprocess and I presume he stuck with that in spite of any suggestion otherwise from me. If the pip command line interface is changed, *every* program that uses it could be broken.

    I agree with Ned that pip_gui should ideally be part of the pip package, I would be happy if Donald were to review what Upendra has and will produce, pronounce it good, and ask to have it for pip.

    ncoghlan commented 8 years ago

    pip_gui.pip_tkinter.utils.runpip has indeed switched to using subprocess (and yes, the PyPA crew are significantly more careful with backwards compatibility there), but there are still a couple of other API imports in that module: https://github.com/upendra-k14/pip_gui/blob/dump_code/pip_tkinter/utils.py#L7 (I didn't check other code to see if the affected APIs are used anywhere)

    I do like the idea of *bundling* pip_gui in a variant of the ensurepip style, rather than having it as a conventional standard library component, though - it means we can simplify the backwards compatibility guarantee by noting that, if you're using the provided GUI, doing "pip install --upgrade pip" may also require doing "pip install --upgrade pip-tkinter".

    terryjreedy commented 8 years ago

    I am unassigning myself because this has moved out of my sphere of expertise and authority. Someone else should take responsibility for getting this committed. I added this as a dependency of bpo-23551, which is about the IDLE menu entry and invocation of the gui, wherever it ends up.

    terryjreedy commented 8 years ago

    Raymond, since you are the one who proposed making a pip-gui accessible from IDLE, you might want to comment on where and how it should be installed. Ned Deily and Nick Coughlin are dubious about putting it anywhere in the stdlib, including idlelib. One alternative is putting it on PyPI. The discussion starts with Ned's first post, msg268947, on July 20.

    ncoghlan commented 8 years ago

    Terry, would you be open to overseeing the merge of a version that bootstrapped itself as follows:

    Then, pip-gui itself could just be a normal PyPI package, without any dependency vendoring, and without any specific coupling to the CPython release process.

    terryjreedy commented 8 years ago

    Upendra: you own the code you are writing. Are you willing to create and maintain for some time a PyPI project?

    If so, Nick, Donald, or someone should be willing and able to help. If you do so, please make someone a backup co-owner, to make it less likely that it becomes an orphan project.

    It would be silly to tell beginners that they must learn to use a console to run pip to install pipgui so they can avoid using a console to run pip. If we go this route, I could, at least as a backup, have the IDLE menu event handle conditionally offer to install pipgui. See msg269252 of bpo-23551.

    A separate 'ensurepipgui' doesn't seem necessary to me. Once pip is known to be installed, it can be used to install pipgui. Once pipgui exists, ensurepip should just install it as its last step. Nick, what do you think?

    One concern I have is that installing pipgui from PyPI seems more of a security risk than pre-installing it. Before committing to idlelib, I would review it before testing on my own machine. Any further changes would have to be by a core developer, and would be published on Python-checkins for anyone to review. The latter does not happen for external projects. (Upendra, please don't take offense from this. Donald is a core developer with a long history, including with security issues. You aren't. And I have not much experience with security issues either.)

    Another issue with pip and pipgui is that PyPI is apparently vulnerable to typosquatting attacks, see http://arstechnica.co.uk/security/2016/06/german-student-university-of-hamburg-typosquatting-attack/ I believe beginners are more susceptible to mistyping package names. The above report makes me realize that installing from a stored requirements list is a good idea, and think that pipgui, at least when run from IDLE, should install from a whitelist, (in idlelib, for IDLE?). Some instructors might require this or want to add or subtract names.

    terryjreedy commented 8 years ago

    Our messages crossed. See msg269266 for fuller response.

    ncoghlan commented 8 years ago

    Right, I think we need to separate two questions here:

    1. Making a GUI for pip available *at all*. At the moment, there isn't really one, so even if instructors want to offer one, they can't without writing it first. That's a reported PyPA issue here: https://github.com/pypa/packaging-problems/issues/57

    2. Whether to endorse and bundle such a GUI with CPython, and integrate it with IDLE.

    I think the first aspect is an unequivocally good idea, and I'd encourage Upendra to head down that path to make it available to folks that are interested in having a cross-platform GUI for working with pip packages, regardless of what happens on the CPython integration front.

    For the second point, I'll note that Donald was a trusted *PyPA* developer prior to our collaboration on PEP-453 - he became a CPython core developer specifically to maintain ensurepip.

    I believe that "cross-community collaboration" model would also be a good fit for integration of a pip GUI distributed that was otherwise distributed via PyPI - we'd want core developers, or folks trusted by core developers, reviewing and maintaining the PyPI package, without necessarily pulling it directly into the CPython maintenance workflows.

    ncoghlan commented 8 years ago

    As far as the security questions go, yes, this is one of the benefits of education focused stributions like the Raspbian used on the Raspberry Pi - they can make extra packages available without introducing kids to the idea of downloading and running arbitrary components from the internet before they're adequately equipped to judge the risks of what they're running.

    That's the other big reason I think the PyPI approach will be valuable - by offering educators something that's potentially useful to them (a pip GUI), you'd hopefully be able to attract more direct feedback around how to make it ever more suitable to that use case.

    c6bec776-4609-40f6-b75b-fd5d2778bdf3 commented 8 years ago

    In ref. to msg269264:

    @Terry, I am ready to maintain this project. But for as backup is concerned I really don't know a lot of people and where should I look for them.

    In reference to msg269038:

    I was more engrossed in reading through other messages related to pip gui that I forgot to clarify about it.

    For pip install and uninstall command, I have used the pip.main() instead of subprocess module. There were two reasons for it ( what I thought):

    1. More reliable, because I thought the output on CLI may change more frequently than arguments in pip.main(). (I think may be this assumption is wrong).

    2. I figured out a way to clear pip loggers ( which caused to produce duplicate output ). I found it on a issue in pip Github repo :

    Adding one line of : pip.logger.consumers = [] in runpip(). It cleared the pip loggers responsible for producing duplicate output. ( due to this I liked pip.main(). The only troubling part about it was duplicate output )

    This is just what I thought. I can very easily switch to subprocess module. Very less changes will be required in the code.

    c6bec776-4609-40f6-b75b-fd5d2778bdf3 commented 8 years ago

    I am trying something similar to BrownTruck in issue : https://github.com/pypa/pip/pull/3733

    I tried to execute pip.main('install','-U',\<some_package>) from a thread. I got a similar error :

    Traceback (most recent call last):
      File "/usr/local/lib/python3.4/dist-packages/pip/commands/install.py", line 299, in run
        requirement_set.prepare_files(finder)
      File "/usr/local/lib/python3.4/dist-packages/pip/req/req_set.py", line 370, in prepare_files
        ignore_dependencies=self.ignore_dependencies))
      File "/usr/local/lib/python3.4/dist-packages/pip/req/req_set.py", line 476, in _prepare_file
        with indent_log():
      File "/usr/lib/python3.4/contextlib.py", line 59, in __enter__
        return next(self.gen)
      File "/usr/local/lib/python3.4/dist-packages/pip/utils/logging.py", line 34, in indent_log
        _log_state.indentation += num
    AttributeError: '_thread._local' object has no attribute 'indentation'

    There is some problem with threading.local() in pip.utils.logging. Can anyone please suggest a workaround for it. It is necessary for me to use threads other than the main GUI thread to update text. I need to update text and do long processes ( like searching for results using pip search command or installing or uninstalling) when someone presses a button.

    When I don't use threading to update text, the GUI text is updated only after the callback returns.

    c6bec776-4609-40f6-b75b-fd5d2778bdf3 commented 8 years ago

    Refer to : msg269285

    This is the code :

    ...............

    from pip_tkinter.utils import pip_install_from_PyPI
    
            curr_item = self.multi_items_list.scroll_tree.focus()
            item_dict = self.multi_items_list.scroll_tree.item(curr_item)
            selected_module = item_dict['values'][0]
            self.controller.debug_bar.config(
                text='Installing package {}...Please wait'.format(selected_module))
    
            self.install_queue = queue.Queue()
            self.install_thread = threading.Thread(
                target=pip_install_from_PyPI,
                kwargs={
                    'package_args':selected_module,
                    'thread_queue':self.install_queue})
            self.install_thread.start()
            self.after(100, self.check_install_queue)
    terryjreedy commented 8 years ago

    Upendra, with respect to the error installing timingwheel, msg268983, that looks like a bug in timingwheel. Report it to the pip or timingwheel list or tracker. I ran the command normally and got the same exception, with less noise. It is not a problem with using main.

    C:\Programs\Python36>python -m pip install -U timingwheel
    Collecting timingwheel
      Downloading timingwheel-0.4.tar.gz
        Complete output from command python setup.py egg_info:
        Traceback (most recent call last):
          File "<string>", line 1, in <module>
          File "C:\Users\Terry\AppData\Local\Temp\pip-build-ypf8yppj\timingwheel\setup.py", line 3, in <module>
            from timingwheel import version
          File "C:\Users\Terry\AppData\Local\Temp\pip-build-ypf8yppj\timingwheel\timingwheel\__init__.py", line 1, in <module>
            from timingwheel import BaseWheel, TimingWheel
        ImportError: cannot import name 'BaseWheel'
    \----------------------------------------

    Command "python setup.py egg_info" failed with error code 1 in C:\Users\Terry\AppData\Local\Temp\pip-build-ypf8yppj\timingwheel\

    terryjreedy commented 8 years ago

    With respect to threading: I have close to 0 experience. I know that tkinter is supposed to be 'thread-safe' (Martin Loewis) and that people have real problems mixing threads with tkinter. If you can create a minimal complete verifiable example (SO MCVE), try asking on python-list, or SO, so you can reach people who do know threading.

    I suppose you can already guess my thought: for a first draft, block and let users wait. For anything I have done with pip, that would not be very long.

    I have done preliminary successful experiments with integrating asyncio and tkinter loop. When I posted to the python-ideas thread on the subject, I got no response, so I moved on. Perhaps I should work on it some more, but I am also busy with IDLE.

    c6bec776-4609-40f6-b75b-fd5d2778bdf3 commented 8 years ago

    For using threading with Tkinter there are two options : either to use threading or asyncio ( coroutines ). Because asyncio is easier as compared to threading, therefore I would like to use it.

    But, coroutines are available only in Python >=3.5. Therefore should we target all Python 3 users or Python>=3.5 users?

    c6bec776-4609-40f6-b75b-fd5d2778bdf3 commented 8 years ago

    @Terry,

    I am switching between different frames using frame.tkraise() method in order to switch the user attention.

    Now, if I want to test which frame is at top what should I check for or which parameter I should check.

    terryjreedy commented 8 years ago

    Window stacking order can be queried with tcl calls: https://stackoverflow.com/questions/10343759/determining-what-tkinter-window-is-currently-on-top/10391659#10391659. I do not if there is the equivalent for frames. Note that uses can change window stack order, hence the need for a query, but not frame stack order.

    https://stackoverflow.com/questions/35690249/tkinter-is-it-possible-to-change-the-stacking-order-of-placed-frames claims that frames are initially stacked in order created. Verify if you want. After that, keep track of how you change the order.