Metadata-Version: 2.5
Name: curlike
Version: 0.1.0
Summary: A drop-in curl: the real curl when there is one, with syshttp's proxy and hooks applied, else a curl-compatible command over the standard library
Project-URL: Homepage, https://github.com/jose-pr/curlike
Project-URL: Documentation, https://jose-pr.github.io/curlike/
Project-URL: Issues, https://github.com/jose-pr/curlike/issues
Author-email: jose-pr <jose-pr@coqui.dev>
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: duho<0.8,>=0.7.0
Requires-Dist: proxylib<3,>=2.0.2
Requires-Dist: syshttp<0.2,>=0.1.0
Provides-Extra: dev
Requires-Dist: black; extra == 'dev'
Requires-Dist: build; extra == 'dev'
Requires-Dist: netimps<0.5,>=0.4.1; extra == 'dev'
Requires-Dist: pytest; extra == 'dev'
Provides-Extra: dns
Requires-Dist: netimps<0.5,>=0.4.1; extra == 'dns'
Provides-Extra: docs
Requires-Dist: mkdocs; extra == 'docs'
Requires-Dist: mkdocs-material; extra == 'docs'
Requires-Dist: mkdocstrings[python]; extra == 'docs'
Description-Content-Type: text/markdown

# curlike

[![Version](https://img.shields.io/pypi/v/curlike.svg)](https://pypi.org/project/curlike/)
[![Python versions](https://img.shields.io/pypi/pyversions/curlike.svg)](https://pypi.org/project/curlike/)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/jose-pr/curlike/blob/main/LICENSE)
[![Docs](https://img.shields.io/badge/docs-latest-blue.svg)](https://jose-pr.github.io/curlike/)
[![CI](https://img.shields.io/github/actions/workflow/status/jose-pr/curlike/test.yml)](https://github.com/jose-pr/curlike/actions/workflows/test.yml)

**A `curl` that works everywhere Python does.** `pycurl` is a
curl-compatible command in pure Python, over the standard library, with
curl's exit codes and messages, checked line for line against real curl; and
`curlike` is the library behind it. It never runs the real curl.
Documentation: <https://jose-pr.github.io/curlike/>.

## Features

- **Answers as curl does** — the common surface (request,
  auth, body, output, downloads, TLS, proxies including SOCKS and https
  proxies, redirects, cookies, `-w`, `--retry`). The exit codes and messages
  are measured against curl's own builds, and the version it imitates is
  configurable.
- **Fails loud** — an option it does not implement is `curl: (2) Unsupported
  options: …`, never silently ignored.
- **Your own TLS context** — from Python, `curlike.main(argv, ssl_context=...)`
  runs the curl command line over a context you built: mutual TLS with a
  keystore identity, a cipher list, a pinned protocol version.
- **The system's proxy** — [syshttp](https://github.com/jose-pr/syshttp)
  routes it: `SYSHTTP_PROXY`, the `*_PROXY` variables, else the system's
  configuration for the URL (PAC and WPAD included), its `prefix[:/endpoint]`
  gateways included.

## Installation

```bash
pip install curlike
```

| Extra | Adds | Needed for |
| --- | --- | --- |
| `dns` | `netimps` | `--dns-servers`, `--dns-ipv4-addr`, `--dns-ipv6-addr`, `--dns-interface`, `--doh-url`, `--interface` by name |

## Quick start

```python
import curlike

rc = curlike.main(["-s", "-o", "page.html", "https://example.com/"])
```

Mutual TLS with a context of your own:

```python
import ssl
import curlike

ctx = ssl.create_default_context()
ctx.load_cert_chain("client.pem", "client.key")
rc = curlike.main(["-s", "https://mtls.example/"], ssl_context=ctx)
```

## Command line

```bash
pycurl https://example.com
pycurl -s -o out.json -H 'Accept: application/json' https://api.example.com/x
python -m curlike -X POST --json '{"k":1}' https://httpbin.org/post
```

## API overview

| Module | Purpose |
| --- | --- |
| `curlike` | `main()` / `run_fallback()`: the command; `caller_steering()`, `requested_url()`, `find_real_curl()`, `describe_curl()` for a launcher |

The other modules hold the command's option groups and transfer machinery
and are private.

## Settings

Every variable has a full name, read under each prefix of `SYSHTTP_PREFIX`
(a `:`-separated list of literal prefixes; none by default, so the names as
written): `SYSHTTP_PREFIX=AGENTS_` reads `AGENTS_SYSHTTP_PROXY`,
`AGENTS_HTTPS_PROXY` and `AGENTS_NO_PROXY` and nothing unprefixed, `AGENTS_:`
falls back to the plain names.

| Variable | Sets |
| --- | --- |
| `SYSHTTP_PREFIX` | the prefixes the variables below are read under (all but `CURL_CA_BUNDLE`) |
| `SYSHTTP_PROXY` and the other `SYSHTTP_*` proxy settings, `HTTP_PROXY` / `HTTPS_PROXY` / `ALL_PROXY`, `NO_PROXY` | the proxy and its bypass list, as [syshttp](https://jose-pr.github.io/syshttp/) reads them |
| `CURLIKE_PYLIB` | where to find duho when it is not installed: for a host tool that runs curlike from a zipapp (`.pyz`) or a vendored directory |
| `CURL_CA_BUNDLE` | the CA bundle, as in curl: read as written, under no prefix |

## Development

```bash
dotagents pyvenv            # or any Python 3.9+ virtual environment
.pyvenv/<tag>/Scripts/python -m pip install -e ../syshttp -e ".[dev]"
.pyvenv/<tag>/Scripts/python -m pytest -q
```

The parity tests compare curlike with the real curl on PATH, and are
skipped when there is none.

### Releasing

This project follows [Semantic Versioning](https://semver.org/) and keeps a
[`CHANGELOG.md`](https://github.com/jose-pr/curlike/blob/main/CHANGELOG.md).
Pushing a tag matching `v*` triggers the release workflow: test gate → build
(checking the tag names the version built) → a strict docs build as a gate →
GitHub release → publish. The release workflow never deploys the docs site
itself: for a final release its last job dispatches the docs workflow at the
tag, which owns every Pages deploy.

## License

MIT — see [LICENSE](https://github.com/jose-pr/curlike/blob/main/LICENSE).
