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 initnow 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 toNoneand be mistaken for Terraform requesting a destroy. - Unsupported flags inside collection
a_obj()elements are rejected. Members of an object nested ina_list,a_set, ora_mapcannot declarecomputed,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 raisesIncompleteResourceStateErrorfor 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.
StopProvidernow propagates an advisory stop request throughctx.stop_requestedinstead 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
CtyValuemust 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_argumentnow reaches Terraform so diagnostics point to the offending expression. terraform plan -generate-config-outnow removes computed-only attributes from generated configuration, so Terraform does not reject the file it asked the provider to produce.- Attribute
description_kindreaches 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-unlockremains 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, andcom1are escaped instead of resolving to devices. - Windows now uses
msvcrt.lockingfor 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 byfcntl.lockfelsewhere.
Operational diagnostics
provide --log-levelnow 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 FILEkeeps the path separate from the loaded configuration object, applies it before context construction, and makes the chosen file available consistently throughPYVIDER_CONFIG_FILE.
Changed
- The minimum
pyvider-ctyversion is now0.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
googlesearch-scraper dependency is no longer installed with every provider.
For the complete canonical record, see the Pyvider v0.7.0 release.