diff --git a/docs/index.rst b/docs/index.rst index b6822409..a832ee8e 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -49,7 +49,7 @@ You can quickly play with Pipenv right in your browser: Install Pipenv Today! --------------------- -If you're on MacOS, you can install Pipenv easily with Homebrew:: +If you're on MacOS, you can install Pipenv easily with Homebrew. You can also use Linuxbrew on Linux using the same command:: $ brew install pipenv diff --git a/docs/install.rst b/docs/install.rst index f529e249..4039cdb5 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -52,16 +52,16 @@ check this by running:: $ pip --version pip 9.0.1 -If you installed Python from source, with an installer from `python.org`_, or -via `Homebrew`_ you should already have pip. If you're on Linux and installed +If you installed Python from source, with an installer from `python.org`_, via `Homebrew`_ or via `Linuxbrew`_ you should already have pip. If you're on Linux and installed using your OS package manager, you may have to `install pip `_ separately. -If you plan to install Pipenv using Homebrew you can skip this step. The -Homebrew installer takes care of pip for you. +If you plan to install Pipenv using Homebrew or Linuxbrew you can skip this step. The +Homebrew/Linuxbrew installer takes care of pip for you. .. _getting started tutorial: https://opentechschool.github.io/python-beginners/en/getting_started.html#what-is-python-exactly .. _python.org: https://python.org .. _Homebrew: https://brew.sh +.. _Linuxbrew: https://linuxbrew.sh/ .. _Installing Python: http://docs.python-guide.org/en/latest/starting/installation/ @@ -83,13 +83,13 @@ cases. ☤ Homebrew Installation of Pipenv --------------------------------- -Homebrew is a popular open-source package management system for macOS. +`Homebrew`_ is a popular open-source package management system for macOS. For Linux users, `Linuxbrew`_ is a Linux port of that. -Installing pipenv via Homebrew will keep pipenv and all of its dependencies in +Installing pipenv via Homebrew or Linuxbrew will keep pipenv and all of its dependencies in an isolated virtual environment so it doesn't interfere with the rest of your Python installation. -Once you have installed `Homebrew`_ simply run:: +Once you have installed Homebrew or Linuxbrew simply run:: $ brew install pipenv diff --git a/news/3348.feature.rst b/news/3348.feature.rst new file mode 100644 index 00000000..50547a3d --- /dev/null +++ b/news/3348.feature.rst @@ -0,0 +1 @@ +Added support for ``--verbose`` output to ``pipenv run``. \ No newline at end of file diff --git a/news/3351.bugfix.rst b/news/3351.bugfix.rst new file mode 100644 index 00000000..d2d9c675 --- /dev/null +++ b/news/3351.bugfix.rst @@ -0,0 +1 @@ +Fix a bug that ``--site-packages`` flag is not recognized. diff --git a/news/3362.trivial.rst b/news/3362.trivial.rst new file mode 100644 index 00000000..2216b071 --- /dev/null +++ b/news/3362.trivial.rst @@ -0,0 +1 @@ +The inline tables won't be rewritten now. diff --git a/news/3384.bugfix.rst b/news/3384.bugfix.rst new file mode 100644 index 00000000..f85cd168 --- /dev/null +++ b/news/3384.bugfix.rst @@ -0,0 +1 @@ +Fix unhashable type error during ``$ pipenv install --selective-upgrade`` diff --git a/pipenv/cli/command.py b/pipenv/cli/command.py index ae7111f1..ec1bef61 100644 --- a/pipenv/cli/command.py +++ b/pipenv/cli/command.py @@ -70,7 +70,6 @@ def cli( python=False, help=False, py=False, - site_packages=False, envs=False, man=False, completion=False, @@ -198,7 +197,7 @@ def cli( ) ctx.abort() # --two / --three was passed… - if (state.python or state.three is not None) or site_packages: + if (state.python or state.three is not None) or state.site_packages: ensure_project( three=state.three, python=state.python, diff --git a/pipenv/core.py b/pipenv/core.py index 2b8c7eeb..9c1971d5 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -1829,7 +1829,7 @@ def do_install( if not is_star(section[package__name]) and is_star(package__val): # Support for VCS dependencies. package_args[i] = convert_deps_to_pip( - {packages: section[package__name]}, project=project, r=False + {package__name: section[package__name]}, project=project, r=False )[0] except KeyError: pass @@ -2310,6 +2310,9 @@ def do_run(command, args, three=None, python=False, pypi_mirror=None): try: script = project.build_script(command, args) + cmd_string = ' '.join([script.command] + script.args) + if environments.is_verbose(): + click.echo(crayons.normal("$ {0}".format(cmd_string)), err=True) except ScriptEmptyError: click.echo("Can't run script {0!r}-it's empty?", err=True) if os.name == "nt": diff --git a/pipenv/utils.py b/pipenv/utils.py index 9f03465c..08847e59 100644 --- a/pipenv/utils.py +++ b/pipenv/utils.py @@ -83,19 +83,32 @@ def cleanup_toml(tml): def convert_toml_outline_tables(parsed): """Converts all outline tables to inline tables.""" - if isinstance(parsed, tomlkit.container.Container): - empty_inline_table = tomlkit.inline_table - else: - empty_inline_table = toml.TomlDecoder().get_empty_inline_table + def convert_tomlkit_table(section): + for key, value in section._body: + if not key: + continue + if hasattr(value, "keys") and not isinstance(value, tomlkit.items.InlineTable): + table = tomlkit.inline_table() + table.update(value.value) + section[key.key] = table + + def convert_toml_table(section): + for package, value in section.items(): + if hasattr(value, "keys") and not isinstance(value, toml.decoder.InlineTableDict): + table = toml.TomlDecoder().get_empty_inline_table() + table.update(value) + section[package] = table + + is_tomlkit_parsed = isinstance(parsed, tomlkit.container.Container) for section in ("packages", "dev-packages"): table_data = parsed.get(section, {}) - for package, value in table_data.items(): - if hasattr(value, "keys") and not isinstance( - value, (tomlkit.items.InlineTable, toml.decoder.InlineTableDict) - ): - table = empty_inline_table() - table.update(value) - table_data[package] = table + if not table_data: + continue + if is_tomlkit_parsed: + convert_tomlkit_table(table_data) + else: + convert_toml_table(table_data) + return parsed diff --git a/setup.py b/setup.py index 4a6b9389..6583cff1 100644 --- a/setup.py +++ b/setup.py @@ -68,7 +68,7 @@ class DebCommand(Command): class UploadCommand(Command): - """Support setup.py publish.""" + """Support setup.py upload.""" description = "Build and publish the package." user_options = [] diff --git a/tests/integration/test_cli.py b/tests/integration/test_cli.py index 946b98f7..a38883e0 100644 --- a/tests/integration/test_cli.py +++ b/tests/integration/test_cli.py @@ -41,6 +41,20 @@ def test_pipenv_py(PipenvInstance): assert os.path.basename(python).startswith('python') +@pytest.mark.cli +def test_pipenv_site_packages(PipenvInstance): + with PipenvInstance() as p: + c = p.pipenv('--python python --site-packages') + assert c.return_code == 0 + assert 'Making site-packages available' in c.err + + # no-global-site-packages.txt under stdlib dir should not exist. + c = p.pipenv('run python -c "import sysconfig; print(sysconfig.get_path(\'stdlib\'))"') + assert c.return_code == 0 + stdlib_path = c.out.strip() + assert not os.path.isfile(os.path.join(stdlib_path, 'no-global-site-packages.txt')) + + @pytest.mark.cli def test_pipenv_support(PipenvInstance): with PipenvInstance() as p: diff --git a/tests/integration/test_install_basic.py b/tests/integration/test_install_basic.py index 317351a0..f858f8ac 100644 --- a/tests/integration/test_install_basic.py +++ b/tests/integration/test_install_basic.py @@ -446,3 +446,25 @@ def test_install_package_with_dots(PipenvInstance, pypi): c = p.pipenv("install backports.html") assert c.ok assert "backports.html" in p.pipfile["packages"] + + +@pytest.mark.install +def test_rewrite_outline_table(PipenvInstance, pypi): + with PipenvInstance(pypi=pypi, chdir=True) as p: + with open(p.pipfile_path, 'w') as f: + contents = """ +[packages] +six = {version = "*", editable = true} + +[packages.requests] +version = "*" + """.strip() + f.write(contents) + c = p.pipenv("install -e click") + assert c.return_code == 0 + with open(p.pipfile_path) as f: + contents = f.read() + assert "[packages.requests]" not in contents + assert 'six = {version = "*", editable = true}' in contents + assert 'requests = {version = "*"}' in contents + assert 'click = {' in contents diff --git a/tests/integration/test_project.py b/tests/integration/test_project.py index f9a2ba12..6a4a858a 100644 --- a/tests/integration/test_project.py +++ b/tests/integration/test_project.py @@ -148,24 +148,6 @@ six = {{version = "*", index = "pypi"}} assert c.return_code == 0 -@pytest.mark.install -@pytest.mark.project -def test_rewrite_outline_table(PipenvInstance, pypi): - with PipenvInstance(pypi=pypi, chdir=True) as p: - with open(p.pipfile_path, 'w') as f: - contents = """ -[packages.requests] -version = "*" - """.strip() - f.write(contents) - c = p.pipenv('install click') - assert c.return_code == 0 - with open(p.pipfile_path) as f: - contents = f.read() - assert "[packages.requests]" not in contents - assert 'requests = {version = "*"}' in contents - - @pytest.mark.install @pytest.mark.project def test_include_editable_packages(PipenvInstance, pypi, testsroot, pathlib_tmpdir): @@ -185,6 +167,7 @@ def test_include_editable_packages(PipenvInstance, pypi, testsroot, pathlib_tmpd @pytest.mark.project +@pytest.mark.virtualenv def test_run_in_virtualenv(PipenvInstance, pypi, virtualenv): with PipenvInstance(chdir=True, pypi=pypi) as p: os.environ.pop("PIPENV_IGNORE_VIRTUALENVS", None)