poetry-pyinstaller-plugin


Namepoetry-pyinstaller-plugin JSON
Version 1.2.1 PyPI version JSON
download
home_pagehttps://github.com/thmahe/poetry-pyinstaller-plugin
SummaryPoetry plugin to build and/or bundle executable binaries with PyInstaller
upload_time2024-10-30 20:57:07
maintainerNone
docs_urlNone
authorThomas Mahé
requires_python<=3.13,>=3.8
licenseMIT
keywords poetry plugin pyinstaller binary
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # PyInstaller plugin for Poetry

Easily create executable binaries from your `pyproject.toml` using [PyInstaller](https://pyinstaller.org).

## Features
* **Multiple distribution formats**
  * **Single file** created in `dist` folder (executable archive)
  * **Folder** created in `dist` folder (containing executable and libraries)
  * **Bundled** executable in platform specific wheels as scripts
    * Both single file & folder distribution type can be bundled in wheels

## Installation

To install `poetry-pyinstaller-plugin` run the following command:
```shell
poetry self add poetry-pyinstaller-plugin
# or
pipx inject poetry poetry-pyinstaller-plugin
```

If you are having troubles to install the plugin please refer to Poetry documentation: https://python-poetry.org/docs/plugins/#using-plugins

## Configuration

Are listed in this sections all options available to configure `poetry-pyinstaller-plugin` in your `pyproject.toml`

* `[tool.poetry-pyinstaller-plugin]`
  * `version` (string) 
    * Version of PyInstaller to use during build
    * Does not support version constraint
  * `exclude-include` (boolean) 
    * Exclude poetry include. Default: `False`
  * `pre-build` (string)
    * Pre-build hook. `path.to.my.hook:pre-build-hook`
  * `post-build` (string)
    * Post-build hook. `path.to.my.hook:post-build-hook`
  * `use-poetry-install` (boolean) 
    * The default mode `False` installs packages (including "*pyinstaller*", "*certifi*" & "*cffi*") to the actual
      virtual environment by using internally pip. It will not use `poetry.lock` file, just the dependencies from the
      `pyproject.toml` configuration file.
    * When set to `True` the virtual environment should be completely installed by poetry including "*pyinstaller*"
      and optional "*certifi*" & "*cffi*" (for custom certificates).\
      This is done by adding them as dependencies to the `pyproject.toml` configuration file and run `poetry install`
      before starting `poetry build` command. Recommendation is the usage of an separate dependency group for
      pyinstaller.
  * `scripts` (dictionary) 
    * Where key is the program name and value a path to script or a `PyInstallerTarget` spec
    * Example: `prog-name = "my_package/script.py"`
  * `certifi` (dictionary)
    * `append` (list): List of certificates to include in `certifi.where()`
  * `collect` (dictionary)
    * `submodules` (list): Collect all submodules for specified package(s) or module(s)
    * `data` (list): Collect all data for specified package(s) or module(s)
    * `binaries` (list): Collect all binaries for specified package(s) or module(s)
    * `all` (list): Collect all submodules, data files, and binaries for specified package(s) or module(s)
  * `copy-metadata` (list) : list of packages for which metadata must be copied
  * `recursive-copy-metadata` (list) : list of packages for which metadata must be copied (including dependencies)
  * `include` (dictionary) : 
    * Data file(s) to include. `{source: destination}`
  * `package` (dictionary) : 
    * File(s) to include with executable. `{source: destination}`

`PyinstallerTarget` spec:
* `source` (string): Path to your program entrypoint
* `type` (string, **default:** `onedir`): Type of distribution format. Must be one of `onefile`, `onedir`
* `bundle` (boolean, **default:** `false`): Include executable binary onto wheel
* `noupx` (boolean, **default:** `false`) : Disable UPX archiving
* `strip` (boolean, **default** `false`) : Apply a symbol-table strip to the executable and shared libs (not recommended for Windows)
* `console` (boolean, **default** `false`) : Open a console window for standard i/o (default). On Windows this option has no effect if the first script is a ‘.pyw’ file.
* `windowed` (boolean, **default** `false`) : Windows and Mac OS X: do not provide a console window for standard i/o. On Mac OS this also triggers building a Mac OS .app bundle. On Windows this option is automatically set if the first script is a ‘.pyw’ file. This option is ignored on *NIX systems.
* `icon` (Path, **default** PyInstaller’s icon) : FILE.ico: apply the icon to a Windows executable. FILE.exe,ID: extract the icon with ID from an exe. FILE.icns: apply the icon to the .app bundle on Mac OS. Use “NONE” to not apply any icon, thereby making the OS to show some default
* `uac_admin` (boolean, **default** `false`) : Using this option creates a Manifest that will request elevation upon application start.
* `uac_uiaccess` (boolean, **default** `false`) : Using this option allows an elevated application to work with Remote Desktop.
* `argv_emulation` (boolean, **default** `false`) : Enable argv emulation for macOS app bundles. If enabled, the initial open document/URL event is processed by the bootloader and the passed file paths or URLs are appended to sys.argv.
* `arch` (string, **default** `null`) : Target architecture (macOS only; valid values: x86_64, arm64, universal2).
* `hiddenimport` (string | list), **default** `null`) : Hidden imports needed by the program (eg PIL._tkinter_finder for customtkinter).
* `runtime_hooks` (List[str], **default** `null`): One or more runtime hook paths to bundle with the executable. These hooks are executed before any other code or module to set up special features of the runtime environment.
* `add_version` (bool, **default** `False`): Add `tool.poetry.version` to built executable (suffix)
* `when` (str, **default** `None`): Restrict build depending on package version. Possible values: `release`, `prerelease`. Target allways built when unset (default: `None`)

### Examples

```toml
[tool.poetry-pyinstaller-plugin]
# Pyinstaller version (Optional, latest if not set)
# Does not support version constraint (eg: ^6.4)
version = "6.7.0"

# Disable UPX compression
disable-upx = true

# Include metadata from selected packages (including dependencies)
recursive-copy-metadata = [
    "requests"
]

# Include metadata from selected packages
copy-metadata = [
    "boto3"
]

[tool.poetry-pyinstaller-plugin.scripts]
hello-world = "my_package/main.py"
# Equivalent to
hello-world = { source = "my_package/main.py", type = "onedir", bundle = false }

# Single file bundled in wheel
single-file-bundled = { source = "my_package/main.py", type = "onefile", bundle = true}

# Single file with package version in final executable name
hello-world = { source = "my_package/main.py", type = "onedir", add_version = true } # -> hello-world-X.X.X

# Restrict build on package version
hello-world = { source = "my_package/main.py", type = "onedir", when = "release" } # -> when tool.poetry.version == x.x.x
hello-world-internal = { source = "my_package/main.py", type = "onedir", when = "prerelease" } # -> when tool.poetry.version == x.x.x[a|b|rc]

# Folder bundled in wheel
folder-bundled = { source = "my_package/main.py", type = "onedir", bundle = true}

# Include a runtime hook
hook-example = { runtime_hooks = ['hooks/my_hook.py'], source = ... }

[tool.poetry-pyinstaller-plugin.certifi]
# Section dedicated to certifi, required if certificates must be included in certifi store
append = ['certs/my_cert.pem']

[tool.poetry-pyinstaller-plugin.collect]
# Collect all submodules, data files & binaries for 'package_A' and 'package_B'
all = ['package_A', 'package_B']
```

## Usage

Once configured `poetry-pyinstaller-plugin` is attached to the `poetry build` command.
```text
$ poetry build
Building binaries with PyInstaller Python 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0]
  - Building hello-world DIRECTORY
  - Built hello-world -> 'dist/pyinstaller/hello-world'
  - Building single-file-bundled SINGLE_FILE BUNDLED
  - Built single-file-bundled -> 'dist/pyinstaller/single-file-bundled'
  - Building folder-bundled DIRECTORY BUNDLED
  - Built folder-bundled -> 'dist/pyinstaller/folder-bundled'
Building my_package (0.0.0)
  - Building sdist
  - Built my_package-0.0.0.tar.gz
  - Building wheel
  - Built my_package-0.0.0-py3-none-any.whl
  - Adding single-file-bundled to data scripts my_package-0.0.0-py3-none-any.whl
  - Adding folder-bundled to data scripts my_package-0.0.0-py3-none-any.whl
Replacing platform in wheels (manylinux_2_35_x86_64)
  - my_package-0.0.0-py3-none-manylinux_2_35_x86_64.whl
```

### Build verbosity settings

Logging verbosity during PyInstaller build phase is configured through `poetry build` command using `--verbose/-v` option.

Available levels:
* `-v` : Set `--log-level=WARN`
* `-vv` : Set `--log-level=INFO`
* `-vvv` : Set `--log-level=DEBUG` & `--debug=all`
#### Example:
```text
$ poetry build --format pyinstaller -v
Using virtualenv: /home/.../.cache/pypoetry/virtualenvs/one-file-rP3OcWW--py3.10
  - Installing requests (>=2.32.3,<3.0.0)
Preparing PyInstaller 6.4.0 environment /home/.../.cache/pypoetry/virtualenvs/one-file-rP3OcWW--py3.10
Building binaries with PyInstaller Python 3.10 [manylinux_2_35_x86_64]
  - Building one-file SINGLE_FILE
      59 INFO: PyInstaller: 6.4.0, contrib hooks: 2024.7
      59 INFO: Python: 3.10.12
      60 INFO: Platform: Linux-6.5.0-41-generic-x86_64-with-glibc2.35
      60 INFO: wrote dist/pyinstaller/manylinux_2_35_x86_64/.specs/one-file.spec
      ...
      4009 INFO: Appending PKG archive to custom ELF section in EXE
      4020 INFO: Building EXE from EXE-00.toc completed successfully.
  - Built one-file -> 'dist/pyinstaller/manylinux_2_35_x86_64/one-file'
```

Expected directory structure:
```text
.
├── build ...................... PyInstaller intermediate build directory
│    ├── folder-bundled
│    ├── hello-world
│    └── single-file-bundled 
├── dist ....................... Result of `poetry build` command
│    ├── pyinstaller ............. PyInstaller output
│    │    ├── .specs/ ............ Specs files
│    │    ├── hello-world/
│    │    ├── folder-bundled/ 
│    │    └── single-file-bundled
│    ├── my_package-0.0.0-py3-none-manylinux_2_35_x86_64.whl ... Wheel with bundled binaries
│    └── my_package-0.0.0.tar.gz ............................... Source archive, binaries are never included
├── pyproject.toml
└── my_package
    ├── __init__.py
    └── main.py
```

## Dependencies notice

Major benefit of this plugin is to create dependency free wheels with executable binaries (including dependencies).

It is then recommended to include your dependencies as optional in your `pyproject.toml`

### Example
```toml
[tool.poetry]
name = "my-package"

[tool.poetry.dependencies]
python = "^3.8"
rich = {version = "^13.7.0", optional = true}

[tool.poetry.extras]
with-deps = ["rich"]
```

Resulting package will not require any dependency except if installed with extra `with-deps`.
```shell
# Installation without dependencies (included in executable binaries)
$ pip install my-package

# Installation with dependencies (If package imported as modules in another project)
$ pip install my-package[with-deps] 
```

Bundled binaries must be built with all dependencies installed in build environment.

## Packaging additional files

This plugin by default supports `tool.poetry.include`, but it can be disabled
for more control. You can also add files *next* to the executable by using the
`package` setting

### Example
```toml
[tool.poetry]
name = "my_project"
include = [
    { path = "README.md", format = ["sdist"] },
]

[tool.poetry-pyinstaller-plugin]
# Disable [tool.poetry.include] and use plugin settings instead
exclude-include = true

[tool.poetry-pyinstaller-plugin.scripts]
hello-world = "my_package/main.py"

[tool.poetry-pyinstaller-plugin.package]
# 1-1 next to executable
"README.md" = "."

# renaming next to executable
"user/README.md" = "USER_README.md"

# directory next to executable
"docs" = "."

[tool.poetry-pyinstaller-plugin.include]
# loose files in bundle
"icons/*" = "."

# entire directory in bundle
"images/*" = "element_images"
```

Expected directory structure:
```text
.
├── build ...................... PyInstaller intermediate build directory
├── dist ....................... Result of `poetry build` command
│    ├── pyinstaller ............. PyInstaller output
│    │    ├── .specs/ ............ Specs files
│    │    └── hello-world/
│    │          ├── docs/ ............ Packaged Docs
│    │          │     ├── how_to.md
│    │          │     └── if_breaks.md
│    │          ├── my_project_internal/ ............ Onedir bundle
│    │          │     ├── main_icon.svg ............... Included icon
│    │          │     ├── extra_icon.svg .............. Included icon
│    │          │     └── element_images/ ............. Included images
│    │          │           ├── footer_icon.svg
│    │          │           └── header_icon.svg
│    │          ├── my_project.exe ............ Bundled program
│    │          ├── README.md ................. Packaged Readme
│    │          └── USER_README.md. ........... Packaged User Readme
│    ├── my_package-0.0.0-py3-none-manylinux_2_35_x86_64.whl ... Wheel with bundled binaries
│    └── my_package-0.0.0.tar.gz ............................... Source archive, includes README.md
├── docs/
│    ├── how_to.md
│    └── if_breaks.md
├── user/
│    └── README.md
├── icons/
│    ├── main_icon.svg
│    └── extra_icon.svg
├── images/
│    ├── footer_icon.md
│    └── header_icon.svg
├── pyproject.toml
├── README.py
└── my_package
    ├── __init__.py
    └── main.py
```

## Hooks

The `pre-build` and `post-build` settings allow you to call a python function before and after the pyinstaller build. Each hook is passed a [hook interface](#hook_interface) class that allows access to Poetry, io and the virtual environment.

This lets you have further control in niche situations.

### Example
```toml
[tool.poetry]
name = "my_project"

[tool.poetry-pyinstaller-plugin]
# ran after requirements install and before builds
pre-build = "hooks.pyinstaller:post_build"

# ran after all builds are done
post-build = "hooks.pyinstaller:post_build"

[tool.poetry-pyinstaller-plugin.scripts]
hello-world = "my_package/main.py"

[tool.poetry-pyinstaller-plugin.package]
# package output from mkdocs
"site" = "docs"
```

<a name="hooks_pyinstaller"></a> **hooks/pyinstaller.py**:
```python
import shutil
from pathlib import Path
from typing import TYPE_CHECKING

def pre_build(interface) -> None:
    """
    Pyinstaller pre build hook. Build local documentation.
    """
    interface.write_line("  - <b>Building local docs</b>")

    test_group = interface.poetry.package._dependency_groups["docs"]  # noqa: SLF001
    for req in test_group.dependencies:
        pip_r = req.base_pep_508_name_resolved.replace(" (", "").replace(
            ")", ""
        )
        interface.write_line(f"    - Installing <c1>{req}</c1>")
        interface.run_pip(
            "install",
            "--disable-pip-version-check",
            "--ignore-installed",
            "--no-input",
            pip_r,
        )

    interface.run("poetry", "run", "mkdocs", "build", "--no-directory-urls")
    interface.write_line("    - <fg=green>Docs built</>")

def post_build(interface) -> None:
    """
    Pyinstaller post build hook. Version built directory, remove generated folders.
    """
    dist_path = Path("dist", "pyinstaller", interface.platform)
    version = interface.pyproject_data["tool"]["poetry"]["version"]

    interface.write_line("  - <b>Visioning built</b>")
    for script in interface.pyproject_data["tool"]["poetry-pyinstaller-plugin"]["scripts"]:
        source = Path(dist_path, script)
        destination = Path(dist_path, f"{script}_{version}")

        if destination.exists():
            shutil.rmtree(destination)  # remove existing

        shutil.move(f"{source}", f"{destination}")
        interface.write_line(
            f"    - Updated "
            f"<success>{script}</success> -> "
            f"<success>{script}_{version}</success>"
        )

    interface.write_line("  - <b>Cleaning</b>")
    shutil.rmtree(Path("build"))
    interface.write_line("    - Removed build directory")
    shutil.rmtree(Path("site"))
    interface.write_line("    - Removed site directory")
```

<details>

<summary><a name="hook_interface"></a>Hook Interface</summary>

Here are the attributes and functions for the hook interface class, see example [hook file](#hooks_pyinstaller) for basic usage.

> Note: If using linter(s), placing this class in a `TYPE_CHECKING` block will remove *most* errors.

```python
from typing import Dict, List, Any

class PyIntallerHookInterface:
    """
    Pyinstaller hook interface

    Attributes:
        _io (IO): cleo.io.io IO instance
        _venv (VirtualEnv): poetry.utils.env VirtualEnv instance
        poetry (Poetry): poetry.poetry Poetry instance
        pyproject_data (dict): pyproject.TOML contents
        platform (str): platform string
    """

    poetry: Any
    pyproject_data: Dict
    platform: str

    def run(self, command: str, *args: str) -> None:
        """Run command in virtual environment"""

    def run_pip(self, *args: str) -> None:
        """Install requirements in virtual environment"""

    def write_line(self, output: str) -> None:
        """Output message with Poetry IO"""
```

</details>


            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/thmahe/poetry-pyinstaller-plugin",
    "name": "poetry-pyinstaller-plugin",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<=3.13,>=3.8",
    "maintainer_email": null,
    "keywords": "poetry, plugin, pyinstaller, binary",
    "author": "Thomas Mah\u00e9",
    "author_email": "contact@tmahe.dev",
    "download_url": "https://files.pythonhosted.org/packages/b8/92/ce26d071cfb82efdd29b44ecad2f488d7a51d1155e71e2085e7ecda9d774/poetry_pyinstaller_plugin-1.2.1.tar.gz",
    "platform": null,
    "description": "# PyInstaller plugin for Poetry\n\nEasily create executable binaries from your `pyproject.toml` using [PyInstaller](https://pyinstaller.org).\n\n## Features\n* **Multiple distribution formats**\n  * **Single file** created in `dist` folder (executable archive)\n  * **Folder** created in `dist` folder (containing executable and libraries)\n  * **Bundled** executable in platform specific wheels as scripts\n    * Both single file & folder distribution type can be bundled in wheels\n\n## Installation\n\nTo install `poetry-pyinstaller-plugin` run the following command:\n```shell\npoetry self add poetry-pyinstaller-plugin\n# or\npipx inject poetry poetry-pyinstaller-plugin\n```\n\nIf you are having troubles to install the plugin please refer to Poetry documentation: https://python-poetry.org/docs/plugins/#using-plugins\n\n## Configuration\n\nAre listed in this sections all options available to configure `poetry-pyinstaller-plugin` in your `pyproject.toml`\n\n* `[tool.poetry-pyinstaller-plugin]`\n  * `version` (string) \n    * Version of PyInstaller to use during build\n    * Does not support version constraint\n  * `exclude-include` (boolean) \n    * Exclude poetry include. Default: `False`\n  * `pre-build` (string)\n    * Pre-build hook. `path.to.my.hook:pre-build-hook`\n  * `post-build` (string)\n    * Post-build hook. `path.to.my.hook:post-build-hook`\n  * `use-poetry-install` (boolean) \n    * The default mode `False` installs packages (including \"*pyinstaller*\", \"*certifi*\" & \"*cffi*\") to the actual\n      virtual environment by using internally pip. It will not use `poetry.lock` file, just the dependencies from the\n      `pyproject.toml` configuration file.\n    * When set to `True` the virtual environment should be completely installed by poetry including \"*pyinstaller*\"\n      and optional \"*certifi*\" & \"*cffi*\" (for custom certificates).\\\n      This is done by adding them as dependencies to the `pyproject.toml` configuration file and run `poetry install`\n      before starting `poetry build` command. Recommendation is the usage of an separate dependency group for\n      pyinstaller.\n  * `scripts` (dictionary) \n    * Where key is the program name and value a path to script or a `PyInstallerTarget` spec\n    * Example: `prog-name = \"my_package/script.py\"`\n  * `certifi` (dictionary)\n    * `append` (list): List of certificates to include in `certifi.where()`\n  * `collect` (dictionary)\n    * `submodules` (list): Collect all submodules for specified package(s) or module(s)\n    * `data` (list): Collect all data for specified package(s) or module(s)\n    * `binaries` (list): Collect all binaries for specified package(s) or module(s)\n    * `all` (list): Collect all submodules, data files, and binaries for specified package(s) or module(s)\n  * `copy-metadata` (list) : list of packages for which metadata must be copied\n  * `recursive-copy-metadata` (list) : list of packages for which metadata must be copied (including dependencies)\n  * `include` (dictionary) : \n    * Data file(s) to include. `{source: destination}`\n  * `package` (dictionary) : \n    * File(s) to include with executable. `{source: destination}`\n\n`PyinstallerTarget` spec:\n* `source` (string): Path to your program entrypoint\n* `type` (string, **default:** `onedir`): Type of distribution format. Must be one of `onefile`, `onedir`\n* `bundle` (boolean, **default:** `false`): Include executable binary onto wheel\n* `noupx` (boolean, **default:** `false`) : Disable UPX archiving\n* `strip` (boolean, **default** `false`) : Apply a symbol-table strip to the executable and shared libs (not recommended for Windows)\n* `console` (boolean, **default** `false`) : Open a console window for standard i/o (default). On Windows this option has no effect if the first script is a \u2018.pyw\u2019 file.\n* `windowed` (boolean, **default** `false`) : Windows and Mac OS X: do not provide a console window for standard i/o. On Mac OS this also triggers building a Mac OS .app bundle. On Windows this option is automatically set if the first script is a \u2018.pyw\u2019 file. This option is ignored on *NIX systems.\n* `icon` (Path, **default** PyInstaller\u2019s icon) : FILE.ico: apply the icon to a Windows executable. FILE.exe,ID: extract the icon with ID from an exe. FILE.icns: apply the icon to the .app bundle on Mac OS. Use \u201cNONE\u201d to not apply any icon, thereby making the OS to show some default\n* `uac_admin` (boolean, **default** `false`) : Using this option creates a Manifest that will request elevation upon application start.\n* `uac_uiaccess` (boolean, **default** `false`) : Using this option allows an elevated application to work with Remote Desktop.\n* `argv_emulation` (boolean, **default** `false`) : Enable argv emulation for macOS app bundles. If enabled, the initial open document/URL event is processed by the bootloader and the passed file paths or URLs are appended to sys.argv.\n* `arch` (string, **default** `null`) : Target architecture (macOS only; valid values: x86_64, arm64, universal2).\n* `hiddenimport` (string | list), **default** `null`) : Hidden imports needed by the program (eg PIL._tkinter_finder for customtkinter).\n* `runtime_hooks` (List[str], **default** `null`): One or more runtime hook paths to bundle with the executable. These hooks are executed before any other code or module to set up special features of the runtime environment.\n* `add_version` (bool, **default** `False`): Add `tool.poetry.version` to built executable (suffix)\n* `when` (str, **default** `None`): Restrict build depending on package version. Possible values: `release`, `prerelease`. Target allways built when unset (default: `None`)\n\n### Examples\n\n```toml\n[tool.poetry-pyinstaller-plugin]\n# Pyinstaller version (Optional, latest if not set)\n# Does not support version constraint (eg: ^6.4)\nversion = \"6.7.0\"\n\n# Disable UPX compression\ndisable-upx = true\n\n# Include metadata from selected packages (including dependencies)\nrecursive-copy-metadata = [\n    \"requests\"\n]\n\n# Include metadata from selected packages\ncopy-metadata = [\n    \"boto3\"\n]\n\n[tool.poetry-pyinstaller-plugin.scripts]\nhello-world = \"my_package/main.py\"\n# Equivalent to\nhello-world = { source = \"my_package/main.py\", type = \"onedir\", bundle = false }\n\n# Single file bundled in wheel\nsingle-file-bundled = { source = \"my_package/main.py\", type = \"onefile\", bundle = true}\n\n# Single file with package version in final executable name\nhello-world = { source = \"my_package/main.py\", type = \"onedir\", add_version = true } # -> hello-world-X.X.X\n\n# Restrict build on package version\nhello-world = { source = \"my_package/main.py\", type = \"onedir\", when = \"release\" } # -> when tool.poetry.version == x.x.x\nhello-world-internal = { source = \"my_package/main.py\", type = \"onedir\", when = \"prerelease\" } # -> when tool.poetry.version == x.x.x[a|b|rc]\n\n# Folder bundled in wheel\nfolder-bundled = { source = \"my_package/main.py\", type = \"onedir\", bundle = true}\n\n# Include a runtime hook\nhook-example = { runtime_hooks = ['hooks/my_hook.py'], source = ... }\n\n[tool.poetry-pyinstaller-plugin.certifi]\n# Section dedicated to certifi, required if certificates must be included in certifi store\nappend = ['certs/my_cert.pem']\n\n[tool.poetry-pyinstaller-plugin.collect]\n# Collect all submodules, data files & binaries for 'package_A' and 'package_B'\nall = ['package_A', 'package_B']\n```\n\n## Usage\n\nOnce configured `poetry-pyinstaller-plugin` is attached to the `poetry build` command.\n```text\n$ poetry build\nBuilding binaries with PyInstaller Python 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0]\n  - Building hello-world DIRECTORY\n  - Built hello-world -> 'dist/pyinstaller/hello-world'\n  - Building single-file-bundled SINGLE_FILE BUNDLED\n  - Built single-file-bundled -> 'dist/pyinstaller/single-file-bundled'\n  - Building folder-bundled DIRECTORY BUNDLED\n  - Built folder-bundled -> 'dist/pyinstaller/folder-bundled'\nBuilding my_package (0.0.0)\n  - Building sdist\n  - Built my_package-0.0.0.tar.gz\n  - Building wheel\n  - Built my_package-0.0.0-py3-none-any.whl\n  - Adding single-file-bundled to data scripts my_package-0.0.0-py3-none-any.whl\n  - Adding folder-bundled to data scripts my_package-0.0.0-py3-none-any.whl\nReplacing platform in wheels (manylinux_2_35_x86_64)\n  - my_package-0.0.0-py3-none-manylinux_2_35_x86_64.whl\n```\n\n### Build verbosity settings\n\nLogging verbosity during PyInstaller build phase is configured through `poetry build` command using `--verbose/-v` option.\n\nAvailable levels:\n* `-v` : Set `--log-level=WARN`\n* `-vv` : Set `--log-level=INFO`\n* `-vvv` : Set `--log-level=DEBUG` & `--debug=all`\n#### Example:\n```text\n$ poetry build --format pyinstaller -v\nUsing virtualenv: /home/.../.cache/pypoetry/virtualenvs/one-file-rP3OcWW--py3.10\n  - Installing requests (>=2.32.3,<3.0.0)\nPreparing PyInstaller 6.4.0 environment /home/.../.cache/pypoetry/virtualenvs/one-file-rP3OcWW--py3.10\nBuilding binaries with PyInstaller Python 3.10 [manylinux_2_35_x86_64]\n  - Building one-file SINGLE_FILE\n      59 INFO: PyInstaller: 6.4.0, contrib hooks: 2024.7\n      59 INFO: Python: 3.10.12\n      60 INFO: Platform: Linux-6.5.0-41-generic-x86_64-with-glibc2.35\n      60 INFO: wrote dist/pyinstaller/manylinux_2_35_x86_64/.specs/one-file.spec\n      ...\n      4009 INFO: Appending PKG archive to custom ELF section in EXE\n      4020 INFO: Building EXE from EXE-00.toc completed successfully.\n  - Built one-file -> 'dist/pyinstaller/manylinux_2_35_x86_64/one-file'\n```\n\nExpected directory structure:\n```text\n.\n\u251c\u2500\u2500 build ...................... PyInstaller intermediate build directory\n\u2502    \u251c\u2500\u2500 folder-bundled\n\u2502    \u251c\u2500\u2500 hello-world\n\u2502    \u2514\u2500\u2500 single-file-bundled \n\u251c\u2500\u2500 dist ....................... Result of `poetry build` command\n\u2502    \u251c\u2500\u2500 pyinstaller ............. PyInstaller output\n\u2502    \u2502    \u251c\u2500\u2500 .specs/ ............ Specs files\n\u2502    \u2502    \u251c\u2500\u2500 hello-world/\n\u2502    \u2502    \u251c\u2500\u2500 folder-bundled/ \n\u2502    \u2502    \u2514\u2500\u2500 single-file-bundled\n\u2502    \u251c\u2500\u2500 my_package-0.0.0-py3-none-manylinux_2_35_x86_64.whl ... Wheel with bundled binaries\n\u2502    \u2514\u2500\u2500 my_package-0.0.0.tar.gz ............................... Source archive, binaries are never included\n\u251c\u2500\u2500 pyproject.toml\n\u2514\u2500\u2500 my_package\n    \u251c\u2500\u2500 __init__.py\n    \u2514\u2500\u2500 main.py\n```\n\n## Dependencies notice\n\nMajor benefit of this plugin is to create dependency free wheels with executable binaries (including dependencies).\n\nIt is then recommended to include your dependencies as optional in your `pyproject.toml`\n\n### Example\n```toml\n[tool.poetry]\nname = \"my-package\"\n\n[tool.poetry.dependencies]\npython = \"^3.8\"\nrich = {version = \"^13.7.0\", optional = true}\n\n[tool.poetry.extras]\nwith-deps = [\"rich\"]\n```\n\nResulting package will not require any dependency except if installed with extra `with-deps`.\n```shell\n# Installation without dependencies (included in executable binaries)\n$ pip install my-package\n\n# Installation with dependencies (If package imported as modules in another project)\n$ pip install my-package[with-deps] \n```\n\nBundled binaries must be built with all dependencies installed in build environment.\n\n## Packaging additional files\n\nThis plugin by default supports `tool.poetry.include`, but it can be disabled\nfor more control. You can also add files *next* to the executable by using the\n`package` setting\n\n### Example\n```toml\n[tool.poetry]\nname = \"my_project\"\ninclude = [\n    { path = \"README.md\", format = [\"sdist\"] },\n]\n\n[tool.poetry-pyinstaller-plugin]\n# Disable [tool.poetry.include] and use plugin settings instead\nexclude-include = true\n\n[tool.poetry-pyinstaller-plugin.scripts]\nhello-world = \"my_package/main.py\"\n\n[tool.poetry-pyinstaller-plugin.package]\n# 1-1 next to executable\n\"README.md\" = \".\"\n\n# renaming next to executable\n\"user/README.md\" = \"USER_README.md\"\n\n# directory next to executable\n\"docs\" = \".\"\n\n[tool.poetry-pyinstaller-plugin.include]\n# loose files in bundle\n\"icons/*\" = \".\"\n\n# entire directory in bundle\n\"images/*\" = \"element_images\"\n```\n\nExpected directory structure:\n```text\n.\n\u251c\u2500\u2500 build ...................... PyInstaller intermediate build directory\n\u251c\u2500\u2500 dist ....................... Result of `poetry build` command\n\u2502    \u251c\u2500\u2500 pyinstaller ............. PyInstaller output\n\u2502    \u2502    \u251c\u2500\u2500 .specs/ ............ Specs files\n\u2502    \u2502    \u2514\u2500\u2500 hello-world/\n\u2502    \u2502          \u251c\u2500\u2500 docs/ ............ Packaged Docs\n\u2502    \u2502          \u2502     \u251c\u2500\u2500 how_to.md\n\u2502    \u2502          \u2502     \u2514\u2500\u2500 if_breaks.md\n\u2502    \u2502          \u251c\u2500\u2500 my_project_internal/ ............ Onedir bundle\n\u2502    \u2502          \u2502     \u251c\u2500\u2500 main_icon.svg ............... Included icon\n\u2502    \u2502          \u2502     \u251c\u2500\u2500 extra_icon.svg .............. Included icon\n\u2502    \u2502          \u2502     \u2514\u2500\u2500 element_images/ ............. Included images\n\u2502    \u2502          \u2502           \u251c\u2500\u2500 footer_icon.svg\n\u2502    \u2502          \u2502           \u2514\u2500\u2500 header_icon.svg\n\u2502    \u2502          \u251c\u2500\u2500 my_project.exe ............ Bundled program\n\u2502    \u2502          \u251c\u2500\u2500 README.md ................. Packaged Readme\n\u2502    \u2502          \u2514\u2500\u2500 USER_README.md. ........... Packaged User Readme\n\u2502    \u251c\u2500\u2500 my_package-0.0.0-py3-none-manylinux_2_35_x86_64.whl ... Wheel with bundled binaries\n\u2502    \u2514\u2500\u2500 my_package-0.0.0.tar.gz ............................... Source archive, includes README.md\n\u251c\u2500\u2500 docs/\n\u2502    \u251c\u2500\u2500 how_to.md\n\u2502    \u2514\u2500\u2500 if_breaks.md\n\u251c\u2500\u2500 user/\n\u2502    \u2514\u2500\u2500 README.md\n\u251c\u2500\u2500 icons/\n\u2502    \u251c\u2500\u2500 main_icon.svg\n\u2502    \u2514\u2500\u2500 extra_icon.svg\n\u251c\u2500\u2500 images/\n\u2502    \u251c\u2500\u2500 footer_icon.md\n\u2502    \u2514\u2500\u2500 header_icon.svg\n\u251c\u2500\u2500 pyproject.toml\n\u251c\u2500\u2500 README.py\n\u2514\u2500\u2500 my_package\n    \u251c\u2500\u2500 __init__.py\n    \u2514\u2500\u2500 main.py\n```\n\n## Hooks\n\nThe `pre-build` and `post-build` settings allow you to call a python function before and after the pyinstaller build. Each hook is passed a [hook interface](#hook_interface) class that allows access to Poetry, io and the virtual environment.\n\nThis lets you have further control in niche situations.\n\n### Example\n```toml\n[tool.poetry]\nname = \"my_project\"\n\n[tool.poetry-pyinstaller-plugin]\n# ran after requirements install and before builds\npre-build = \"hooks.pyinstaller:post_build\"\n\n# ran after all builds are done\npost-build = \"hooks.pyinstaller:post_build\"\n\n[tool.poetry-pyinstaller-plugin.scripts]\nhello-world = \"my_package/main.py\"\n\n[tool.poetry-pyinstaller-plugin.package]\n# package output from mkdocs\n\"site\" = \"docs\"\n```\n\n<a name=\"hooks_pyinstaller\"></a> **hooks/pyinstaller.py**:\n```python\nimport shutil\nfrom pathlib import Path\nfrom typing import TYPE_CHECKING\n\ndef pre_build(interface) -> None:\n    \"\"\"\n    Pyinstaller pre build hook. Build local documentation.\n    \"\"\"\n    interface.write_line(\"  - <b>Building local docs</b>\")\n\n    test_group = interface.poetry.package._dependency_groups[\"docs\"]  # noqa: SLF001\n    for req in test_group.dependencies:\n        pip_r = req.base_pep_508_name_resolved.replace(\" (\", \"\").replace(\n            \")\", \"\"\n        )\n        interface.write_line(f\"    - Installing <c1>{req}</c1>\")\n        interface.run_pip(\n            \"install\",\n            \"--disable-pip-version-check\",\n            \"--ignore-installed\",\n            \"--no-input\",\n            pip_r,\n        )\n\n    interface.run(\"poetry\", \"run\", \"mkdocs\", \"build\", \"--no-directory-urls\")\n    interface.write_line(\"    - <fg=green>Docs built</>\")\n\ndef post_build(interface) -> None:\n    \"\"\"\n    Pyinstaller post build hook. Version built directory, remove generated folders.\n    \"\"\"\n    dist_path = Path(\"dist\", \"pyinstaller\", interface.platform)\n    version = interface.pyproject_data[\"tool\"][\"poetry\"][\"version\"]\n\n    interface.write_line(\"  - <b>Visioning built</b>\")\n    for script in interface.pyproject_data[\"tool\"][\"poetry-pyinstaller-plugin\"][\"scripts\"]:\n        source = Path(dist_path, script)\n        destination = Path(dist_path, f\"{script}_{version}\")\n\n        if destination.exists():\n            shutil.rmtree(destination)  # remove existing\n\n        shutil.move(f\"{source}\", f\"{destination}\")\n        interface.write_line(\n            f\"    - Updated \"\n            f\"<success>{script}</success> -> \"\n            f\"<success>{script}_{version}</success>\"\n        )\n\n    interface.write_line(\"  - <b>Cleaning</b>\")\n    shutil.rmtree(Path(\"build\"))\n    interface.write_line(\"    - Removed build directory\")\n    shutil.rmtree(Path(\"site\"))\n    interface.write_line(\"    - Removed site directory\")\n```\n\n<details>\n\n<summary><a name=\"hook_interface\"></a>Hook Interface</summary>\n\nHere are the attributes and functions for the hook interface class, see example [hook file](#hooks_pyinstaller) for basic usage.\n\n> Note: If using linter(s), placing this class in a `TYPE_CHECKING` block will remove *most* errors.\n\n```python\nfrom typing import Dict, List, Any\n\nclass PyIntallerHookInterface:\n    \"\"\"\n    Pyinstaller hook interface\n\n    Attributes:\n        _io (IO): cleo.io.io IO instance\n        _venv (VirtualEnv): poetry.utils.env VirtualEnv instance\n        poetry (Poetry): poetry.poetry Poetry instance\n        pyproject_data (dict): pyproject.TOML contents\n        platform (str): platform string\n    \"\"\"\n\n    poetry: Any\n    pyproject_data: Dict\n    platform: str\n\n    def run(self, command: str, *args: str) -> None:\n        \"\"\"Run command in virtual environment\"\"\"\n\n    def run_pip(self, *args: str) -> None:\n        \"\"\"Install requirements in virtual environment\"\"\"\n\n    def write_line(self, output: str) -> None:\n        \"\"\"Output message with Poetry IO\"\"\"\n```\n\n</details>\n\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Poetry plugin to build and/or bundle executable binaries with PyInstaller",
    "version": "1.2.1",
    "project_urls": {
        "Homepage": "https://github.com/thmahe/poetry-pyinstaller-plugin",
        "Repository": "https://github.com/thmahe/poetry-pyinstaller-plugin"
    },
    "split_keywords": [
        "poetry",
        " plugin",
        " pyinstaller",
        " binary"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "3577cc39fb21be89692129910c882d8ae275be650fbf40cd793155b30cc8060a",
                "md5": "7263c27a5979af15f89e104e87e408a7",
                "sha256": "070318d1d92054f84c7fc58234fe68f68f3b2b0b5c954b24e77d97179a20b556"
            },
            "downloads": -1,
            "filename": "poetry_pyinstaller_plugin-1.2.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "7263c27a5979af15f89e104e87e408a7",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<=3.13,>=3.8",
            "size": 15595,
            "upload_time": "2024-10-30T20:57:06",
            "upload_time_iso_8601": "2024-10-30T20:57:06.075960Z",
            "url": "https://files.pythonhosted.org/packages/35/77/cc39fb21be89692129910c882d8ae275be650fbf40cd793155b30cc8060a/poetry_pyinstaller_plugin-1.2.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "b892ce26d071cfb82efdd29b44ecad2f488d7a51d1155e71e2085e7ecda9d774",
                "md5": "50e8ad90b985137d622ae5a592d4cd5e",
                "sha256": "c88511ccc8c3497b57f773f5f3993cbb3f4858b48c270593416261dc816dd2bc"
            },
            "downloads": -1,
            "filename": "poetry_pyinstaller_plugin-1.2.1.tar.gz",
            "has_sig": false,
            "md5_digest": "50e8ad90b985137d622ae5a592d4cd5e",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<=3.13,>=3.8",
            "size": 17821,
            "upload_time": "2024-10-30T20:57:07",
            "upload_time_iso_8601": "2024-10-30T20:57:07.022112Z",
            "url": "https://files.pythonhosted.org/packages/b8/92/ce26d071cfb82efdd29b44ecad2f488d7a51d1155e71e2085e7ecda9d774/poetry_pyinstaller_plugin-1.2.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-10-30 20:57:07",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "thmahe",
    "github_project": "poetry-pyinstaller-plugin",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "poetry-pyinstaller-plugin"
}
        
Elapsed time: 0.36705s