match-expression


Namematch-expression JSON
Version 0.1.2 PyPI version JSON
download
home_pageNone
SummaryA Python implementation of TypeScript's ts-pattern, type-safe pattern matching with an expressive API
upload_time2025-08-17 15:36:23
maintainerNone
docs_urlNone
authorNone
requires_python>=3.12
licenseMIT
keywords exhaustive functional match pattern pattern-matching ts-pattern type-safe typescript
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # match-expression

A Python implementation of TypeScript's [ts-pattern](https://github.com/gvergnaud/ts-pattern), bringing powerful, type-safe pattern matching to Python with an expressive, chainable API.

## Features

- **Chainable API**: Intuitive `match(value).case(pattern, then).exhaustive()` syntax
- **Type-safe**: Full type inference support with pyright/mypy
- **Exhaustiveness checking**: Ensures all cases are handled at compile time
- **Zero dependencies**: Lightweight and fast
- **Pythonic**: Leverages Python 3.12+ type system features

## Installation

```bash
pip install match_expression
```

## Quick Start

```python
from typing import Literal
from py_pattern import match

# Literal type matching
def process_status(status: Literal["pending", "success", "error"]) -> int:
    return (
        match(status)
        .case("pending", 0)
        .case("success", 1)
        .case("error", -1)
        .exhaustive()
    )

# Type matching with classes
class Dog:
    def bark(self) -> str:
        return "Woof!"

class Cat:
    def meow(self) -> str:
        return "Meow!"

def handle_animal(animal: Dog | Cat) -> str:
    return (
        match(animal)
        .case(Dog, lambda d: d.bark())
        .case(Cat, lambda c: c.meow())
        .exhaustive()
    )
```

## Examples

### Literal Type Matching

```python
from typing import Literal
from py_pattern import match

type Platform = Literal["web", "mobile", "desktop"]

def get_app_name(platform: Platform) -> str:
    return (
        match(platform)
        .case("web", "Web Application")
        .case("mobile", "Mobile App")
        .case("desktop", "Desktop Software")
        .exhaustive()
    )

# Type checker knows all cases are covered!
```

### Class Type Matching

```python
from py_pattern import match

class Success:
    def __init__(self, value: str):
        self.value = value

class Error:
    def __init__(self, message: str):
        self.message = message

def handle_result(result: Success | Error) -> str:
    return (
        match(result)
        .case(Success, lambda s: f"Success: {s.value}")
        .case(Error, lambda e: f"Error: {e.message}")
        .exhaustive()
    )
```

### Using `otherwise` for Default Cases

```python
from py_pattern import match

def classify_number(n: int) -> str:
    return (
        match(n)
        .case(0, "zero")
        .case(1, "one")
        .case(2, "two")
        .otherwise("many")
    )
```

### Mixed Return Types

The library correctly infers union return types:

```python
from py_pattern import match

def process(value: int | str) -> int | str:
    return (
        match(value)
        .case(int, lambda i: i * 2)      # Returns int
        .case(str, lambda s: s.upper())  # Returns str
        .exhaustive()
    )
    # Type is inferred as: int | str
```

## API Reference

### `match(value: V) -> Match[V]`
Starts a pattern matching chain.

### `.case(pattern: P, then: R) -> Case[V, P, R]`
Matches against a pattern. If the pattern matches, executes `then`.

- `pattern`: A value to match against (for literals) or a type (for isinstance checks)
- `then`: The value to return or a function to execute with the matched value

### `.exhaustive() -> R`
Ensures all cases are handled. Raises `ExhaustiveError` if not all cases are covered.

### `.otherwise(default: R) -> R`
Provides a default value for unmatched cases.

## Type Checking

The library is designed to work with type checkers like pyright and mypy:

```bash
# Install pyright
pip install pyright

# Type check your code
pyright your_file.py
```

## Contributing

Contributions are welcome! Here's how to get started:

