crosscontract 0.2.2__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.
- crosscontract-0.2.2/.github/CODEOWNERS +1 -0
- crosscontract-0.2.2/.github/ISSUE_TEMPLATE/bug_report.md +31 -0
- crosscontract-0.2.2/.github/ISSUE_TEMPLATE/discussion---design-proposal.md +24 -0
- crosscontract-0.2.2/.github/ISSUE_TEMPLATE/documentation-request.md +20 -0
- crosscontract-0.2.2/.github/ISSUE_TEMPLATE/feature_request.md +31 -0
- crosscontract-0.2.2/.github/ISSUE_TEMPLATE/improvement.md +20 -0
- crosscontract-0.2.2/.github/ISSUE_TEMPLATE/maintenance---chore.md +21 -0
- crosscontract-0.2.2/.github/ISSUE_TEMPLATE/qa---test-case.md +22 -0
- crosscontract-0.2.2/.github/copilot-instructions.md +76 -0
- crosscontract-0.2.2/.github/workflows/check_pr_title.yml +26 -0
- crosscontract-0.2.2/.github/workflows/check_pr_to_main.yml +18 -0
- crosscontract-0.2.2/.github/workflows/deploy_docs.yml +53 -0
- crosscontract-0.2.2/.github/workflows/publish_pypi.yml +59 -0
- crosscontract-0.2.2/.github/workflows/release_main_branch.yml +31 -0
- crosscontract-0.2.2/.github/workflows/test_and_coverage.yml +75 -0
- crosscontract-0.2.2/.github/workflows/versioning.yml +37 -0
- crosscontract-0.2.2/.gitignore +210 -0
- crosscontract-0.2.2/.pre-commit-config.yaml +15 -0
- crosscontract-0.2.2/.python-version +1 -0
- crosscontract-0.2.2/.vscode/launch.json +33 -0
- crosscontract-0.2.2/.vscode/settings.json +27 -0
- crosscontract-0.2.2/CHANGELOG.md +73 -0
- crosscontract-0.2.2/LICENSE +21 -0
- crosscontract-0.2.2/PKG-INFO +23 -0
- crosscontract-0.2.2/README.md +6 -0
- crosscontract-0.2.2/docs/about.md +3 -0
- crosscontract-0.2.2/docs/client/index.md +26 -0
- crosscontract-0.2.2/docs/contracts/gdp_example.yaml +31 -0
- crosscontract-0.2.2/docs/contracts/index.md +40 -0
- crosscontract-0.2.2/docs/contracts/metadata.md +63 -0
- crosscontract-0.2.2/docs/contracts/schema.md +21 -0
- crosscontract-0.2.2/docs/index.md +98 -0
- crosscontract-0.2.2/docs/notebooks/.gitignore +2 -0
- crosscontract-0.2.2/docs/reference/client.md +7 -0
- crosscontract-0.2.2/docs/reference/contracts.md +30 -0
- crosscontract-0.2.2/mkdocs.yml +74 -0
- crosscontract-0.2.2/notebooks/.gitkeep +0 -0
- crosscontract-0.2.2/notebooks/client_tutorial.ipynb +1557 -0
- crosscontract-0.2.2/notebooks/contract_tutorial.ipynb +295 -0
- crosscontract-0.2.2/pyproject.toml +108 -0
- crosscontract-0.2.2/scripts/copy_notebooks_to_docs.py +21 -0
- crosscontract-0.2.2/src/crosscontract/__init__.py +14 -0
- crosscontract-0.2.2/src/crosscontract/contracts/__init__.py +9 -0
- crosscontract-0.2.2/src/crosscontract/contracts/contracts/__init__.py +4 -0
- crosscontract-0.2.2/src/crosscontract/contracts/contracts/base_contract.py +103 -0
- crosscontract-0.2.2/src/crosscontract/contracts/contracts/cross_contract.py +64 -0
- crosscontract-0.2.2/src/crosscontract/contracts/schema/__init__.py +29 -0
- crosscontract-0.2.2/src/crosscontract/contracts/schema/adapters/__init__.py +18 -0
- crosscontract-0.2.2/src/crosscontract/contracts/schema/adapters/abstract_adapter.py +30 -0
- crosscontract-0.2.2/src/crosscontract/contracts/schema/adapters/pandera_adapter.py +557 -0
- crosscontract-0.2.2/src/crosscontract/contracts/schema/adapters/pydantic_adapter.py +288 -0
- crosscontract-0.2.2/src/crosscontract/contracts/schema/adapters/sqlalchemy_adapter.py +168 -0
- crosscontract-0.2.2/src/crosscontract/contracts/schema/adapters/utils.py +30 -0
- crosscontract-0.2.2/src/crosscontract/contracts/schema/exceptions/__init__.py +1 -0
- crosscontract-0.2.2/src/crosscontract/contracts/schema/exceptions/validation_error.py +222 -0
- crosscontract-0.2.2/src/crosscontract/contracts/schema/field_descriptors/__init__.py +20 -0
- crosscontract-0.2.2/src/crosscontract/contracts/schema/field_descriptors/descriptors.py +66 -0
- crosscontract-0.2.2/src/crosscontract/contracts/schema/field_descriptors/field_descriptors.py +89 -0
- crosscontract-0.2.2/src/crosscontract/contracts/schema/fields/__init__.py +18 -0
- crosscontract-0.2.2/src/crosscontract/contracts/schema/fields/base.py +61 -0
- crosscontract-0.2.2/src/crosscontract/contracts/schema/fields/datetime_field.py +37 -0
- crosscontract-0.2.2/src/crosscontract/contracts/schema/fields/list_field.py +55 -0
- crosscontract-0.2.2/src/crosscontract/contracts/schema/fields/numeric_field.py +44 -0
- crosscontract-0.2.2/src/crosscontract/contracts/schema/fields/string_field.py +48 -0
- crosscontract-0.2.2/src/crosscontract/contracts/schema/reference/__init__.py +4 -0
- crosscontract-0.2.2/src/crosscontract/contracts/schema/reference/foreign_key.py +150 -0
- crosscontract-0.2.2/src/crosscontract/contracts/schema/reference/primary_key.py +52 -0
- crosscontract-0.2.2/src/crosscontract/contracts/schema/schema.py +253 -0
- crosscontract-0.2.2/src/crosscontract/contracts/schema/validation/__init__.py +3 -0
- crosscontract-0.2.2/src/crosscontract/contracts/schema/validation/validate_dataframe.py +81 -0
- crosscontract-0.2.2/src/crosscontract/contracts/utils.py +35 -0
- crosscontract-0.2.2/src/crosscontract/contracts/valid_items.py +14 -0
- crosscontract-0.2.2/src/crosscontract/crossclient/__init__.py +3 -0
- crosscontract-0.2.2/src/crosscontract/crossclient/crossclient.py +146 -0
- crosscontract-0.2.2/src/crosscontract/crossclient/exceptions/__init__.py +24 -0
- crosscontract-0.2.2/src/crosscontract/crossclient/exceptions/exception_factory.py +104 -0
- crosscontract-0.2.2/src/crosscontract/crossclient/exceptions/exceptions.py +104 -0
- crosscontract-0.2.2/src/crosscontract/crossclient/logger.py +4 -0
- crosscontract-0.2.2/src/crosscontract/crossclient/services/__init__.py +4 -0
- crosscontract-0.2.2/src/crosscontract/crossclient/services/contract_resource.py +303 -0
- crosscontract-0.2.2/src/crosscontract/crossclient/services/contract_service.py +267 -0
- crosscontract-0.2.2/src/crosscontract/py.typed +0 -0
- crosscontract-0.2.2/src/tests/__init__.py +1 -0
- crosscontract-0.2.2/src/tests/contracts/contracts/test_contracts.py +113 -0
- crosscontract-0.2.2/src/tests/contracts/frictionless_package_standard_v2.json +2886 -0
- crosscontract-0.2.2/src/tests/contracts/frictionless_table_standard_v1.json +1516 -0
- crosscontract-0.2.2/src/tests/contracts/frictionless_table_standard_v2.json +2431 -0
- crosscontract-0.2.2/src/tests/contracts/schema/__init__.py +0 -0
- crosscontract-0.2.2/src/tests/contracts/schema/adapters/test_integration_pandera.py +139 -0
- crosscontract-0.2.2/src/tests/contracts/schema/adapters/test_integration_pandera_references.py +195 -0
- crosscontract-0.2.2/src/tests/contracts/schema/adapters/test_integration_pydantic.py +190 -0
- crosscontract-0.2.2/src/tests/contracts/schema/adapters/test_pandera_pandas_adapter.py +300 -0
- crosscontract-0.2.2/src/tests/contracts/schema/adapters/test_pydantic_adapater.py +683 -0
- crosscontract-0.2.2/src/tests/contracts/schema/adapters/test_sqlaqlchemy_adapter.py +204 -0
- crosscontract-0.2.2/src/tests/contracts/schema/adapters/test_utils_adapter.py +20 -0
- crosscontract-0.2.2/src/tests/contracts/schema/exceptions/__init__.py +0 -0
- crosscontract-0.2.2/src/tests/contracts/schema/exceptions/test_validation_error.py +377 -0
- crosscontract-0.2.2/src/tests/contracts/schema/reference/__init__.py +0 -0
- crosscontract-0.2.2/src/tests/contracts/schema/reference/test_foreign_key.py +229 -0
- crosscontract-0.2.2/src/tests/contracts/schema/reference/test_primary_key.py +28 -0
- crosscontract-0.2.2/src/tests/contracts/schema/test_descriptors.py +125 -0
- crosscontract-0.2.2/src/tests/contracts/schema/test_schema.py +339 -0
- crosscontract-0.2.2/src/tests/contracts/schema/validation/__init__.py +0 -0
- crosscontract-0.2.2/src/tests/contracts/schema/validation/test_pandas_validation.py +192 -0
- crosscontract-0.2.2/src/tests/contracts/simple_contract.yaml +39 -0
- crosscontract-0.2.2/src/tests/contracts/test_utils.py +46 -0
- crosscontract-0.2.2/src/tests/crossclient/conftest.py +69 -0
- crosscontract-0.2.2/src/tests/crossclient/contracts/__init__.py +0 -0
- crosscontract-0.2.2/src/tests/crossclient/contracts/test_contract_resource.py +444 -0
- crosscontract-0.2.2/src/tests/crossclient/contracts/test_contracts_service.py +341 -0
- crosscontract-0.2.2/src/tests/crossclient/exceptions/__init__.py +0 -0
- crosscontract-0.2.2/src/tests/crossclient/exceptions/test_exception_factory.py +183 -0
- crosscontract-0.2.2/src/tests/crossclient/exceptions/test_exceptions.py +60 -0
- crosscontract-0.2.2/src/tests/crossclient/test_crossclient.py +138 -0
- crosscontract-0.2.2/uv.lock +3360 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
* @jabrell
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug report
|
|
3
|
+
about: Report a software bug or issue
|
|
4
|
+
title: "\U0001F41E Bug: [describe the issue]"
|
|
5
|
+
labels: bug
|
|
6
|
+
assignees: ''
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
### Describe the Bug
|
|
11
|
+
A clear and concise description of what the bug is.
|
|
12
|
+
|
|
13
|
+
### Steps to Reproduce
|
|
14
|
+
1. Go to '...'
|
|
15
|
+
2. Click on '...'
|
|
16
|
+
3. Scroll down to '...'
|
|
17
|
+
4. See error
|
|
18
|
+
|
|
19
|
+
### Expected Behavior
|
|
20
|
+
What you expected to happen instead.
|
|
21
|
+
|
|
22
|
+
### Screenshots or Logs
|
|
23
|
+
If applicable, add screenshots or logs to help explain the issue.
|
|
24
|
+
|
|
25
|
+
### Environment
|
|
26
|
+
- Device: [eg. Laptop 13", iPhone 15, iPad Air]
|
|
27
|
+
- OS: [e.g. Windows 11, macOS 14]
|
|
28
|
+
- Browser/app version: [e.g. Chrome 115, v2.3.1]
|
|
29
|
+
|
|
30
|
+
### Additional context
|
|
31
|
+
Add any other context about the problem here.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Discussion / Design Proposal
|
|
3
|
+
about: Share an idea or proposal for feedback
|
|
4
|
+
title: "\U0001F4AD Discussion: [topic or idea]"
|
|
5
|
+
labels: question
|
|
6
|
+
assignees: ''
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
### Topic
|
|
11
|
+
Briefly describe the concept, idea, or challenge.
|
|
12
|
+
|
|
13
|
+
### Problem Statement
|
|
14
|
+
What problem are we trying to solve or avoid?
|
|
15
|
+
|
|
16
|
+
### Proposed Direction
|
|
17
|
+
Outline your suggested approach or solution.
|
|
18
|
+
|
|
19
|
+
### Alternatives Considered
|
|
20
|
+
Any other directions you thought of or rejected?
|
|
21
|
+
|
|
22
|
+
### Open Questions
|
|
23
|
+
- [ ] What are the trade-offs?
|
|
24
|
+
- [ ] What do we need to learn or test?
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Documentation Request
|
|
3
|
+
about: Request updates or additions to documentation
|
|
4
|
+
title: "\U0001F4DA Docs: [topic or file name]"
|
|
5
|
+
labels: documentation
|
|
6
|
+
assignees: ''
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
### Topic or Page
|
|
11
|
+
Which doc or section needs an update?
|
|
12
|
+
|
|
13
|
+
### Problem or Gap
|
|
14
|
+
What’s currently unclear, outdated, or missing?
|
|
15
|
+
|
|
16
|
+
### Suggested Changes
|
|
17
|
+
List specific edits, new sections, or examples to add.
|
|
18
|
+
|
|
19
|
+
### Supporting Links or Content
|
|
20
|
+
If relevant, include screenshots, code, or references.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature request
|
|
3
|
+
about: Suggest an new feature or capability
|
|
4
|
+
title: "\U0001F31F Feature: [suggested feature name]"
|
|
5
|
+
labels: feature
|
|
6
|
+
assignees: ''
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
### User Story
|
|
11
|
+
**As a [role],**
|
|
12
|
+
**I want [an action or feature],**
|
|
13
|
+
**So that [a reason or benefit].**
|
|
14
|
+
|
|
15
|
+
### Description
|
|
16
|
+
A detailed explanation of the feature you'd like to see.
|
|
17
|
+
|
|
18
|
+
### Acceptance Criteria
|
|
19
|
+
- [ ] Criteria 1: Describe the first acceptance criterion here.
|
|
20
|
+
- [ ] Criteria 2: Describe the second acceptance criterion here.
|
|
21
|
+
- [ ] Criteria 3: Describe additional criteria as needed.
|
|
22
|
+
|
|
23
|
+
### Definition of Done
|
|
24
|
+
- [ ] All acceptance criteria are met.
|
|
25
|
+
- [ ] Code is reviewed and approved.
|
|
26
|
+
- [ ] Necessary tests are written and pass.
|
|
27
|
+
- [ ] Documentation is updated, if applicable.
|
|
28
|
+
- [ ] Feature is deployed to the [environment name].
|
|
29
|
+
|
|
30
|
+
### Additional Context
|
|
31
|
+
Add any related links, screenshots, or prior discussions.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Improvement
|
|
3
|
+
about: Propose improvements to existing features
|
|
4
|
+
title: "\U0001F501 Improve: [feature/component name]"
|
|
5
|
+
labels: ''
|
|
6
|
+
assignees: ''
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
### Current Behavior
|
|
11
|
+
Briefly describe what the current functionality is and any issues with it.
|
|
12
|
+
|
|
13
|
+
### Suggested Improvement
|
|
14
|
+
Describe how this feature could be improved, optimized, or simplified.
|
|
15
|
+
|
|
16
|
+
### Why This Matters
|
|
17
|
+
Explain the impact or benefit of this change to users or maintainers.
|
|
18
|
+
|
|
19
|
+
### Related Issues or Feedback
|
|
20
|
+
List any related discussions, issues, or user requests.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Maintenance / Chore
|
|
3
|
+
about: Internal development or maintenance task
|
|
4
|
+
title: "\U0001F6E0️ Chore: [task name]"
|
|
5
|
+
labels: ''
|
|
6
|
+
assignees: ''
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
### Task Description
|
|
11
|
+
Explain what needs to be done and why.
|
|
12
|
+
|
|
13
|
+
### Context
|
|
14
|
+
Is this related to refactoring, tech debt, infra updates, etc.?
|
|
15
|
+
|
|
16
|
+
### Dependencies
|
|
17
|
+
Does this task block or depend on other issues?
|
|
18
|
+
|
|
19
|
+
### Definition of Done
|
|
20
|
+
- [ ] Clear outcome or artifact produced
|
|
21
|
+
- [ ] No user-visible changes unless noted
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: QA / Test Case
|
|
3
|
+
about: Add or request test scenarios or QA validation
|
|
4
|
+
title: "\U0001F9EA Test Case: [area or component]"
|
|
5
|
+
labels: ''
|
|
6
|
+
assignees: ''
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
### What to Test
|
|
11
|
+
Describe the functionality or area that needs testing.
|
|
12
|
+
|
|
13
|
+
###Test Scenarios
|
|
14
|
+
- [ ] Scenario 1: ...
|
|
15
|
+
- [ ] Scenario 2: ...
|
|
16
|
+
- [ ] Scenario 3: ...
|
|
17
|
+
|
|
18
|
+
### Expected Results
|
|
19
|
+
Describe what each test should confirm or validate.
|
|
20
|
+
|
|
21
|
+
### Environment / Test Notes
|
|
22
|
+
Mention browsers, platforms, or edge cases to consider.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# GitHub Copilot Instructions
|
|
2
|
+
|
|
3
|
+
You are an expert **Senior Python Software Engineer** specializing in distributed systems, data modeling, and API design. You are responsible for maintaining a Python Package that provides high-integrity data contracts and SDKs.
|
|
4
|
+
|
|
5
|
+
## 1. Interaction Protocol (CRITICAL)
|
|
6
|
+
|
|
7
|
+
- **Plan First:** For logic changes, refactoring, or new features, **do not write code immediately**. Outline a step-by-step plan.
|
|
8
|
+
- **Confirm:** Explicitly ask: _"Does this plan align with your intent, or should we adjust?"_ Wait for approval.
|
|
9
|
+
- **Clarify:** If requirements are vague, ask clarifying questions immediately.
|
|
10
|
+
|
|
11
|
+
## 2. Project Structure (The Map)
|
|
12
|
+
|
|
13
|
+
The project is a Monorepo managed by `uv`. Always check relative paths against this map:
|
|
14
|
+
|
|
15
|
+
- **Root Configs:** `pyproject.toml`, `uv.lock`, `mkdocs.yml` (Documentation).
|
|
16
|
+
- **Libraries & Packages:**
|
|
17
|
+
- `src/crosscontract/contracts/`: Data Contracts, Schema definitions, and Pydantic models.
|
|
18
|
+
- `src/crosscontract/crossclient/`: Synchronous HTTP client SDK.
|
|
19
|
+
- **Data & Scripts:**
|
|
20
|
+
- `notebooks/`: Notebooks for illustration and experimentation.
|
|
21
|
+
- **Documentation:**
|
|
22
|
+
- `docs/`: MkDocs documentation source files.
|
|
23
|
+
|
|
24
|
+
## 3. Tech Stack & Standards
|
|
25
|
+
|
|
26
|
+
- **Language:** Python 3.12+ (Use modern type hinting: PEP 604 union types `int | str`, `Generic` types, and `TypedDict`).
|
|
27
|
+
- **Data Contracts (Pydantic v2):**
|
|
28
|
+
- **Models:** Use `ConfigDict(extra='forbid', str_strip_whitespace=True)` for strict validation.
|
|
29
|
+
- **Polymorphism:** Use `Annotated[Union[...], Field(discriminator="type")]` for polymorphic list fields (e.g., `FieldUnion`).
|
|
30
|
+
- **Frictionless Compat:** `TableSchema` models may use camelCase fields (e.g., `primaryKey`) to match JSON schema standards directly.
|
|
31
|
+
- **Validation:** Use `model_validator(mode='after')` for cross-field validation.
|
|
32
|
+
- **Data Validation:**
|
|
33
|
+
- Use **Pandera** (`pandera.pandas`) for DataFrame-level validation.
|
|
34
|
+
- **API Client:**
|
|
35
|
+
- Use `httpx.Client` for **synchronous** operations.
|
|
36
|
+
- **Error Handling:** Raise `CrossClientError` base exception. Map 422 responses to `ValidationError` containing detailed structure.
|
|
37
|
+
- **Context Manager:** The client is designed to be used as a context manager (`with CrossClient(...) as client:`).
|
|
38
|
+
- **Package Manager:** **uv**.
|
|
39
|
+
- Use `uv sync` or `uv add`. Do not suggest `pip`.
|
|
40
|
+
|
|
41
|
+
## 4. Code Style & Linting
|
|
42
|
+
|
|
43
|
+
- **Linting:** Strictly follow `ruff` rules. Configured in `pyproject.toml`.
|
|
44
|
+
- **Imports:** Grouping: 1. Stdlib, 2. Third-party (include `pydantic`, `pandas`, `httpx`), 3. Workspace packages (`crosscontract`), 4. Local modules.
|
|
45
|
+
- **Typing:** **Strict typing is required.** Use `Any` only as a last resort. Use `Self` for method return types where applicable.
|
|
46
|
+
- **Naming:** Follow PEP8. Exceptions allowed for specific Schema fields (camelCase) where mapping to external JSON standards is required.
|
|
47
|
+
|
|
48
|
+
## 5. Documentation (MkDocs)
|
|
49
|
+
|
|
50
|
+
- **Google Style:** All public APIs must have Google-style docstrings.
|
|
51
|
+
- **Admonitions:** Use MkDocs Material syntax (e.g., `!!! note "Title"`) in docstrings and `.md` files.
|
|
52
|
+
- **Root Config:** `mkdocs.yml` in the root directory controls the docs site.
|
|
53
|
+
- **Documentation:** When adding features, identify which file in `docs/` needs an update.
|
|
54
|
+
|
|
55
|
+
## 6. Testing
|
|
56
|
+
|
|
57
|
+
- **Pattern:** Use **Arrange-Act-Assert (AAA)**.
|
|
58
|
+
- **Tooling:** Use `pytest` for all tests. Use `respx` for mocking HTTP requests.
|
|
59
|
+
- **Contract Testing:** Ensure every Pydantic model has a test case for:
|
|
60
|
+
1. Valid data (Happy path).
|
|
61
|
+
2. Invalid data (Edge cases/Validation errors).
|
|
62
|
+
3. Serialization to/from JSON.
|
|
63
|
+
- **Isolation:** Mock external API calls using `respx` to test the client without hitting real endpoints.
|
|
64
|
+
- **Organization:** Mirror source structure under `tests/`. Group related cases in classes.
|
|
65
|
+
|
|
66
|
+
## 7. Frictionless Mapping Reference (Internal)
|
|
67
|
+
|
|
68
|
+
When implementing Frictionless schemas in Pydantic:
|
|
69
|
+
|
|
70
|
+
- `name` -> Field name
|
|
71
|
+
- `type` -> Python type hint (mapped via `FieldUnion` discriminators)
|
|
72
|
+
- `title` -> `Field(title=...)`
|
|
73
|
+
- `constraints.required` -> Non-optional type hint
|
|
74
|
+
- `description` -> `Field(description=...)`
|
|
75
|
+
- `constraints.enum` -> `Literal` or `Enum`
|
|
76
|
+
- `primaryKey` -> `primaryKey` field in `TableSchema`
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: Lint PR Title
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_call:
|
|
5
|
+
|
|
6
|
+
jobs:
|
|
7
|
+
validate_title:
|
|
8
|
+
runs-on: ubuntu-latest
|
|
9
|
+
steps:
|
|
10
|
+
- uses: amannn/action-semantic-pull-request@v5
|
|
11
|
+
env:
|
|
12
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
13
|
+
with:
|
|
14
|
+
# The complete recommended list
|
|
15
|
+
types: |
|
|
16
|
+
feat
|
|
17
|
+
fix
|
|
18
|
+
docs
|
|
19
|
+
style
|
|
20
|
+
refactor
|
|
21
|
+
perf
|
|
22
|
+
test
|
|
23
|
+
ci
|
|
24
|
+
chore
|
|
25
|
+
revert
|
|
26
|
+
requireScope: false
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Orchestrator workflow for the main branch.
|
|
2
|
+
# Runs tests on every PR to the main branch.
|
|
3
|
+
name: Check PR Main Branch
|
|
4
|
+
|
|
5
|
+
on:
|
|
6
|
+
pull_request:
|
|
7
|
+
branches:
|
|
8
|
+
- main
|
|
9
|
+
types:
|
|
10
|
+
- opened
|
|
11
|
+
- edited
|
|
12
|
+
- synchronize
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
lint_pr_title:
|
|
16
|
+
uses: ./.github/workflows/check_pr_title.yml
|
|
17
|
+
test_and_coverage:
|
|
18
|
+
uses: ./.github/workflows/test_and_coverage.yml
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Reusable workflow that builds the MkDocs documentation site and deploys
|
|
2
|
+
# it to GitHub Pages. Requires 'workflow_call' or 'workflow_dispatch'.
|
|
3
|
+
name: Build and Deploy Docs
|
|
4
|
+
|
|
5
|
+
on:
|
|
6
|
+
workflow_call:
|
|
7
|
+
inputs:
|
|
8
|
+
ref:
|
|
9
|
+
description: "The git ref to check out (tag, branch, or SHA)"
|
|
10
|
+
required: false
|
|
11
|
+
type: string
|
|
12
|
+
default: ""
|
|
13
|
+
workflow_dispatch:
|
|
14
|
+
permissions:
|
|
15
|
+
contents: write
|
|
16
|
+
pages: write
|
|
17
|
+
id-token: write
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
deploy:
|
|
21
|
+
environment:
|
|
22
|
+
name: github-pages
|
|
23
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
steps:
|
|
26
|
+
- name: Checkout repository
|
|
27
|
+
uses: actions/checkout@v6
|
|
28
|
+
|
|
29
|
+
- name: Install uv
|
|
30
|
+
uses: astral-sh/setup-uv@v7
|
|
31
|
+
with:
|
|
32
|
+
enable-cache: true
|
|
33
|
+
cache-dependency-glob: "uv.lock"
|
|
34
|
+
|
|
35
|
+
- name: Set up Python
|
|
36
|
+
run: uv python install 3.12
|
|
37
|
+
|
|
38
|
+
- name: Install dependencies
|
|
39
|
+
run: uv sync --group docs
|
|
40
|
+
|
|
41
|
+
- name: Build Docs
|
|
42
|
+
# Change 'gh-deploy' to 'build'. This creates the 'site' folder.
|
|
43
|
+
run: uv run mkdocs build
|
|
44
|
+
|
|
45
|
+
- name: Upload artifact
|
|
46
|
+
uses: actions/upload-pages-artifact@v3
|
|
47
|
+
with:
|
|
48
|
+
# MkDocs builds to the 'site' directory by default
|
|
49
|
+
path: "./site"
|
|
50
|
+
|
|
51
|
+
- name: Deploy to GitHub Pages
|
|
52
|
+
id: deployment
|
|
53
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Standalone workflow to publish the package to PyPI.
|
|
2
|
+
# Triggered manually. Defaults to the latest release tag.
|
|
3
|
+
name: Publish to PyPI
|
|
4
|
+
|
|
5
|
+
on:
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
inputs:
|
|
8
|
+
version:
|
|
9
|
+
description: "Version tag to publish (e.g. v0.2.1). Defaults to latest release."
|
|
10
|
+
required: false
|
|
11
|
+
type: string
|
|
12
|
+
default: ""
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
resolve_version:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
outputs:
|
|
18
|
+
tag: ${{ steps.resolve.outputs.tag }}
|
|
19
|
+
steps:
|
|
20
|
+
- name: Get latest release tag
|
|
21
|
+
id: resolve
|
|
22
|
+
env:
|
|
23
|
+
GH_TOKEN: ${{ github.token }}
|
|
24
|
+
run: |
|
|
25
|
+
if [ -n "${{ inputs.version }}" ]; then
|
|
26
|
+
echo "tag=${{ inputs.version }}" >> $GITHUB_OUTPUT
|
|
27
|
+
else
|
|
28
|
+
LATEST=$(gh release view --repo ${{ github.repository }} --json tagName -q .tagName)
|
|
29
|
+
echo "tag=$LATEST" >> $GITHUB_OUTPUT
|
|
30
|
+
fi
|
|
31
|
+
- name: Validate tag exists
|
|
32
|
+
if: inputs.version != ''
|
|
33
|
+
env:
|
|
34
|
+
GH_TOKEN: ${{ github.token }}
|
|
35
|
+
run: |
|
|
36
|
+
if ! gh release view ${{ inputs.version }} --repo ${{ github.repository }} > /dev/null 2>&1; then
|
|
37
|
+
echo "Error: version '${{ inputs.version }}' not found in releases"
|
|
38
|
+
exit 1
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
publish:
|
|
42
|
+
needs: resolve_version
|
|
43
|
+
runs-on: ubuntu-latest
|
|
44
|
+
environment:
|
|
45
|
+
name: pypi-test
|
|
46
|
+
url: https://test.pypi.org/p/crosscontract
|
|
47
|
+
permissions:
|
|
48
|
+
id-token: write
|
|
49
|
+
steps:
|
|
50
|
+
- uses: actions/checkout@v4
|
|
51
|
+
with:
|
|
52
|
+
ref: ${{ needs.resolve_version.outputs.tag }}
|
|
53
|
+
- uses: astral-sh/setup-uv@v5
|
|
54
|
+
- run: uv build
|
|
55
|
+
- name: Inspect wheel contents
|
|
56
|
+
run: unzip -l dist/*.whl
|
|
57
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
58
|
+
with:
|
|
59
|
+
repository-url: https://test.pypi.org/legacy/
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Orchestrator workflow to deploy a new release when changes are pushed to the
|
|
2
|
+
# main branch. It runs tests, creates a release if needed, and deploys docs if
|
|
3
|
+
#the release was successful.
|
|
4
|
+
name: Release Main Branch
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
push:
|
|
9
|
+
branches:
|
|
10
|
+
- main
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test_and_coverage:
|
|
14
|
+
uses: ./.github/workflows/test_and_coverage.yml
|
|
15
|
+
|
|
16
|
+
release:
|
|
17
|
+
needs: test_and_coverage
|
|
18
|
+
if: success()
|
|
19
|
+
uses: ./.github/workflows/versioning.yml
|
|
20
|
+
permissions:
|
|
21
|
+
contents: write
|
|
22
|
+
secrets: inherit
|
|
23
|
+
|
|
24
|
+
deploy_docs:
|
|
25
|
+
needs: release
|
|
26
|
+
if: >-
|
|
27
|
+
success() &&
|
|
28
|
+
(needs.release.outputs.released == 'true' || needs.release.result == 'success')
|
|
29
|
+
uses: ./.github/workflows/deploy_docs.yml
|
|
30
|
+
with:
|
|
31
|
+
ref: ${{ needs.release.outputs.released == 'true' && needs.release.outputs.tag || github.ref }}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Reusable workflow that runs the test suite and generates coverage reports
|
|
2
|
+
# for Python 3.12 and 3.13. It includes pre-commit checks.
|
|
3
|
+
name: Test and Coverage
|
|
4
|
+
|
|
5
|
+
on:
|
|
6
|
+
workflow_call:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
pre-commit:
|
|
11
|
+
name: Check Pre-commit Hooks
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- name: Checkout repository
|
|
15
|
+
uses: actions/checkout@v6
|
|
16
|
+
|
|
17
|
+
- name: Install uv
|
|
18
|
+
uses: astral-sh/setup-uv@v7
|
|
19
|
+
with:
|
|
20
|
+
enable-cache: true
|
|
21
|
+
cache-dependency-glob: "uv.lock"
|
|
22
|
+
|
|
23
|
+
- name: Set up Python
|
|
24
|
+
run: uv python install 3.12
|
|
25
|
+
|
|
26
|
+
- name: Install dependencies
|
|
27
|
+
run: uv sync
|
|
28
|
+
|
|
29
|
+
- name: Run pre-commit
|
|
30
|
+
run: uv run pre-commit run --all-files
|
|
31
|
+
|
|
32
|
+
test:
|
|
33
|
+
name: Test (Python ${{ matrix.python-version }})
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
strategy:
|
|
36
|
+
fail-fast: false
|
|
37
|
+
matrix:
|
|
38
|
+
python-version:
|
|
39
|
+
- "3.11"
|
|
40
|
+
- "3.12"
|
|
41
|
+
- "3.13"
|
|
42
|
+
|
|
43
|
+
steps:
|
|
44
|
+
- name: Checkout repository
|
|
45
|
+
uses: actions/checkout@v6
|
|
46
|
+
|
|
47
|
+
- name: Install uv
|
|
48
|
+
uses: astral-sh/setup-uv@v7
|
|
49
|
+
with:
|
|
50
|
+
enable-cache: true
|
|
51
|
+
cache-dependency-glob: "uv.lock"
|
|
52
|
+
|
|
53
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
54
|
+
run: uv python install ${{ matrix.python-version }}
|
|
55
|
+
|
|
56
|
+
- name: Install dependencies
|
|
57
|
+
run: uv sync
|
|
58
|
+
|
|
59
|
+
- name: Run tests with coverage
|
|
60
|
+
run: |
|
|
61
|
+
set -o pipefail
|
|
62
|
+
uv run coverage run -m pytest | tee pytest.log
|
|
63
|
+
|
|
64
|
+
- name: Generate Reports
|
|
65
|
+
if: success() || failure()
|
|
66
|
+
run: |
|
|
67
|
+
echo "## Test Summary (Python ${{ matrix.python-version }})" >> $GITHUB_STEP_SUMMARY
|
|
68
|
+
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
69
|
+
cat pytest.log >> $GITHUB_STEP_SUMMARY
|
|
70
|
+
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
71
|
+
|
|
72
|
+
echo "## Coverage Summary (Python ${{ matrix.python-version }})" >> $GITHUB_STEP_SUMMARY
|
|
73
|
+
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
74
|
+
uv run coverage report >> $GITHUB_STEP_SUMMARY
|
|
75
|
+
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: Versioning
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_call:
|
|
5
|
+
outputs:
|
|
6
|
+
released:
|
|
7
|
+
description: "True if a release was created"
|
|
8
|
+
value: ${{ jobs.versioning.outputs.released }}
|
|
9
|
+
tag:
|
|
10
|
+
description: "The tag created (e.g. v1.0.1)"
|
|
11
|
+
value: ${{ jobs.versioning.outputs.tag }}
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
versioning:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
permissions:
|
|
17
|
+
contents: write # Required to push the new version commit and tag
|
|
18
|
+
outputs:
|
|
19
|
+
released: ${{ steps.release.outputs.released }}
|
|
20
|
+
tag: ${{ steps.release.outputs.tag }}
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- name: Generate token
|
|
24
|
+
id: generate-token
|
|
25
|
+
uses: actions/create-github-app-token@v2
|
|
26
|
+
with:
|
|
27
|
+
app-id: ${{ secrets.APP_ID }}
|
|
28
|
+
private-key: ${{ secrets.APP_PRIVATE_KEY }}
|
|
29
|
+
- uses: actions/checkout@v6.0.2
|
|
30
|
+
with:
|
|
31
|
+
fetch-depth: 0
|
|
32
|
+
token: ${{ steps.generate-token.outputs.token }}
|
|
33
|
+
- name: Python Semantic Release
|
|
34
|
+
id: release
|
|
35
|
+
uses: python-semantic-release/python-semantic-release@v10.5.3
|
|
36
|
+
with:
|
|
37
|
+
github_token: ${{ steps.generate-token.outputs.token }}
|