DVPPython Studio
Module 8: Model the evaluation domain / Build 1 of 4

Model a job with immutable values

Represent one evaluation job, validate its actual values and serialize fresh data without claiming media was inspected.

Runs on your computer · 60–90 minutes · no paid services

Download practice filesFiles, commands & notes

Without JavaScript, use the step links and keep your files on your computer.

One useful idea

A class groups values and behavior under one name. A dataclass generates an initializer from declared fields; type annotations explain the intended types but do not validate incoming data. Use __post_init__ for runtime checks. In this kit, EvaluationJob requires schema version exactly integer 1, a canonical job identifier, a bounded prompt, a calendar-valid UTC timestamp and two distinct asset references. Boolean True is not a schema integer even though True == 1 in Python.

Frozen dataclasses refuse ordinary field assignment. They do not recursively freeze a list stored in a field. AssetRef is itself frozen and the job owns a tuple of exactly two AssetRef values. Both asset IDs and URI strings must differ. Together those immutable nested values prevent ordinary mutation through job.assets. This is value ownership, not a hostile-code security boundary or a file permission system.

A classmethod receives the class as cls. EvaluationJob.from_mapping reads an exact serialized dictionary, validates each nested asset, converts the input asset list to an owned tuple, then constructs cls. Unknown fields, duplicate IDs or locators, invalid text and invalid dates are refused rather than silently repaired. A URI is only a declared locator; accepting its spelling does not prove a file exists or decode a video.

to_dict returns fresh dictionaries and a fresh serialized asset list. asdict traverses the dataclasses; the serializer explicitly chooses a list because that is the external schema. Editing a returned mapping must not edit the immutable job or another serialization. FrozenInstanceError is an expected assignment refusal in this example. Do not broadly catch every exception: an unexpected programming fault should remain visible.

The starter supplies reviewed model and validation classes. Writing job_record composes that assistance; it does not prove you independently designed a domain model. Trace the reviewed class first, then build a small frozen value class of your own on changed inputs for the transfer task. Record exactly which validators and definitions you reused.

Refresh first: Domain-kit setup, Typed records and schema versions, Dictionaries and returned data.

Trace a finished example

from dataclasses import dataclass, FrozenInstanceError
import json
from pathlib import Path
from evalkit.model import EvaluationJob, identifier

# A small class definition: identifier is a disclosed reviewed validator.
@dataclass(frozen=True)
class NamedAsset:
    asset_id: str

    def __post_init__(self):
        identifier(self.asset_id)

example = NamedAsset("asset_demo")
print(example.asset_id)

source = json.loads(Path("fixtures/job.json").read_text(encoding="utf-8"))
job = EvaluationJob.from_mapping(source)
print(job.job_id, type(job.assets).__name__, len(job.assets))
serialized = job.to_dict()
serialized["assets"][0]["uri"] = "changed.mov"
print(job.assets[0].uri)
try:
    job.job_id = "changed"
except FrozenInstanceError:
    print("assignment refused")
source["schema_version"] = True
try:
    EvaluationJob.from_mapping(source)
except ValueError:
    print("boolean version refused")

The small NamedAsset class demonstrates the decorator, field annotation, self and post-initialization runtime check before the larger job model. NamedAsset("asset_demo") calls the generated initializer. The job then owns a tuple of frozen references; fresh serialization edits do not alter it. Assignment and boolean-version refusals have different causes; neither examines media.

The finished implementation is in evalkit/core.py. Reading it is guided practice, not independent evidence.

Predict ownership

If frozen=True protects the job, is a mutable list inside it automatically frozen?

Compare your answer · self-reviewed

No. Frozen protects ordinary field assignment, not nested lists. This model deliberately uses a tuple of frozen AssetRef values, and serialization returns fresh mutable containers.

Find the type gap

Why is schema_version == 1 alone insufficient?

Compare your answer · self-reviewed

True equals 1 in Python. Require type(value) is int as well as the declared version so boolean values do not silently enter this integer schema.

Recall external evidence

Does a valid URI prove the video is readable?

