Tests test_get_default_path, test_run* fail sh >= 2
When running the test suite against sh version 2.0.0 or 2.0.2, I get the following failures:
FAILED tests/test_cli.py::test_get_default_path - sh.CommandNotFound: cd
FAILED tests/test_cli.py::test_run - sh.CommandNotFound: cd
FAILED tests/test_cli.py::test_run_with_existing_variable - sh.CommandNotFound: cd
FAILED tests/test_cli.py::test_run_with_existing_variable_not_overridden - sh.CommandNotFound: cd
FAILED tests/test_cli.py::test_run_with_none_value - sh.CommandNotFound: cd
Full output
$ tox -e py310 py310: recreate env because requirements removed: sh<2 py310: remove tox env folder /tmp/python-dotenv/.tox/py310 py310: install_deps> python -I -m pip install click ipython pytest pytest-cov sh==2.0.0 .pkg: _optional_hooks> python /usr/lib/python3.11/site-packages/pyproject_api/_backend.py True setuptools.build_meta __legacy__ .pkg: get_requires_for_build_sdist> python /usr/lib/python3.11/site-packages/pyproject_api/_backend.py True setuptools.build_meta __legacy__ .pkg: prepare_metadata_for_build_wheel> python /usr/lib/python3.11/site-packages/pyproject_api/_backend.py True setuptools.build_meta __legacy__ .pkg: build_sdist> python /usr/lib/python3.11/site-packages/pyproject_api/_backend.py True setuptools.build_meta __legacy__ py310: install_package> python -I -m pip install --force-reinstall --no-deps /tmp/python-dotenv/.tox/.tmp/package/4/python-dotenv-0.21.1.tar.gz py310: commands[0]> pytest --cov --cov-report=term-missing --cov-config setup.cfg ========================================================= test session starts ========================================================= platform linux -- Python 3.10.10, pytest-7.2.1, pluggy-1.0.0 cachedir: .tox/py310/.pytest_cache rootdir: /tmp/python-dotenv, configfile: setup.cfg, testpaths: tests plugins: cov-4.0.0 collected 150 items tests/test_cli.py ............................FFFFF.... [ 24%] tests/test_ipython.py ... [ 26%] tests/test_main.py ............................................................ [ 66%] tests/test_parser.py ........................................... [ 95%] tests/test_utils.py . [ 96%] tests/test_variables.py ...... [100%] ============================================================== FAILURES =============================================================== ________________________________________________________ test_get_default_path ________________________________________________________ tmp_path = PosixPath('/tmp/pytest-of-mgorny/pytest-3/test_get_default_path0') def test_get_default_path(tmp_path): > sh.cd(str(tmp_path)) tests/test_cli.py:156: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ .tox/py310/lib/python3.10/site-packages/sh.py:3679: in __getattr__ return self.__env[name] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = {}, k = 'cd' def __getitem__(self, k): if k == "args": # Let the deprecated '_args' context manager be imported as 'args' k = "_args" # if we're trying to import something real, see if it's in our global scope. # what defines "real" is that it's in our allowlist if k in self.allowlist: return self.globs[k] # somebody tried to be funny and do "from sh import *" if k == "__all__": warnings.warn( "Cannot import * from sh. Please import sh or import programs " "individually." ) return [] # check if we're naming a dynamically generated ReturnCode exception exc = get_exc_from_name(k) if exc: return exc # https://github.com/ipython/ipython/issues/2577 # https://github.com/amoffat/sh/issues/97#issuecomment-10610629 if k.startswith("__") and k.endswith("__"): raise AttributeError # is it a command? cmd = resolve_command(k, self.globs[Command.__name__], self.baked_args) if cmd: return cmd # is it a custom builtin? builtin = getattr(self, "b_" + k, None) if builtin: return builtin # how about an environment variable? # this check must come after testing if its a command, because on some # systems, there are an environment variables that can conflict with # command names. # https://github.com/amoffat/sh/issues/238 try: return os.environ[k] except KeyError: pass # nothing found, raise an exception > raise CommandNotFound(k) E sh.CommandNotFound: cd .tox/py310/lib/python3.10/site-packages/sh.py:3459: CommandNotFound ______________________________________________________________ test_run _______________________________________________________________ tmp_path = PosixPath('/tmp/pytest-of-mgorny/pytest-3/test_run0') def test_run(tmp_path): > sh.cd(str(tmp_path)) tests/test_cli.py:166: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ .tox/py310/lib/python3.10/site-packages/sh.py:3679: in __getattr__ return self.__env[name] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = {}, k = 'cd' def __getitem__(self, k): if k == "args": # Let the deprecated '_args' context manager be imported as 'args' k = "_args" # if we're trying to import something real, see if it's in our global scope. # what defines "real" is that it's in our allowlist if k in self.allowlist: return self.globs[k] # somebody tried to be funny and do "from sh import *" if k == "__all__": warnings.warn( "Cannot import * from sh. Please import sh or import programs " "individually." ) return [] # check if we're naming a dynamically generated ReturnCode exception exc = get_exc_from_name(k) if exc: return exc # https://github.com/ipython/ipython/issues/2577 # https://github.com/amoffat/sh/issues/97#issuecomment-10610629 if k.startswith("__") and k.endswith("__"): raise AttributeError # is it a command? cmd = resolve_command(k, self.globs[Command.__name__], self.baked_args) if cmd: return cmd # is it a custom builtin? builtin = getattr(self, "b_" + k, None) if builtin: return builtin # how about an environment variable? # this check must come after testing if its a command, because on some # systems, there are an environment variables that can conflict with # command names. # https://github.com/amoffat/sh/issues/238 try: return os.environ[k] except KeyError: pass # nothing found, raise an exception > raise CommandNotFound(k) E sh.CommandNotFound: cd .tox/py310/lib/python3.10/site-packages/sh.py:3459: CommandNotFound ___________________________________________________ test_run_with_existing_variable ___________________________________________________ tmp_path = PosixPath('/tmp/pytest-of-mgorny/pytest-3/test_run_with_existing_variabl0') def test_run_with_existing_variable(tmp_path): > sh.cd(str(tmp_path)) tests/test_cli.py:177: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ .tox/py310/lib/python3.10/site-packages/sh.py:3679: in __getattr__ return self.__env[name] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = {}, k = 'cd' def __getitem__(self, k): if k == "args": # Let the deprecated '_args' context manager be imported as 'args' k = "_args" # if we're trying to import something real, see if it's in our global scope. # what defines "real" is that it's in our allowlist if k in self.allowlist: return self.globs[k] # somebody tried to be funny and do "from sh import *" if k == "__all__": warnings.warn( "Cannot import * from sh. Please import sh or import programs " "individually." ) return [] # check if we're naming a dynamically generated ReturnCode exception exc = get_exc_from_name(k) if exc: return exc # https://github.com/ipython/ipython/issues/2577 # https://github.com/amoffat/sh/issues/97#issuecomment-10610629 if k.startswith("__") and k.endswith("__"): raise AttributeError # is it a command? cmd = resolve_command(k, self.globs[Command.__name__], self.baked_args) if cmd: return cmd # is it a custom builtin? builtin = getattr(self, "b_" + k, None) if builtin: return builtin # how about an environment variable? # this check must come after testing if its a command, because on some # systems, there are an environment variables that can conflict with # command names. # https://github.com/amoffat/sh/issues/238 try: return os.environ[k] except KeyError: pass # nothing found, raise an exception > raise CommandNotFound(k) E sh.CommandNotFound: cd .tox/py310/lib/python3.10/site-packages/sh.py:3459: CommandNotFound ___________________________________________ test_run_with_existing_variable_not_overridden ____________________________________________ tmp_path = PosixPath('/tmp/pytest-of-mgorny/pytest-3/test_run_with_existing_variabl1') def test_run_with_existing_variable_not_overridden(tmp_path): > sh.cd(str(tmp_path)) tests/test_cli.py:190: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ .tox/py310/lib/python3.10/site-packages/sh.py:3679: in __getattr__ return self.__env[name] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = {}, k = 'cd' def __getitem__(self, k): if k == "args": # Let the deprecated '_args' context manager be imported as 'args' k = "_args" # if we're trying to import something real, see if it's in our global scope. # what defines "real" is that it's in our allowlist if k in self.allowlist: return self.globs[k] # somebody tried to be funny and do "from sh import *" if k == "__all__": warnings.warn( "Cannot import * from sh. Please import sh or import programs " "individually." ) return [] # check if we're naming a dynamically generated ReturnCode exception exc = get_exc_from_name(k) if exc: return exc # https://github.com/ipython/ipython/issues/2577 # https://github.com/amoffat/sh/issues/97#issuecomment-10610629 if k.startswith("__") and k.endswith("__"): raise AttributeError # is it a command? cmd = resolve_command(k, self.globs[Command.__name__], self.baked_args) if cmd: return cmd # is it a custom builtin? builtin = getattr(self, "b_" + k, None) if builtin: return builtin # how about an environment variable? # this check must come after testing if its a command, because on some # systems, there are an environment variables that can conflict with # command names. # https://github.com/amoffat/sh/issues/238 try: return os.environ[k] except KeyError: pass # nothing found, raise an exception > raise CommandNotFound(k) E sh.CommandNotFound: cd .tox/py310/lib/python3.10/site-packages/sh.py:3459: CommandNotFound ______________________________________________________ test_run_with_none_value _______________________________________________________ tmp_path = PosixPath('/tmp/pytest-of-mgorny/pytest-3/test_run_with_none_value0') def test_run_with_none_value(tmp_path): > sh.cd(str(tmp_path)) tests/test_cli.py:203: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ .tox/py310/lib/python3.10/site-packages/sh.py:3679: in __getattr__ return self.__env[name] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = {}, k = 'cd' def __getitem__(self, k): if k == "args": # Let the deprecated '_args' context manager be imported as 'args' k = "_args" # if we're trying to import something real, see if it's in our global scope. # what defines "real" is that it's in our allowlist if k in self.allowlist: return self.globs[k] # somebody tried to be funny and do "from sh import *" if k == "__all__": warnings.warn( "Cannot import * from sh. Please import sh or import programs " "individually." ) return [] # check if we're naming a dynamically generated ReturnCode exception exc = get_exc_from_name(k) if exc: return exc # https://github.com/ipython/ipython/issues/2577 # https://github.com/amoffat/sh/issues/97#issuecomment-10610629 if k.startswith("__") and k.endswith("__"): raise AttributeError # is it a command? cmd = resolve_command(k, self.globs[Command.__name__], self.baked_args) if cmd: return cmd # is it a custom builtin? builtin = getattr(self, "b_" + k, None) if builtin: return builtin # how about an environment variable? # this check must come after testing if its a command, because on some # systems, there are an environment variables that can conflict with # command names. # https://github.com/amoffat/sh/issues/238 try: return os.environ[k] except KeyError: pass # nothing found, raise an exception > raise CommandNotFound(k) E sh.CommandNotFound: cd .tox/py310/lib/python3.10/site-packages/sh.py:3459: CommandNotFound ---------- coverage: platform linux, python 3.10.10-final-0 ---------- Name Stmts Miss Cover Missing ------------------------------------------------------------------------------------------- .tox/py310/lib/python3.10/site-packages/dotenv/__init__.py 21 21 0% 1-42 .tox/py310/lib/python3.10/site-packages/dotenv/__main__.py 3 3 0% 3-6 .tox/py310/lib/python3.10/site-packages/dotenv/cli.py 106 106 0% 1-199 .tox/py310/lib/python3.10/site-packages/dotenv/ipython.py 21 21 0% 1-39 .tox/py310/lib/python3.10/site-packages/dotenv/main.py 174 174 0% 1-375 .tox/py310/lib/python3.10/site-packages/dotenv/parser.py 117 117 0% 1-175 .tox/py310/lib/python3.10/site-packages/dotenv/variables.py 54 54 0% 1-86 .tox/py310/lib/python3.10/site-packages/dotenv/version.py 1 1 0% 1 ------------------------------------------------------------------------------------------- TOTAL 497 497 0% ======================================================= short test summary info ======================================================= FAILED tests/test_cli.py::test_get_default_path - sh.CommandNotFound: cd FAILED tests/test_cli.py::test_run - sh.CommandNotFound: cd FAILED tests/test_cli.py::test_run_with_existing_variable - sh.CommandNotFound: cd FAILED tests/test_cli.py::test_run_with_existing_variable_not_overridden - sh.CommandNotFound: cd FAILED tests/test_cli.py::test_run_with_none_value - sh.CommandNotFound: cd ==================================================== 5 failed, 145 passed in 4.52s ==================================================== py310: exit 1 (5.39 seconds) /tmp/python-dotenv> pytest --cov --cov-report=term-missing --cov-config setup.cfg pid=47129 .pkg: _exit> python /usr/lib/python3.11/site-packages/pyproject_api/_backend.py True setuptools.build_meta __legacy__ py310: FAIL code 1 (20.09=setup[14.70]+cmd[5.39] seconds) evaluation failed :( (20.21 seconds)
(here I've modifed tox.ini to test different versions)