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

Conquer the land of arguing snakes #788

Closed

Conversation

pawamoy
Copy link

@pawamoy pawamoy commented Feb 3, 2022

Implements #519 (draft)

Original PR title is "Add CLI to run any Python program based on argparse", feel free to put it back 😂

  • You're opening this PR against the current release branch
  • Works on both Python 2.7 & Python 3.x
  • Commits have been squashed and includes the relevant issue number
  • Pull request description contains link to relevant issue or detailed notes on changes
  • This must include example code demonstrating your feature or the bug being fixed
  • All existing tests pass: they don't, I have errors like this:
    • AttributeError: module 'wx' has no attribute 'TaskBarIcon'
  • Your bug fix / feature has associated test coverage
  • README.md is updated (if relevant)

So, this PR basically adds a CLI to Gooey, allowing users to run any argparse-based Python program from the command line. I personally think it's awesome. You still need to pass the module path and function name as module.path:function_name because I couldn't find a way yet to infer it from the console script name. Indeed, the console script name can be different than the library name. We could try and read the script itself, as it's quite standardized, to find the actual function to import, but it's not bullet-proof either: on Windows such scripts are written as .exe, and I don't think it's easy to read. Maybe there's a way with importlib.metadata.

I went with a simple sys.argv, because using argparse in the CLI felt a bit too... recursive? But after all, why not, this would allow to run Gooey on itself, which is kind of awesome too. Imagine typing just "gooey" in the terminal: it opens a simple window with a single input, and a list of detected scripts/libraries/entrypoints (not sure how to do that yet). You type one, hit enter, and a new window pops up, this time with the selected program options and stuff.

@pawamoy pawamoy force-pushed the issue-519-run-any-program branch from da7ef80 to 50583cd Compare February 3, 2022 11:16
gooey/application.py Outdated Show resolved Hide resolved
gooey/application.py Outdated Show resolved Hide resolved
@pawamoy
Copy link
Author

pawamoy commented Feb 3, 2022

# in gooey's venv
pip install aria2p
gooey aria2p.cli.main:main
# gooey'd aria2p window pops up
Peek.2022-02-03.12-37.mp4

@chriskiehl
Copy link
Owner

+100 points for the sweet demo video!

I did a bad job of keeping the contributing document updated (Whoops!). 1.0.9 was abandoned in favor of the now released 1.2.0. A bunch of stuff was moved around, so you'll need to target that branch instead (sorry!).

The application.py file, for instance, is now bootstrap.py and lives in the main gui module. There's also a bunch of lingering dead code which you'll have to watch out for, but if you update the PR we can work through any dragons caused by my laziness.

@pawamoy pawamoy changed the base branch from 1.0.9-release to 1.2.1-release February 4, 2022 08:34
@pawamoy pawamoy changed the base branch from 1.2.1-release to 1.0.9-release February 4, 2022 08:34
@pawamoy
Copy link
Author

pawamoy commented Feb 4, 2022

Damn, it was just there (1.2.1-release) and I missed it somehow 😑
No problem, I'll see if I can rebase without too much trouble 🙂

@pawamoy pawamoy force-pushed the issue-519-run-any-program branch from 50583cd to 6787cac Compare February 4, 2022 16:39
@pawamoy pawamoy changed the base branch from 1.0.9-release to 1.2.1-release February 4, 2022 16:41
@pawamoy
Copy link
Author

pawamoy commented Feb 4, 2022

OK, branch stuff looks good.

@pawamoy
Copy link
Author

pawamoy commented Feb 6, 2022

I'm able to find the function to import based on the script name thanks to importlib.metadata.entry_points.
However the window does not pop up anymore since I rebased on release 1.2.1. Did something changed? Is there a method I need to call on the Gooey instance?

gooey/cli.py Outdated Show resolved Hide resolved
args = args or sys.argv[1:]
if not args:
# without args we assume we want to run gooey on gooey itself
# TODO: rewrite using argparse
Copy link
Author

@pawamoy pawamoy Feb 6, 2022

Choose a reason for hiding this comment

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

Running Gooey on itself requires rewriting this function with an argparse parser. Let me know if this is something you'd like 🙂

Copy link
Owner

Choose a reason for hiding this comment

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

I'll leave it up to you ^_^

I'd be fine going sans additional configuration for the initial release of this -- let it "bake" a bit and see if people need the functionality. On the flip side, if you want to throw a parser in there so people can control things that's fine, too. You may be able to even generate a options for all of the params directly from the type definition by looking through its __annotations__ (in theory).

gooey/cli.py Show resolved Hide resolved
@pawamoy pawamoy marked this pull request as ready for review February 6, 2022 12:29
gooey/cli.py Outdated Show resolved Hide resolved
import sys
from importlib import import_module
try:
from importlib.metadata import entry_points
Copy link
Owner

Choose a reason for hiding this comment

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

Explain a bit about these different versions?

Copy link
Author

Choose a reason for hiding this comment

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