Compare your answer · self-reviewed

No. This model validates a supplied locator, not existence, decoding, permission, authorship or media quality. Those require separate checks and evidence.

Try the idea in this browser

Runs in this browser · optional preparation · local project checks remain separate

Try a small function before opening your local files. Python downloads when you choose Run; if it cannot load, your code stays here and the local kit still works. The worker executes on your device, not on a DVP server. Only run code you trust: this is not a hostile-code security sandbox.

JavaScript loads the practice controls. Python starts only after Run.

Read the browser task briefs without running Python

Guided model a job with immutable values

Use invented in-memory values only. Reviewed scalar validators, immutable model classes and rubric strategies are supplied and disclosed. Implement your own job_record, not the finished task function. These checks assess composition, not independent model/helper design, file publication, media quality or portfolio defense. Implement job_record in practice.py using the disclosed EvaluationJob class, returning its fresh serialized mapping. Do not import the finished core.job_record function. Test changed fields, exact schema/type refusals and ownership. Then author your own small frozen asset value class with a runtime validator; the supplied model tests alone cannot assess independent class design.

Independent model a job with immutable values

Use invented in-memory values only. Reviewed scalar validators, immutable model classes and rubric strategies are supplied and disclosed. Implement your own job_record, not the finished task function. These checks assess composition, not independent model/helper design, file publication, media quality or portfolio defense. Implement job_record in practice.py using the disclosed EvaluationJob class, returning its fresh serialized mapping. Do not import the finished core.job_record function. Test changed fields, exact schema/type refusals and ownership. Then author your own small frozen asset value class with a runtime validator; the supplied model tests alone cannot assess independent class design.

Change it, then build your own

One controlled change

Change the job ID and prompt, preserve the two different assets, then try the same URI for both assets and an impossible calendar date. Predict fresh output or ValueError before running.

Your independent task

Implement job_record in practice.py using the disclosed EvaluationJob class, returning its fresh serialized mapping. Do not import the finished core.job_record function. Test changed fields, exact schema/type refusals and ownership. Then author your own small frozen asset value class with a runtime validator; the supplied model tests alone cannot assess independent class design.

What success looks like

Build 1 checks changed typed fields, exact versions, nested ownership, distinct assets and declared validation boundaries. They are composition checks using reviewed model assistance, not an independent domain-model certificate or a media inspection.

Hint 1 · a question

Draw source dictionary → typed job → serialized dictionary. Which containers belong to the caller, and which must be newly owned?

Hint 2 · a concept cue

from_mapping validates and constructs an owned job. to_dict returns an external schema with fresh containers. The wrapper composes these two reviewed operations.

Hint 3 · a localized example

A separate frozen dataclass can validate its fields in __post_init__. Use a tuple or frozen value for nested data; frozen=True alone does not freeze a list.

Need the complete worked solution?

Open evalkit/core.py from the kit. Trace it, close it, then try fresh inputs in your own files. Treat the attempt as guided; seeing the solution does not award a practical pass.

Course help is guidance, not independent evidence. With JavaScript, opening help records guidance locally; otherwise note it in your README. Reset does not erase that history.

Repair a failed check

If source dictionaries change, stop retaining caller-owned nested containers. If a returned serialization changes the job, make fresh nested mappings. If bool passes as schema version, use the exact integer check. If a list remains inside a frozen value, distinguish shallow field freezing from immutable nested ownership.

NotImplementedError means a practice stub is still unfinished. Read the failing test name and the last error line. Change one behavior, rerun that build, then rerun all implemented builds.

Show it works on new inputs

Create a changed two-asset job and six refused cases, retaining actual results. Build your own small frozen value class and test initialization, ordinary assignment refusal and serialized ownership. Explain the difference between field freezing, type annotations and runtime validation, and disclose reviewed helpers.

Self-review: name the input, result, refused case and reason. Your local test output and explanation are separate from a quiz score; this page does not certify a pass.

Keep the idea

Model boundaries protect meaning and ownership. A well-formed job is a starting point, not proof that its media or supplied claims are true.