← Back to changelog
Release v0.7.0

Pyvider 0.7.0: Validate early, preserve state faithfully

Pyvider 0.7.0 is a correctness release. It moves schema and state failures closer to the provider code that caused them, closes lifecycle paths that could lose information or act on the wrong intent, and makes state-store behavior safer across platforms.

Breaking changes

  • Terraform-invalid schemas now fail where they are authored. Pyvider applies Terraform’s internal schema rules before a provider is loaded. Invalid block cardinality, conflicting attribute and block names, unsupported write-only placement, invalid names, and other shapes Terraform would reject during terraform init now stop the provider’s own test run with a declaration-level error.
  • State and configuration classes must match their declared schemas. A required class field with no corresponding schema attribute now raises StateClassMismatchError. It can no longer degrade to None and be mistaken for Terraform requesting a destroy.
  • Unsupported flags inside collection a_obj() elements are rejected. Members of an object nested in a_list, a_set, or a_map cannot declare computed, sensitive, write_only, or a default, because that collection representation cannot publish those flags to Terraform. Nested blocks remain the supported form when those behaviors are needed.
  • State locks no longer expire by default. Terraform does not renew a lock during an operation, so a fixed five-minute lease could let another writer enter during a long-running apply. Expiring leases remain available as an explicit configuration and produce a warning.
  • Filesystem state IDs use safe, percent-escaped path segments. Only lowercase letters, digits, -, and _ remain literal. Other characters are escaped so case-distinct IDs stay distinct on case-folding filesystems and unsafe names cannot become special files. Existing state files are adopted and renamed on first access after an exact directory-entry match, so the migration is automatic.

Added

  • Returned-state completeness validation. complete_state_dict() checks every schema attribute after apply and read. It inserts null for write-only values and raises IncompleteResourceStateError for any other missing attribute, naming the resource type, attribute, and state class that needs attention.
  • assert_schema_state_parity(). Provider tests can statically check that every non-write-only schema attribute has a matching state-class field. The helper enforces the same invariant as the runtime check before a provider reaches Terraform.

Fixed

Lifecycle and planning safety

  • Updates can no longer be misclassified as destroys when a state class cannot be constructed. Create, update, and destroy selection now follows Terraform’s raw planned-state intent.
  • Optional-and-computed attributes preserve prior state when configuration is null, avoiding perpetual diffs and unintended replacement.
  • Private state survives a plan unless a resource deliberately replaces it, and private-state decryption errors are no longer mistaken for recoverable schema changes.
  • StopProvider now propagates an advisory stop request through ctx.stop_requested instead of tearing down the server while an apply is still in flight.
  • Write-only state is recursively set to null at the protocol boundary across plan, apply, read, import, upgrade, and move, including attributes nested in blocks and objects.

Unknowns and value fidelity

  • Refined unknown values are recognized as unknown instead of being treated as iterable concrete values and crashing a plan.
  • A known provider configuration containing nested unknown values defers correctly rather than failing despite Terraform still resolving its inputs.
  • Set elements remain paired with their own configured values even when a plan hook changes the set’s size.
  • Absent collection blocks encode to the empty value required by their nesting mode instead of always becoming null.
  • Upgrade and move decode state JSON with arbitrary-precision numbers, preventing untouched numeric values from being rounded.
  • A hand-built CtyValue must conform to its declared type before it is marshalled, giving list-resource and function results the same validation as raw Python values.

RPC and component correctness

  • Upgrade refuses absent and legacy flatmap state instead of inventing an empty object, while cross-type moves validate returned state and preserve resource identity.
  • Every list resource must have the matching managed resource Terraform uses to resolve its results.
  • Ephemeral resources can close and renew without declaring or returning private state.
  • Resource contexts receive configured capability instances rather than the provider’s capability-flags structure.
  • Function arguments bind by name when defaults omit null inputs, and FunctionError.function_argument now reaches Terraform so diagnostics point to the offending expression.
  • terraform plan -generate-config-out now removes computed-only attributes from generated configuration, so Terraform does not reject the file it asked the provider to produce.
  • Attribute description_kind reaches the wire, preserving whether provider documentation was authored as Markdown or plain text.

State-store and cross-platform safety

  • The default non-expiring lock prevents a running apply from losing its state lock; terraform force-unlock remains the recovery path for abandoned locks.
  • A malformed lease timestamp is treated as corrupt lock data instead of wedging the state permanently.
  • State IDs that differ only by case map to different files and different locks on case-folding filesystems.
  • Windows device names such as con, nul, and com1 are escaped instead of resolving to devices.
  • Windows now uses msvcrt.locking for an OS-managed cross-process mutex. It replaces the stale-sentinel race and releases when the file handle or process closes, matching the guarantee provided by fcntl.lockf elsewhere.

Operational diagnostics

  • provide --log-level now controls the initialized logger with the documented environment and configuration precedence.
  • Background provider-initialization failures are logged when they happen instead of surfacing only as an unhandled-task warning at shutdown.
  • The plugin magic cookie is validated against the expected value, and provider-detection errors stay off the stdout handshake channel.
  • The documentation-link checker reports how many links and files it verified and fails if extraction finds no internal links.
  • pyvider --config FILE keeps the path separate from the loaded configuration object, applies it before context construction, and makes the chosen file available consistently through PYVIDER_CONFIG_FILE.

Changed

  • The minimum pyvider-cty version is now 0.5.3.
  • The development and documentation dependency groups now require provide-testkit>=0.4.5; this does not add a runtime dependency to installed providers.

Removed

  • The unused google search-scraper dependency is no longer installed with every provider.

For the complete canonical record, see the Pyvider v0.7.0 release.