importlib.metadata is included in the standard library since Python 3.8 only.
Since you support lower versions, the importlib-metadata package is required (it's a simple backport).
Therefore, we must handle both cases in the code since the import path is not the same (importlib.metadata vs. importlib_metadata).

@chriskiehl
Copy link
Owner

Re: tests: Give a pull on 1.2.1 and the tests should run for you. There were previously a lot of broken paths because I'm an IDE scrub and PyCharm was patching all the paths for me.

Re: merging the feature: you'll need to also do the less fun stuff and update the docs ^_^ We should update the Usage section of the README with a small example. Additionally, depending on how much it takes to explain, you can expand the "How To" either later with a specific section in the README, or with lengthier guidance in the docs/ directory.

@pawamoy pawamoy force-pushed the issue-519-run-any-program branch from 9b491c8 to cf77dba Compare February 8, 2022 10:59
@pawamoy
Copy link
Author

pawamoy commented Feb 8, 2022

Better, no path-related errors anymore, though it seems I have an incompatible wxPython/rewx version? All tests fail with AttributeError: module 'wx' has no attribute 'TaskBarIcon'. Any hint? 😄

Here's the full traceback:

Traceback (most recent call last):
  File "/media/data/dev/Gooey/gooey/tests/test_time_remaining.py", line 37, in test_time_remaining_visibility_on_complete
    with instrumentGooey(self.make_parser(), timing_options=testdata) as (app, frame, gapp):
  File "/home/pawamoy/.basher-packages/pyenv/pyenv/versions/3.9.9/lib/python3.9/contextlib.py", line 119, in __enter__
    return next(self.gen)
  File "/media/data/dev/Gooey/gooey/tests/harness.py", line 30, in instrumentGooey
    app, frame = bootstrap._build_app(buildspec, app)
  File "/media/data/dev/Gooey/gooey/gui/bootstrap.py", line 42, in _build_app
    gapp2 = render(create_element(RGooey, merge(build_spec, imagesPaths)), None)
  File "/media/data/dev/Gooey/.venv/lib/python3.9/site-packages/rewx/core.py", line 247, in render
    return element['type'].render_component(element, parent)
  File "/media/data/dev/Gooey/.venv/lib/python3.9/site-packages/rewx/core.py", line 166, in render_component
    instance.base = render(instance.render(), parent)
  File "/media/data/dev/Gooey/.venv/lib/python3.9/site-packages/rewx/core.py", line 220, in render
    instance = mount(element, parent)
  File "/media/data/dev/Gooey/.venv/lib/python3.9/site-packages/rewx/dispatch.py", line 26, in wrapper
    return registry[element['type']](element, parent)
  File "/media/data/dev/Gooey/.venv/lib/python3.9/site-packages/rewx/widgets.py", line 85, in frame
    return update(element, instance)
  File "/media/data/dev/Gooey/.venv/lib/python3.9/site-packages/rewx/dispatch.py", line 26, in wrapper
    return registry[element['type']](element, parent)
  File "/media/data/dev/Gooey/.venv/lib/python3.9/site-packages/rewx/widgets.py", line 103, in frame
    frame.taskbarIcon = wx.TaskBarIcon(iconType=wx.adv.TBI_DOCK)
AttributeError: module 'wx' has no attribute 'TaskBarIcon'

Do I have an incompatible system lib? API docs say TaskBarIcon is in wx.adv: https://docs.wxpython.org/wx.adv.TaskBarIcon.html?highlight=taskbaricon#wx.adv.TaskBarIcon, and indeed I can import it from there.

@chriskiehl
Copy link
Owner

Do I have an incompatible system lib?

Nay, that was a bug in rewx. I pushed a fix. If you upgrade the dep things should start working again.

@pawamoy
Copy link
Author

pawamoy commented Feb 9, 2022

Still no luck 😅

% python -m unittest
.Traceback (most recent call last):
  File "/media/data/dev/Gooey/.venv/lib/python3.9/site-packages/wx/core.py", line 2217, in OnPreInit
    self.InitLocale()
  File "/media/data/dev/Gooey/gooey/tests/__init__.py", line 60, in InitLocale
    locale.setlocale(locale.LC_ALL, lang)
  File "/home/pawamoy/.basher-packages/pyenv/pyenv/versions/3.9.9/lib/python3.9/locale.py", line 610, in setlocale
    return _setlocale(category, locale)
locale.Error: unsupported locale setting
[1]    158722 segmentation fault (core dumped)  python -m unittest

I'm on Arch by the way :trollface:

@pawamoy
Copy link
Author

pawamoy commented Feb 9, 2022

Maybe you could setup a test suite in GitHub CI in the meantime.

@pawamoy
Copy link
Author

pawamoy commented Feb 14, 2022

Something like this:

# .github/workflows/ci.yml
name: ci

jobs:
  tests:
    strategy:
      matrix:
        os:
        - ubuntu-latest
        - macos-latest
        - windows-latest
        python-version:
        - "3.7"
        - "3.8"
        - "3.9"
        - "3.10"
        - "3.11-dev"

    runs-on: ${{ matrix.os }}

    steps:
    - name: Checkout
      uses: actions/checkout@v2    

    - name: Set up Python
      uses: actions/setup-python@v2
      with:
        python-version: ${{ matrix.python-version }}

    - name: Install project and dependencies
      run: pip install .

    - name: Run the test suite
      run: python -m unittest

@pawamoy
Copy link
Author

pawamoy commented Jun 19, 2022

Hi @chriskiehl, how are you? Just coming back to ask you how do you see this going forward? Would you like to setup CI using GitHub Actions? I can send a PR with the contents above, though it'll probably need some tinkering (installing system libs, etc.). Or maybe you'd simply prefer I finish the TODOs so we can merge?

@pawamoy
Copy link
Author

pawamoy commented Apr 14, 2023

Gentle ping 🙂 No obligation to deal with this, just let me know if I should ping you again in a few months, or just close the PR 😄

@pawamoy pawamoy closed this Sep 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants