pycrucible


Namepycrucible JSON
Version 0.3.0 PyPI version JSON
download
home_pageNone
SummaryPython wrapper for the PyCrucible CLI tool
upload_time2025-07-26 07:32:42
maintainerNone
docs_urlNone
authorNone
requires_python>=3.6
licenseMIT
keywords install python installer install python python packaging python build tool pycrucible pyinstaller py2exe python wrapper python cli tool
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            ![Poster image of PyCrucible](/assets/PyCrucible_poster.png)

## Overview
This tool runs a Python application using the UV binary. It extracts your application, optionally reads configuration from pycrucible.toml or pyproject.toml, and uses uv to execute it in an ephemeral environment.

## What does this mean?
You get a single self-contained binary that can be distributed across machines running the same platform. No Python installation is required - just an internet connection. Run the executable, and it takes care of the rest.

> [!NOTE]
> This readme is for version v0.3.x. A few important changes has been made, but mostly to the better use of tool.
>
> You can see all the changes in [CHANGELOG FILE](https://github.com/razorblade23/PyCrucible/blob/main/CHANGELOG.md).

## Documentation
Documentation can be found at [PyCrucible docs](https://pycrucible.razorblade23.dev).

## Documentation
Better documentation can be found at [docs](https://pycrucible.razorblade23.dev).

## How to get `PyCrucible`
There are a couple of ways to get PyCrucible.

### Using `PyPI`
PyCrucible is published to `PyPI` for every release. All you need to do is:
```bash
pip install pycrucible
```

### Using `Github Releases`
You can download pre-made binaries for your system from [Github Releases](https://github.com/razorblade23/PyCrucible/releases/latest) page

### Downloading and building from source code
1. Ensure you have [Rust](https://www.rust-lang.org/) installed.

2. Clone the repository
```git clone https://github.com/razorblade23/PyCrucible```

3. Change directory to be inside of a project
```cd PyCrucible```

4. Build Runner
```cargo build -p pycrucible_runner --release```

5. Build Pycrucible
```cargo build -p pycrucible --release```

> [!NOTE]
> The resulting binary will be in `target/release/pycrucible`.

## How to use `PyCrucible`
All you need for starting is a single `main.py` file with some code.

If you installed it using `pip` you can just run it with:
```bash
pycrucible -e .
```

This will embed your project and produce a new binary which is by default called `launcher` (or `launcher.exe` on Windows).
> [!TIP]
> To configure the output path and name of your binary, use `-o` or `--output` flag.
>
> Example: `pycrucible -e . -o ./myapp` (or `pycrucible -e . -o ./myapp.exe`)

This is now all you need to distribute your python project to other people.

No python required on their end. Just this single binary.

Running `pycrucible --help` reveals more options:
```bash
$ pycrucible --help
Tool to generate python executable by melding UV and python source code in crucible of one binary

Usage: pycrucible [OPTIONS]

Options:
  -e, --embed <EMBED>
          Directory containing Python project to embed. When specified, creates a new binary with the embedded project
  -o, --output <OUTPUT>
          Output path for the new binary when using --embed
      --uv-path <UV_PATH>
          Path to `uv` executable. If not found, it will be downloaded automatically [default: `.`]
      --debug
          Enable debug output
  -h, --help
          Print help
  -V, --version
          Print version
```


## How to configure `PyCrucible`
Configuration can be set in two files:
- `pycrucible.toml`
- `pyproject.toml`

> [!NOTE]
> When both `pycrucible.toml` and `pyproject.toml` are discovered, configuration from `pycrucible.toml` will take effect.

> [!IMPORTANT]
> When using any configuration, only `entrypoint` is required. Other options are optional.

> [!TIP]
> In both `pycrucible.toml` and `pyproject.toml` directive `entrypoint` can also be replaced by just `entry`.

Both of these files have exact same configuration options. You can find example file for `pycrucible.toml` [here](https://raw.githubusercontent.com/razorblade23/PyCrucible/refs/heads/main/pycrucible.toml.example)

In `pycrucible.toml` you would define configuration like this:
```toml
entrypoint = "src/main.py"
# or
entry = "src/main.py"

[options]
debug = false
extract_to_temp = false
delete_after_run = false

[package.patterns]
include = [
    "**/*.py",
]
exclude = [
    "**/__pycache__/**",
]

[env]
FOO = "foo"
BAR = "bar"

[hooks]
pre_run = "some_script.py"
post_run = "some_other_script.py"
```

In `pyproject.toml` you would define configuration like this:
```toml
[tool.pycrucible]
entrypoint = "src/main.py"
# or
entry = "src/main.py"

[tool.pycrucible.options]
debug = false
extract_to_temp = false
delete_after_run = false
offline_mode = false

[tool.pycrucible.patterns]
include = [
    "**/*.py",
]
exclude = [
    "**/__pycache__/**",
]

[tool.pycrucible.env]
FOO = "foo"
BAR = "bar"

[tool.pycrucible.hooks]
pre_run = "some_script.py"
post_run = "some_other_script.py"
```

### Update your project from GitHub
In configuration file its possible to set your GitHub repository, so the resulting binary will always check for update before running the application.

In `pycrucible.toml` it would look like this:
```toml
[source]
repository = "https://github.com/username/repo"
branch = "main"
update_strategy = "pull"
```


In `pyproject.toml` it would look like this-
```toml
[tool.pycrucible.source]
repository = "https://github.com/username/repo"
branch = "main"
update_strategy = "pull"
```

#### Default configuration
```python
entrypoint = "main.py"

# Options
debug = false
extract_to_temp = false
delete_after_run = false

# Patterns
patterns.include = [
    "**/*.py",
]
patterns.exclude = [
    ".venv/**/*",
    "**/__pycache__/**",
    ".git/**/*",
    "**/*.pyc",
    "**/*.pyo",
    "**/*.pyd"
]

# Source repository (GitHub)
source = None

# Enviroment variables
env = None

# Pre and post run hooks
hooks = None
```
If any of these configuration options is not used, it will be replaced with default value.
#### NOTE - `entrypoint` directive is required when using any configuration options.

## Features
- **Cross-Platform**: 
    - [x] Windows support
    - [x] macOS support (testing)
    - [x] Linux support
- **Small overhead**:
    - [x] Runner binary that embeds your project is **just 2 MB**. This ofcourse grows with embedding `uv` and your project.
- **Configurable**: 
    - [ ] Use `pycrucible.toml` or `pyproject.toml` to customize embedding details
        - [x] entrypoint
        - [x] include/exlude files
        - [x] arguments to `uv`
        - [x] env variables
        - [x] update source code from github
        - [x] pre and post run hooks (python scripts)
        - [ ] offline mode
        - [x] extract to temporary directory (removes temporary directory after running automaticly)
        - [x] remove extracted files after running
    - [x] Support for multiple ways of defining requirements
        - [x] `uv` initialized `pyproject.toml` (This is preffered !)
        - [x] `requirements.txt`
        - [x] `pylock.toml`
        - [x] `setup.py`
        - [x] `setup.cfg`
    - [x] Load the project as a directory
- **Tests**:
    - [x] Unit tests covering as much as i can make it

## Thanks to
The idea is inspired by [Packaged](https://packaged.live/).

Thanks to all the briliant developers at `Astral`.
They did awesome job with [uv](https://astral.sh/blog/uv).

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "pycrucible",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.6",
    "maintainer_email": null,
    "keywords": "install, python installer, install python, python packaging, python build tool, pycrucible, pyinstaller, py2exe, python wrapper, python cli tool",
    "author": null,
    "author_email": "razorblade23 <contact@razorblade23.dev>",
    "download_url": null,
    "platform": null,
    "description": "![Poster image of PyCrucible](/assets/PyCrucible_poster.png)\n\n## Overview\nThis tool runs a Python application using the UV binary. It extracts your application, optionally reads configuration from pycrucible.toml or pyproject.toml, and uses uv to execute it in an ephemeral environment.\n\n## What does this mean?\nYou get a single self-contained binary that can be distributed across machines running the same platform. No Python installation is required - just an internet connection. Run the executable, and it takes care of the rest.\n\n> [!NOTE]\n> This readme is for version v0.3.x. A few important changes has been made, but mostly to the better use of tool.\n>\n> You can see all the changes in [CHANGELOG FILE](https://github.com/razorblade23/PyCrucible/blob/main/CHANGELOG.md).\n\n## Documentation\nDocumentation can be found at [PyCrucible docs](https://pycrucible.razorblade23.dev).\n\n## Documentation\nBetter documentation can be found at [docs](https://pycrucible.razorblade23.dev).\n\n## How to get `PyCrucible`\nThere are a couple of ways to get PyCrucible.\n\n### Using `PyPI`\nPyCrucible is published to `PyPI` for every release. All you need to do is:\n```bash\npip install pycrucible\n```\n\n### Using `Github Releases`\nYou can download pre-made binaries for your system from [Github Releases](https://github.com/razorblade23/PyCrucible/releases/latest) page\n\n### Downloading and building from source code\n1. Ensure you have [Rust](https://www.rust-lang.org/) installed.\n\n2. Clone the repository\n```git clone https://github.com/razorblade23/PyCrucible```\n\n3. Change directory to be inside of a project\n```cd PyCrucible```\n\n4. Build Runner\n```cargo build -p pycrucible_runner --release```\n\n5. Build Pycrucible\n```cargo build -p pycrucible --release```\n\n> [!NOTE]\n> The resulting binary will be in `target/release/pycrucible`.\n\n## How to use `PyCrucible`\nAll you need for starting is a single `main.py` file with some code.\n\nIf you installed it using `pip` you can just run it with:\n```bash\npycrucible -e .\n```\n\nThis will embed your project and produce a new binary which is by default called `launcher` (or `launcher.exe` on Windows).\n> [!TIP]\n> To configure the output path and name of your binary, use `-o` or `--output` flag.\n>\n> Example: `pycrucible -e . -o ./myapp` (or `pycrucible -e . -o ./myapp.exe`)\n\nThis is now all you need to distribute your python project to other people.\n\nNo python required on their end. Just this single binary.\n\nRunning `pycrucible --help` reveals more options:\n```bash\n$ pycrucible --help\nTool to generate python executable by melding UV and python source code in crucible of one binary\n\nUsage: pycrucible [OPTIONS]\n\nOptions:\n  -e, --embed <EMBED>\n          Directory containing Python project to embed. When specified, creates a new binary with the embedded project\n  -o, --output <OUTPUT>\n          Output path for the new binary when using --embed\n      --uv-path <UV_PATH>\n          Path to `uv` executable. If not found, it will be downloaded automatically [default: `.`]\n      --debug\n          Enable debug output\n  -h, --help\n          Print help\n  -V, --version\n          Print version\n```\n\n\n## How to configure `PyCrucible`\nConfiguration can be set in two files:\n- `pycrucible.toml`\n- `pyproject.toml`\n\n> [!NOTE]\n> When both `pycrucible.toml` and `pyproject.toml` are discovered, configuration from `pycrucible.toml` will take effect.\n\n> [!IMPORTANT]\n> When using any configuration, only `entrypoint` is required. Other options are optional.\n\n> [!TIP]\n> In both `pycrucible.toml` and `pyproject.toml` directive `entrypoint` can also be replaced by just `entry`.\n\nBoth of these files have exact same configuration options. You can find example file for `pycrucible.toml` [here](https://raw.githubusercontent.com/razorblade23/PyCrucible/refs/heads/main/pycrucible.toml.example)\n\nIn `pycrucible.toml` you would define configuration like this:\n```toml\nentrypoint = \"src/main.py\"\n# or\nentry = \"src/main.py\"\n\n[options]\ndebug = false\nextract_to_temp = false\ndelete_after_run = false\n\n[package.patterns]\ninclude = [\n    \"**/*.py\",\n]\nexclude = [\n    \"**/__pycache__/**\",\n]\n\n[env]\nFOO = \"foo\"\nBAR = \"bar\"\n\n[hooks]\npre_run = \"some_script.py\"\npost_run = \"some_other_script.py\"\n```\n\nIn `pyproject.toml` you would define configuration like this:\n```toml\n[tool.pycrucible]\nentrypoint = \"src/main.py\"\n# or\nentry = \"src/main.py\"\n\n[tool.pycrucible.options]\ndebug = false\nextract_to_temp = false\ndelete_after_run = false\noffline_mode = false\n\n[tool.pycrucible.patterns]\ninclude = [\n    \"**/*.py\",\n]\nexclude = [\n    \"**/__pycache__/**\",\n]\n\n[tool.pycrucible.env]\nFOO = \"foo\"\nBAR = \"bar\"\n\n[tool.pycrucible.hooks]\npre_run = \"some_script.py\"\npost_run = \"some_other_script.py\"\n```\n\n### Update your project from GitHub\nIn configuration file its possible to set your GitHub repository, so the resulting binary will always check for update before running the application.\n\nIn `pycrucible.toml` it would look like this:\n```toml\n[source]\nrepository = \"https://github.com/username/repo\"\nbranch = \"main\"\nupdate_strategy = \"pull\"\n```\n\n\nIn `pyproject.toml` it would look like this-\n```toml\n[tool.pycrucible.source]\nrepository = \"https://github.com/username/repo\"\nbranch = \"main\"\nupdate_strategy = \"pull\"\n```\n\n#### Default configuration\n```python\nentrypoint = \"main.py\"\n\n# Options\ndebug = false\nextract_to_temp = false\ndelete_after_run = false\n\n# Patterns\npatterns.include = [\n    \"**/*.py\",\n]\npatterns.exclude = [\n    \".venv/**/*\",\n    \"**/__pycache__/**\",\n    \".git/**/*\",\n    \"**/*.pyc\",\n    \"**/*.pyo\",\n    \"**/*.pyd\"\n]\n\n# Source repository (GitHub)\nsource = None\n\n# Enviroment variables\nenv = None\n\n# Pre and post run hooks\nhooks = None\n```\nIf any of these configuration options is not used, it will be replaced with default value.\n#### NOTE - `entrypoint` directive is required when using any configuration options.\n\n## Features\n- **Cross-Platform**: \n    - [x] Windows support\n    - [x] macOS support (testing)\n    - [x] Linux support\n- **Small overhead**:\n    - [x] Runner binary that embeds your project is **just 2 MB**. This ofcourse grows with embedding `uv` and your project.\n- **Configurable**: \n    - [ ] Use `pycrucible.toml` or `pyproject.toml` to customize embedding details\n        - [x] entrypoint\n        - [x] include/exlude files\n        - [x] arguments to `uv`\n        - [x] env variables\n        - [x] update source code from github\n        - [x] pre and post run hooks (python scripts)\n        - [ ] offline mode\n        - [x] extract to temporary directory (removes temporary directory after running automaticly)\n        - [x] remove extracted files after running\n    - [x] Support for multiple ways of defining requirements\n        - [x] `uv` initialized `pyproject.toml` (This is preffered !)\n        - [x] `requirements.txt`\n        - [x] `pylock.toml`\n        - [x] `setup.py`\n        - [x] `setup.cfg`\n    - [x] Load the project as a directory\n- **Tests**:\n    - [x] Unit tests covering as much as i can make it\n\n## Thanks to\nThe idea is inspired by [Packaged](https://packaged.live/).\n\nThanks to all the briliant developers at `Astral`.\nThey did awesome job with [uv](https://astral.sh/blog/uv).\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Python wrapper for the PyCrucible CLI tool",
    "version": "0.3.0",
    "project_urls": {
        "Homepage": "https://github.com/razorblade23/PyCrucible",
        "Issues": "https://github.com/razorblade23/PyCrucible/issues",
        "Repository": "https://github.com/razorblade23/PyCrucible.git"
    },
    "split_keywords": [
        "install",
        " python installer",
        " install python",
        " python packaging",
        " python build tool",
        " pycrucible",
        " pyinstaller",
        " py2exe",
        " python wrapper",
        " python cli tool"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "1d6582b6a3e3d892ee821df3d5f252714589e61acdbfd21f16c76e4a88e6bedb",
                "md5": "26605fee402a79bf302becbbe17cbf62",
                "sha256": "31ebe993145bff3f4d99db4542a1546f90b4f3579793321b7ab936c6a62078e4"
            },
            "downloads": -1,
            "filename": "pycrucible-0.3.0-py3-none-macosx_10_12_x86_64.whl",
            "has_sig": false,
            "md5_digest": "26605fee402a79bf302becbbe17cbf62",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.6",
            "size": 2416443,
            "upload_time": "2025-07-26T07:32:42",
            "upload_time_iso_8601": "2025-07-26T07:32:42.536949Z",
            "url": "https://files.pythonhosted.org/packages/1d/65/82b6a3e3d892ee821df3d5f252714589e61acdbfd21f16c76e4a88e6bedb/pycrucible-0.3.0-py3-none-macosx_10_12_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "ae3a2b019100acce54149a2fa296de91930dd9e6af3c373f9cecc3555fb5a812",
                "md5": "0bb7ca3728534e224ac9a2b3a5eefb2a",
                "sha256": "14c4ddd1df7872af55e50bb1411c0323f6f4d61600f118378723a5e1adabaa1e"
            },
            "downloads": -1,
            "filename": "pycrucible-0.3.0-py3-none-manylinux_2_39_x86_64.whl",
            "has_sig": false,
            "md5_digest": "0bb7ca3728534e224ac9a2b3a5eefb2a",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.6",
            "size": 2706557,
            "upload_time": "2025-07-26T07:32:44",
            "upload_time_iso_8601": "2025-07-26T07:32:44.768178Z",
            "url": "https://files.pythonhosted.org/packages/ae/3a/2b019100acce54149a2fa296de91930dd9e6af3c373f9cecc3555fb5a812/pycrucible-0.3.0-py3-none-manylinux_2_39_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "f711b567431241933968076126590df1f9458b9ae751d011bf7746b209965a58",
                "md5": "921e045a0ac049512aac12420a5a3134",
                "sha256": "700830b0619e34482e7179e905fc92ec22af92ea97ee5d438cc276705f4bfc35"
            },
            "downloads": -1,
            "filename": "pycrucible-0.3.0-py3-none-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "921e045a0ac049512aac12420a5a3134",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.6",
            "size": 2596143,
            "upload_time": "2025-07-26T07:32:46",
            "upload_time_iso_8601": "2025-07-26T07:32:46.346780Z",
            "url": "https://files.pythonhosted.org/packages/f7/11/b567431241933968076126590df1f9458b9ae751d011bf7746b209965a58/pycrucible-0.3.0-py3-none-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-26 07:32:42",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "razorblade23",
    "github_project": "PyCrucible",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "pycrucible"
}
        
Elapsed time: 2.19449s