Opened 3 years ago
Last modified 5 months ago
#8238 assigned defect
User-installed bundles interfering with build
Reported by: | Eric Pettersen | Owned by: | Greg Couch |
---|---|---|---|
Priority: | high | Milestone: | 1.11 |
Component: | Build System | Version: | |
Keywords: | Cc: | chimera-programmers | |
Blocked By: | Blocking: | ||
Notify when closed: | Platform: | all | |
Project: | ChimeraX |
Description (last modified by )
When doing "make install" from top ChimeraX directory:
/Applications/Xcode.app/Contents/Developer/usr/bin/make build
if [ ! -d "/Users/pett/src/chimerax/build/lib/python3.9/site-packages/chimerax" ]; then mkdir -p /Users/pett/src/chimerax/build/lib/python3.9/site-packages/chimerax; fi
/Applications/Xcode.app/Contents/Developer/usr/bin/make -C add_charge build
PYTHONNOUSERSITE=1 ../../../ChimeraX.app/Contents/bin/python3.9 -I -m chimerax.core --nogui --exit --safemode --cmd "devel build . exit true "
Unknown bundle name 'ChimeraX-MouseModes' listed in Initializations section for bundle SEQCROW
Traceback (most recent call last):
File
"/Users/pett/src/chimerax/ChimeraX.app/Contents/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/runpy.py",
line 197, in _run_module_as_main
return _run_code(code, main_globals, None,
File
"/Users/pett/src/chimerax/ChimeraX.app/Contents/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/runpy.py",
line 87, in _run_code
exec(code, run_globals)
File
"/Users/pett/src/chimerax/ChimeraX.app/Contents/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-
packages/chimerax/core/main.py", line 1043, in <module>
exit_code = init(sys.argv)
File
"/Users/pett/src/chimerax/ChimeraX.app/Contents/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-
packages/chimerax/core/main.py", line 642, in init
toolshed.init(sess.logger, debug=sess.debug,
File
"/Users/pett/src/chimerax/ChimeraX.app/Contents/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-
packages/chimerax/core/toolshed/init.py", line 1376, in init
_toolshed = Toolshed(*args, kw)
File
"/Users/pett/src/chimerax/ChimeraX.app/Contents/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-
packages/chimerax/core/toolshed/init.py", line 365, in init
self.reload(logger, check_remote=check_remote,
rebuild_cache=rebuild_cache, _session=session)
File
"/Users/pett/src/chimerax/ChimeraX.app/Contents/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-
packages/chimerax/core/toolshed/init.py", line 424, in reload
self._installed_bundle_info.load(logger, cache_file=cache_file,
File
"/Users/pett/src/chimerax/ChimeraX.app/Contents/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-
packages/chimerax/core/toolshed/installed.py", line 60, in load
self.extend(self._order_bundles(dist_bundle_map, logger))
File
"/Users/pett/src/chimerax/ChimeraX.app/Contents/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-
packages/chimerax/core/toolshed/installed.py", line 248, in _order_bundles
explicit_reverse_order.setdefault(dist_key, set()).add(d.key)
UnboundLocalError: local variable 'dist_key' referenced before assignment
UnboundLocalError: local variable 'dist_key' referenced before assignment
File
"/Users/pett/src/chimerax/ChimeraX.app/Contents/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-
packages/chimerax/core/toolshed/installed.py", line 248, in _order_bundles
explicit_reverse_order.setdefault(dist_key, set()).add(d.key)
_See log for complete Python traceback._
make[4]: * [wheel] Error 1
make[3]: * [add_charge.build] Error 2
make[2]: * [install] Error 2
make[1]: * [bundles.install] Error 2
make: * [install] Error 2
Change History (22)
comment:1 by , 3 years ago
comment:2 by , 3 years ago
Milestone: | → 1.6 |
---|
comment:3 by , 3 years ago
Milestone: | 1.6 → 1.7 |
---|---|
Owner: | changed from | to
Zach, please take a look at this. Also check if PYTHONNOUSERSITE=1 is still needed.
comment:4 by , 3 years ago
Adding "user false" to the command does not help, but this error looks like it happens before we even get into bundle builder. Maybe when we're in safemode we shouldn't look at the user's installed bundles or try to reload the bundle cache. What do you think?
comment:5 by , 3 years ago
Yes, that's a good idea. That could be part of the safemode behavior. As long as we can still install/update "user" bundles, we're good.
comment:6 by , 3 years ago
What's happening is that during main, we're initializing a Toolshed instance but not passing it safe_mode until a couple lines later in the call to ts.bootstrap_bundles()
I added safe_mode to Toolshed's initializer, and was able to build add_charge, but during our build process we have BUILD_AND_INSTALL defined, so when we try to install it we run into the next problem: if we use safe_mode as a flag for whether or not to build the bundle cache, then when we go to install a bundle it's not there for ts.find_bundle.
So we can return None if we're in safe_mode, but then there's nothing to set the install timestamp on. And if we guard that behind safemode, we're back to dist_key referenced before assignment when we go to install it except this time the traceback is in toolshed_utils:
Distribution is in ./dist/ChimeraX_AddCharge-1.5.10-py3-none-any.whl Installing bundle Executing: toolshed install ./dist/ChimeraX_AddCharge-1.5.10-py3-none-any.whl userOnly false noDeps true Errors may have occurred when running pip: pip standard error: --- [notice] A new release of pip is available: 23.0 -> 23.0.1 [notice] To update, run: /Users/zjp/git/rbvi/ChimeraX/ChimeraX.app/Contents/bin/python3.9 -m pip install --upgrade pip --- pip standard output: --- Looking in indexes: https://pypi.org/simple, https://cxtoolshed.rbvi.ucsf.edu/pypi/ Processing ./dist/ChimeraX_AddCharge-1.5.10-py3-none-any.whl ChimeraX-AddCharge is already installed with the same version as the provided wheel. Use --force-reinstall to force an installation of the wheel. --- No bundles were installed Unknown bundle name 'ChimeraX-MouseModes' listed in Initializations section for bundle SEQCROW Traceback (most recent call last): File "/Users/zjp/git/rbvi/ChimeraX/src/bundles/core/src/commands/devel.py", line 174, in _run unbound_method(bb, *args, **kw) File "/Users/zjp/git/rbvi/ChimeraX/ChimeraX.app/Contents/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/chimerax/bundle_builder/bundle_builder.py", line 154, in make_install run(session, cmd) File "/Users/zjp/git/rbvi/ChimeraX/src/bundles/core/src/commands/run.py", line 38, in run results = command.run(text, log=log, return_json=return_json) File "/Users/zjp/git/rbvi/ChimeraX/src/bundles/core/src/commands/cli.py", line 2897, in run result = ci.function(session, **kw_args) File "/Users/zjp/git/rbvi/ChimeraX/src/bundles/core/src/commands/toolshed.py", line 301, in toolshed_install ts.install_bundle(bundles, logger, **kw) File "/Users/zjp/git/rbvi/ChimeraX/src/bundles/core/src/toolshed/__init__.py", line 919, in install_bundle _install_bundle(self, bundle, logger, per_user=per_user, reinstall=reinstall, session=session, no_deps=no_deps) File "/Users/zjp/git/rbvi/ChimeraX/ChimeraX.app/Contents/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/chimerax/toolshed_utils/__init__.py", line 256, in _install_bundle changes = toolshed.reload(logger, rebuild_cache=True, report=True) File "/Users/zjp/git/rbvi/ChimeraX/src/bundles/core/src/toolshed/__init__.py", line 426, in reload self._installed_bundle_info.load(logger, cache_file=cache_file, File "/Users/zjp/git/rbvi/ChimeraX/src/bundles/core/src/toolshed/installed.py", line 60, in load self.extend(self._order_bundles(dist_bundle_map, logger)) File "/Users/zjp/git/rbvi/ChimeraX/src/bundles/core/src/toolshed/installed.py", line 248, in _order_bundles explicit_reverse_order.setdefault(dist_key, set()).add(d.key) UnboundLocalError: local variable 'dist_key' referenced before assignment
It's honestly probably simpler to just temporarily move the user site directory before a build and restore it afterward.
comment:7 by , 2 years ago
Description: | modified (diff) |
---|
During a programmer's meeting I said I would investigate whether this was still a problem. It is still a problem.
comment:8 by , 2 years ago
Owner: | changed from | to
---|
I propose this patch which appears to fix things:
diff --git a/src/bundles/core/src/__main__.py b/src/bundles/core/src/__main__.py index 2fd520add..7b6d80a32 100644 --- a/src/bundles/core/src/__main__.py +++ b/src/bundles/core/src/__main__.py @@ -663,7 +663,8 @@ def init(argv, event_loop=True): toolshed_url = opts.toolshed toolshed.init(sess.logger, debug=sess.debug, check_available=opts.get_available_bundles, - remote_url=toolshed_url, session=sess) + remote_url=toolshed_url, session=sess, + safe_mode = opts.safe_mode) sess.toolshed = toolshed.get_toolshed() if opts.module != 'pip' and opts.run_path is None: # keep bugs in ChimeraX from preventing pip from working diff --git a/src/bundles/core/src/toolshed/__init__.py b/src/bundles/core/src/toolshed/__init__.py index 191509818..6fed418c5 100644 --- a/src/bundles/core/src/toolshed/__init__.py +++ b/src/bundles/core/src/toolshed/__init__.py @@ -287,7 +287,7 @@ class Toolshed: """ def __init__(self, logger, rebuild_cache=False, check_remote=False, - remote_url=None, check_available=True, session=None): + remote_url=None, check_available=True, session=None, safe_mode = False): """Initialize Toolshed instance. Parameters @@ -310,7 +310,7 @@ class Toolshed: self.remote_url = _DefaultRemoteURL else: self.remote_url = remote_url - self._safe_mode = None + self._safe_mode = safe_mode self._repo_locator = None self._installed_bundle_info = None self._available_bundle_info = None @@ -368,7 +368,8 @@ class Toolshed: if (check_available and self._available_bundle_info is not None and self._available_bundle_info.toolshed_url != self.remote_url): self._available_bundle_info = None - self.reload(logger, check_remote=check_remote, rebuild_cache=rebuild_cache, _session=session) + if not self._safe_mode: + self.reload(logger, check_remote=check_remote, rebuild_cache=rebuild_cache, _session=session) from datetime import datetime from ..core_settings import settings now = datetime.now() @@ -419,7 +420,6 @@ class Toolshed: True to check remote server for updated information; False to ignore remote server """ - _debug("reload", rebuild_cache, check_remote) changes = {} if reread_cache or rebuild_cache:
comment:9 by , 23 months ago
Owner: | changed from | to
---|
comment:10 by , 23 months ago
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
Committed the fix today.
comment:11 by , 23 months ago
Resolution: | fixed |
---|---|
Status: | closed → reopened |
comment:12 by , 23 months ago
Instead of simply not reloading in safemode, maybe we should ignore the user directory.
comment:14 by , 23 months ago
Owner: | changed from | to
---|---|
Status: | reopened → assigned |
Can you review this diff, Greg? Now instead of not reloading the cache, in safe mode I just look at the distribution's site-packages directory to see what's installed in safe mode.
diff --git a/src/bundles/core/src/toolshed/__init__.py b/src/bundles/core/src/toolshed/__init__.py index b0f91aabc..806264210 100644 --- a/src/bundles/core/src/toolshed/__init__.py +++ b/src/bundles/core/src/toolshed/__init__.py @@ -373,8 +373,7 @@ class Toolshed: if (check_available and self._available_bundle_info is not None and self._available_bundle_info.toolshed_url != self.remote_url): self._available_bundle_info = None - if not self._safe_mode: - self.reload(logger, check_remote=check_remote, rebuild_cache=rebuild_cache, _session=session) + self.reload(logger, check_remote=check_remote, rebuild_cache=rebuild_cache, _session=session, safe_mode = safe_mode) from datetime import datetime from ..core_settings import settings now = datetime.now() @@ -411,7 +410,7 @@ class Toolshed: _debug("finished loading bundles") def reload(self, logger, *, session=None, reread_cache=True, rebuild_cache=False, - check_remote=False, report=False, _session=None): + check_remote=False, report=False, _session=None, safe_mode = False): """Supported API. Discard and reread bundle info. Parameters @@ -435,7 +434,8 @@ class Toolshed: cache_file = self._bundle_cache(False, logger) self._installed_bundle_info.load(logger, cache_file=cache_file, rebuild_cache=rebuild_cache, - write_cache=cache_file is not None) + write_cache=cache_file is not None, + safe_mode = safe_mode) if report: if save is None: logger.info("Initial installed bundles.") diff --git a/src/bundles/core/src/toolshed/installed.py b/src/bundles/core/src/toolshed/installed.py index d96dbe021..1ed6f030c 100644 --- a/src/bundles/core/src/toolshed/installed.py +++ b/src/bundles/core/src/toolshed/installed.py @@ -34,11 +34,14 @@ class InstalledBundleCache(list): super().__init__(*args, **kw) self._help_directories = None - def load(self, logger, cache_file=None, rebuild_cache=False, write_cache=True): + def load(self, logger, cache_file=None, rebuild_cache=False, write_cache=True, safe_mode=False): """Load list of installed bundles. Bundles are ordered based on dependency with dependent - bundles appearing later in the list.""" + bundles appearing later in the list. + + safe_mode implies write_cache=False and takes precedence + """ # # Load bundle info. If not rebuild_cache, try reading @@ -47,10 +50,14 @@ class InstalledBundleCache(list): # try to create the cache file. # _debug("InstalledBundleCache.load: rebuild_cache", rebuild_cache) - if cache_file and not rebuild_cache: - if self._read_cache(cache_file): - _debug("InstalledBundleCache.load: using cached data") - return + if not safe_mode: + # In safe mode, don't rely on the bundle cache. Regenerate the + # list of bundles from the bundles installed in the distribution + # and nothing more + if cache_file and not rebuild_cache: + if self._read_cache(cache_file): + _debug("InstalledBundleCache.load: using cached data") + return # # Okay, no cache. Go through all installed packages # and look for ChimeraX bundles @@ -58,7 +65,20 @@ class InstalledBundleCache(list): _debug("InstalledBundleCache.load: rebuilding cache") from pkg_resources import WorkingSet dist_bundle_map = {} - for d in WorkingSet(): + working_set = WorkingSet() + if safe_mode: + # Remove the user site directory from the working set search path + # so that we only get bundles installed into the distribution + import site + dist_site = None + for _site in site.getsitepackages(): + if _site.endswith('site-packages'): + dist_site = _site + break + for entry in working_set.entries: + if not entry.startswith(dist_site): + working_set.entries.remove(entry) + for d in working_set: _debug("InstalledBundleCache.load: package %s" % d) bi = _make_bundle_info(d, True, logger) if bi is not None:
comment:15 by , 23 months ago
With this patch I was able to get through an install. I then manually installed SEQCROW after editing its metadata to make it work on 1.8 and did another build. Then it failed, again
comment:16 by , 23 months ago
You know, I think this was milestoned for 1.7 more so it wouldn't fall through the cracks than it absolutely needed to be in 1.7 per se. Maybe we could revert 1.7 to the way it was and put these new changes only on the 1.8 branch?
comment:18 by , 23 months ago
Milestone: | 1.8 → 1.7 |
---|
OK, I'm just going to revert my last patch then because it broke the builds.
comment:19 by , 23 months ago
Milestone: | 1.7 → 1.8 |
---|
Eric said this doesn't have to get fixed for 1.7.
comment:20 by , 17 months ago
Milestone: | 1.8 → 1.9 |
---|
This should be fixed by modifying the devel install command. We should be explicitly using "devel install user false" in our source tree.