Skip to content

Add openlifu version check and installation button in login module#561

Merged
ebrahimebrahim merged 4 commits into
mainfrom
544_install_openlifu
Apr 10, 2026
Merged

Add openlifu version check and installation button in login module#561
ebrahimebrahim merged 4 commits into
mainfrom
544_install_openlifu

Conversation

@sadhana-r

@sadhana-r sadhana-r commented Mar 13, 2026

Copy link
Copy Markdown
Contributor

Closes #544

  • The install python requirements button is always enabled.
  • The button text updates to indicate whether openlifu is installed, and what version is required
  • If openlifu is not installed, entering the login module will prompt the user automatically to install openlifu since it is required for initializing default user accounts.
  • If openlifu is installed, but is not the latest version, the user is not automatically prompted to update openlifu, but the button and status icon indicate that the latest version is not installed.

Todo:

  • Confirm that the changes to the user account settings don't break things in the custom app.

@ebrahimebrahim ebrahimebrahim self-requested a review April 2, 2026 22:02

@ebrahimebrahim ebrahimebrahim left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This looks great to me! It works very well

I agree that we should check that nothing broke int he custom app before merging.

BTW did the login module always import openlifu on entry? That creates a situation where you can never validly get to the install button in the first place if you didn't already have some version of openlifu installed.

Comment on lines +67 to +74
def get_required_openlifu_version() -> "Optional[str]":
"""Return the required openlifu version pinned in
python-requirements.txt, or None."""
requirements_path = Path(__file__).parent / 'Resources/python-requirements.txt'
for line in requirements_path.read_text().splitlines():
if line.startswith('openlifu=='):
return line.split('==', 1)[1].strip()
return None

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I am thinking about what would happen when someone puts a git+... sort of requirement for openlifu, as we often do while testing unreleased versions of openlifu. I think it's okay to not support version checking in those cases, since they are debug cases, but should the version check auto-pass or auto-fail? Right now I think it autopasses because this would return None. Maybe that is fine, just brinign up the question.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good point - I didn't consder that situation. You're right, right now it auto-passes so the user isn't notified that a dev version needs to be installed. Currently the version check only fails if openlifu is not installed or it is the wrong released version.

I'm going to push a commit that handles the dev situation such that it auto-fails/notifies the user - it's an easy check and doesn't break anything else.
Screenshot 2026-04-03 091222

While testing this, I noticed that there is potentially an issue in the current main branch of openlifu (OpenwaterHealth/openlifu-python@9f17b94). When installed, openlifu.util.assets is not recognized. But I didn't get this error with an older commit (pre v0.18). Do you mind testing it on your end?

@ebrahimebrahim

ebrahimebrahim commented Apr 2, 2026

Copy link
Copy Markdown
Contributor

BTW did the login module always import openlifu on entry? That creates a situation where you can never validly get to the install button in the first place if you didn't already have some version of openlifu installed.

Below is a suggested fix from a claude conversion, which I think I agree with but see if you think there's an issue ... there are few cases to consider: no openlifu, openlifu but no database, database but no users in it, ....

We can do it in this PR or we can do it later, all fine.
Just raising this now because we are sticking the install button into the login module in this PR; it may make sense to eliminate the circularity.

(ai generated content)

Here's the issue and proposed fix:

Problem: OpenLIFULogin.setup() calls _initDefaultUsers() which calls openlifu_lz() to create User objects. This triggers the install prompt before the user can reach the Home module's install button — a catch-22.

Proposed fix: Lazy-init the default users. Skip _initDefaultUsers() in setup() when openlifu isn't installed, and add a guard method:

def _ensureDefaultUsers(self):
    if self._default_anonymous_user is None and python_requirements_exist():
        self._initDefaultUsers()

Call _ensureDefaultUsers() at the start of methods that use the default users (updateWidgetLoginState, logout, onUserAccountModeClicked, onDatabaseChanged). In setup(), wrap the relevant lines:

if python_requirements_exist():
    self._initDefaultUsers()
    self.logic.active_user = self._default_anonymous_user

This is safe because before openlifu is installed, there's no database and no login — the default users serve no purpose. Once the user installs openlifu via Home and navigates back or connects a database, _ensureDefaultUsers() will initialize them on demand.

For the custom app, openlifu is always bundled so this path doesn't apply. If desired, the custom app could add an early fatal error if openlifu isn't importable, rather than silently breaking.

@sadhana-r

Copy link
Copy Markdown
Contributor Author

I agree that we should check that nothing broke int he custom app before merging.

Custom app seems to work as expected
Screenshot 2026-04-03 084811

@sadhana-r

Copy link
Copy Markdown
Contributor Author

BTW did the login module always import openlifu on entry? That creates a situation where you can never validly get to the install button in the first place if you didn't already have some version of openlifu installed.

Yes, this has always been the case! Before it was in the __init__ function of the login module so
couldn't even load the module without installing openlifu. But it hasn't really been an issue because the user is automatically prompted to install openlifu as soon as they open the module. So there was never a sitation where you are in the login module, with openlifu not installed.

The claude suggested fix works well for handling the default users, but I realized the other issue is that OpenLIFUSonicationControlLogic's init function calls openlifu_lz() (for lifu interface related functions) and the login module currently initializes all of the moduels in self.cacheAllLoginRelatedWidgets().

So we need to either make changes to the sonication control module to avoid openlifu dependency at startup or the login module should not cache the sonication control module if openlifu isn't installed. perhaps better to do this in a separate PR?
Screenshot 2026-04-03 095828

@ebrahimebrahim

Copy link
Copy Markdown
Contributor

The claude suggested fix works well for handling the default users, but I realized the other issue is that OpenLIFUSonicationControlLogic's init function calls openlifu_lz() (for lifu interface related functions) and the login module currently initializes all of the moduels in self.cacheAllLoginRelatedWidgets().

So we need to either make changes to the sonication control module to avoid openlifu dependency at startup or the login module should not cache the sonication control module if openlifu isn't installed. perhaps better to do this in a separate PR?

Yes, agreed, a separate PR. We can put it off indefinitely for now ... it is good that we have a clear explanation of the problem and possible solutions recorded here

@sadhana-r sadhana-r requested a review from ebrahimebrahim April 7, 2026 12:10

@ebrahimebrahim ebrahimebrahim left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks great! One small change and we should be good to merge

Comment thread OpenLIFULib/OpenLIFULib/lazyimport.py Outdated
return False
required_hash = required.split('+g')[-1]
installed_hash = installed.split('+g')[-1]
return installed_hash.startswith(required_hash)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
return installed_hash.startswith(required_hash)
return required_hash.startswith(installed_hash) or installed_hash.startswith(required_hash)

One might be shorter than the other which would make startswith fail; a symmetric comparison like this removes the worry

(commit hashes get truncated to various lengths by various tools/conventions)

@sadhana-r sadhana-r force-pushed the 544_install_openlifu branch from 6eeeeac to ab7d49b Compare April 10, 2026 01:24
@ebrahimebrahim ebrahimebrahim merged commit c8e632b into main Apr 10, 2026
1 check passed
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.

Add openlifu Python library installer/updater to Login module

2 participants