Closed Bug 1759329 Opened 2 years ago Closed 2 years ago

[python 3.9] ImportError: cannot import name 'readPlist' from 'plistlib' (/usr/local/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/plistlib.py)

Categories

(Firefox Build System :: General, defect)

defect

Tracking

(firefox100 fixed)

RESOLVED FIXED
100 Branch
Tracking Status
firefox100 --- fixed

People

(Reporter: cpeterson, Assigned: mhentges)

References

Details

Attachments

(1 file)

After updating mozilla-central (to cset 8620f13a9748) today, mach configure fails with python 3.9, but succeeds with /usr/local/Cellar/python@3.8/3.8.12_1/bin/python3.8 mach configure. I'm running Homebrew's python@3.9.10 on macOS 11.6.4. Note that I ran mach bootstrap with python 3.8 due to mach bootstrap bug 1759322 with python 3.9, in case that matters.

I get the following error message when running mach configure, even after deleting my entire ~/.mozbuild directory and local objdir:

ImportError: cannot import name 'readPlist' from 'plistlib' (/usr/local/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/plistlib.py)

  File "/Users/chris/Code/mozilla/firefox/python/mozbuild/mozbuild/artifact_commands.py", line 265, in artifact_toolchain
    from mozbuild.artifacts import ArtifactCache
  File "/Users/chris/Code/mozilla/firefox/python/mozbuild/mozbuild/artifacts.py", line 66, in <module>
    import mozinstall
  File "/usr/local/lib/python3.9/site-packages/mozinstall/__init__.py", line 8, in <module>
    from .mozinstall import *
  File "/usr/local/lib/python3.9/site-packages/mozinstall/mozinstall.py", line 31, in <module>
    from plistlib import readPlist

Sentry event ID: e4d1324236ca4e7681f8a6b39892bd3f
Sentry is attempting to send 0 pending error messages
...

See the attached log file for the full log.

Woah woah, why is mozinstall being imported from /usr/local/lib/python3.9 instead of testing/mozbase/mozinstall (as defined here)?

  • Are you setting the MACH_USE_SYSTEM_PYTHON, MOZ_AUTOMATION, or MACH_BUILD_PYTHON_NATIVE_PACKAGE_SOURCE=system environment variables?
  • If not, can you add a couple lines before import mozinstall that do import sys and print(sys.path)? If you're not configuring Mach to "use the system python", then the system python paths (such as /usr/local/lib/python3.9) should have been scrubbed.
Flags: needinfo?(cpeterson)

I was going to close this bug as invalid for now because I can no longer reproduce it, but I see you already closed it as a duplicate of my mach configure bug 1759322. Maybe the testing I did for the python 3.9 error in mach bootstrap bug 1759322 had some side effect on my python site-packages?