1. Clone the repository
```bash
git clone https://github.com/qodot/match-expression.git
cd match-expression
```

2. Install development dependencies
```bash
uv sync --dev
```

3. Run tests
```bash
uv run pytest
```

4. Type check
```bash
uv run pyright src/ tests/
```

## Requirements

- Python 3.12 or higher
- No external dependencies

## License

MIT License - see LICENSE file for details
            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "match-expression",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.12",
    "maintainer_email": null,
    "keywords": "exhaustive, functional, match, pattern, pattern-matching, ts-pattern, type-safe, typescript",
    "author": null,
    "author_email": "Qodot <qodot@example.com>",
    "download_url": "https://files.pythonhosted.org/packages/e5/a7/cb495fa4e576640629d8e2a2e798f4594985df8029fe4c3e3fa6d251e858/match_expression-0.1.2.tar.gz",
    "platform": null,
    "description": "# match-expression\n\nA Python implementation of TypeScript's [ts-pattern](https://github.com/gvergnaud/ts-pattern), bringing powerful, type-safe pattern matching to Python with an expressive, chainable API.\n\n## Features\n\n- **Chainable API**: Intuitive `match(value).case(pattern, then).exhaustive()` syntax\n- **Type-safe**: Full type inference support with pyright/mypy\n- **Exhaustiveness checking**: Ensures all cases are handled at compile time\n- **Zero dependencies**: Lightweight and fast\n- **Pythonic**: Leverages Python 3.12+ type system features\n\n## Installation\n\n```bash\npip install match_expression\n```\n\n## Quick Start\n\n```python\nfrom typing import Literal\nfrom py_pattern import match\n\n# Literal type matching\ndef process_status(status: Literal[\"pending\", \"success\", \"error\"]) -> int:\n    return (\n        match(status)\n        .case(\"pending\", 0)\n        .case(\"success\", 1)\n        .case(\"error\", -1)\n        .exhaustive()\n    )\n\n# Type matching with classes\nclass Dog:\n    def bark(self) -> str:\n        return \"Woof!\"\n\nclass Cat:\n    def meow(self) -> str:\n        return \"Meow!\"\n\ndef handle_animal(animal: Dog | Cat) -> str:\n    return (\n        match(animal)\n        .case(Dog, lambda d: d.bark())\n        .case(Cat, lambda c: c.meow())\n        .exhaustive()\n    )\n```\n\n## Examples\n\n### Literal Type Matching\n\n```python\nfrom typing import Literal\nfrom py_pattern import match\n\ntype Platform = Literal[\"web\", \"mobile\", \"desktop\"]\n\ndef get_app_name(platform: Platform) -> str:\n    return (\n        match(platform)\n        .case(\"web\", \"Web Application\")\n        .case(\"mobile\", \"Mobile App\")\n        .case(\"desktop\", \"Desktop Software\")\n        .exhaustive()\n    )\n\n# Type checker knows all cases are covered!\n```\n\n### Class Type Matching\n\n```python\nfrom py_pattern import match\n\nclass Success:\n    def __init__(self, value: str):\n        self.value = value\n\nclass Error:\n    def __init__(self, message: str):\n        self.message = message\n\ndef handle_result(result: Success | Error) -> str:\n    return (\n        match(result)\n        .case(Success, lambda s: f\"Success: {s.value}\")\n        .case(Error, lambda e: f\"Error: {e.message}\")\n        .exhaustive()\n    )\n```\n\n### Using `otherwise` for Default Cases\n\n```python\nfrom py_pattern import match\n\ndef classify_number(n: int) -> str:\n    return (\n        match(n)\n        .case(0, \"zero\")\n        .case(1, \"one\")\n        .case(2, \"two\")\n        .otherwise(\"many\")\n    )\n```\n\n### Mixed Return Types\n\nThe library correctly infers union return types:\n\n```python\nfrom py_pattern import match\n\ndef process(value: int | str) -> int | str:\n    return (\n        match(value)\n        .case(int, lambda i: i * 2)      # Returns int\n        .case(str, lambda s: s.upper())  # Returns str\n        .exhaustive()\n    )\n    # Type is inferred as: int | str\n```\n\n## API Reference\n\n### `match(value: V) -> Match[V]`\nStarts a pattern matching chain.\n\n### `.case(pattern: P, then: R) -> Case[V, P, R]`\nMatches against a pattern. If the pattern matches, executes `then`.\n\n- `pattern`: A value to match against (for literals) or a type (for isinstance checks)\n- `then`: The value to return or a function to execute with the matched value\n\n### `.exhaustive() -> R`\nEnsures all cases are handled. Raises `ExhaustiveError` if not all cases are covered.\n\n### `.otherwise(default: R) -> R`\nProvides a default value for unmatched cases.\n\n## Type Checking\n\nThe library is designed to work with type checkers like pyright and mypy:\n\n```bash\n# Install pyright\npip install pyright\n\n# Type check your code\npyright your_file.py\n```\n\n## Contributing\n\nContributions are welcome! Here's how to get started:\n\n1. Clone the repository\n```bash\ngit clone https://github.com/qodot/match-expression.git\ncd match-expression\n```\n\n2. Install development dependencies\n```bash\nuv sync --dev\n```\n\n3. Run tests\n```bash\nuv run pytest\n```\n\n4. Type check\n```bash\nuv run pyright src/ tests/\n```\n\n## Requirements\n\n- Python 3.12 or higher\n- No external dependencies\n\n## License\n\nMIT License - see LICENSE file for details",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A Python implementation of TypeScript's ts-pattern, type-safe pattern matching with an expressive API",
    "version": "0.1.2",
    "project_urls": {
        "Bug Tracker": "https://github.com/qodot/match-expression/issues",
        "Homepage": "https://github.com/qodot/match-expression",
        "Repository": "https://github.com/qodot/match-expression"
    },
    "split_keywords": [
        "exhaustive",
        " functional",
        " match",
        " pattern",
        " pattern-matching",
        " ts-pattern",
        " type-safe",
        " typescript"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "3457838b51851dd08977295dad2b9ab68872fe0c7f99a90393263e30acb1987c",
                "md5": "afbfa567bc2bc77ee75f4b938d78eb18",
                "sha256": "62f3847495ae2a6c6c07c2ed4643c3683796c250bd1ed4a0043e1bacaa7ed794"
            },
            "downloads": -1,
            "filename": "match_expression-0.1.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "afbfa567bc2bc77ee75f4b938d78eb18",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.12",
            "size": 4751,
            "upload_time": "2025-08-17T15:36:22",
            "upload_time_iso_8601": "2025-08-17T15:36:22.673688Z",
            "url": "https://files.pythonhosted.org/packages/34/57/838b51851dd08977295dad2b9ab68872fe0c7f99a90393263e30acb1987c/match_expression-0.1.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "e5a7cb495fa4e576640629d8e2a2e798f4594985df8029fe4c3e3fa6d251e858",
                "md5": "34627ec514bc4ad21b20f9a283284315",
                "sha256": "e1e5fe34ac3f52bb41f2338b6c4c39e4a88416ef1c5762c06c906042a5939003"
            },
            "downloads": -1,
            "filename": "match_expression-0.1.2.tar.gz",
            "has_sig": false,
            "md5_digest": "34627ec514bc4ad21b20f9a283284315",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.12",
            "size": 5121,
            "upload_time": "2025-08-17T15:36:23",
            "upload_time_iso_8601": "2025-08-17T15:36:23.941195Z",
            "url": "https://files.pythonhosted.org/packages/e5/a7/cb495fa4e576640629d8e2a2e798f4594985df8029fe4c3e3fa6d251e858/match_expression-0.1.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-17 15:36:23",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "qodot",
    "github_project": "match-expression",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "match-expression"
}
        
Elapsed time: 2.32353s