open-data-products 0.1.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.
Files changed (169) hide show
  1. open_data_products-0.1.0/.flake8 +16 -0
  2. open_data_products-0.1.0/.gitignore +7 -0
  3. open_data_products-0.1.0/.mcp.json +8 -0
  4. open_data_products-0.1.0/AGENTS.md +102 -0
  5. open_data_products-0.1.0/BUILD.md +207 -0
  6. open_data_products-0.1.0/CONTRIBUTING.md +461 -0
  7. open_data_products-0.1.0/LICENSE +203 -0
  8. open_data_products-0.1.0/MANIFEST.in +18 -0
  9. open_data_products-0.1.0/PKG-INFO +421 -0
  10. open_data_products-0.1.0/README.md +372 -0
  11. open_data_products-0.1.0/docs/API.md +1247 -0
  12. open_data_products-0.1.0/docs/agent-surface.md +98 -0
  13. open_data_products-0.1.0/docs/commands.md +238 -0
  14. open_data_products-0.1.0/docs/data-contracts.md +65 -0
  15. open_data_products-0.1.0/docs/functional-test-report.md +86 -0
  16. open_data_products-0.1.0/docs/generation.md +298 -0
  17. open_data_products-0.1.0/docs/online-llm-generation-story.md +159 -0
  18. open_data_products-0.1.0/docs/tooling-development-model.md +145 -0
  19. open_data_products-0.1.0/examples/advanced_features.py +524 -0
  20. open_data_products-0.1.0/examples/apps/README.md +41 -0
  21. open_data_products-0.1.0/examples/apps/document_inspector/cli.py +117 -0
  22. open_data_products-0.1.0/examples/apps/pricing_402_builder/cli.py +101 -0
  23. open_data_products-0.1.0/examples/apps/pricing_402_builder/priced_product.yaml +18 -0
  24. open_data_products-0.1.0/examples/apps/vocabulary_finder/cli.py +103 -0
  25. open_data_products-0.1.0/examples/basic_usage.py +305 -0
  26. open_data_products-0.1.0/examples/comprehensive_example.py +177 -0
  27. open_data_products-0.1.0/examples/contract.yaml +23 -0
  28. open_data_products-0.1.0/examples/demo_product.json +56 -0
  29. open_data_products-0.1.0/examples/demo_product.yaml +51 -0
  30. open_data_products-0.1.0/examples/graph.graphml +15 -0
  31. open_data_products-0.1.0/examples/guides/01-validate-product.md +55 -0
  32. open_data_products-0.1.0/examples/guides/02-explain-and-summarize.md +57 -0
  33. open_data_products-0.1.0/examples/guides/03-use-vocabulary-helpers.md +52 -0
  34. open_data_products-0.1.0/examples/guides/04-convert-graph-to-odpg.md +62 -0
  35. open_data_products-0.1.0/examples/guides/05-llm-generate-one-signal.md +61 -0
  36. open_data_products-0.1.0/examples/guides/06-llm-use-online-provider.md +82 -0
  37. open_data_products-0.1.0/examples/guides/07-llm-generate-fragment-set.md +79 -0
  38. open_data_products-0.1.0/examples/guides/08-llm-full-cycle-catalog-and-graph.md +131 -0
  39. open_data_products-0.1.0/examples/guides/README.md +27 -0
  40. open_data_products-0.1.0/examples/odpc_catalog.html +142 -0
  41. open_data_products-0.1.0/examples/odpc_catalog.yaml +34 -0
  42. open_data_products-0.1.0/examples/odpc_catalog_fragments/catalog_metadata.yaml +6 -0
  43. open_data_products-0.1.0/examples/odpc_catalog_fragments/customer_product.yaml +11 -0
  44. open_data_products-0.1.0/examples/odpc_catalog_fragments/customer_retention_use_case.yaml +8 -0
  45. open_data_products-0.1.0/examples/odps_v41_example.py +280 -0
  46. open_data_products-0.1.0/examples/product.yaml +146 -0
  47. open_data_products-0.1.0/images/agent.png +0 -0
  48. open_data_products-0.1.0/images/feedback.png +0 -0
  49. open_data_products-0.1.0/images/glance.png +0 -0
  50. open_data_products-0.1.0/images/llms.png +0 -0
  51. open_data_products-0.1.0/llms.txt +250 -0
  52. open_data_products-0.1.0/open_data_products/__init__.py +162 -0
  53. open_data_products-0.1.0/open_data_products/_io.py +44 -0
  54. open_data_products-0.1.0/open_data_products/_search.py +55 -0
  55. open_data_products-0.1.0/open_data_products/agent.py +381 -0
  56. open_data_products-0.1.0/open_data_products/cli.py +1178 -0
  57. open_data_products-0.1.0/open_data_products/contracts/__init__.py +60 -0
  58. open_data_products-0.1.0/open_data_products/contracts/alignment.py +373 -0
  59. open_data_products-0.1.0/open_data_products/contracts/datacontract_cli_adapter.py +423 -0
  60. open_data_products-0.1.0/open_data_products/contracts/errors.py +11 -0
  61. open_data_products-0.1.0/open_data_products/contracts/loader.py +226 -0
  62. open_data_products-0.1.0/open_data_products/contracts/models.py +244 -0
  63. open_data_products-0.1.0/open_data_products/contracts/product.py +267 -0
  64. open_data_products-0.1.0/open_data_products/generation/__init__.py +1047 -0
  65. open_data_products-0.1.0/open_data_products/generation/data/__init__.py +1 -0
  66. open_data_products-0.1.0/open_data_products/generation/data/prompts/__init__.py +1 -0
  67. open_data_products-0.1.0/open_data_products/generation/data/prompts/odpc_objective_fragment.md +59 -0
  68. open_data_products-0.1.0/open_data_products/generation/data/prompts/odpc_signal_fragment.md +85 -0
  69. open_data_products-0.1.0/open_data_products/generation/data/prompts/odpc_use_case_fragment.md +60 -0
  70. open_data_products-0.1.0/open_data_products/generation/data/prompts/odpg_graph_yaml.md +66 -0
  71. open_data_products-0.1.0/open_data_products/generation/data/prompts/odps_data_product_fragment.md +65 -0
  72. open_data_products-0.1.0/open_data_products/generation/data/prompts/system.md +23 -0
  73. open_data_products-0.1.0/open_data_products/generation/fragments/__init__.py +1 -0
  74. open_data_products-0.1.0/open_data_products/generation/fragments/business_objective_reduce-departure-delay-minutes.yaml +25 -0
  75. open_data_products-0.1.0/open_data_products/generation/fragments/graph_explorer.html +1920 -0
  76. open_data_products-0.1.0/open_data_products/generation/fragments/odpg_graph.yaml +91 -0
  77. open_data_products-0.1.0/open_data_products/generation/fragments/product_reference_airport-operations-performance.yaml +21 -0
  78. open_data_products-0.1.0/open_data_products/generation/fragments/product_reference_flight-connection-reliability.yaml +21 -0
  79. open_data_products-0.1.0/open_data_products/generation/fragments/product_reference_passenger-flow-queue.yaml +21 -0
  80. open_data_products-0.1.0/open_data_products/generation/fragments/signal_baggage-belt-congestion-signal.yaml +28 -0
  81. open_data_products-0.1.0/open_data_products/generation/fragments/signal_inbound-connection-risk-signal.yaml +31 -0
  82. open_data_products-0.1.0/open_data_products/generation/fragments/signal_security-queue-surge-signal.yaml +30 -0
  83. open_data_products-0.1.0/open_data_products/generation/fragments/signal_turnaround-delay-spike-signal.yaml +30 -0
  84. open_data_products-0.1.0/open_data_products/generation/fragments/use_case_flight-delay-risk-monitoring.yaml +26 -0
  85. open_data_products-0.1.0/open_data_products/generation/fragments/use_case_passenger-connection-protection.yaml +27 -0
  86. open_data_products-0.1.0/open_data_products/generation/generation.config.yaml +79 -0
  87. open_data_products-0.1.0/open_data_products/generation/source_docs/README.md +60 -0
  88. open_data_products-0.1.0/open_data_products/generation/source_docs/__init__.py +1 -0
  89. open_data_products-0.1.0/open_data_products/generation/source_docs/airport-business-objective.txt +20 -0
  90. open_data_products-0.1.0/open_data_products/generation/source_docs/airport-operations-brief.md +26 -0
  91. open_data_products-0.1.0/open_data_products/generation/source_docs/baggage-belt-congestion-signal.txt +20 -0
  92. open_data_products-0.1.0/open_data_products/generation/source_docs/connection-reliability-brief.md +26 -0
  93. open_data_products-0.1.0/open_data_products/generation/source_docs/flight-delay-use-case.md +22 -0
  94. open_data_products-0.1.0/open_data_products/generation/source_docs/inbound-connection-risk-signal.txt +20 -0
  95. open_data_products-0.1.0/open_data_products/generation/source_docs/passenger-connection-use-case.md +27 -0
  96. open_data_products-0.1.0/open_data_products/generation/source_docs/passenger-flow-brief.md +24 -0
  97. open_data_products-0.1.0/open_data_products/generation/source_docs/security-queue-surge-signal.txt +20 -0
  98. open_data_products-0.1.0/open_data_products/generation/source_docs/turnaround-delay-signal.txt +20 -0
  99. open_data_products-0.1.0/open_data_products/mcp/__init__.py +12 -0
  100. open_data_products-0.1.0/open_data_products/mcp/manifest.py +44 -0
  101. open_data_products-0.1.0/open_data_products/mcp/server.py +114 -0
  102. open_data_products-0.1.0/open_data_products/mcp/tools.py +598 -0
  103. open_data_products-0.1.0/open_data_products/odpc/__init__.py +48 -0
  104. open_data_products-0.1.0/open_data_products/odpc/catalog.py +692 -0
  105. open_data_products-0.1.0/open_data_products/odpc/cli.py +143 -0
  106. open_data_products-0.1.0/open_data_products/odpc/data/__init__.py +1 -0
  107. open_data_products-0.1.0/open_data_products/odpc/data/catalog/__init__.py +1 -0
  108. open_data_products-0.1.0/open_data_products/odpc/data/catalog/objects.jsonl +6 -0
  109. open_data_products-0.1.0/open_data_products/odpc/data/schema/__init__.py +1 -0
  110. open_data_products-0.1.0/open_data_products/odpc/data/schema/odpc.json +810 -0
  111. open_data_products-0.1.0/open_data_products/odpc/data/schema/odpc.yaml +590 -0
  112. open_data_products-0.1.0/open_data_products/odpc/data/templates/__init__.py +1 -0
  113. open_data_products-0.1.0/open_data_products/odpc/data/templates/catalog.html +128 -0
  114. open_data_products-0.1.0/open_data_products/odpg/__init__.py +54 -0
  115. open_data_products-0.1.0/open_data_products/odpg/_explorer_template.py +1634 -0
  116. open_data_products-0.1.0/open_data_products/odpg/cli.py +309 -0
  117. open_data_products-0.1.0/open_data_products/odpg/convert.py +533 -0
  118. open_data_products-0.1.0/open_data_products/odpg/data/__init__.py +0 -0
  119. open_data_products-0.1.0/open_data_products/odpg/data/graph/__init__.py +0 -0
  120. open_data_products-0.1.0/open_data_products/odpg/data/graph/graph.yaml +112 -0
  121. open_data_products-0.1.0/open_data_products/odpg/data/graph/objects.jsonl +63 -0
  122. open_data_products-0.1.0/open_data_products/odpg/data/schema/__init__.py +0 -0
  123. open_data_products-0.1.0/open_data_products/odpg/data/schema/odpg.json +276 -0
  124. open_data_products-0.1.0/open_data_products/odpg/data/schema/odpg.yaml +219 -0
  125. open_data_products-0.1.0/open_data_products/odpg/graph.py +772 -0
  126. open_data_products-0.1.0/open_data_products/odps/__init__.py +92 -0
  127. open_data_products-0.1.0/open_data_products/odps/_document.py +56 -0
  128. open_data_products-0.1.0/open_data_products/odps/_iso_codes.py +72 -0
  129. open_data_products-0.1.0/open_data_products/odps/_state.py +63 -0
  130. open_data_products-0.1.0/open_data_products/odps/_validators.py +338 -0
  131. open_data_products-0.1.0/open_data_products/odps/codecs.py +614 -0
  132. open_data_products-0.1.0/open_data_products/odps/core.py +611 -0
  133. open_data_products-0.1.0/open_data_products/odps/data/__init__.py +1 -0
  134. open_data_products-0.1.0/open_data_products/odps/data/schema/__init__.py +1 -0
  135. open_data_products-0.1.0/open_data_products/odps/data/schema/odps.json +1207 -0
  136. open_data_products-0.1.0/open_data_products/odps/enums.py +308 -0
  137. open_data_products-0.1.0/open_data_products/odps/exceptions.py +84 -0
  138. open_data_products-0.1.0/open_data_products/odps/models.py +433 -0
  139. open_data_products-0.1.0/open_data_products/odps/protocols.py +313 -0
  140. open_data_products-0.1.0/open_data_products/odps/validation.py +573 -0
  141. open_data_products-0.1.0/open_data_products/odps/validators.py +8 -0
  142. open_data_products-0.1.0/open_data_products/odpv/__init__.py +44 -0
  143. open_data_products-0.1.0/open_data_products/odpv/cli.py +129 -0
  144. open_data_products-0.1.0/open_data_products/odpv/data/__init__.py +1 -0
  145. open_data_products-0.1.0/open_data_products/odpv/data/vocab/__init__.py +1 -0
  146. open_data_products-0.1.0/open_data_products/odpv/data/vocab/core.yaml +363 -0
  147. open_data_products-0.1.0/open_data_products/odpv/data/vocab/governance.yaml +432 -0
  148. open_data_products-0.1.0/open_data_products/odpv/data/vocab/odpv.json +2372 -0
  149. open_data_products-0.1.0/open_data_products/odpv/data/vocab/odpv.yaml +1784 -0
  150. open_data_products-0.1.0/open_data_products/odpv/data/vocab/relationships.yaml +550 -0
  151. open_data_products-0.1.0/open_data_products/odpv/data/vocab/terms.jsonl +59 -0
  152. open_data_products-0.1.0/open_data_products/odpv/data/vocab/value.yaml +423 -0
  153. open_data_products-0.1.0/open_data_products/odpv/vocabulary.py +559 -0
  154. open_data_products-0.1.0/open_data_products/pricing.py +53 -0
  155. open_data_products-0.1.0/open_data_products/resources.py +154 -0
  156. open_data_products-0.1.0/open_data_products/results.py +55 -0
  157. open_data_products-0.1.0/open_data_products/summary.py +81 -0
  158. open_data_products-0.1.0/open_data_products.egg-info/PKG-INFO +421 -0
  159. open_data_products-0.1.0/open_data_products.egg-info/SOURCES.txt +167 -0
  160. open_data_products-0.1.0/open_data_products.egg-info/dependency_links.txt +1 -0
  161. open_data_products-0.1.0/open_data_products.egg-info/entry_points.txt +3 -0
  162. open_data_products-0.1.0/open_data_products.egg-info/requires.txt +24 -0
  163. open_data_products-0.1.0/open_data_products.egg-info/top_level.txt +1 -0
  164. open_data_products-0.1.0/pyproject.toml +206 -0
  165. open_data_products-0.1.0/requirements.txt +2 -0
  166. open_data_products-0.1.0/setup.cfg +4 -0
  167. open_data_products-0.1.0/skills/odp-author/SKILL.md +60 -0
  168. open_data_products-0.1.0/skills/odp-explore-graph/SKILL.md +57 -0
  169. open_data_products-0.1.0/skills/odp-validate/SKILL.md +52 -0
@@ -0,0 +1,16 @@
1
+ [flake8]
2
+ max-line-length = 88
3
+ extend-ignore =
4
+ E203,
5
+ E501,
6
+ W503
7
+ exclude =
8
+ .git,
9
+ .mypy_cache,
10
+ .pytest_cache,
11
+ __pycache__,
12
+ build,
13
+ dist,
14
+ open_data_products.egg-info
15
+ per-file-ignores =
16
+ open_data_products/odps/__init__.py:F401,F403,E402
@@ -0,0 +1,7 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ build/
4
+ dist/
5
+ *.egg-info/
6
+ .worktrees/
7
+ .DS_Store
@@ -0,0 +1,8 @@
1
+ {
2
+ "mcpServers": {
3
+ "open_data_products": {
4
+ "command": "open-data-products",
5
+ "args": ["serve"]
6
+ }
7
+ }
8
+ }
@@ -0,0 +1,102 @@
1
+ # AGENTS.md
2
+
3
+ Instruction file for AI coding agents (Claude Code, Codex, Cursor, Gemini)
4
+ working in this repository. Authoritative project conventions; precedence over
5
+ generic defaults.
6
+
7
+ ## Project
8
+
9
+ Python SDK + MCP surface for the OpenDataProducts.org standards family
10
+ (ODPS, ODPC, ODPG, ODPV). Single package: `open_data_products`.
11
+
12
+ ## Stack
13
+
14
+ - Python ≥ 3.8 (tested through 3.12; CI runs on 3.14)
15
+ - Runtime deps: `PyYAML`, `certifi`, `jsonschema`, `pycountry`, `phonenumbers`
16
+ - Dev deps: `pytest`, `pytest-cov`, `black`, `flake8`, `mypy`, `build`, `twine`
17
+ - No web framework, no DB, no async runtime.
18
+
19
+ ## Style
20
+
21
+ - 4-space indent. Black with `line-length = 88`. No `any` in type hints.
22
+ - Public API surface lives in `open_data_products/__init__.py` — list new
23
+ exports there explicitly; do not rely on barrel re-exports.
24
+ - Per-spec helpers live under `open_data_products/<spec>/`. Cross-spec
25
+ facades live at the package root (`agent.py`, `cli.py`, `summary.py`,
26
+ `pricing.py`, `mcp/`).
27
+ - Internal-only modules use a leading `_` prefix; do not export them.
28
+ - Docstrings: one-line summary, optional short body. No paragraph essays.
29
+
30
+ ## Structure
31
+
32
+ ```
33
+ open_data_products/
34
+ __init__.py # public API surface
35
+ agent.py # cross-spec load/detect/validate/explain/refs
36
+ cli.py # `open-data-products` console script
37
+ summary.py # load_summary — artifact references (no body)
38
+ pricing.py # ODPS PricingPlans → HTTP 402 envelope
39
+ resources.py # bundled resource registry
40
+ results.py # ValidationResult, Reference, Resource dataclasses
41
+ mcp/
42
+ tools.py # MCP tool registry (data + handlers)
43
+ manifest.py # ARWS agent manifest
44
+ server.py # stdio JSON-RPC 2.0 MCP server
45
+ odps/ # spec-specific package
46
+ odpc/ odpg/ odpv/
47
+ skills/ # SKILL.md bundles for agent hosts
48
+ tests/
49
+ ```
50
+
51
+ New code goes in the smallest existing module that fits its spec namespace.
52
+ Do not introduce parallel `validation.py` / `validators.py` style splits;
53
+ that confusion already exists and should be merged, not extended.
54
+
55
+ ## Testing
56
+
57
+ - `pytest -q` from repo root. Target: 100% green.
58
+ - New behaviour requires a test in `tests/test_<area>.py`.
59
+ - Conformance to agenticpatterns.veso.ai prescriptions is enforced by
60
+ `tests/test_agentic_patterns.py`. Treat that file as the spec — when
61
+ changing the agent surface, update the test first, watch it fail, then
62
+ implement.
63
+ - Use `tmp_path` fixtures, not real filesystem state.
64
+
65
+ ## Git
66
+
67
+ - Branch: `feat/<short-description>`, `fix/<short-description>`, etc.
68
+ - Commit messages: imperative, one logical change per commit.
69
+ - One PR per concern. Don't bundle a refactor with a feature.
70
+ - Never `--amend` after pushing. Never `git push --force` to `main`.
71
+
72
+ ## Security
73
+
74
+ - No hardcoded secrets in source or fixtures. The SDK has no credential
75
+ surface today; if you add one, read from env vars and document it here.
76
+ - The MCP server is `safe`-class only today (read-only). When you add a
77
+ `state-changing` or `destructive` tool, set the `class` field in
78
+ `mcp/tools.py` accordingly and update `tests/test_agentic_patterns.py`.
79
+ - Bundled JSON Schemas are loaded with `jsonschema`'s default checker.
80
+ Do not load arbitrary remote schemas at validate time.
81
+
82
+ ## Pre-Commit Checklist
83
+
84
+ Before marking work complete, run all four:
85
+
86
+ 1. `pytest -q` — all tests pass
87
+ 2. `python -c "import open_data_products"` — package imports cleanly
88
+ 3. `python -m open_data_products.cli manifest --json | python -m json.tool`
89
+ — manifest renders and parses
90
+ 4. No new files in `docs/superpowers/` (that path is reserved for legacy
91
+ AI-planning artifacts already deleted; do not recreate)
92
+
93
+ ## Anti-patterns to avoid
94
+
95
+ - Returning full document bodies from MCP handlers — use `load_summary`
96
+ for references; only load full docs when validation/explanation needs them
97
+ - Adding console_script entry points beyond `open-data-products` — the
98
+ unified subcommand CLI is the contract
99
+ - Importing from `open_data_products.odps.codecs` in user-facing code —
100
+ that module is internal glue between models and YAML/JSON
101
+ - Storing absolute filesystem paths in tool responses — return logical IDs
102
+ and let the resource registry resolve them
@@ -0,0 +1,207 @@
1
+ # Building and Distributing Open Data Products Python SDK
2
+
3
+ This guide explains how to package the Open Data Products Python SDK as a wheel file for distribution.
4
+
5
+ ## Quick Reference
6
+
7
+ ```bash
8
+ # Install build tools
9
+ pip install build
10
+
11
+ # Build the package with minimal output
12
+ python -m build --quiet
13
+
14
+ # Install locally for testing
15
+ pip install dist/open_data_products-0.2.0-py3-none-any.whl
16
+
17
+ # Test functionality
18
+ python -c "import open_data_products; print(open_data_products.__version__)"
19
+ ```
20
+
21
+ ## Prerequisites
22
+
23
+ Install build tools:
24
+ ```bash
25
+ pip install build twine
26
+ ```
27
+
28
+ ## Method 1: Using `build` (Recommended - PEP 517 compliant)
29
+
30
+ The modern way using `pyproject.toml`:
31
+
32
+ ```bash
33
+ # Install build dependencies
34
+ pip install build
35
+
36
+ # Build the package with minimal output (creates both wheel and source distribution)
37
+ python -m build --quiet
38
+
39
+ # This creates files in dist/:
40
+ # - open_data_products-0.2.0-py3-none-any.whl (wheel file)
41
+ # - open_data_products-0.2.0.tar.gz (source distribution)
42
+ ```
43
+
44
+ ## Method 2: Build with specific options
45
+
46
+ ```bash
47
+ # Build with clean environment
48
+ python -m build --wheel --outdir dist/
49
+
50
+ # Build source distribution only
51
+ python -m build --sdist
52
+
53
+ # Build with verbose output
54
+ python -m build --wheel --verbose
55
+ ```
56
+
57
+
58
+ ## Installing the Built Wheel
59
+
60
+ After building, install the wheel locally for testing:
61
+
62
+ ```bash
63
+ # Install the built wheel
64
+ pip install dist/open_data_products-0.2.0-py3-none-any.whl
65
+
66
+ # Or install in development mode with extras
67
+ pip install -e ".[dev]"
68
+ ```
69
+
70
+ ## Verifying the Package
71
+
72
+ Test the installed package:
73
+
74
+ ```python
75
+ import open_data_products
76
+ print(open_data_products.__version__) # Should print 0.2.0
77
+
78
+ from open_data_products.odps import OpenDataProduct, ODPSValidator
79
+ from open_data_products.odps.models import ProductDetails
80
+
81
+ # Test basic functionality
82
+ product = ProductDetails(
83
+ name="Test",
84
+ product_id="test-001",
85
+ visibility="public",
86
+ status="production",
87
+ type="dataset"
88
+ )
89
+ odp = OpenDataProduct(product)
90
+ odp.validate()
91
+ print("✓ Package working correctly")
92
+ ```
93
+
94
+ ## Publishing to PyPI
95
+
96
+ ### Test PyPI (Recommended for testing)
97
+
98
+ ```bash
99
+ # Upload to Test PyPI first
100
+ python -m twine upload --repository testpypi dist/*
101
+
102
+ # Install from Test PyPI to verify
103
+ pip install --index-url https://test.pypi.org/simple/ odps-python
104
+ ```
105
+
106
+ ### Production PyPI
107
+
108
+ ```bash
109
+ # Upload to production PyPI
110
+ python -m twine upload dist/*
111
+
112
+ # Configure credentials first:
113
+ # Create ~/.pypirc with your API tokens
114
+ ```
115
+
116
+ ## Package Structure
117
+
118
+ The built wheel contains:
119
+ ```
120
+ odps_python-0.2.0-py3-none-any.whl
121
+ ├── odps/
122
+ │ ├── __init__.py # Package entry point with version
123
+ │ ├── core.py # Main OpenDataProduct class
124
+ │ ├── models.py # Data models for ODPS components
125
+ │ └── validators.py # International standards validation
126
+ ├── odps_python-0.2.0.dist-info/
127
+ │ ├── METADATA # Package metadata
128
+ │ ├── WHEEL # Wheel metadata
129
+ │ ├── RECORD # File checksums
130
+ │ └── top_level.txt # Top-level packages
131
+ ```
132
+
133
+ ## Build Configuration
134
+
135
+ ### pyproject.toml (Modern)
136
+ - Defines build system requirements
137
+ - Specifies metadata and dependencies
138
+ - Configures development tools (black, mypy)
139
+ - PEP 517/518 compliant
140
+
141
+
142
+ ## Troubleshooting
143
+
144
+ ### Common Issues
145
+
146
+ 1. **Import errors during build**:
147
+ ```bash
148
+ # Ensure all dependencies are installed
149
+ pip install -r requirements.txt
150
+ ```
151
+
152
+ 2. **Version conflicts**:
153
+ ```bash
154
+ # Clean previous builds
155
+ rm -rf build/ dist/ *.egg-info/
156
+ python -m build --quiet
157
+ ```
158
+
159
+ 3. **Missing files in wheel**:
160
+ ```bash
161
+ # Check MANIFEST.in or pyproject.toml package discovery
162
+ python -m build --verbose
163
+ ```
164
+
165
+ 4. **Upload failures**:
166
+ ```bash
167
+ # Check credentials and package name availability
168
+ python -m twine check dist/*
169
+ ```
170
+
171
+ ## Distribution Checklist
172
+
173
+ - [ ] Version number updated in `__init__.py`
174
+ - [ ] CHANGELOG.md updated with release notes
175
+ - [ ] README.md reflects current features
176
+ - [ ] All tests passing
177
+ - [ ] Dependencies properly specified
178
+ - [ ] Built wheel installs and imports correctly
179
+ - [ ] Uploaded to Test PyPI successfully
180
+ - [ ] Documentation is current
181
+
182
+ ## Automated Building
183
+
184
+ For CI/CD, add to your workflow:
185
+
186
+ ```yaml
187
+ # .github/workflows/build.yml
188
+ name: Build and Test
189
+ on: [push, pull_request]
190
+ jobs:
191
+ build:
192
+ runs-on: ubuntu-latest
193
+ steps:
194
+ - uses: actions/checkout@v3
195
+ - name: Set up Python
196
+ uses: actions/setup-python@v4
197
+ with:
198
+ python-version: 3.9
199
+ - name: Install dependencies
200
+ run: |
201
+ pip install build twine
202
+ pip install -e ".[dev]"
203
+ - name: Build package
204
+ run: python -m build --quiet
205
+ - name: Check package
206
+ run: python -m twine check dist/*
207
+ ```