Skip to content

refactor(core): replace __getattribute__ op magic with typed explicit…#53

Merged
Datata1 merged 1 commit into
mainfrom
refactor/02-typed-operation-dispatch
Jul 12, 2026
Merged

refactor(core): replace __getattribute__ op magic with typed explicit…#53
Datata1 merged 1 commit into
mainfrom
refactor/02-typed-operation-dispatch

Conversation

@Datata1

@Datata1 Datata1 commented Jul 12, 2026

Copy link
Copy Markdown
Owner

… dispatch

Implements plans/refactor/02-typed-operation-dispatch.md:

  • APIOperation/StreamOperation become frozen generic dataclasses; response_model drives both validation and the static return type (types.NoneType for void endpoints, replacing type(None) sentinels)
  • New execute_operation(client, op, *, data, params, path_params) frees the dispatch from executor state: endpoint templates are formatted from explicit path params instead of scraping executor dict/model_dump
  • input_model is now enforced: dict payloads are validated before the request is sent (previously declared but silently ignored)
  • Fix falsy-body bug: data={} is now sent as a JSON body (previously dropped by a truthiness check)
  • ResourceBase and new BoundModel (pydantic entity base carrying the bound HTTP client) each expose a typed generic _execute; entities (Team, Workspace, Domain) migrate from the executor mixin
  • Delete _APIOperationExecutor, APIRequestHandler, AsyncCallable and all Field(default=) wiring; domain ops are defined once with their final response models instead of model_copy overrides; Domain.verify_status return type fixed to DomainVerificationStatus
  • Remove src/codesphere/core and src/codesphere/resources from the ty ratchet; uv run ty check passes over both
  • CONTRIBUTING.md: new-resource recipe and public-API policy

Public user-facing API is unchanged; codesphere.core internals are declared private.

… dispatch

Implements plans/refactor/02-typed-operation-dispatch.md:

- APIOperation/StreamOperation become frozen generic dataclasses;
  response_model drives both validation and the static return type
  (types.NoneType for void endpoints, replacing type(None) sentinels)
- New execute_operation(client, op, *, data, params, path_params) frees
  the dispatch from executor state: endpoint templates are formatted from
  explicit path params instead of scraping executor __dict__/model_dump
- input_model is now enforced: dict payloads are validated before the
  request is sent (previously declared but silently ignored)
- Fix falsy-body bug: data={} is now sent as a JSON body (previously
  dropped by a truthiness check)
- ResourceBase and new BoundModel (pydantic entity base carrying the
  bound HTTP client) each expose a typed generic _execute; entities
  (Team, Workspace, Domain) migrate from the executor mixin
- Delete _APIOperationExecutor, APIRequestHandler, AsyncCallable and all
  Field(default=<op>) wiring; domain ops are defined once with their
  final response models instead of model_copy overrides;
  Domain.verify_status return type fixed to DomainVerificationStatus
- Remove src/codesphere/core and src/codesphere/resources from the ty
  ratchet; uv run ty check passes over both
- CONTRIBUTING.md: new-resource recipe and public-API policy

Public user-facing API is unchanged; codesphere.core internals are
declared private.
@Datata1 Datata1 self-assigned this Jul 12, 2026
@Datata1 Datata1 merged commit 5ed602d into main Jul 12, 2026
3 of 4 checks passed
@github-actions

Copy link
Copy Markdown

🛡️ Bandit Security Scan Results

✅ No security issues found by Bandit.

@github-actions

Copy link
Copy Markdown

Coverage

Pytest Coverage Report
FileStmtsMissBranchBrPartCoverMissing
__init__.py9000100% 
client.py22000100% 
config.py9000100% 
exceptions.py9435382356%25–26, 30, 40–42, 53->58, 54->55, 55, 73->74, 74, 85–87, 101–104, 106–107, 148–151, 158–160, 196->197, 197–199, 204->205, 205, 206->207, 207, 210->211, 211, 214, 215->216, 216, 217->218, 218–219, 222
http_client.py54610288%41->exit, 46->exit, 79–80, 82–83, 88–89
utils.py2716181531%12->13, 13–14, 27–33, 35–36, 41–44, 46
core
   __init__.py4000100% 
   base.py47020100% 
   handler.py59318096%80–82
   operations.py15000100% 
resources
   __init__.py0000100% 
resources/metadata
   __init__.py3000100% 
   operations.py6000100% 
   resources.py13000100% 
   schemas.py28000100% 
resources/team
   __init__.py5000100% 
   operations.py8000100% 
   resources.py11000100% 
   schemas.py27000100% 
resources/team/domain
   __init__.py0000100% 
   manager.py21000100% 
   operations.py12000100% 
   resources.py2650081%31, 33, 36, 39–40
   schemas.py34000100% 
resources/team/usage
   __init__.py3000100% 
   manager.py4528292%99->102, 102, 162->165, 165
   operations.py4000100% 
   schemas.py8515141372%69->70, 70, 84–85, 88, 96–99, 114–115, 118, 126–129
resources/workspace
   __init__.py5000100% 
   operations.py12000100% 
   resources.py1624280%13->14, 14, 19->20, 20
   schemas.py99146681%100–101, 103–109, 115–116, 118, 142, 161
resources/workspace/envVars
   __init__.py3000100% 
   models.py30212486%34->36, 36–37, 39->exit
   operations.py7000100% 
   schemas.py4000100% 
resources/workspace/git
   __init__.py3000100% 
   models.py20040100% 
   operations.py8000100% 
   schema.py4000100% 
resources/workspace/landscape
   __init__.py3000100% 
   models.py99736889%28->29, 29, 126->129, 132->135, 156->157, 157–158, 160->155, 163->164, 164, 168–170
   operations.py11000100% 
   resources.py0000100% 
   schemas.py2972910489%122–123, 126, 131–132, 135–136, 139, 144–146, 149–150, 153, 260, 267–268, 343–345, 347–349, 351–352, 467–468, 475–476
resources/workspace/logs
   __init__.py3000100% 
   models.py15586625435%41–42, 48, 50–52, 54, 57–58, 61, 64–65, 67–70, 72–73, 76–77, 79–80, 82–83, 85–87, 89–90, 92–96, 98–99, 101–103, 105–110, 123–124, 214–216, 225–227, 236–238, 248–257, 267–276, 286–295
   operations.py5000100% 
   schemas.py19000100% 
TOTAL147422224213379% 

Test Execution Summary

Tests Skipped Failures Errors Time
263 0 💤 0 ❌ 0 🔥 2.674s ⏱️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant