-
Notifications
You must be signed in to change notification settings - Fork 10
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
feat: add abstract app module and refactor config #206
base: main
Are you sure you want to change the base?
feat: add abstract app module and refactor config #206
Conversation
Works on all three UIs offers a generic function to ask a question that platform independent. If the user fails to offer a response, the installer will terminate. In the GUI this still works, however it may not be desirable to prompt the user for each question. So long as we don't attempt to access the variable before the user has had a chance to put in their preferences it will not prompt them Changed the GUI to gray out the other widgets if the product is not selected. start_ensure_config is called AFTER product is set, if it's called before it attempts to figure out which platform it's on, prompting the user with an additional dialog (not ideal, but acceptable)
8042817
to
82d0c94
Compare
ou_dedetai/tui_app.py
Outdated
|
||
def get_version(self, dialog): | ||
self.product_e.wait() | ||
question = f"Which version of {config.FLPRODUCT} should the script install?" # noqa: E501 | ||
question = f"Which version of {self.conf.faithlife_product} should the script install?" # noqa: E501 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To my knowledge, I need to wait on self.product_e.wait() as if not, the TUI charges through the installer process; should this way now be handled by the TUI's implementation of app._hook_product_update()?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Surprisingly enough it didn't charge through - it waited for the question to be answered before going to the next screen probably because we have two main threads in the TUI:
- The input processing thread (main, don't block me)
- When events are triggered they're spawned on a new thread (this is the installation thread). Since the ask call is blocking, this gets stopped while the user is inputting their value (which the processing is done on the first thread)
Then if you notice in TUI's ask implementation there is an event wait to communicate between the two threads
Comments on DemonstrationThanks for this! The framework you have here looks great. The TUI is a Frankenstein of my own thought, so anything that simplifies it and makes it less bloated is great—I do like seeing lines of code removed. As mentioned to Nate, I see tui_screen.py as a library that could feasibly be used outside of our project, so also the same with certain aspects of the display code in tui_app.py, say lines 1–350. LogosLinuxInstaller/ou_dedetai/tui_app.py Lines 1 to 350 in 0def2e5
(Given the hope of simplifying our queue/event code, many of these lines could be squashed/removed.) The task processor code in tui_app and in gui_app could also be brought into the abstract class. I would also hope that the choice_processor code in tui_app.py might find its way there. @n8marti has handled the GUI, so I will leave that to him. (Given your review, you might be the third person we've needed: someone who understands both the TUI and the GUI, haha.) I originally tried to code for the various UIs particularly in msg.py. This eventually got away from me and found its way back in msg.status(). There's likely a fair chunk of room for messaging to be brought into the abstract class given how much code is relatively unused in that module and how msg.status is accounting for each UI. The abstract class lets us do that without all the if/elif. General CommentsI had also tried this in installer, but the GUI needed enough odds and ends to be separated at the time. Now that we have our working base, I think it'd be great to try to reel in the various odd bits and make these more united, all in the spirit of #147. As mentioned elsewhere, this would also be helpful for #2 and #87, and for drastically improving code reusability/maintenance. Given your further comments about the suggested config changes, that would go well with #187. While I think all these issues are too much for one PR, I do think we could lump #147 and #187 into this PR's scope as a way of refactoring our code. Thinking Out LoudThis framework might enable me to further simplify the various calls within tui_app to tui_screen. tui_curses and tui_dialog are fairly static at this point. There are some parts of tui_screen that need to be abstracted, particularly in the console_screen. I've also considered changing the tui_screen class to utilize a method of the tui_app that flags the need for tui_app.refresh to be run again. |
Am I understanding correctly that in the GUI the user will see the "Choose which FaithLife product" window first, then they will see the GUI installer window, with all the options pre-populated with defaults? So then they can make adjustments, or just click "Install"? |
Not quite, I liked the current GUI flow so much I didn't want to modify it. Before and after this PR it behaves the same, however if someday in the future there was a code path that tried to retrieve the faithlife product before the prompt showed up, it would open a separate dialog asking that question. In the GUI's case we probably want to avoid this, however the code will handle that case and avoid an error if such a code path were to exist in the future. |
Okay, I'm happy with that. |
If you @ctrlaltf24 can take care of the potential merge conflicts, then I'll look it over again for approval. |
Expanding usage of this framework.... |
and migrate APPDIR_BINDIR and WINESERVER_EXE
I've always liked picking an auto-formatter and just letting it do it's thing rather than trying to have humans being consistent with a styling. How about https://docs.astral.sh/ruff/ ? |
Co-authored-by: n8marti
want to initialize logging as early as possible on the offchance reading config fails
fixed
See comment #206 (comment)
Fixed, good catch |
I like the idea of the Installer window actually just being an Installer
_configuration_ window, whose only job is to let the user select
non-default config. Then all the statusing and progressing could just
happen in the Control Panel window. But in that case I'd suggest a separate
button in the CP called "Options" or "Config" somewhere near the "Install"
button. It would disappear once the app is installed. That's where my
thinking leads to, anyway.
…On Fri, Dec 6, 2024, 9:12 PM Nathan Shaaban ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In ou_dedetai/gui.py
<#206 (comment)>
:
> - # Status area.
- s1 = Separator(self, orient='horizontal')
- self.statusvar = StringVar()
- self.status_label = Label(self, textvariable=self.statusvar)
- self.progressvar = IntVar()
- self.progress = Progressbar(self, variable=self.progressvar)
-
We have a couple options:
- Close the installer window after it started the install (and gray
out the install button), showing the progress on the control window. This
may be useful if we ever have an "express install button" where the user
doesn't select any preferences, it just goes with the default
- Make it look how it did before, using a conditional to figure out
whether or not to send status messages to the installer window or control
window
—
Reply to this email directly, view it on GitHub
<#206 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AFSOCVI7FBNWKRE6GVLMD2D2EIAMPAVCNFSM6AAAAABQQOILYSVHI2DSMVQWIX3LMV43YUDVNRWFEZLROVSXG5CSMV3GSZLXHMZDIOBVG43TMMRUGU>
.
You are receiving this because you were mentioned.Message ID:
***@***.***
.com>
|
I responded to Nathan's comment above and to make sure it isn't lost between different locations, if we want the GUI to have an install button and a second button, perhaps it should be Install (no options, just defaults) and Advanced Install, but it sounds like six of one and half a dozen of another with your suggestion, Nate. |
I'm all for automation. |
and moved faithlife products/versions to a constants
On a good day: 1Mbps down, 500Kbps up
On a bad day: 128Kbps down, 64Kbps up
Either way, though, we have very high latency. Usually 1-4 seconds for a
successful ping to a public IP.
In my test yesterday the GUI froze for at least 5, maybe 10 seconds waiting
for the network activity to finish.
…On Fri, Dec 6, 2024, 11:31 PM Nathan Shaaban ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In ou_dedetai/gui_app.py
<#206 (comment)>
:
> + # FIXME: consider what to do if network is slow, we may want to do this on a
+ # Separate thread to not hang the UI
how slow are we talking for your internet @n8marti
<https://github.com/n8marti> ?
Doing this on another thread introduces a case (that was completely
removed by this refactor) where the install isn't ready immediately. rn if
you load this dialog you can hit install at once, no branches, no installs
not ready yet, etc. I'm not sure the delay is worth loosing that
—
Reply to this email directly, view it on GitHub
<#206 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AFSOCVPQN24AC4VAMFN7TNL2EIQSHAVCNFSM6AAAAABQQOILYSVHI2DSMVQWIX3LMV43YUDVNRWFEZLROVSXG5CSMV3GSZLXHMZDIOBWGAZDEMRTGE>
.
You are receiving this because you were mentioned.Message ID:
***@***.***
.com>
|
Hmm the network cache should make this problem less bad. I could spawn a thread as soon as the GUI launches that populates all these defaults, so the user wouldn't be aware of the latency. Would that be an acceptable solution? Trying not to allow the case where the installer window is shown and some values may not be initialized yet - would rather not have the branching |
All we're really needing is to get the Logos/Verbum release list, right?
Why not show the CP window, but then deactivate the Install button until
the network activity is done?
…On Sat, Dec 7, 2024, 11:50 AM Nathan Shaaban ***@***.***> wrote:
On a good day: 1Mbps down, 500Kbps up On a bad day: 128Kbps down, 64Kbps
up Either way, though, we have very high latency. Usually 1-4 seconds for a
successful ping to a public IP. In my test yesterday the GUI froze for at
least 5, maybe 10 seconds waiting for the network activity to finish.
Hmm the network cache should make this problem less bad.
I could spawn a thread as soon as the GUI launches that populates all
these defaults, so the user wouldn't be aware of the latency. Would that be
an acceptable solution?
Trying not to allow the case where the installer window is shown and some
values may not be initialized yet - would rather not have the branching
—
Reply to this email directly, view it on GitHub
<#206 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AFSOCVJY4HMAAJAOZY3VRHT2ELHF7AVCNFSM6AAAAABQQOILYSVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDKMRVGA3DSMZUHA>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
My hesitation is I'd rather not end up with a case where the user gets App.ask'ed a question. If faithlife_produce_version isn't set early, it will be easier to accidentally introduce code paths that would individually prompt the user for this value. That would happen if anywhere in the app the faithlife_produce_version is accessed before it's set. By blocking we're assured by the time the UI displays this value is set. Otherwise if it's not blocked we'd have to think about the case where it isn't set yet in at least part of the GUI. |
It's a nice improvement in the GUI with the [Install] [Advanced install] options. Not sure about the look of it, but I don' t have any better ideas at this point. I just did a completely clean test run: no config, no network cache file, no existing LogosBible10 folder. It failed with this result:
And here's the Exception thrown in the terminal:
I'm not sure which is the cause and which are symptoms, but it seems the "auto-config" set the wine binary as the appimage in my Downloads folder (rather than one to be copied into LogosBible10), the appimage was never copied into LogosBible10, but the symlinks were still created in LogosBible10 as if the appimage were there, but then the installer looked for the symlinks in the Downloads folder, which were not there:
|
Another issue we need to figure out is orphaned mounted appimages. I was suspicious, and I found dozens of them in
This could very well pre-date the refactor, but it still needs to be sorted out. I'll more into it tonight if I have time. |
One minor change: There's a typo in this status message: "Setting Font Smooting to RGB..." should say "Smoothing" |
Also properly parse legacy ENVs as bools Also dump other configs
in the case .vscode is a symlink
Should be fixed, try again
likely independent, not addressing in this PR |
recently added a full config hook in installer.install, these separate ones are no longer needed
gray out install buttons until faithlife product versions downloads (so we know which one to install)
- de-couple wine_binary_files from faithlife_product_version - populate product release immediately if possible
Code ready for review, everything should be function, may be a couple lingering bugs, planning to do more testing. Not planning on making any more changes that aren't bug fixes
Improvements
Type Enforcement
Types are checked using a static analysis tool (mypy) to ensure nothing is None when it shouldn't be (or a Path when it should be a string)
Network Caching
All network requests are cached
Tested via:
Config Enforcement
Wrapper struct to ensure all config variables are set, if not the user is prompted (invalid answers are prompted again).
Additionally configuration hooks were added so all UIs can refresh themselves if the config changes underneath them. A reload function has also been added (TUI only as it's for power users and offers no benefit to the cli)
Config Format Change
In the interest of consistency of variable names, the config keys have changed. Legacy values will continue to be read (and written). New keys take precedence. This new config can be copied to older versions of the installer and it should (mostly) work (not aware of any deficiencies however downgrading is hard to support). Legacy paths are moved to the new location.
Graphical User Interface (tinker)
Ensured that the ask function was never called. We want to use the given UI, as it's prettier. However if the case should arise where we accidentally access a variable before we set it, the user will see a pop-up with the one question. Data flow has been changed to pull all values from the config, it no longer stores copies. It also now populates all drop-downs in real-time as other drop-downs are changed, as a result there was no longer any need for the "Get EXE" and "Get Release List" buttons, so they were removed. Progress bar now considers the entire installation rather than "completing" after each step.
Terminal User Interface (curses)
Appears the same as before from the user's standpoint, however now there is a generic ask page, greatly cutting down on the number of queues/Events. There may be some more unused Queues/Events lingering, didn't see value in cleaning them up.
Command Line Interface
Prompts appears the same as before, progress bar is now prepended to status lines
Closing Notes
One goal of this refactor was to keep the code from being understood by someone who is already familar with it. There is a couple new concepts, the abstract base class, reworked config, and network cache, but the core logic of how it works remains unchanged. If something isn't clear please ask.
Screenshots
GUI Sample
TUI Sample
CLI Sample
GUI behavior
Before Product is selected
After product is selected
Fixes: #147, #234, #35, #168, #155