(In reply to Mitchell Hentges [:mhentges] 🦀 from comment #1)

Woah woah, why is mozinstall being imported from /usr/local/lib/python3.9 instead of testing/mozbase/mozinstall (as defined here)?

  • Are you setting the MACH_USE_SYSTEM_PYTHON, MOZ_AUTOMATION, or MACH_BUILD_PYTHON_NATIVE_PACKAGE_SOURCE=system environment variables?

No

  • If not, can you add a couple lines before import mozinstall that do import sys and print(sys.path)? If you're not configuring Mach to "use the system python", then the system python paths (such as /usr/local/lib/python3.9) should have been scrubbed.

I added print(sys.path) to python/mozbuild/mozbuild/artifacts.py before import mozinstall and AFAICT it isn't called when I run mach configure or /usr/local/bin/python3.9 mach configure. ?!

Flags: needinfo?(cpeterson)

I'm closing this bug as invalid because I can no longer reproduce the mach bootstrap or mach configure errors after I pip3 uninstall'd all the moz packages in /usr/local/lib/python3.9/site-packages.

If you think mach wanting to import from the system packages in /usr/local/lib/python3.9/site-packages is still a bug that should be fixed in mach and is not just user error (for having old moz packages installed by pip3), feel free to reopen this bug.

Status: NEW → RESOLVED
Closed: 2 years ago
Resolution: --- → INVALID

I added print(sys.path) to python/mozbuild/mozbuild/artifacts.py before import mozinstall and AFAICT it isn't called when I run mach configure or /usr/local/bin/python3.9 mach configure. ?!

Ah, artifacts.py is only imported if an artifact needs to be re-bootstrapped. If you managed to work around this at some point (probably with py 3.8), then ./mach configure won't feel the need to bootstrap unless you delete the downloaded artifacts - or if you run the artifact code by-hand.

If you think mach wanting to import from the system packages in /usr/local/lib/python3.9/site-packages is still a bug that should be fixed in mach and is not just user error (for having old moz packages installed by pip3), feel free to reopen this bug.

Yeah, if you don't mind, I'd really like to dig into what's wrong here.

To reproduce with that print(sys.path) thing, I bet that you need to do the following:

  1. pip3 install mozinstall==2.0.0
  2. ./mach artifact toolchain --from-build linux64-clang-tidy (the artifact itself doesn't matter, so long as it exercises the artifact code)

Let me know if that repro's the problem and what the printed sys.path is.

Status: RESOLVED → REOPENED
Flags: needinfo?(cpeterson)
Resolution: INVALID → ---

(In reply to Mitchell Hentges [:mhentges] 🦀 from comment #5)

To reproduce with that print(sys.path) thing, I bet that you need to do the following:

  1. pip3 install mozinstall==2.0.0
  2. ./mach artifact toolchain --from-build linux64-clang-tidy (the artifact itself doesn't matter, so long as it exercises the artifact code)

Let me know if that repro's the problem and what the printed sys.path is.

Yes. I can repro the ImportError: cannot import name 'readPlist' from 'plistlib' (/usr/local/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/plistlib.py) using your instructions.

The sys.path printed is:

['', '/usr/local/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python39.zip', '/usr/local/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9', '/usr/local/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/lib-dynload', '/usr/local/lib/python3.9/site-packages', '/Users/chris/Code/mozilla/firefox/build', '/Users/chris/Code/mozilla/firefox/config', '/Users/chris/Code/mozilla/firefox/config/mozunit', '/Users/chris/Code/mozilla/firefox/dom/bindings', '/Users/chris/Code/mozilla/firefox/dom/bindings/parser', '/Users/chris/Code/mozilla/firefox/layout/tools/reftest', '/Users/chris/Code/mozilla/firefox/python/l10n', '/Users/chris/Code/mozilla/firefox/python/mach', '/Users/chris/Code/mozilla/firefox/python/mozboot', '/Users/chris/Code/mozilla/firefox/python/mozbuild', '/Users/chris/Code/mozilla/firefox/python/mozlint', '/Users/chris/Code/mozilla/firefox/python/mozperftest', '/Users/chris/Code/mozilla/firefox/python/mozrelease', '/Users/chris/Code/mozilla/firefox/python/mozterm', '/Users/chris/Code/mozilla/firefox/python/mozversioncontrol', '/Users/chris/Code/mozilla/firefox/security/manager/tools', '/Users/chris/Code/mozilla/firefox/taskcluster', '/Users/chris/Code/mozilla/firefox/testing', '/Users/chris/Code/mozilla/firefox/testing/awsy', '/Users/chris/Code/mozilla/firefox/testing/condprofile', '/Users/chris/Code/mozilla/firefox/testing/firefox-ui/harness', '/Users/chris/Code/mozilla/firefox/testing/marionette/client', '/Users/chris/Code/mozilla/firefox/testing/marionette/harness', '/Users/chris/Code/mozilla/firefox/testing/mozbase/manifestparser', '/Users/chris/Code/mozilla/firefox/testing/mozbase/mozcrash', '/Users/chris/Code/mozilla/firefox/testing/mozbase/mozdebug', '/Users/chris/Code/mozilla/firefox/testing/mozbase/mozdevice', '/Users/chris/Code/mozilla/firefox/testing/mozbase/mozfile', '/Users/chris/Code/mozilla/firefox/testing/mozbase/mozgeckoprofiler', '/Users/chris/Code/mozilla/firefox/testing/mozbase/mozhttpd', '/Users/chris/Code/mozilla/firefox/testing/mozbase/mozinfo', '/Users/chris/Code/mozilla/firefox/testing/mozbase/mozinstall', '/Users/chris/Code/mozilla/firefox/testing/mozbase/mozleak', '/Users/chris/Code/mozilla/firefox/testing/mozbase/mozlog', '/Users/chris/Code/mozilla/firefox/testing/mozbase/moznetwork', '/Users/chris/Code/mozilla/firefox/testing/mozbase/mozpower', '/Users/chris/Code/mozilla/firefox/testing/mozbase/mozprocess', '/Users/chris/Code/mozilla/firefox/testing/mozbase/mozprofile', '/Users/chris/Code/mozilla/firefox/testing/mozbase/mozproxy', '/Users/chris/Code/mozilla/firefox/testing/mozbase/mozrunner', '/Users/chris/Code/mozilla/firefox/testing/mozbase/mozscreenshot', '/Users/chris/Code/mozilla/firefox/testing/mozbase/mozsystemmonitor', '/Users/chris/Code/mozilla/firefox/testing/mozbase/moztest', '/Users/chris/Code/mozilla/firefox/testing/mozbase/mozversion', '/Users/chris/Code/mozilla/firefox/testing/raptor', '/Users/chris/Code/mozilla/firefox/testing/talos', '/Users/chris/Code/mozilla/firefox/testing/web-platform', '/Users/chris/Code/mozilla/firefox/testing/web-platform/tests/tools/third_party/funcsigs', '/Users/chris/Code/mozilla/firefox/testing/web-platform/tests/tools/third_party/h2', '/Users/chris/Code/mozilla/firefox/testing/web-platform/tests/tools/third_party/hpack', '/Users/chris/Code/mozilla/firefox/testing/web-platform/tests/tools/third_party/html5lib', '/Users/chris/Code/mozilla/firefox/testing/web-platform/tests/tools/third_party/hyperframe', '/Users/chris/Code/mozilla/firefox/testing/web-platform/tests/tools/third_party/pywebsocket3', '/Users/chris/Code/mozilla/firefox/testing/web-platform/tests/tools/third_party/webencodings', '/Users/chris/Code/mozilla/firefox/testing/web-platform/tests/tools/wptrunner', '/Users/chris/Code/mozilla/firefox/testing/web-platform/tests/tools/wptserve', '/Users/chris/Code/mozilla/firefox/testing/xpcshell', '/Users/chris/Code/mozilla/firefox/third_party/python/Jinja2', '/Users/chris/Code/mozilla/firefox/third_party/python/MarkupSafe/src', '/Users/chris/Code/mozilla/firefox/third_party/python/PyYAML/lib3', '/Users/chris/Code/mozilla/firefox/third_party/python/aiohttp', '/Users/chris/Code/mozilla/firefox/third_party/python/appdirs', '/Users/chris/Code/mozilla/firefox/third_party/python/async_timeout', '/Users/chris/Code/mozilla/firefox/third_party/python/attrs', '/Users/chris/Code/mozilla/firefox/third_party/python/blessings', '/Users/chris/Code/mozilla/firefox/third_party/python/cbor2', '/Users/chris/Code/mozilla/firefox/third_party/python/certifi', '/Users/chris/Code/mozilla/firefox/third_party/python/chardet', '/Users/chris/Code/mozilla/firefox/third_party/python/click', '/Users/chris/Code/mozilla/firefox/third_party/python/colorama', '/Users/chris/Code/mozilla/firefox/third_party/python/compare_locales', '/Users/chris/Code/mozilla/firefox/third_party/python/cookies', '/Users/chris/Code/mozilla/firefox/third_party/python/cram', '/Users/chris/Code/mozilla/firefox/third_party/python/diskcache', '/Users/chris/Code/mozilla/firefox/third_party/python/distro', '/Users/chris/Code/mozilla/firefox/third_party/python/dlmanager', '/Users/chris/Code/mozilla/firefox/third_party/python/ecdsa', '/Users/chris/Code/mozilla/firefox/third_party/python/esprima', '/Users/chris/Code/mozilla/firefox/third_party/python/fluent.migrate', '/Users/chris/Code/mozilla/firefox/third_party/python/fluent.syntax', '/Users/chris/Code/mozilla/firefox/third_party/python/gyp/pylib', '/Users/chris/Code/mozilla/firefox/third_party/python/idna', '/Users/chris/Code/mozilla/firefox/third_party/python/idna-ssl', '/Users/chris/Code/mozilla/firefox/third_party/python/importlib_metadata', '/Users/chris/Code/mozilla/firefox/third_party/python/iso8601', '/Users/chris/Code/mozilla/firefox/third_party/python/jsmin', '/Users/chris/Code/mozilla/firefox/third_party/python/json-e', '/Users/chris/Code/mozilla/firefox/third_party/python/jsonschema', '/Users/chris/Code/mozilla/firefox/third_party/python/mohawk', '/Users/chris/Code/mozilla/firefox/third_party/python/mozilla_version', '/Users/chris/Code/mozilla/firefox/third_party/python/multidict', '/Users/chris/Code/mozilla/firefox/third_party/python/packaging', '/Users/chris/Code/mozilla/firefox/third_party/python/pathspec', '/Users/chris/Code/mozilla/firefox/third_party/python/pip', '/Users/chris/Code/mozilla/firefox/third_party/python/pip_tools', '/Users/chris/Code/mozilla/firefox/third_party/python/ply', '/Users/chris/Code/mozilla/firefox/third_party/python/pyasn1', '/Users/chris/Code/mozilla/firefox/third_party/python/pyasn1_modules', '/Users/chris/Code/mozilla/firefox/third_party/python/pylru', '/Users/chris/Code/mozilla/firefox/third_party/python/pyparsing', '/Users/chris/Code/mozilla/firefox/third_party/python/pyrsistent', '/Users/chris/Code/mozilla/firefox/third_party/python/python-hglib', '/Users/chris/Code/mozilla/firefox/third_party/python/pytoml', '/Users/chris/Code/mozilla/firefox/third_party/python/redo', '/Users/chris/Code/mozilla/firefox/third_party/python/requests', '/Users/chris/Code/mozilla/firefox/third_party/python/requests_unixsocket', '/Users/chris/Code/mozilla/firefox/third_party/python/responses', '/Users/chris/Code/mozilla/firefox/third_party/python/rsa', '/Users/chris/Code/mozilla/firefox/third_party/python/sentry_sdk', '/Users/chris/Code/mozilla/firefox/third_party/python/setuptools', '/Users/chris/Code/mozilla/firefox/third_party/python/six', '/Users/chris/Code/mozilla/firefox/third_party/python/slugid', '/Users/chris/Code/mozilla/firefox/third_party/python/taskcluster', '/Users/chris/Code/mozilla/firefox/third_party/python/taskcluster_taskgraph', '/Users/chris/Code/mozilla/firefox/third_party/python/taskcluster_urls', '/Users/chris/Code/mozilla/firefox/third_party/python/tqdm', '/Users/chris/Code/mozilla/firefox/third_party/python/typing_extensions', '/Users/chris/Code/mozilla/firefox/third_party/python/urllib3', '/Users/chris/Code/mozilla/firefox/third_party/python/voluptuous', '/Users/chris/Code/mozilla/firefox/third_party/python/wheel', '/Users/chris/Code/mozilla/firefox/third_party/python/yamllint', '/Users/chris/Code/mozilla/firefox/third_party/python/yarl', '/Users/chris/Code/mozilla/firefox/third_party/python/zipp', '/Users/chris/Code/mozilla/firefox/toolkit/components/telemetry/tests/marionette/harness', '/Users/chris/Code/mozilla/firefox/tools', '/Users/chris/Code/mozilla/firefox/tools/moztreedocs', '/Users/chris/Code/mozilla/firefox/xpcom/ds/tools', '/Users/chris/Code/mozilla/firefox/xpcom/geckoprocesstypes_generator', '/Users/chris/Code/mozilla/firefox/xpcom/idl-parser', '/Users/chris/.mozbuild/srcdirs/firefox-e8b6fa201362/_virtualenvs/mach', '/Users/chris/.mozbuild/srcdirs/firefox-e8b6fa201362/_virtualenvs/mach/lib/python3.9/site-packages']

Flags: needinfo?(cpeterson) → needinfo?(mhentges)

Here's my env, showing that I don't have any MACH or PYTHONPATH environment variables set:

TERM_PROGRAM=Apple_Terminal
SHELL=/bin/zsh
TERM=xterm-256color
TMPDIR=/var/folders/m7/4q4wv4g90093djk7c8k0nvvc0000gp/T/
TERM_PROGRAM_VERSION=440
TERM_SESSION_ID=5798AB25-6B82-405C-8172-CA4223332A14
USER=chris
SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.P7qhp3ODbo/Listeners
PATH=/Users/chris/.cargo/bin:/usr/local/Homebrew/bin:/Applications/Visual\ Studio\ Code.app/Contents/Resources/app/bin:/usr/local/sbin:/usr/local/bin/phabricator:/usr/local/bin/phabricator/arcanist/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/VMware Fusion.app/Contents/Public:/opt/X11/bin:/Library/Apple/usr/bin
LaunchInstanceID=1DEEB219-7876-4814-BF72-C62AE1BB7E89
__CFBundleIdentifier=com.apple.Terminal
PWD=/Users/chris
XPC_FLAGS=0x0
XPC_SERVICE_NAME=0
SHLVL=1
HOME=/Users/chris
LOGNAME=chris
OLDPWD=/Users/chris/Code/mozilla/firefox
HOMEBREW_NO_ENV_HINTS=1
BUILD_SYSTEM_TELEMETRY=1
MOZ_ALLOW_DOWNGRADE=1
MOZ_NODE_PATH=/usr/local/bin/node
JAVA_HOME=/usr/local/opt/openjdk@8
LANG=en_US.UTF-8
_=/usr/bin/env

Interesting, thanks!
We can see the _virtualenvs/mach/... paths in your sys.path, so Mach is correctly identifying that it should be using the virtualenv. My next guess is that it's failing to scrub the "system site-packages" properly.

Chris, can you start a fresh Python 3 REPL (probably by running python3) then execute the following commands, sharing the full output to this bug?

import sys
import site
print(site.getusersitepackages())
print(site.getsitepackages())
site_packages = [site.getusersitepackages()] + site.getsitepackages()
print([path for path in sys.path if path not in site_packages])
Flags: needinfo?(mhentges) → needinfo?(cpeterson)
% which python3
/usr/local/bin/python3
% python3
Python 3.9.10 (main, Jan 15 2022, 11:48:00) 
[Clang 13.0.0 (clang-1300.0.29.3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> import site
>>> print(site.getusersitepackages())
/Users/chris/Library/Python/3.9/lib/python/site-packages
>>> print(site.getsitepackages())
['/usr/local/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages']
>>> site_packages = [site.getusersitepackages()] + site.getsitepackages()
>>> print([path for path in sys.path if path not in site_packages])
['', '/usr/local/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python39.zip', '/usr/local/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9', '/usr/local/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/lib-dynload', '/usr/local/lib/python3.9/site-packages']
>>>
Flags: needinfo?(cpeterson) → needinfo?(mhentges)

Thanks Chris! I think I see the issue here! We're trying to calculate all the site_packages directories, of which there are generally two:

  • The system "site_packages" directory
  • The user "site_packages" directory (pip3 install --user ...)

Next, generally, Python's sys.path contains the following:

  • Standard library
  • System site_packages
  • User site_packages

Interestingly, with brew's python, the "system site_packages" added to the sys.path is different from the "system site_packages" reported by the site module. Hmm.

I'll take it from here, thanks again for your help!

Flags: needinfo?(mhentges)
Assignee: nobody → mhentges
Status: REOPENED → ASSIGNED
...
# the Cellar site-packages is a symlink to the HOMEBREW_PREFIX
# site_packages; prefer the shorter paths
long_prefix = re.compile(r'#{rack}/[0-9\._abrc]+/Frameworks/Python\.framework/Versions/#{version.major_minor}/lib/python#{version.major_minor}/site-packages')
sys.path = [long_prefix.sub('#{HOMEBREW_PREFIX/"lib/python#{version.major_minor}/site-packages"}', p) for p in sys.path]
...

Brew, you're breaking my heart right now.

Previously, when trying to determine the minimal sys.path that just
includes the standard library (but no pip-installed packages), we
would resolve the sys.path and remove the system and user
site-packages. However, this "removal" step didn't work as-is for
brew's Python, because its "system site-packages" is //different//
from its site.getsitepackages().

Stepping back though, there's an easier solution: run python with the
-S flag, and no "site" paths or custom initialization logic will add
anything extra to the stdlib.

Pushed by mhentges@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/59c6e83f9144
Properly exclude Brew's site-packages when using Mach venv r=ahal
Status: ASSIGNED → RESOLVED
Closed: 2 years ago2 years ago
Resolution: --- → FIXED
Target Milestone: --- → 100 Branch
See Also: 1759322
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: