tshu


Nametshu JSON
Version 0.1.1 PyPI version JSON
download
home_pageNone
SummaryRun safe and cross-platform bash commands using Python 3.14's t-strings
upload_time2025-07-29 10:19:19
maintainerNone
docs_urlNone
authorNone
requires_python>=3.14b4
licenseNone
keywords t-strings bash shell sh
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # ![](./docs/assets/tshu-logo.svg)

> [!WARNING]
> WIP. Until v1.0.0 is released, API is subject to drastic changes.

[![image](https://img.shields.io/pypi/v/tshu.svg)](https://pypi.python.org/pypi/tshu)
[![image](https://img.shields.io/pypi/l/tshu.svg)](https://github.com/aspizu/tshu/blob/main/LICENSE)
[![image](https://img.shields.io/pypi/pyversions/tshu.svg)](https://pypi.python.org/pypi/tshu)
[![Discord](https://img.shields.io/badge/Discord-%235865F2.svg?logo=discord&logoColor=white)](https://discord.gg/MMfMkRuhAf)

[**Documentation**](https://aspizu.github.io/tshu/)

Run safe and cross-platform bash commands using Python 3.14's t-strings

Uses [brush](https://github.com/reubeno/brush) for a cross-platform bash implementation.

```py
from tshu import sh
await sh(t"uv add tshu")
```

## Installation

```shell
uv add tshu
```

## Usage

```py
from tshu import sh
```

### Run a bash command.

Always use a t-string, regular strings are not allowed to prevent accidental usage of
f-strings.

```py
await sh(t"cat /usr/share/dict/words | wc -l")
```

### Run a bash command with user input

You still need to quote substitutions to prevent word-splitting. Word-splitting is a
feature, not a vuln.

Substitutions use variables to prevent shell injection. These temporary variables
are not accessible by child programs as they are not exported and have random names.

```py
await sh(t'cat "{__file__}" | wc -l')
```

### Exit code and check

By default, awaiting a command returns the exit code. [tshu.CommandError][] is raised
when a command returns a non-zero exit code. To disable this behaviour, either
pass `check=False` to `sh` or set `sh.check = False` to disable checking globally.

### Suppress command output

Either pass `quiet=True` or set `sh.quiet = True` to suppress output globally.

### Change working directory

Either pass `cwd=...` or set `sh.cwd = "..."`. You can use `pathlib.Path`.

### Set environment variables

Either modify `os.environ` or pass `env={}`. These are exported, so accessible to
child programs, use substitutions to pass user input.

### Pass standard input

input can be string or bytes.

```py
assert await sh(t"wc -l", input="1\n2\n3\n").json() == 3
```

### Capture the stdout, stderr of a program

```py
result = await sh(t"help").output()
result.returncode
result.stdout
result.stderr
```

### Get standard output directly

Use `.text()` to directly get the output as string (utf-8 encoded).

```py
contents = await sh(t"cat file.txt").text()
```

### Get standard output directly as bytes

```py
contents = await sh(t"cat file.bin").bytes()
```

### Get standard output parsed as JSON

```py
data = await sh(t"cat file.json").json()
```


            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "tshu",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.14b4",
    "maintainer_email": null,
    "keywords": "t-strings, bash, shell, sh",
    "author": null,
    "author_email": "Priyanshu Dangare <aspizu@protonmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/96/a8/4eb2366ad02f2179cef4fecaa403cca0d3dfaf14729f042edf275fb8a76d/tshu-0.1.1.tar.gz",
    "platform": null,
    "description": "# ![](./docs/assets/tshu-logo.svg)\n\n> [!WARNING]\n> WIP. Until v1.0.0 is released, API is subject to drastic changes.\n\n[![image](https://img.shields.io/pypi/v/tshu.svg)](https://pypi.python.org/pypi/tshu)\n[![image](https://img.shields.io/pypi/l/tshu.svg)](https://github.com/aspizu/tshu/blob/main/LICENSE)\n[![image](https://img.shields.io/pypi/pyversions/tshu.svg)](https://pypi.python.org/pypi/tshu)\n[![Discord](https://img.shields.io/badge/Discord-%235865F2.svg?logo=discord&logoColor=white)](https://discord.gg/MMfMkRuhAf)\n\n[**Documentation**](https://aspizu.github.io/tshu/)\n\nRun safe and cross-platform bash commands using Python 3.14's t-strings\n\nUses [brush](https://github.com/reubeno/brush) for a cross-platform bash implementation.\n\n```py\nfrom tshu import sh\nawait sh(t\"uv add tshu\")\n```\n\n## Installation\n\n```shell\nuv add tshu\n```\n\n## Usage\n\n```py\nfrom tshu import sh\n```\n\n### Run a bash command.\n\nAlways use a t-string, regular strings are not allowed to prevent accidental usage of\nf-strings.\n\n```py\nawait sh(t\"cat /usr/share/dict/words | wc -l\")\n```\n\n### Run a bash command with user input\n\nYou still need to quote substitutions to prevent word-splitting. Word-splitting is a\nfeature, not a vuln.\n\nSubstitutions use variables to prevent shell injection. These temporary variables\nare not accessible by child programs as they are not exported and have random names.\n\n```py\nawait sh(t'cat \"{__file__}\" | wc -l')\n```\n\n### Exit code and check\n\nBy default, awaiting a command returns the exit code. [tshu.CommandError][] is raised\nwhen a command returns a non-zero exit code. To disable this behaviour, either\npass `check=False` to `sh` or set `sh.check = False` to disable checking globally.\n\n### Suppress command output\n\nEither pass `quiet=True` or set `sh.quiet = True` to suppress output globally.\n\n### Change working directory\n\nEither pass `cwd=...` or set `sh.cwd = \"...\"`. You can use `pathlib.Path`.\n\n### Set environment variables\n\nEither modify `os.environ` or pass `env={}`. These are exported, so accessible to\nchild programs, use substitutions to pass user input.\n\n### Pass standard input\n\ninput can be string or bytes.\n\n```py\nassert await sh(t\"wc -l\", input=\"1\\n2\\n3\\n\").json() == 3\n```\n\n### Capture the stdout, stderr of a program\n\n```py\nresult = await sh(t\"help\").output()\nresult.returncode\nresult.stdout\nresult.stderr\n```\n\n### Get standard output directly\n\nUse `.text()` to directly get the output as string (utf-8 encoded).\n\n```py\ncontents = await sh(t\"cat file.txt\").text()\n```\n\n### Get standard output directly as bytes\n\n```py\ncontents = await sh(t\"cat file.bin\").bytes()\n```\n\n### Get standard output parsed as JSON\n\n```py\ndata = await sh(t\"cat file.json\").json()\n```\n\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Run safe and cross-platform bash commands using Python 3.14's t-strings",
    "version": "0.1.1",
    "project_urls": {
        "Documentation": "https://aspizu.github.io/tshu/",
        "Homepage": "https://github.com/aspizu/tshu",
        "Issues": "https://github.com/aspizu/tshu/issues",
        "Repository": "https://github.com/aspizu/tshu"
    },
    "split_keywords": [
        "t-strings",
        " bash",
        " shell",
        " sh"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "e11edfd93fcc21198f83cbc2537524c6389547a505511cc99cbd136c27484ed2",
                "md5": "af041ae74cae57db81adaa58970bfa0d",
                "sha256": "c62b68319c3b830095f199dda76059c3b224e9b97d6cb8f3f84a69d9610dd23c"
            },
            "downloads": -1,
            "filename": "tshu-0.1.1-cp314-cp314-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "af041ae74cae57db81adaa58970bfa0d",
            "packagetype": "bdist_wheel",
            "python_version": "cp314",
            "requires_python": ">=3.14b4",
            "size": 2672521,
            "upload_time": "2025-07-29T10:19:17",
            "upload_time_iso_8601": "2025-07-29T10:19:17.698927Z",
            "url": "https://files.pythonhosted.org/packages/e1/1e/dfd93fcc21198f83cbc2537524c6389547a505511cc99cbd136c27484ed2/tshu-0.1.1-cp314-cp314-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "96a84eb2366ad02f2179cef4fecaa403cca0d3dfaf14729f042edf275fb8a76d",
                "md5": "bb400b4ba6349032145ef5f285e4fcba",
                "sha256": "6b7049bc7d8ba8a6c6bb6e96c2106630116928633ca02b2df518edb9b56b3c5a"
            },
            "downloads": -1,
            "filename": "tshu-0.1.1.tar.gz",
            "has_sig": false,
            "md5_digest": "bb400b4ba6349032145ef5f285e4fcba",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.14b4",
            "size": 35285,
            "upload_time": "2025-07-29T10:19:19",
            "upload_time_iso_8601": "2025-07-29T10:19:19.150079Z",
            "url": "https://files.pythonhosted.org/packages/96/a8/4eb2366ad02f2179cef4fecaa403cca0d3dfaf14729f042edf275fb8a76d/tshu-0.1.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-29 10:19:19",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "aspizu",
    "github_project": "tshu",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "tshu"
}
        
Elapsed time: 0.74409s