Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT}

USER vscode

RUN curl -sSf https://rye.astral.sh/get | RYE_VERSION="0.44.0" RYE_INSTALL_OPTION="--yes" bash
ENV PATH=/home/vscode/.rye/shims:$PATH
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

RUN echo "[[ -d .venv ]] && source .venv/bin/activate || export PATH=\$PATH" >> /home/vscode/.bashrc
4 changes: 2 additions & 2 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"context": ".."
},

"postStartCommand": "rye sync --all-features",
"postStartCommand": "uv sync --all-extras",

"customizations": {
"vscode": {
Expand All @@ -20,7 +20,7 @@
"python.defaultInterpreterPath": ".venv/bin/python",
"python.typeChecking": "basic",
"terminal.integrated.env.linux": {
"PATH": "/home/vscode/.rye/shims:${env:PATH}"
"PATH": "${env:PATH}"
}
}
}
Expand Down
39 changes: 15 additions & 24 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,13 @@ jobs:
steps:
- uses: actions/checkout@v6

- name: Install Rye
run: |
curl -sSf https://rye.astral.sh/get | bash
echo "$HOME/.rye/shims" >> $GITHUB_PATH
env:
RYE_VERSION: '0.44.0'
RYE_INSTALL_OPTION: '--yes'
- name: Install uv
uses: astral-sh/setup-uv@v5
with:
version: '0.9.13'

- name: Install dependencies
run: rye sync --all-features
run: uv sync --all-extras

- name: Run lints
run: ./scripts/lint
Expand All @@ -46,19 +43,16 @@ jobs:
steps:
- uses: actions/checkout@v6

- name: Install Rye
run: |
curl -sSf https://rye.astral.sh/get | bash
echo "$HOME/.rye/shims" >> $GITHUB_PATH
env:
RYE_VERSION: '0.44.0'
RYE_INSTALL_OPTION: '--yes'
- name: Install uv
uses: astral-sh/setup-uv@v5
with:
version: '0.9.13'

- name: Install dependencies
run: rye sync --all-features
run: uv sync --all-extras

- name: Run build
run: rye build
run: uv build

- name: Get GitHub OIDC Token
if: github.repository == 'stainless-sdks/cas-parser-python'
Expand All @@ -83,13 +77,10 @@ jobs:
steps:
- uses: actions/checkout@v6

- name: Install Rye
run: |
curl -sSf https://rye.astral.sh/get | bash
echo "$HOME/.rye/shims" >> $GITHUB_PATH
env:
RYE_VERSION: '0.44.0'
RYE_INSTALL_OPTION: '--yes'
- name: Install uv
uses: astral-sh/setup-uv@v5
with:
version: '0.9.13'

- name: Bootstrap
run: ./scripts/bootstrap
Expand Down
11 changes: 4 additions & 7 deletions .github/workflows/publish-pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,10 @@ jobs:
steps:
- uses: actions/checkout@v6

- name: Install Rye
run: |
curl -sSf https://rye.astral.sh/get | bash
echo "$HOME/.rye/shims" >> $GITHUB_PATH
env:
RYE_VERSION: '0.44.0'
RYE_INSTALL_OPTION: '--yes'
- name: Install uv
uses: astral-sh/setup-uv@v5
with:
version: '0.9.13'

- name: Publish to PyPI
run: |
Expand Down
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "1.2.1"
".": "1.3.0"
}
4 changes: 2 additions & 2 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 4
configured_endpoints: 17
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/cas-parser%2Fcas-parser-56b0f699c5437d9e5326626d35dfc972c17d01f12cb416c7f4854c8ea6d0e95e.yml
openapi_spec_hash: 158f405c1880706266d83e6ff16b9d2f
config_hash: cb5d75abef6264b5d86448caf7295afa
config_hash: c9c82d7a2437cc99fc06dd1f92cf76ab
2 changes: 1 addition & 1 deletion Brewfile
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
brew "rye"
brew "uv"

14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# Changelog

## 1.3.0 (2026-02-14)

