Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,091 changes: 1,091 additions & 0 deletions crates/sqltide-python/src/shapes/cli_service.rs

Large diffs are not rendered by default.

984 changes: 984 additions & 0 deletions crates/sqltide-python/src/shapes/executor_ops.rs

Large diffs are not rendered by default.

39 changes: 32 additions & 7 deletions crates/sqltide-python/src/shapes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ use pyo3::types::{
IntoPyDict, PyCFunction, PyDict, PyFloat, PyFrozenSet, PyString, PyTuple, PyType,
};

mod cli_service;
mod compiler_analysis;
mod compiler_project;
mod executor_ops;
mod planner_execution;

/// The callable a `default_factory` field calls for each new instance.
Expand Down Expand Up @@ -77,10 +79,11 @@ impl FieldSpec {
};
}

/// A check run on the bound and normalized field values, as the rest of `__post_init__` did.
pub(crate) type PostInit = for<'py> fn(&[Bound<'py, PyAny>]) -> PyResult<()>;
/// The rest of `__post_init__`, run on the bound and normalized field values: it may reject them
/// or replace them in place.
pub(crate) type PostInit = for<'py> fn(&mut [Bound<'py, PyAny>]) -> PyResult<()>;

/// One shape: its class name, fields in declaration order and optional post-init check.
/// One shape: its class name, fields in declaration order and optional post-init hook.
pub(crate) struct ShapeSpec {
pub(crate) qualname: &'static str,
pub(crate) fields: &'static [FieldSpec],
Expand All @@ -104,8 +107,8 @@ pub(crate) const fn unraw(name: &'static str) -> &'static str {
/// `Name { field, field(default = Given::None), ... }`, optionally followed by
/// `@impl { ... }` holding its extra methods and properties. `Name: Base { ... }` subclasses
/// another shape and lists the base fields first, `Name @no_repr { ... }` keeps the object
/// repr, as `@dataclass(repr=False)` did, and `@post_init(check)` after the fields runs a
/// check over the bound values.
/// repr, as `@dataclass(repr=False)` did, and `@post_init(hook)` after the fields runs a hook
/// that may reject or replace the bound values.
macro_rules! shapes {
(@repr) => { true };
(@repr no_repr) => { false };
Expand Down Expand Up @@ -385,7 +388,7 @@ pub(crate) fn bind<'py>(
*value = coerce(py, field.coerce, value)?;
}
if let Some(check) = spec.post_init {
check(&values)?;
check(&mut values)?;
}
Ok(values)
}
Expand Down Expand Up @@ -788,6 +791,15 @@ pub(crate) fn add_class<T: pyo3::PyTypeInfo>(module: &Bound<'_, PyModule>) -> Py
add(module, name.to_str()?, class)
}

/// The native exception `name` raised with `message`.
pub(crate) fn raised(py: Python<'_>, name: &str, message: String) -> PyResult<PyErr> {
Ok(PyErr::from_value(
py.import("sqltide._native")?
.getattr(name)?
.call1((message,))?,
))
}

/// Constants built on first read, by name.
static LAZY_VALUES: PyOnceLock<Py<PyDict>> = PyOnceLock::new();

Expand Down Expand Up @@ -853,5 +865,18 @@ pub(crate) fn lazy_constants(
pub(crate) fn register(module: &Bound<'_, PyModule>) -> PyResult<()> {
compiler_analysis::register(module)?;
compiler_project::register(module)?;
planner_execution::register(module)
planner_execution::register(module)?;
executor_ops::register(module)?;
cli_service::register(module)?;
lazy_constants(
module,
&[
(
"CLICKHOUSE_REPLAY_BOUNDARY_MODES",
planner_execution::clickhouse_replay_boundary_modes,
),
("SQLTIDE_TOOL_VERSION", cli_service::tool_version),
("WORKFLOW_PHASE_ORDER", cli_service::workflow_phase_order),
],
)
}
16 changes: 4 additions & 12 deletions crates/sqltide-python/src/shapes/planner_execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ use pyo3::sync::PyOnceLock;
use pyo3::types::{IntoPyDict, PyFrozenSet, PyString, PyTuple};

use super::{
Coerce, Given, add, add_class, base_init, exception, lazy_constants, native_enum, path, shapes,
str_enum,
Coerce, Given, add, add_class, base_init, exception, native_enum, path, shapes, str_enum,
};

const PLANNER_TYPES: &str = "sqltide.compiler.planner.types";
Expand Down Expand Up @@ -84,7 +83,7 @@ fn publish_operation<'py>(value: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyAn
}

/// `RollbackRequest`: exactly one of a deployment ID and `previous` names the target.
fn rollback_target(values: &[Bound<'_, PyAny>]) -> PyResult<()> {
fn rollback_target(values: &mut [Bound<'_, PyAny>]) -> PyResult<()> {
let [deployment_id, previous, ..] = values else {
return Err(PyValueError::new_err(
"rollback request bound too few values",
Expand Down Expand Up @@ -978,7 +977,7 @@ fn exceptions(module: &Bound<'_, PyModule>) -> PyResult<()> {

/// `frozenset(AdapterReplayBoundaryMode)`, built on first read because the enum is still
/// defined in Python.
fn clickhouse_replay_boundary_modes(py: Python<'_>) -> PyResult<Bound<'_, PyAny>> {
pub(super) fn clickhouse_replay_boundary_modes(py: Python<'_>) -> PyResult<Bound<'_, PyAny>> {
let modes: Bound<'_, PyAny> = py
.import("sqltide.adapter.types")?
.getattr("AdapterReplayBoundaryMode")?;
Expand Down Expand Up @@ -1223,12 +1222,5 @@ pub(super) fn register(module: &Bound<'_, PyModule>) -> PyResult<()> {
add_class::<RollbackRequest>(module)?;
add_class::<RollbackPlan>(module)?;
add_class::<RepairActiveViewRequest>(module)?;
add_class::<RepairActiveViewResult>(module)?;
lazy_constants(
module,
&[(
"CLICKHOUSE_REPLAY_BOUNDARY_MODES",
clickhouse_replay_boundary_modes,
)],
)
add_class::<RepairActiveViewResult>(module)
}
17 changes: 16 additions & 1 deletion python-boundary.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# still carries planning, validation, rendering or other movable logic counts as movable until
# that logic moves to Rust.
# Native failures must surface as errors; `handled_native_errors` lists the reviewed exceptions.
remaining_lines = 4784
remaining_lines = 2685

[[stays]]
path = "adapter/classes/adapter.py"
Expand Down Expand Up @@ -110,6 +110,11 @@ path = "events/types.py"
rule = 3
note = "Rule 3: Public AuditTransition and ObservedCommand enums and the SensorEvent alias re-exported by sqltide.events; data only."

[[stays]]
path = "executor/destruction/types.py"
rule = 1
note = "Rule 1: Logic-free protocols DestructionPlanningConnection (the read-only adapter surface destruction planning calls) and DestructionPlanStore (the reviewed single-use plan store) and the data-only type alias DestructionClock the destruction runtime consumes, beside native re-exports of the destruction value enums; no logic."

[[stays]]
path = "executor/kafka_admin/_helpers/offset_reset.py"
rule = 4
Expand Down Expand Up @@ -215,3 +220,13 @@ path = "sensors/classes/polling_sensor_context.py"
rule = 3
note = "Rule 3: PollingSensorContext that user polling sensors receive, re-exported by sqltide.sensors; read-only properties."


[[stays]]
path = "auth/models.py"
rule = 4
note = "Rule 4: pydantic request bodies LoginRequest, CreateUserRequest, UpdateUserRequest, PasswordResetRequest, RoleRequest and ProjectRoleRequest, which the native dev server validates with pydantic for the account routes. They hold only field declarations with Field constraints and defaults and no custom validators or model config; the other names here are native re-exports of the account shapes."

[[stays]]
path = "dev_server/types.py"
rule = 1
note = "Rule 1: Logic-free protocols CompileAuthorizationGuard, the reload guard native DevServerState.reload_guarded calls, and DevServerReporter, the terminal narrator native create_dev_app, run_dev_server and BuildProcessManager call; and the data-only type aliases KafkaClientKey, used by the rule-4 Kafka topic and lag collectors, and KafkaLagOffsets, used by the lag collector. The other names here are native re-exports of the dev server value enums; no logic."
15 changes: 15 additions & 0 deletions scripts/shape_surface/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@
"sqltide.adapter.constants:REPLAY_VALUE_KIND_TIMESTAMP": _NATIVE_CONSTANT,
"sqltide.adapter.constants:TARGET_MUTATION_LOCK_TABLE_NAME": _NATIVE_CONSTANT,
"sqltide.adapters.clickhouse.constants:CLICKHOUSE_DEFAULT_INDEX_GRANULARITY": _NATIVE_CONSTANT,
"sqltide.auth.constants:CONTROL_STORE_TABLE_PREFIX": _NATIVE_CONSTANT,
"sqltide.auth.constants:STREAMBUILD_CONTROL_STORE_TABLE_PREFIX": _NATIVE_CONSTANT,
"sqltide.cli.build.constants:BUILD_CANCELLED_MESSAGE": _NATIVE_CONSTANT,
"sqltide.cli.entry.constants:ACTIVE_VIEW_SUBCOMMAND": _NATIVE_CONSTANT,
"sqltide.cli.entry.constants:DIRECT_ONLY_COMMANDS": _NATIVE_CONSTANT,
"sqltide.cli.entry.models:CliConnectionOptions": _CLI_INTERNAL,
"sqltide.cli.entry.models:ResolvedCliInvocation": _CLI_INTERNAL,
"sqltide.cli.entry.models:ResolvedCliProjectConfig": _CLI_INTERNAL,
Expand Down Expand Up @@ -90,9 +95,18 @@
"sqltide.compiler.discovery.types:PipelineFacts": _UNUSED_SHAPE,
"sqltide.compiler.discovery.types:ProjectPolicyFacts": _UNUSED_SHAPE,
"sqltide.compiler.test_discovery.models:SqlTestHeader": _UNUSED_SHAPE,
"sqltide.dev_server.constants:REDACTED_SECRET_PLACEHOLDER": _NATIVE_CONSTANT,
"sqltide.executor.auditing.types:AuditResultStatus": _UNUSED_SHAPE,
"sqltide.executor.deployment.types:NativeDeploymentSummary": _NATIVE_INTERCHANGE,
"sqltide.executor.deployment.types:NativeInventoryRecord": _NATIVE_INTERCHANGE,
"sqltide.executor.destruction.models:DestructionPlanParts": _UNUSED_SHAPE,
"sqltide.executor.destruction.models:RelationalStoredDestructionPlan": _NATIVE_INTERCHANGE,
"sqltide.executor.readiness.models:ColumnNameSystemRow": _UNUSED_SHAPE,
"sqltide.executor.readiness.models:CountQueryRow": _UNUSED_SHAPE,
"sqltide.executor.readiness.models:CreateTableQueryRow": _UNUSED_SHAPE,
"sqltide.executor.readiness.models:OffsetSummaryQueryRow": _UNUSED_SHAPE,
"sqltide.executor.readiness.models:ScalarSummaryQueryRow": _UNUSED_SHAPE,
"sqltide.executor.reconcile.models:ReconcileCandidate": _UNUSED_SHAPE,
"sqltide.executor.reconcile.types:NativeObjectKey": _NATIVE_INTERCHANGE,
"sqltide.executor.reconcile.types:NativeReconcileObject": _NATIVE_INTERCHANGE,
"sqltide.executor.reconcile.types:NativeReconcileOutcome": _NATIVE_INTERCHANGE,
Expand All @@ -105,6 +119,7 @@
"sqltide.executor.testing.constants:COMPARISON_ROW_VALUES_INDEX": _NATIVE_CONSTANT,
"sqltide.executor.testing.constants:MISSING_DIFF_TYPE": _NATIVE_CONSTANT,
"sqltide.executor.testing.constants:UNEXPECTED_DIFF_TYPE": _NATIVE_CONSTANT,
"sqltide.executor.testing.models:ComparisonRows": _UNUSED_SHAPE,
"sqltide.sensors.constants:DEFAULT_DISPATCH_LEASE_TTL_SECONDS": _NATIVE_CONSTANT,
"sqltide.sensors.constants:DEFAULT_EVENT_BATCH_LIMIT": _NATIVE_CONSTANT,
"sqltide.sensors.constants:DISPATCH_LEASE_NAME": _NATIVE_CONSTANT,
Expand Down
Loading
Loading