python-postman 0.3.0__tar.gz → 0.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- python_postman-0.7.0/.github/workflows/python-publish.yml +65 -0
- {python-postman-0.3.0 → python_postman-0.7.0}/.gitignore +1 -0
- python_postman-0.7.0/PKG-INFO +331 -0
- python_postman-0.7.0/README.md +296 -0
- python_postman-0.7.0/pyproject.toml +97 -0
- python_postman-0.7.0/python_postman/__init__.py +85 -0
- python_postman-0.7.0/python_postman/exceptions/__init__.py +15 -0
- python_postman-0.7.0/python_postman/exceptions/base.py +28 -0
- python_postman-0.7.0/python_postman/exceptions/file_error.py +16 -0
- python_postman-0.7.0/python_postman/exceptions/parse_error.py +16 -0
- python_postman-0.7.0/python_postman/exceptions/validation_error.py +16 -0
- python_postman-0.7.0/python_postman/models/__init__.py +37 -0
- python_postman-0.7.0/python_postman/models/auth.py +360 -0
- python_postman-0.7.0/python_postman/models/body.py +605 -0
- python_postman-0.7.0/python_postman/models/collection.py +292 -0
- python_postman-0.7.0/python_postman/models/collection_info.py +95 -0
- python_postman-0.7.0/python_postman/models/event.py +219 -0
- python_postman-0.7.0/python_postman/models/folder.py +137 -0
- python_postman-0.7.0/python_postman/models/header.py +423 -0
- python_postman-0.7.0/python_postman/models/item.py +44 -0
- python_postman-0.7.0/python_postman/models/request.py +147 -0
- python_postman-0.7.0/python_postman/models/url.py +415 -0
- python_postman-0.7.0/python_postman/models/variable.py +234 -0
- python_postman-0.7.0/python_postman/parser.py +134 -0
- python_postman-0.7.0/python_postman/utils/__init__.py +8 -0
- python_postman-0.7.0/python_postman/utils/json_parser.py +139 -0
- python_postman-0.7.0/python_postman/utils/validators.py +36 -0
- python_postman-0.7.0/tests/__init__.py +1 -0
- python_postman-0.7.0/tests/test_auth.py +445 -0
- python_postman-0.7.0/tests/test_body.py +509 -0
- python_postman-0.7.0/tests/test_collection.py +119 -0
- python_postman-0.7.0/tests/test_collection_info.py +145 -0
- python_postman-0.7.0/tests/test_data/README.md +58 -0
- python_postman-0.7.0/tests/test_data/auth_collection.json +153 -0
- python_postman-0.7.0/tests/test_data/empty_collection.json +9 -0
- python_postman-0.7.0/tests/test_data/events_collection.json +91 -0
- python_postman-0.7.0/tests/test_data/invalid_collection.json +14 -0
- python_postman-0.7.0/tests/test_data/malformed_json.json +16 -0
- python_postman-0.7.0/tests/test_data/nested_collection.json +192 -0
- python_postman-0.7.0/tests/test_data/simple_collection.json +62 -0
- python_postman-0.7.0/tests/test_event.py +400 -0
- python_postman-0.7.0/tests/test_exceptions.py +185 -0
- python_postman-0.7.0/tests/test_folder.py +197 -0
- python_postman-0.7.0/tests/test_header.py +520 -0
- python_postman-0.7.0/tests/test_integration.py +495 -0
- python_postman-0.7.0/tests/test_item.py +72 -0
- python_postman-0.7.0/tests/test_json_parser.py +341 -0
- python_postman-0.7.0/tests/test_parser.py +399 -0
- python_postman-0.7.0/tests/test_request.py +114 -0
- python_postman-0.7.0/tests/test_url.py +362 -0
- python_postman-0.7.0/tests/test_variable.py +279 -0
- python_postman-0.7.0/uv.lock +450 -0
- python-postman-0.3.0/PKG-INFO +0 -73
- python-postman-0.3.0/README.md +0 -60
- python-postman-0.3.0/examples/collections/Coinmarketcap.postman_collection.json +0 -180
- python-postman-0.3.0/examples/collections/PokeAPI.postman_collection.json +0 -66
- python-postman-0.3.0/examples/models/coinmarketcap_example.py +0 -63
- python-postman-0.3.0/examples/models/pokeapi_example.py +0 -66
- python-postman-0.3.0/pypostman/__init__.py +0 -0
- python-postman-0.3.0/pypostman/__main__.py +0 -17
- python-postman-0.3.0/pypostman/auth.py +0 -77
- python-postman-0.3.0/pypostman/body.py +0 -8
- python-postman-0.3.0/pypostman/collection.py +0 -36
- python-postman-0.3.0/pypostman/config.py +0 -108
- python-postman-0.3.0/pypostman/environment.py +0 -101
- python-postman-0.3.0/pypostman/event.py +0 -30
- python-postman-0.3.0/pypostman/header.py +0 -18
- python-postman-0.3.0/pypostman/item.py +0 -28
- python-postman-0.3.0/pypostman/modules/file.py +0 -203
- python-postman-0.3.0/pypostman/modules/http.py +0 -126
- python-postman-0.3.0/pypostman/modules/logger.py +0 -49
- python-postman-0.3.0/pypostman/postman.py +0 -143
- python-postman-0.3.0/pypostman/request.py +0 -17
- python-postman-0.3.0/pypostman/template.py +0 -5
- python-postman-0.3.0/pypostman/url.py +0 -94
- python-postman-0.3.0/pypostman/utils/cli.py +0 -42
- python-postman-0.3.0/pypostman/utils/load_dotenvc.py +0 -99
- python-postman-0.3.0/pypostman/variable.py +0 -62
- python-postman-0.3.0/pyproject.toml +0 -23
- python-postman-0.3.0/python_postman.egg-info/PKG-INFO +0 -73
- python-postman-0.3.0/python_postman.egg-info/SOURCES.txt +0 -34
- python-postman-0.3.0/python_postman.egg-info/dependency_links.txt +0 -1
- python-postman-0.3.0/python_postman.egg-info/entry_points.txt +0 -2
- python-postman-0.3.0/python_postman.egg-info/requires.txt +0 -16
- python-postman-0.3.0/python_postman.egg-info/top_level.txt +0 -1
- python-postman-0.3.0/setup.cfg +0 -4
- {python-postman-0.3.0 → python_postman-0.7.0}/LICENSE +0 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# This workflow will upload a Python Package to PyPI when a release is published
|
|
2
|
+
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries
|
|
3
|
+
|
|
4
|
+
name: Publish Python Package to PyPI
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
release:
|
|
8
|
+
types: [published]
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
build:
|
|
15
|
+
name: Build distribution 📦
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- name: Checkout repository
|
|
19
|
+
uses: actions/checkout@v5
|
|
20
|
+
|
|
21
|
+
- name: Set up Python
|
|
22
|
+
uses: actions/setup-python@v6
|
|
23
|
+
with:
|
|
24
|
+
python-version: "3.x"
|
|
25
|
+
cache: pip # Cache pip dependencies for faster runs
|
|
26
|
+
|
|
27
|
+
- name: Install build dependencies
|
|
28
|
+
run: |
|
|
29
|
+
python -m pip install --upgrade pip
|
|
30
|
+
python -m pip install build
|
|
31
|
+
|
|
32
|
+
- name: Build package
|
|
33
|
+
run: python -m build
|
|
34
|
+
|
|
35
|
+
- name: Verify build artifacts
|
|
36
|
+
run: |
|
|
37
|
+
ls -la dist/
|
|
38
|
+
python -m pip install twine
|
|
39
|
+
python -m twine check dist/*
|
|
40
|
+
|
|
41
|
+
- name: Store the distribution packages
|
|
42
|
+
uses: actions/upload-artifact@v4
|
|
43
|
+
with:
|
|
44
|
+
name: python-package-distributions
|
|
45
|
+
path: dist/
|
|
46
|
+
|
|
47
|
+
publish-to-pypi:
|
|
48
|
+
name: Publish Python 🐍 distribution 📦 to PyPI
|
|
49
|
+
needs: [build]
|
|
50
|
+
runs-on: ubuntu-latest
|
|
51
|
+
environment:
|
|
52
|
+
name: pypi
|
|
53
|
+
url: https://pypi.org/p/${{ github.event.repository.name }}
|
|
54
|
+
permissions:
|
|
55
|
+
id-token: write # IMPORTANT: mandatory for trusted publishing
|
|
56
|
+
|
|
57
|
+
steps:
|
|
58
|
+
- name: Download all the dists
|
|
59
|
+
uses: actions/download-artifact@v4
|
|
60
|
+
with:
|
|
61
|
+
name: python-package-distributions
|
|
62
|
+
path: dist/
|
|
63
|
+
|
|
64
|
+
- name: Publish distribution 📦 to PyPI
|
|
65
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: python-postman
|
|
3
|
+
Version: 0.7.0
|
|
4
|
+
Summary: A Python library for parsing and working with Postman collection.json files
|
|
5
|
+
Project-URL: Homepage, https://github.com/python-postman/python-postman
|
|
6
|
+
Project-URL: Repository, https://github.com/python-postman/python-postman
|
|
7
|
+
Project-URL: Documentation, https://python-postman.readthedocs.io
|
|
8
|
+
Project-URL: Bug Tracker, https://github.com/python-postman/python-postman/issues
|
|
9
|
+
Author: Python Postman Contributors
|
|
10
|
+
License: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: api,collection,http,parser,postman,testing
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
25
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
26
|
+
Classifier: Topic :: Software Development :: Testing
|
|
27
|
+
Requires-Python: >=3.9
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: black>=23.0.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: isort>=5.12.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: mypy>=1.0.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
|
|
33
|
+
Requires-Dist: pytest>=8.4.2; extra == 'dev'
|
|
34
|
+
Description-Content-Type: text/markdown
|
|
35
|
+
|
|
36
|
+
# Python Postman Collection Parser
|
|
37
|
+
|
|
38
|
+
A Python library for parsing and working with Postman collection.json files. This library provides a clean, object-oriented interface for reading Postman collections and accessing their components programmatically.
|
|
39
|
+
|
|
40
|
+
## Features
|
|
41
|
+
|
|
42
|
+
- **Parse Postman Collections**: Load collections from files, JSON strings, or dictionaries
|
|
43
|
+
- **Object-Oriented API**: Work with collections using intuitive Python objects
|
|
44
|
+
- **Full Collection Support**: Access requests, folders, variables, authentication, and scripts
|
|
45
|
+
- **Validation**: Built-in validation for collection structure and schema compliance
|
|
46
|
+
- **Iteration**: Easy iteration through all requests regardless of folder structure
|
|
47
|
+
- **Search**: Find requests and folders by name
|
|
48
|
+
- **Type Hints**: Full type annotation support for better IDE experience
|
|
49
|
+
|
|
50
|
+
## Installation
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install python-postman
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Quick Start
|
|
57
|
+
|
|
58
|
+
### Loading a Collection
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
from python_postman import PythonPostman
|
|
62
|
+
|
|
63
|
+
# Load from file
|
|
64
|
+
collection = PythonPostman.from_file("path/to/collection.json")
|
|
65
|
+
|
|
66
|
+
# Load from JSON string
|
|
67
|
+
json_string = '{"info": {"name": "My Collection"}, "item": []}'
|
|
68
|
+
collection = PythonPostman.from_json(json_string)
|
|
69
|
+
|
|
70
|
+
# Load from dictionary
|
|
71
|
+
collection_dict = {"info": {"name": "My Collection"}, "item": []}
|
|
72
|
+
collection = PythonPostman.from_dict(collection_dict)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Accessing Collection Information
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
# Basic collection info
|
|
79
|
+
print(f"Collection Name: {collection.info.name}")
|
|
80
|
+
print(f"Description: {collection.info.description}")
|
|
81
|
+
print(f"Schema: {collection.info.schema}")
|
|
82
|
+
|
|
83
|
+
# Collection-level variables
|
|
84
|
+
for variable in collection.variables:
|
|
85
|
+
print(f"Variable: {variable.key} = {variable.value}")
|
|
86
|
+
|
|
87
|
+
# Collection-level authentication
|
|
88
|
+
if collection.auth:
|
|
89
|
+
print(f"Auth Type: {collection.auth.type}")
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Working with Requests
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
# Iterate through all requests (flattens folder structure)
|
|
96
|
+
for request in collection.get_all_requests():
|
|
97
|
+
print(f"Request: {request.method} {request.name}")
|
|
98
|
+
print(f"URL: {request.url}")
|
|
99
|
+
|
|
100
|
+
# Access headers
|
|
101
|
+
for header in request.headers:
|
|
102
|
+
print(f"Header: {header.key} = {header.value}")
|
|
103
|
+
|
|
104
|
+
# Access request body
|
|
105
|
+
if request.body:
|
|
106
|
+
print(f"Body Type: {request.body.mode}")
|
|
107
|
+
print(f"Body Content: {request.body.raw}")
|
|
108
|
+
|
|
109
|
+
# Find specific request by name
|
|
110
|
+
request = collection.get_request_by_name("Login Request")
|
|
111
|
+
if request:
|
|
112
|
+
print(f"Found request: {request.method} {request.url}")
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Working with Folders
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
# Access top-level items
|
|
119
|
+
for item in collection.items:
|
|
120
|
+
if hasattr(item, 'items'): # It's a folder
|
|
121
|
+
print(f"Folder: {item.name}")
|
|
122
|
+
print(f"Items in folder: {len(item.items)}")
|
|
123
|
+
|
|
124
|
+
# Get all requests in this folder
|
|
125
|
+
for request in item.get_requests():
|
|
126
|
+
print(f" Request: {request.name}")
|
|
127
|
+
else: # It's a request
|
|
128
|
+
print(f"Request: {item.name}")
|
|
129
|
+
|
|
130
|
+
# Find specific folder by name
|
|
131
|
+
folder = collection.get_folder_by_name("Authentication")
|
|
132
|
+
if folder:
|
|
133
|
+
print(f"Found folder: {folder.name}")
|
|
134
|
+
print(f"Subfolders: {len(folder.get_subfolders())}")
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Working with Variables
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
# Collection variables
|
|
141
|
+
for var in collection.variables:
|
|
142
|
+
print(f"Collection Variable: {var.key} = {var.value}")
|
|
143
|
+
if var.description:
|
|
144
|
+
print(f" Description: {var.description}")
|
|
145
|
+
|
|
146
|
+
# Folder variables (if folder has variables)
|
|
147
|
+
for item in collection.items:
|
|
148
|
+
if hasattr(item, 'variables') and item.variables:
|
|
149
|
+
print(f"Folder '{item.name}' variables:")
|
|
150
|
+
for var in item.variables:
|
|
151
|
+
print(f" {var.key} = {var.value}")
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Authentication
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
# Collection-level auth
|
|
158
|
+
if collection.auth:
|
|
159
|
+
print(f"Collection Auth: {collection.auth.type}")
|
|
160
|
+
|
|
161
|
+
# Access auth details based on type
|
|
162
|
+
if collection.auth.type == "bearer":
|
|
163
|
+
token = collection.auth.bearer.get("token")
|
|
164
|
+
print(f"Bearer Token: {token}")
|
|
165
|
+
elif collection.auth.type == "basic":
|
|
166
|
+
username = collection.auth.basic.get("username")
|
|
167
|
+
print(f"Basic Auth Username: {username}")
|
|
168
|
+
|
|
169
|
+
# Request-level auth (overrides collection auth)
|
|
170
|
+
for request in collection.get_all_requests():
|
|
171
|
+
if request.auth:
|
|
172
|
+
print(f"Request '{request.name}' has {request.auth.type} auth")
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Events (Scripts)
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
# Collection-level events
|
|
179
|
+
for event in collection.events:
|
|
180
|
+
print(f"Collection Event: {event.listen}")
|
|
181
|
+
print(f"Script: {event.script}")
|
|
182
|
+
|
|
183
|
+
# Request-level events
|
|
184
|
+
for request in collection.get_all_requests():
|
|
185
|
+
for event in request.events:
|
|
186
|
+
if event.listen == "prerequest":
|
|
187
|
+
print(f"Pre-request script for {request.name}")
|
|
188
|
+
elif event.listen == "test":
|
|
189
|
+
print(f"Test script for {request.name}")
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Validation
|
|
193
|
+
|
|
194
|
+
```python
|
|
195
|
+
# Validate collection structure
|
|
196
|
+
validation_result = collection.validate()
|
|
197
|
+
|
|
198
|
+
if validation_result.is_valid:
|
|
199
|
+
print("Collection is valid!")
|
|
200
|
+
else:
|
|
201
|
+
print("Collection validation failed:")
|
|
202
|
+
for error in validation_result.errors:
|
|
203
|
+
print(f" - {error}")
|
|
204
|
+
|
|
205
|
+
# Quick validation without creating full objects
|
|
206
|
+
is_valid = PythonPostman.validate_collection_dict(collection_dict)
|
|
207
|
+
print(f"Collection dict is valid: {is_valid}")
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Creating New Collections
|
|
211
|
+
|
|
212
|
+
```python
|
|
213
|
+
# Create a new empty collection
|
|
214
|
+
collection = PythonPostman.create_collection(
|
|
215
|
+
name="My New Collection",
|
|
216
|
+
description="A collection created programmatically"
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
print(f"Created collection: {collection.info.name}")
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## API Reference
|
|
223
|
+
|
|
224
|
+
### Main Classes
|
|
225
|
+
|
|
226
|
+
- **`PythonPostman`**: Main entry point for loading collections
|
|
227
|
+
- **`Collection`**: Represents a complete Postman collection
|
|
228
|
+
- **`Request`**: Individual HTTP request
|
|
229
|
+
- **`Folder`**: Container for organizing requests and sub-folders
|
|
230
|
+
- **`Variable`**: Collection, folder, or request-level variables
|
|
231
|
+
- **`Auth`**: Authentication configuration
|
|
232
|
+
- **`Event`**: Pre-request scripts and test scripts
|
|
233
|
+
|
|
234
|
+
### Exception Handling
|
|
235
|
+
|
|
236
|
+
The library provides specific exceptions for different error scenarios:
|
|
237
|
+
|
|
238
|
+
```python
|
|
239
|
+
from python_postman import (
|
|
240
|
+
PostmanCollectionError, # Base exception
|
|
241
|
+
CollectionParseError, # JSON parsing errors
|
|
242
|
+
CollectionValidationError, # Structure validation errors
|
|
243
|
+
CollectionFileError, # File operation errors
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
try:
|
|
247
|
+
collection = PythonPostman.from_file("collection.json")
|
|
248
|
+
except CollectionFileError as e:
|
|
249
|
+
print(f"File error: {e}")
|
|
250
|
+
except CollectionParseError as e:
|
|
251
|
+
print(f"Parse error: {e}")
|
|
252
|
+
except CollectionValidationError as e:
|
|
253
|
+
print(f"Validation error: {e}")
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## Requirements
|
|
257
|
+
|
|
258
|
+
- Python 3.8+
|
|
259
|
+
- No external dependencies for core functionality
|
|
260
|
+
|
|
261
|
+
## Development
|
|
262
|
+
|
|
263
|
+
### Setting up Development Environment
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
# Clone the repository
|
|
267
|
+
git clone https://github.com/python-postman/python-postman.git
|
|
268
|
+
cd python-postman
|
|
269
|
+
|
|
270
|
+
# Install development dependencies
|
|
271
|
+
pip install -e ".[dev]"
|
|
272
|
+
|
|
273
|
+
# Run tests
|
|
274
|
+
pytest
|
|
275
|
+
|
|
276
|
+
# Run tests with coverage
|
|
277
|
+
pytest --cov=python_postman
|
|
278
|
+
|
|
279
|
+
# Format code
|
|
280
|
+
black python_postman tests
|
|
281
|
+
isort python_postman tests
|
|
282
|
+
|
|
283
|
+
# Type checking
|
|
284
|
+
mypy python_postman
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Running Tests
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
# Run all tests
|
|
291
|
+
pytest
|
|
292
|
+
|
|
293
|
+
# Run specific test file
|
|
294
|
+
pytest tests/test_collection.py
|
|
295
|
+
|
|
296
|
+
# Run with verbose output
|
|
297
|
+
pytest -v
|
|
298
|
+
|
|
299
|
+
# Run with coverage report
|
|
300
|
+
pytest --cov=python_postman --cov-report=html
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
## Contributing
|
|
304
|
+
|
|
305
|
+
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
|
|
306
|
+
|
|
307
|
+
1. Fork the repository
|
|
308
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
309
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
310
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
311
|
+
5. Open a Pull Request
|
|
312
|
+
|
|
313
|
+
## License
|
|
314
|
+
|
|
315
|
+
This project is licensed under the MIT License - see the LICENSE file for details.
|
|
316
|
+
|
|
317
|
+
## Changelog
|
|
318
|
+
|
|
319
|
+
### 0.7.0 (Updated version)
|
|
320
|
+
|
|
321
|
+
- Updated version to 0.7.0
|
|
322
|
+
- Updated README.md
|
|
323
|
+
- Updated pyproject.toml
|
|
324
|
+
- Updated tests
|
|
325
|
+
- Updated docs
|
|
326
|
+
- Updated examples
|
|
327
|
+
- Updated code
|
|
328
|
+
|
|
329
|
+
## Support
|
|
330
|
+
|
|
331
|
+
If you encounter any issues or have questions, please file an issue on the [GitHub issue tracker](https://github.com/python-postman/python-postman/issues).
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
# Python Postman Collection Parser
|
|
2
|
+
|
|
3
|
+
A Python library for parsing and working with Postman collection.json files. This library provides a clean, object-oriented interface for reading Postman collections and accessing their components programmatically.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Parse Postman Collections**: Load collections from files, JSON strings, or dictionaries
|
|
8
|
+
- **Object-Oriented API**: Work with collections using intuitive Python objects
|
|
9
|
+
- **Full Collection Support**: Access requests, folders, variables, authentication, and scripts
|
|
10
|
+
- **Validation**: Built-in validation for collection structure and schema compliance
|
|
11
|
+
- **Iteration**: Easy iteration through all requests regardless of folder structure
|
|
12
|
+
- **Search**: Find requests and folders by name
|
|
13
|
+
- **Type Hints**: Full type annotation support for better IDE experience
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install python-postman
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
### Loading a Collection
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
from python_postman import PythonPostman
|
|
27
|
+
|
|
28
|
+
# Load from file
|
|
29
|
+
collection = PythonPostman.from_file("path/to/collection.json")
|
|
30
|
+
|
|
31
|
+
# Load from JSON string
|
|
32
|
+
json_string = '{"info": {"name": "My Collection"}, "item": []}'
|
|
33
|
+
collection = PythonPostman.from_json(json_string)
|
|
34
|
+
|
|
35
|
+
# Load from dictionary
|
|
36
|
+
collection_dict = {"info": {"name": "My Collection"}, "item": []}
|
|
37
|
+
collection = PythonPostman.from_dict(collection_dict)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Accessing Collection Information
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
# Basic collection info
|
|
44
|
+
print(f"Collection Name: {collection.info.name}")
|
|
45
|
+
print(f"Description: {collection.info.description}")
|
|
46
|
+
print(f"Schema: {collection.info.schema}")
|
|
47
|
+
|
|
48
|
+
# Collection-level variables
|
|
49
|
+
for variable in collection.variables:
|
|
50
|
+
print(f"Variable: {variable.key} = {variable.value}")
|
|
51
|
+
|
|
52
|
+
# Collection-level authentication
|
|
53
|
+
if collection.auth:
|
|
54
|
+
print(f"Auth Type: {collection.auth.type}")
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Working with Requests
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
# Iterate through all requests (flattens folder structure)
|
|
61
|
+
for request in collection.get_all_requests():
|
|
62
|
+
print(f"Request: {request.method} {request.name}")
|
|
63
|
+
print(f"URL: {request.url}")
|
|
64
|
+
|
|
65
|
+
# Access headers
|
|
66
|
+
for header in request.headers:
|
|
67
|
+
print(f"Header: {header.key} = {header.value}")
|
|
68
|
+
|
|
69
|
+
# Access request body
|
|
70
|
+
if request.body:
|
|
71
|
+
print(f"Body Type: {request.body.mode}")
|
|
72
|
+
print(f"Body Content: {request.body.raw}")
|
|
73
|
+
|
|
74
|
+
# Find specific request by name
|
|
75
|
+
request = collection.get_request_by_name("Login Request")
|
|
76
|
+
if request:
|
|
77
|
+
print(f"Found request: {request.method} {request.url}")
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Working with Folders
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
# Access top-level items
|
|
84
|
+
for item in collection.items:
|
|
85
|
+
if hasattr(item, 'items'): # It's a folder
|
|
86
|
+
print(f"Folder: {item.name}")
|
|
87
|
+
print(f"Items in folder: {len(item.items)}")
|
|
88
|
+
|
|
89
|
+
# Get all requests in this folder
|
|
90
|
+
for request in item.get_requests():
|
|
91
|
+
print(f" Request: {request.name}")
|
|
92
|
+
else: # It's a request
|
|
93
|
+
print(f"Request: {item.name}")
|
|
94
|
+
|
|
95
|
+
# Find specific folder by name
|
|
96
|
+
folder = collection.get_folder_by_name("Authentication")
|
|
97
|
+
if folder:
|
|
98
|
+
print(f"Found folder: {folder.name}")
|
|
99
|
+
print(f"Subfolders: {len(folder.get_subfolders())}")
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Working with Variables
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
# Collection variables
|
|
106
|
+
for var in collection.variables:
|
|
107
|
+
print(f"Collection Variable: {var.key} = {var.value}")
|
|
108
|
+
if var.description:
|
|
109
|
+
print(f" Description: {var.description}")
|
|
110
|
+
|
|
111
|
+
# Folder variables (if folder has variables)
|
|
112
|
+
for item in collection.items:
|
|
113
|
+
if hasattr(item, 'variables') and item.variables:
|
|
114
|
+
print(f"Folder '{item.name}' variables:")
|
|
115
|
+
for var in item.variables:
|
|
116
|
+
print(f" {var.key} = {var.value}")
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Authentication
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
# Collection-level auth
|
|
123
|
+
if collection.auth:
|
|
124
|
+
print(f"Collection Auth: {collection.auth.type}")
|
|
125
|
+
|
|
126
|
+
# Access auth details based on type
|
|
127
|
+
if collection.auth.type == "bearer":
|
|
128
|
+
token = collection.auth.bearer.get("token")
|
|
129
|
+
print(f"Bearer Token: {token}")
|
|
130
|
+
elif collection.auth.type == "basic":
|
|
131
|
+
username = collection.auth.basic.get("username")
|
|
132
|
+
print(f"Basic Auth Username: {username}")
|
|
133
|
+
|
|
134
|
+
# Request-level auth (overrides collection auth)
|
|
135
|
+
for request in collection.get_all_requests():
|
|
136
|
+
if request.auth:
|
|
137
|
+
print(f"Request '{request.name}' has {request.auth.type} auth")
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Events (Scripts)
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
# Collection-level events
|
|
144
|
+
for event in collection.events:
|
|
145
|
+
print(f"Collection Event: {event.listen}")
|
|
146
|
+
print(f"Script: {event.script}")
|
|
147
|
+
|
|
148
|
+
# Request-level events
|
|
149
|
+
for request in collection.get_all_requests():
|
|
150
|
+
for event in request.events:
|
|
151
|
+
if event.listen == "prerequest":
|
|
152
|
+
print(f"Pre-request script for {request.name}")
|
|
153
|
+
elif event.listen == "test":
|
|
154
|
+
print(f"Test script for {request.name}")
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Validation
|
|
158
|
+
|
|
159
|
+
```python
|
|
160
|
+
# Validate collection structure
|
|
161
|
+
validation_result = collection.validate()
|
|
162
|
+
|
|
163
|
+
if validation_result.is_valid:
|
|
164
|
+
print("Collection is valid!")
|
|
165
|
+
else:
|
|
166
|
+
print("Collection validation failed:")
|
|
167
|
+
for error in validation_result.errors:
|
|
168
|
+
print(f" - {error}")
|
|
169
|
+
|
|
170
|
+
# Quick validation without creating full objects
|
|
171
|
+
is_valid = PythonPostman.validate_collection_dict(collection_dict)
|
|
172
|
+
print(f"Collection dict is valid: {is_valid}")
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Creating New Collections
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
# Create a new empty collection
|
|
179
|
+
collection = PythonPostman.create_collection(
|
|
180
|
+
name="My New Collection",
|
|
181
|
+
description="A collection created programmatically"
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
print(f"Created collection: {collection.info.name}")
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## API Reference
|
|
188
|
+
|
|
189
|
+
### Main Classes
|
|
190
|
+
|
|
191
|
+
- **`PythonPostman`**: Main entry point for loading collections
|
|
192
|
+
- **`Collection`**: Represents a complete Postman collection
|
|
193
|
+
- **`Request`**: Individual HTTP request
|
|
194
|
+
- **`Folder`**: Container for organizing requests and sub-folders
|
|
195
|
+
- **`Variable`**: Collection, folder, or request-level variables
|
|
196
|
+
- **`Auth`**: Authentication configuration
|
|
197
|
+
- **`Event`**: Pre-request scripts and test scripts
|
|
198
|
+
|
|
199
|
+
### Exception Handling
|
|
200
|
+
|
|
201
|
+
The library provides specific exceptions for different error scenarios:
|
|
202
|
+
|
|
203
|
+
```python
|
|
204
|
+
from python_postman import (
|
|
205
|
+
PostmanCollectionError, # Base exception
|
|
206
|
+
CollectionParseError, # JSON parsing errors
|
|
207
|
+
CollectionValidationError, # Structure validation errors
|
|
208
|
+
CollectionFileError, # File operation errors
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
try:
|
|
212
|
+
collection = PythonPostman.from_file("collection.json")
|
|
213
|
+
except CollectionFileError as e:
|
|
214
|
+
print(f"File error: {e}")
|
|
215
|
+
except CollectionParseError as e:
|
|
216
|
+
print(f"Parse error: {e}")
|
|
217
|
+
except CollectionValidationError as e:
|
|
218
|
+
print(f"Validation error: {e}")
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Requirements
|
|
222
|
+
|
|
223
|
+
- Python 3.8+
|
|
224
|
+
- No external dependencies for core functionality
|
|
225
|
+
|
|
226
|
+
## Development
|
|
227
|
+
|
|
228
|
+
### Setting up Development Environment
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
# Clone the repository
|
|
232
|
+
git clone https://github.com/python-postman/python-postman.git
|
|
233
|
+
cd python-postman
|
|
234
|
+
|
|
235
|
+
# Install development dependencies
|
|
236
|
+
pip install -e ".[dev]"
|
|
237
|
+
|
|
238
|
+
# Run tests
|
|
239
|
+
pytest
|
|
240
|
+
|
|
241
|
+
# Run tests with coverage
|
|
242
|
+
pytest --cov=python_postman
|
|
243
|
+
|
|
244
|
+
# Format code
|
|
245
|
+
black python_postman tests
|
|
246
|
+
isort python_postman tests
|
|
247
|
+
|
|
248
|
+
# Type checking
|
|
249
|
+
mypy python_postman
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Running Tests
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
# Run all tests
|
|
256
|
+
pytest
|
|
257
|
+
|
|
258
|
+
# Run specific test file
|
|
259
|
+
pytest tests/test_collection.py
|
|
260
|
+
|
|
261
|
+
# Run with verbose output
|
|
262
|
+
pytest -v
|
|
263
|
+
|
|
264
|
+
# Run with coverage report
|
|
265
|
+
pytest --cov=python_postman --cov-report=html
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
## Contributing
|
|
269
|
+
|
|
270
|
+
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
|
|
271
|
+
|
|
272
|
+
1. Fork the repository
|
|
273
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
274
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
275
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
276
|
+
5. Open a Pull Request
|
|
277
|
+
|
|
278
|
+
## License
|
|
279
|
+
|
|
280
|
+
This project is licensed under the MIT License - see the LICENSE file for details.
|
|
281
|
+
|
|
282
|
+
## Changelog
|
|
283
|
+
|
|
284
|
+
### 0.7.0 (Updated version)
|
|
285
|
+
|
|
286
|
+
- Updated version to 0.7.0
|
|
287
|
+
- Updated README.md
|
|
288
|
+
- Updated pyproject.toml
|
|
289
|
+
- Updated tests
|
|
290
|
+
- Updated docs
|
|
291
|
+
- Updated examples
|
|
292
|
+
- Updated code
|
|
293
|
+
|
|
294
|
+
## Support
|
|
295
|
+
|
|
296
|
+
If you encounter any issues or have questions, please file an issue on the [GitHub issue tracker](https://github.com/python-postman/python-postman/issues).
|