Full Changelog: [v1.2.1...v1.3.0](https://github.com/CASParser/cas-parser-python/compare/v1.2.1...v1.3.0)

### Features

* **api:** manual updates ([98b1422](https://github.com/CASParser/cas-parser-python/commit/98b1422eadacacd06a45ffe4ce7dcab0e2dc9f1b))


### Chores

* update SDK settings ([7fcfc93](https://github.com/CASParser/cas-parser-python/commit/7fcfc935a8b94a8ad6401336cc52f9fe66ae3022))
* update SDK settings ([32181ec](https://github.com/CASParser/cas-parser-python/commit/32181ecb3c8bb0e523506b159320422ef565c411))

## 1.2.1 (2026-02-14)

Full Changelog: [v1.2.0...v1.2.1](https://github.com/CASParser/cas-parser-python/compare/v1.2.0...v1.2.1)
Expand Down
22 changes: 11 additions & 11 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
## Setting up the environment

### With Rye
### With `uv`

We use [Rye](https://rye.astral.sh/) to manage dependencies because it will automatically provision a Python environment with the expected Python version. To set it up, run:
We use [uv](https://docs.astral.sh/uv/) to manage dependencies because it will automatically provision a Python environment with the expected Python version. To set it up, run:

```sh
$ ./scripts/bootstrap
```

Or [install Rye manually](https://rye.astral.sh/guide/installation/) and run:
Or [install uv manually](https://docs.astral.sh/uv/getting-started/installation/) and run:

```sh
$ rye sync --all-features
$ uv sync --all-extras
```

You can then run scripts using `rye run python script.py` or by activating the virtual environment:
You can then run scripts using `uv run python script.py` or by manually activating the virtual environment:

```sh
# Activate the virtual environment - https://docs.python.org/3/library/venv.html#how-venvs-work
# manually activate - https://docs.python.org/3/library/venv.html#how-venvs-work
$ source .venv/bin/activate

# now you can omit the `rye run` prefix
# now you can omit the `uv run` prefix
$ python script.py
```

### Without Rye
### Without `uv`

Alternatively if you don't want to install `Rye`, you can stick with the standard `pip` setup by ensuring you have the Python version specified in `.python-version`, create a virtual environment however you desire and then install dependencies using this command:
Alternatively if you don't want to install `uv`, you can stick with the standard `pip` setup by ensuring you have the Python version specified in `.python-version`, create a virtual environment however you desire and then install dependencies using this command:

```sh
$ pip install -r requirements-dev.lock
Expand All @@ -45,7 +45,7 @@ All files in the `examples/` directory are not modified by the generator and can
```py
# add an example to examples/<your-example>.py

#!/usr/bin/env -S rye run python
#!/usr/bin/env -S uv run python
```

Expand All @@ -72,7 +72,7 @@ Building this package will create two files in the `dist/` directory, a `.tar.gz
To create a distributable version of the library, all you have to do is run this command:

```sh
$ rye build
$ uv build
# or
$ python -m build
```
Expand Down
71 changes: 21 additions & 50 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,23 @@
# Cas Parser Python API library

<!-- prettier-ignore -->
[![PyPI version](https://img.shields.io/pypi/v/cas-parser-python.svg?label=pypi%20(stable))](https://pypi.org/project/cas-parser-python/)
[![PyPI version](https://img.shields.io/pypi/v/cas_parser.svg?label=pypi%20(stable))](https://pypi.org/project/cas_parser/)

The Cas Parser Python library provides convenient access to the Cas Parser REST API from any Python 3.9+
application. The library includes type definitions for all request params and response fields,
and offers both synchronous and asynchronous clients powered by [httpx](https://github.com/encode/httpx).

It is generated with [Stainless](https://www.stainless.com/).

## MCP Server

Use the Cas Parser MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.

[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=cas-parser-node-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsImNhcy1wYXJzZXItbm9kZS1tY3AiXSwiZW52Ijp7IkNBU19QQVJTRVJfQVBJX0tFWSI6Ik15IEFQSSBLZXkifX0)
[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22cas-parser-node-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22cas-parser-node-mcp%22%5D%2C%22env%22%3A%7B%22CAS_PARSER_API_KEY%22%3A%22My%20API%20Key%22%7D%7D)

> Note: You may need to set environment variables in your MCP client.

## Documentation

The REST API documentation can be found on [docs.casparser.in](https://docs.casparser.in/reference). The full API of this library can be found in [api.md](api.md).
The full API of this library can be found in [api.md](api.md).

## Installation

```sh
# install from PyPI
pip install cas-parser-python
pip install cas_parser
```

## Usage
Expand All @@ -39,13 +30,12 @@ from cas_parser import CasParser

client = CasParser(
api_key=os.environ.get("CAS_PARSER_API_KEY"), # This is the default and can be omitted
# or 'production' | 'environment_2'; defaults to "production".
environment="environment_1",
)

unified_response = client.cas_parser.smart_parse(
password="ABCDF",
pdf_url="https://your-cas-pdf-url-here.com",
)
print(unified_response.demat_accounts)
response = client.credits.check()
print(response.enabled_features)
```

While you can provide an `api_key` keyword argument,
Expand All @@ -64,15 +54,14 @@ from cas_parser import AsyncCasParser

client = AsyncCasParser(
api_key=os.environ.get("CAS_PARSER_API_KEY"), # This is the default and can be omitted
# or 'production' | 'environment_2'; defaults to "production".
environment="environment_1",
)


async def main() -> None:
unified_response = await client.cas_parser.smart_parse(
password="ABCDF",
pdf_url="https://your-cas-pdf-url-here.com",
)
print(unified_response.demat_accounts)
response = await client.credits.check()
print(response.enabled_features)


asyncio.run(main())
Expand All @@ -88,7 +77,7 @@ You can enable this by installing `aiohttp`:

```sh
# install from PyPI
pip install cas-parser-python[aiohttp]
pip install cas_parser[aiohttp]
```

Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`:
Expand All @@ -105,11 +94,8 @@ async def main() -> None:
api_key=os.environ.get("CAS_PARSER_API_KEY"), # This is the default and can be omitted
http_client=DefaultAioHttpClient(),
) as client:
unified_response = await client.cas_parser.smart_parse(
password="ABCDF",
pdf_url="https://your-cas-pdf-url-here.com",
)
print(unified_response.demat_accounts)
response = await client.credits.check()
print(response.enabled_features)


asyncio.run(main())
Expand Down Expand Up @@ -140,10 +126,7 @@ from cas_parser import CasParser
client = CasParser()

try:
client.cas_parser.smart_parse(
password="ABCDF",
pdf_url="https://you-cas-pdf-url-here.com",
)
client.credits.check()
except cas_parser.APIConnectionError as e:
print("The server could not be reached")
print(e.__cause__) # an underlying Exception, likely raised within httpx.
Expand Down Expand Up @@ -186,10 +169,7 @@ client = CasParser(
)

# Or, configure per-request:
client.with_options(max_retries=5).cas_parser.smart_parse(
password="ABCDF",
pdf_url="https://you-cas-pdf-url-here.com",
)
client.with_options(max_retries=5).credits.check()
```

### Timeouts
Expand All @@ -212,10 +192,7 @@ client = CasParser(
)

# Override per-request:
client.with_options(timeout=5.0).cas_parser.smart_parse(
password="ABCDF",
pdf_url="https://you-cas-pdf-url-here.com",
)
client.with_options(timeout=5.0).credits.check()
```

On timeout, an `APITimeoutError` is thrown.
Expand Down Expand Up @@ -256,14 +233,11 @@ The "raw" Response object can be accessed by prefixing `.with_raw_response.` to
from cas_parser import CasParser

client = CasParser()
response = client.cas_parser.with_raw_response.smart_parse(
password="ABCDF",
pdf_url="https://you-cas-pdf-url-here.com",
)
response = client.credits.with_raw_response.check()
print(response.headers.get('X-My-Header'))

cas_parser = response.parse() # get the object that `cas_parser.smart_parse()` would have returned
print(cas_parser.demat_accounts)
credit = response.parse() # get the object that `credits.check()` would have returned
print(credit.enabled_features)
```

These methods return an [`APIResponse`](https://github.com/CASParser/cas-parser-python/tree/main/src/cas_parser/_response.py) object.
Expand All @@ -277,10 +251,7 @@ The above interface eagerly reads the full response body when you make the reque
To stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods.

```python
with client.cas_parser.with_streaming_response.smart_parse(
password="ABCDF",
pdf_url="https://you-cas-pdf-url-here.com",
) as response:
with client.credits.with_streaming_response.check() as response:
print(response.headers.get("X-My-Header"))

for line in response.iter_lines():
Expand Down
Loading