Metadata-Version: 2.4
Name: openapi-normalizer
Version: 0.1.0
Summary: Load, resolve, and normalise OpenAPI 3.x / Swagger 2.0 specs into a version-agnostic model.
Project-URL: Homepage, https://github.com/sssdavid529/openapi-normalizer
Project-URL: Repository, https://github.com/sssdavid529/openapi-normalizer
Project-URL: Issues, https://github.com/sssdavid529/openapi-normalizer/issues
Author: David
License-Expression: MIT
License-File: LICENSE
Keywords: api,normalizer,openapi,parser,specification,swagger
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
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: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Requires-Dist: pyyaml>=6.0
Provides-Extra: dev
Requires-Dist: mypy>=1.11; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Requires-Dist: types-pyyaml; extra == 'dev'
Description-Content-Type: text/markdown

# openapi-normalizer

[![PyPI](https://img.shields.io/pypi/v/openapi-normalizer.svg?style=flat)](https://pypi.org/project/openapi-normalizer/)
[![Python](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)

Load, resolve, and normalise **OpenAPI 3.x** and **Swagger 2.0**
specifications into a single, version-agnostic data model.

- 🔗 **$ref resolution** — resolves intra-document references with cycle protection
- 📦 **Version normalisation** — OpenAPI 3.x and Swagger 2.0 become the same internal model
- 🌐 **HTTP + local files** — load specs from URLs or filesystem paths
- 📄 **JSON + YAML** — both formats supported
- ✅ **Typed, tested, and linted**

## Installation

```bash
pip install openapi-normalizer
```

Requires Python 3.10+.

## Quickstart

```python
from openapi_normalizer import load_spec, resolve_refs, parse_spec

# Load from URL or file (JSON or YAML)
document = load_spec("https://petstore3.swagger.io/api/v3/openapi.json")

# Resolve all intra-document $ref pointers
document = resolve_refs(document)

# Normalise into a version-agnostic model
spec = parse_spec(document)

print(spec.title)     # "Swagger Petstore - OpenAPI 3.0"
print(spec.base_url)  # "/api/v3"
for op in spec.operations:
    print(op.method, op.path, op.operation_id)
```

## API

### `load_spec(ref, *, timeout=30.0) → dict`
Load a spec from a URL or local file. Returns the parsed document as a dict.

### `resolve_refs(document) → dict`
Resolve all local `$ref` pointers (e.g. `#/components/schemas/Pet`) in-place. External references are preserved. Cycles are broken safely.

### `detect_version(document) → str`
Return `"openapi-3"` or `"swagger-2"`.

### `parse_spec(document, *, source_ref=None, base_url_override=None) → ParsedSpec`
Normalise a ref-resolved document into a `ParsedSpec` containing:
- `title`, `base_url`, `spec_version`
- `operations` — list of `Operation` (method, path, parameters, request body, tags)
- `security_schemes` — dict of `SecurityScheme` (type, scheme, name, location)

## License

[MIT](LICENSE)
