python-postman 0.7.0__tar.gz → 0.9.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 → python_postman-0.9.0}/.github/workflows/python-publish.yml +64 -64
- {python_postman-0.7.0 → python_postman-0.9.0}/PKG-INFO +274 -21
- python_postman-0.9.0/README.md +545 -0
- python_postman-0.9.0/coverage.json +1 -0
- python_postman-0.9.0/docs/README.md +456 -0
- python_postman-0.9.0/docs/architecture/execution-layer.md +555 -0
- python_postman-0.9.0/docs/architecture/layer-interaction.md +597 -0
- python_postman-0.9.0/docs/architecture/model-layer.md +501 -0
- python_postman-0.9.0/docs/architecture/overview.md +186 -0
- python_postman-0.9.0/docs/examples/description-usage.py +434 -0
- python_postman-0.9.0/docs/examples/generate-documentation.py +439 -0
- python_postman-0.9.0/docs/examples/parse-inspect-modify-execute.py +325 -0
- python_postman-0.9.0/docs/examples/variable-introspection.py +313 -0
- python_postman-0.9.0/docs/guides/decision-tree.md +587 -0
- python_postman-0.9.0/docs/guides/description-fields.md +425 -0
- python_postman-0.9.0/docs/guides/optional-dependencies.md +685 -0
- python_postman-0.9.0/docs/guides/troubleshooting.md +810 -0
- python_postman-0.9.0/docs/guides/variable-scoping.md +471 -0
- python_postman-0.9.0/examples/README.md +308 -0
- python_postman-0.9.0/examples/advanced_execution.py +177 -0
- python_postman-0.9.0/examples/auth_resolution_example.py +186 -0
- python_postman-0.9.0/examples/authentication_examples.py +187 -0
- python_postman-0.9.0/examples/basic_execution.py +67 -0
- python_postman-0.9.0/examples/cftc_execution_example.py +240 -0
- python_postman-0.9.0/examples/complete_workflow.py +440 -0
- python_postman-0.9.0/examples/multi_collection_execution.py +185 -0
- python_postman-0.9.0/examples/path_parameters_example.py +304 -0
- python_postman-0.9.0/examples/projects/README.md +48 -0
- python_postman-0.9.0/examples/projects/microservices-testing/README.md +48 -0
- python_postman-0.9.0/examples/projects/microservices-testing/collections/auth-service.json +55 -0
- python_postman-0.9.0/examples/projects/microservices-testing/collections/order-service.json +60 -0
- python_postman-0.9.0/examples/projects/microservices-testing/collections/user-service.json +59 -0
- python_postman-0.9.0/examples/projects/microservices-testing/environments/microservices.json +30 -0
- python_postman-0.9.0/examples/projects/microservices-testing/main.py +73 -0
- python_postman-0.9.0/examples/projects/rest-api-testing/README.md +63 -0
- python_postman-0.9.0/examples/projects/rest-api-testing/collections/rest-api.json +110 -0
- python_postman-0.9.0/examples/projects/rest-api-testing/environments/dev.json +15 -0
- python_postman-0.9.0/examples/projects/rest-api-testing/environments/prod.json +15 -0
- python_postman-0.9.0/examples/projects/rest-api-testing/main.py +48 -0
- python_postman-0.9.0/examples/projects/rest-api-testing/requirements.txt +2 -0
- python_postman-0.9.0/examples/projects/rest-api-testing/tests/test_rest_api.py +39 -0
- python_postman-0.9.0/examples/request_convenience_methods.py +175 -0
- python_postman-0.9.0/examples/search_example.py +113 -0
- python_postman-0.9.0/examples/statistics_example.py +92 -0
- python_postman-0.9.0/examples/synchronous_execution.py +134 -0
- python_postman-0.9.0/examples/usage_patterns.py +361 -0
- python_postman-0.9.0/examples/variable_examples.py +206 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/pyproject.toml +16 -2
- python_postman-0.9.0/python_postman/__init__.py +195 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/python_postman/exceptions/__init__.py +2 -0
- python_postman-0.9.0/python_postman/exceptions/schema_error.py +35 -0
- python_postman-0.9.0/python_postman/execution/__init__.py +64 -0
- python_postman-0.9.0/python_postman/execution/auth_handler.py +245 -0
- python_postman-0.9.0/python_postman/execution/context.py +341 -0
- python_postman-0.9.0/python_postman/execution/exceptions.py +208 -0
- python_postman-0.9.0/python_postman/execution/executor.py +781 -0
- python_postman-0.9.0/python_postman/execution/extensions.py +420 -0
- python_postman-0.9.0/python_postman/execution/response.py +165 -0
- python_postman-0.9.0/python_postman/execution/results.py +250 -0
- python_postman-0.9.0/python_postman/execution/script_runner.py +468 -0
- python_postman-0.9.0/python_postman/execution/variable_resolver.py +339 -0
- python_postman-0.9.0/python_postman/introspection/__init__.py +14 -0
- python_postman-0.9.0/python_postman/introspection/auth_resolver.py +135 -0
- python_postman-0.9.0/python_postman/introspection/variable_tracer.py +475 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/python_postman/models/__init__.py +9 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/python_postman/models/auth.py +34 -2
- python_postman-0.9.0/python_postman/models/collection.py +495 -0
- python_postman-0.9.0/python_postman/models/cookie.py +495 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/python_postman/models/folder.py +38 -2
- python_postman-0.9.0/python_postman/models/item.py +232 -0
- python_postman-0.9.0/python_postman/models/request.py +599 -0
- python_postman-0.9.0/python_postman/models/response.py +345 -0
- python_postman-0.9.0/python_postman/models/schema.py +144 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/python_postman/models/url.py +29 -3
- python_postman-0.9.0/python_postman/search/__init__.py +7 -0
- python_postman-0.9.0/python_postman/search/query.py +285 -0
- python_postman-0.9.0/python_postman/statistics/__init__.py +7 -0
- python_postman-0.9.0/python_postman/statistics/collector.py +327 -0
- python_postman-0.9.0/python_postman/types/__init__.py +13 -0
- python_postman-0.9.0/python_postman/types/auth_types.py +41 -0
- python_postman-0.9.0/python_postman/types/http_methods.py +39 -0
- python_postman-0.9.0/test_execution_summary.md +459 -0
- python_postman-0.9.0/tests/execution_tests/CFTC_TEST_SUMMARY.md +342 -0
- python_postman-0.9.0/tests/execution_tests/INDEX.md +239 -0
- python_postman-0.9.0/tests/execution_tests/QUICK_START_CFTC.md +127 -0
- python_postman-0.9.0/tests/execution_tests/README_CFTC_TESTS.md +357 -0
- python_postman-0.9.0/tests/execution_tests/example_cftc_usage.py +265 -0
- python_postman-0.9.0/tests/execution_tests/test_cftc_comprehensive.py +839 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/tests/test_auth.py +12 -18
- python_postman-0.9.0/tests/test_auth_handler.py +560 -0
- python_postman-0.9.0/tests/test_auth_resolver.py +561 -0
- python_postman-0.9.0/tests/test_collection.py +329 -0
- python_postman-0.9.0/tests/test_cookie.py +574 -0
- python_postman-0.9.0/tests/test_data/README_integration_tests.md +160 -0
- python_postman-0.9.0/tests/test_data/auth_execution_collection.json +324 -0
- python_postman-0.9.0/tests/test_data/cftc.gov.postman_collection.json +99 -0
- python_postman-0.9.0/tests/test_data/error_scenarios_collection.json +349 -0
- python_postman-0.9.0/tests/test_data/execution_collection.json +285 -0
- python_postman-0.9.0/tests/test_data/nested_execution_collection.json +355 -0
- python_postman-0.9.0/tests/test_data/performance_collection.json +377 -0
- python_postman-0.9.0/tests/test_description_fields.py +389 -0
- python_postman-0.9.0/tests/test_edge_cases.py +972 -0
- python_postman-0.9.0/tests/test_edge_cases.py.bak +963 -0
- python_postman-0.9.0/tests/test_edge_cases_summary.md +121 -0
- python_postman-0.9.0/tests/test_execution_context.py +291 -0
- python_postman-0.9.0/tests/test_execution_exceptions.py +482 -0
- python_postman-0.9.0/tests/test_execution_reporter.py +268 -0
- python_postman-0.9.0/tests/test_executor.py +1917 -0
- python_postman-0.9.0/tests/test_extensions.py +587 -0
- python_postman-0.9.0/tests/test_imports.py +348 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/tests/test_integration.py +8 -8
- python_postman-0.9.0/tests/test_item_clarity.py +221 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/tests/test_parser.py +33 -10
- python_postman-0.9.0/tests/test_request_convenience.py +538 -0
- python_postman-0.9.0/tests/test_request_execution.py +279 -0
- python_postman-0.9.0/tests/test_request_responses.py +309 -0
- python_postman-0.9.0/tests/test_response.py +485 -0
- python_postman-0.9.0/tests/test_response_cookies.py +245 -0
- python_postman-0.9.0/tests/test_schema.py +289 -0
- python_postman-0.9.0/tests/test_script_runner.py +552 -0
- python_postman-0.9.0/tests/test_search.py +396 -0
- python_postman-0.9.0/tests/test_statistics.py +416 -0
- python_postman-0.9.0/tests/test_type_safety.py +192 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/tests/test_url.py +15 -7
- python_postman-0.9.0/tests/test_variable_resolver.py +547 -0
- python_postman-0.9.0/tests/test_variable_tracer.py +522 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/uv.lock +117 -1
- python_postman-0.7.0/README.md +0 -296
- python_postman-0.7.0/python_postman/__init__.py +0 -85
- python_postman-0.7.0/python_postman/models/collection.py +0 -292
- python_postman-0.7.0/python_postman/models/item.py +0 -44
- python_postman-0.7.0/python_postman/models/request.py +0 -147
- python_postman-0.7.0/tests/test_collection.py +0 -119
- {python_postman-0.7.0 → python_postman-0.9.0}/.gitignore +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/LICENSE +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/python_postman/exceptions/base.py +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/python_postman/exceptions/file_error.py +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/python_postman/exceptions/parse_error.py +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/python_postman/exceptions/validation_error.py +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/python_postman/models/body.py +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/python_postman/models/collection_info.py +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/python_postman/models/event.py +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/python_postman/models/header.py +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/python_postman/models/variable.py +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/python_postman/parser.py +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/python_postman/utils/__init__.py +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/python_postman/utils/json_parser.py +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/python_postman/utils/validators.py +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/tests/__init__.py +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/tests/test_body.py +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/tests/test_collection_info.py +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/tests/test_data/README.md +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/tests/test_data/auth_collection.json +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/tests/test_data/empty_collection.json +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/tests/test_data/events_collection.json +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/tests/test_data/invalid_collection.json +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/tests/test_data/malformed_json.json +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/tests/test_data/nested_collection.json +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/tests/test_data/simple_collection.json +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/tests/test_event.py +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/tests/test_exceptions.py +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/tests/test_folder.py +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/tests/test_header.py +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/tests/test_item.py +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/tests/test_json_parser.py +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/tests/test_request.py +0 -0
- {python_postman-0.7.0 → python_postman-0.9.0}/tests/test_variable.py +0 -0
|
@@ -1,65 +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
|
|
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
65
|
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-postman
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.0
|
|
4
4
|
Summary: A Python library for parsing and working with Postman collection.json files
|
|
5
5
|
Project-URL: Homepage, https://github.com/python-postman/python-postman
|
|
6
6
|
Project-URL: Repository, https://github.com/python-postman/python-postman
|
|
@@ -25,23 +25,31 @@ Classifier: Topic :: Internet :: WWW/HTTP
|
|
|
25
25
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
26
26
|
Classifier: Topic :: Software Development :: Testing
|
|
27
27
|
Requires-Python: >=3.9
|
|
28
|
+
Requires-Dist: httpx>=0.28.1
|
|
28
29
|
Provides-Extra: dev
|
|
29
30
|
Requires-Dist: black>=23.0.0; extra == 'dev'
|
|
30
31
|
Requires-Dist: isort>=5.12.0; extra == 'dev'
|
|
31
32
|
Requires-Dist: mypy>=1.0.0; extra == 'dev'
|
|
33
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
32
34
|
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
|
|
33
35
|
Requires-Dist: pytest>=8.4.2; extra == 'dev'
|
|
36
|
+
Provides-Extra: execution
|
|
37
|
+
Requires-Dist: python-dotenv>=1.0.0; extra == 'execution'
|
|
34
38
|
Description-Content-Type: text/markdown
|
|
35
39
|
|
|
36
|
-
# Python Postman
|
|
40
|
+
# Python Postman
|
|
37
41
|
|
|
38
|
-
A Python library for
|
|
42
|
+
A comprehensive Python library for working with Postman collections. Parse, execute, search, and analyze Postman collection.json files with a clean, object-oriented interface. Execute HTTP requests with full async/sync support, dynamic variable resolution, and authentication handling.
|
|
39
43
|
|
|
40
44
|
## Features
|
|
41
45
|
|
|
42
46
|
- **Parse Postman Collections**: Load collections from files, JSON strings, or dictionaries
|
|
43
47
|
- **Object-Oriented API**: Work with collections using intuitive Python objects
|
|
44
|
-
- **Full Collection Support**: Access requests, folders, variables, authentication, and
|
|
48
|
+
- **Full Collection Support**: Access requests, folders, variables, authentication, and events
|
|
49
|
+
- **HTTP Request Execution**: Execute requests using httpx with full async/sync support
|
|
50
|
+
- **Variable Resolution**: Dynamic variable substitution with proper scoping
|
|
51
|
+
- **Authentication Handling**: Automatic auth processing for Bearer, Basic, and API Key
|
|
52
|
+
- **Request Extensions**: Runtime modification of URLs, headers, body, and auth
|
|
45
53
|
- **Validation**: Built-in validation for collection structure and schema compliance
|
|
46
54
|
- **Iteration**: Easy iteration through all requests regardless of folder structure
|
|
47
55
|
- **Search**: Find requests and folders by name
|
|
@@ -50,7 +58,13 @@ A Python library for parsing and working with Postman collection.json files. Thi
|
|
|
50
58
|
## Installation
|
|
51
59
|
|
|
52
60
|
```bash
|
|
61
|
+
# Basic installation (parsing only)
|
|
53
62
|
pip install python-postman
|
|
63
|
+
|
|
64
|
+
# With HTTP execution support
|
|
65
|
+
pip install python-postman[execution]
|
|
66
|
+
# or
|
|
67
|
+
pip install python-postman httpx
|
|
54
68
|
```
|
|
55
69
|
|
|
56
70
|
## Quick Start
|
|
@@ -81,9 +95,13 @@ print(f"Description: {collection.info.description}")
|
|
|
81
95
|
print(f"Schema: {collection.info.schema}")
|
|
82
96
|
|
|
83
97
|
# Collection-level variables
|
|
84
|
-
for variable in collection.variables:
|
|
98
|
+
for variable in collection.variables: # This requests a list of Variable objects
|
|
85
99
|
print(f"Variable: {variable.key} = {variable.value}")
|
|
86
100
|
|
|
101
|
+
# Collection variables dictionary. This is a quick way to get key-value pairs.
|
|
102
|
+
# You can pass/update these and add them to the execution context.
|
|
103
|
+
collection_variables = collection.get_variables()
|
|
104
|
+
|
|
87
105
|
# Collection-level authentication
|
|
88
106
|
if collection.auth:
|
|
89
107
|
print(f"Auth Type: {collection.auth.type}")
|
|
@@ -92,8 +110,16 @@ if collection.auth:
|
|
|
92
110
|
### Working with Requests
|
|
93
111
|
|
|
94
112
|
```python
|
|
113
|
+
# Get a list of requests by name
|
|
114
|
+
collection.list_requests()
|
|
115
|
+
|
|
116
|
+
# Find specific request by name
|
|
117
|
+
login_request = collection.get_request_by_name("Login Request")
|
|
118
|
+
if login_request:
|
|
119
|
+
print(f"Found request: {login_request.method} {login_request.url}")
|
|
120
|
+
|
|
95
121
|
# Iterate through all requests (flattens folder structure)
|
|
96
|
-
for request in collection.
|
|
122
|
+
for request in collection.get_requests():
|
|
97
123
|
print(f"Request: {request.method} {request.name}")
|
|
98
124
|
print(f"URL: {request.url}")
|
|
99
125
|
|
|
@@ -105,11 +131,6 @@ for request in collection.get_all_requests():
|
|
|
105
131
|
if request.body:
|
|
106
132
|
print(f"Body Type: {request.body.mode}")
|
|
107
133
|
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
134
|
```
|
|
114
135
|
|
|
115
136
|
### Working with Folders
|
|
@@ -167,7 +188,7 @@ if collection.auth:
|
|
|
167
188
|
print(f"Basic Auth Username: {username}")
|
|
168
189
|
|
|
169
190
|
# Request-level auth (overrides collection auth)
|
|
170
|
-
for request in collection.
|
|
191
|
+
for request in collection.get_requests():
|
|
171
192
|
if request.auth:
|
|
172
193
|
print(f"Request '{request.name}' has {request.auth.type} auth")
|
|
173
194
|
```
|
|
@@ -175,18 +196,19 @@ for request in collection.get_all_requests():
|
|
|
175
196
|
### Events (Scripts)
|
|
176
197
|
|
|
177
198
|
```python
|
|
178
|
-
#
|
|
199
|
+
# Access script content from collection-level events
|
|
179
200
|
for event in collection.events:
|
|
180
201
|
print(f"Collection Event: {event.listen}")
|
|
181
|
-
print(f"Script: {event.script}")
|
|
202
|
+
print(f"Script Content: {event.script}")
|
|
182
203
|
|
|
183
|
-
#
|
|
184
|
-
|
|
204
|
+
# Access script content from request-level events
|
|
205
|
+
# Note: JavaScript execution is not supported - scripts are accessible as text only
|
|
206
|
+
for request in collection.get_requests():
|
|
185
207
|
for event in request.events:
|
|
186
208
|
if event.listen == "prerequest":
|
|
187
|
-
print(f"Pre-request script for {request.name}")
|
|
209
|
+
print(f"Pre-request script for {request.name}: {event.script}")
|
|
188
210
|
elif event.listen == "test":
|
|
189
|
-
print(f"Test script for {request.name}")
|
|
211
|
+
print(f"Test script for {request.name}: {event.script}")
|
|
190
212
|
```
|
|
191
213
|
|
|
192
214
|
### Validation
|
|
@@ -219,6 +241,237 @@ collection = PythonPostman.create_collection(
|
|
|
219
241
|
print(f"Created collection: {collection.info.name}")
|
|
220
242
|
```
|
|
221
243
|
|
|
244
|
+
## HTTP Request Execution
|
|
245
|
+
|
|
246
|
+
The library supports executing HTTP requests from Postman collections using httpx. This feature requires the `httpx` dependency.
|
|
247
|
+
|
|
248
|
+
### Basic Request Execution
|
|
249
|
+
|
|
250
|
+
```python
|
|
251
|
+
import asyncio
|
|
252
|
+
from python_postman import PythonPostman
|
|
253
|
+
from python_postman.execution import RequestExecutor, ExecutionContext
|
|
254
|
+
|
|
255
|
+
async def main():
|
|
256
|
+
# Load collection
|
|
257
|
+
collection = PythonPostman.from_file("api_collection.json")
|
|
258
|
+
|
|
259
|
+
# Create executor
|
|
260
|
+
executor = RequestExecutor(
|
|
261
|
+
client_config={"timeout": 30.0, "verify": True},
|
|
262
|
+
global_headers={"User-Agent": "python-postman/1.0"}
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
# Create execution context with variables
|
|
266
|
+
context = ExecutionContext(
|
|
267
|
+
environment_variables={
|
|
268
|
+
"base_url": "https://api.example.com",
|
|
269
|
+
"api_key": "your-api-key"
|
|
270
|
+
}
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
# Execute a single request
|
|
274
|
+
request = collection.get_request_by_name("Get Users")
|
|
275
|
+
result = await executor.execute_request(request, context)
|
|
276
|
+
|
|
277
|
+
if result.success:
|
|
278
|
+
print(f"Status: {result.response.status_code}")
|
|
279
|
+
print(f"Response: {result.response.json}")
|
|
280
|
+
print(f"Time: {result.response.elapsed_ms:.2f}ms")
|
|
281
|
+
else:
|
|
282
|
+
print(f"Error: {result.error}")
|
|
283
|
+
|
|
284
|
+
await executor.aclose()
|
|
285
|
+
|
|
286
|
+
asyncio.run(main())
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### Synchronous Execution
|
|
290
|
+
|
|
291
|
+
```python
|
|
292
|
+
from python_postman.execution import RequestExecutor, ExecutionContext
|
|
293
|
+
|
|
294
|
+
# Synchronous execution
|
|
295
|
+
with RequestExecutor() as executor:
|
|
296
|
+
context = ExecutionContext(
|
|
297
|
+
environment_variables={"base_url": "https://httpbin.org"}
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
result = executor.execute_request_sync(request, context)
|
|
301
|
+
if result.success:
|
|
302
|
+
print(f"Status: {result.response.status_code}")
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Collection Execution
|
|
306
|
+
|
|
307
|
+
```python
|
|
308
|
+
# Execute entire collection
|
|
309
|
+
async def execute_collection():
|
|
310
|
+
executor = RequestExecutor()
|
|
311
|
+
|
|
312
|
+
# Sequential execution
|
|
313
|
+
result = await executor.execute_collection(collection)
|
|
314
|
+
print(f"Executed {result.total_requests} requests")
|
|
315
|
+
print(f"Success rate: {result.successful_requests}/{result.total_requests}")
|
|
316
|
+
|
|
317
|
+
# Parallel execution
|
|
318
|
+
result = await executor.execute_collection(
|
|
319
|
+
collection,
|
|
320
|
+
parallel=True,
|
|
321
|
+
stop_on_error=False
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
# Get the request responses
|
|
325
|
+
for result in result.results:
|
|
326
|
+
print(f"Request: {result.request.name}")
|
|
327
|
+
print(f"Result Text: {result.response.text}")
|
|
328
|
+
|
|
329
|
+
print(f"Parallel execution completed in {result.total_time_ms:.2f}ms")
|
|
330
|
+
|
|
331
|
+
await executor.aclose()
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### Variable Management
|
|
335
|
+
|
|
336
|
+
```python
|
|
337
|
+
# Variable scoping: request > folder > collection > environment
|
|
338
|
+
context = ExecutionContext(
|
|
339
|
+
environment_variables={"env": "production"},
|
|
340
|
+
collection_variables={"api_version": "v1", "timeout": "30"},
|
|
341
|
+
folder_variables={"endpoint": "/users"},
|
|
342
|
+
request_variables={"user_id": "12345"}
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
# Variables are resolved with proper precedence
|
|
346
|
+
url = context.resolve_variables("{{base_url}}/{{api_version}}{{endpoint}}/{{user_id}}")
|
|
347
|
+
print(url) # "https://api.example.com/v1/users/12345"
|
|
348
|
+
|
|
349
|
+
# Dynamic variable updates
|
|
350
|
+
context.set_variable("session_token", "abc123", "environment")
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### Path Parameters
|
|
354
|
+
|
|
355
|
+
The library supports both Postman-style variables (`{{variable}}`) and path parameters (`:parameter`):
|
|
356
|
+
|
|
357
|
+
```python
|
|
358
|
+
# Path parameters use :parameterName syntax
|
|
359
|
+
context = ExecutionContext(
|
|
360
|
+
environment_variables={
|
|
361
|
+
"baseURL": "https://api.example.com",
|
|
362
|
+
"userId": "12345",
|
|
363
|
+
"datasetId": "abc123"
|
|
364
|
+
}
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
# Mix Postman variables and path parameters
|
|
368
|
+
url = context.resolve_variables("{{baseURL}}/users/:userId/datasets/:datasetId")
|
|
369
|
+
print(url) # "https://api.example.com/users/12345/datasets/abc123"
|
|
370
|
+
|
|
371
|
+
# Path parameters follow the same scoping rules as Postman variables
|
|
372
|
+
url = context.resolve_variables("{{baseURL}}/:datasetId?$offset=0&$limit=10")
|
|
373
|
+
print(url) # "https://api.example.com/abc123?$offset=0&$limit=10"
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### Request Extensions
|
|
377
|
+
|
|
378
|
+
```python
|
|
379
|
+
from python_postman.execution import RequestExtensions
|
|
380
|
+
|
|
381
|
+
# Runtime request modifications
|
|
382
|
+
extensions = RequestExtensions(
|
|
383
|
+
# Substitute existing values
|
|
384
|
+
header_substitutions={"Authorization": "Bearer {{new_token}}"},
|
|
385
|
+
url_substitutions={"host": "staging.api.example.com"},
|
|
386
|
+
|
|
387
|
+
# Add new values
|
|
388
|
+
header_extensions={"X-Request-ID": "req-{{timestamp}}"},
|
|
389
|
+
param_extensions={"debug": "true", "version": "v2"},
|
|
390
|
+
body_extensions={"metadata": {"client": "python-postman"}}
|
|
391
|
+
)
|
|
392
|
+
|
|
393
|
+
result = await executor.execute_request(
|
|
394
|
+
request,
|
|
395
|
+
context,
|
|
396
|
+
extensions=extensions
|
|
397
|
+
)
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### Authentication
|
|
401
|
+
|
|
402
|
+
```python
|
|
403
|
+
# Authentication is handled automatically based on collection/request auth settings
|
|
404
|
+
|
|
405
|
+
# Bearer Token
|
|
406
|
+
context = ExecutionContext(
|
|
407
|
+
environment_variables={"bearer_token": "eyJhbGciOiJIUzI1NiIs..."}
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
# Basic Auth
|
|
411
|
+
context = ExecutionContext(
|
|
412
|
+
environment_variables={
|
|
413
|
+
"username": "admin",
|
|
414
|
+
"password": "secret123"
|
|
415
|
+
}
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
# API Key
|
|
419
|
+
context = ExecutionContext(
|
|
420
|
+
environment_variables={"api_key": "sk-1234567890abcdef"}
|
|
421
|
+
)
|
|
422
|
+
|
|
423
|
+
# Auth is applied automatically during request execution
|
|
424
|
+
result = await executor.execute_request(request, context)
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
### Request Methods on Models
|
|
428
|
+
|
|
429
|
+
```python
|
|
430
|
+
# Execute requests directly from Request objects
|
|
431
|
+
request = collection.get_request_by_name("Health Check")
|
|
432
|
+
|
|
433
|
+
# Async execution
|
|
434
|
+
result = await request.execute(
|
|
435
|
+
executor=executor,
|
|
436
|
+
context=context,
|
|
437
|
+
substitutions={"env": "staging"}
|
|
438
|
+
)
|
|
439
|
+
|
|
440
|
+
# Sync execution
|
|
441
|
+
result = request.execute_sync(
|
|
442
|
+
executor=executor,
|
|
443
|
+
context=context
|
|
444
|
+
)
|
|
445
|
+
|
|
446
|
+
# Execute collections directly
|
|
447
|
+
result = await collection.execute(
|
|
448
|
+
executor=executor,
|
|
449
|
+
parallel=True
|
|
450
|
+
)
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
### Error Handling
|
|
454
|
+
|
|
455
|
+
```python
|
|
456
|
+
from python_postman.execution import (
|
|
457
|
+
ExecutionError,
|
|
458
|
+
RequestExecutionError,
|
|
459
|
+
VariableResolutionError,
|
|
460
|
+
AuthenticationError
|
|
461
|
+
)
|
|
462
|
+
|
|
463
|
+
try:
|
|
464
|
+
result = await executor.execute_request(request, context)
|
|
465
|
+
if not result.success:
|
|
466
|
+
print(f"Request failed: {result.error}")
|
|
467
|
+
except VariableResolutionError as e:
|
|
468
|
+
print(f"Variable error: {e}")
|
|
469
|
+
except AuthenticationError as e:
|
|
470
|
+
print(f"Auth error: {e}")
|
|
471
|
+
except RequestExecutionError as e:
|
|
472
|
+
print(f"Execution error: {e}")
|
|
473
|
+
```
|
|
474
|
+
|
|
222
475
|
## API Reference
|
|
223
476
|
|
|
224
477
|
### Main Classes
|
|
@@ -229,7 +482,7 @@ print(f"Created collection: {collection.info.name}")
|
|
|
229
482
|
- **`Folder`**: Container for organizing requests and sub-folders
|
|
230
483
|
- **`Variable`**: Collection, folder, or request-level variables
|
|
231
484
|
- **`Auth`**: Authentication configuration
|
|
232
|
-
- **`Event`**: Pre-request
|
|
485
|
+
- **`Event`**: Pre-request and test script definitions (text only, execution not supported)
|
|
233
486
|
|
|
234
487
|
### Exception Handling
|
|
235
488
|
|
|
@@ -316,9 +569,9 @@ This project is licensed under the MIT License - see the LICENSE file for detail
|
|
|
316
569
|
|
|
317
570
|
## Changelog
|
|
318
571
|
|
|
319
|
-
### 0.
|
|
572
|
+
### 0.8.0 (Updated version)
|
|
320
573
|
|
|
321
|
-
- Updated version to 0.
|
|
574
|
+
- Updated version to 0.8.0
|
|
322
575
|
- Updated README.md
|
|
323
576
|
- Updated pyproject.toml
|
|
324
577
|
- Updated tests
|