One useful idea
A contact-sheet plan is instructions, not a rendered image. This function consumes ordered path strings without opening files. A slice paths[start:start + page_size] keeps up to that many elements; a shorter final slice is useful output, not something to discard.
enumerate(paths, 1) produces global one-based positions. Page numbering and frame numbering are different: page 4 can contain globally numbered frames 19–23. Preserve repeated paths if the caller intentionally requested two review positions.
Require a list and a non-boolean page size from 1 to 12. The supplied relative_asset_path helper checks canonical relative POSIX text, refusing dot/empty parts, absolute/drive/backslash paths, control characters, padding and formula-like prefixes. It does not check file existence. Validate first, then return fresh page/frame dictionaries with page, frames, number, path and basename caption.
Refresh first: Loops and lists, List indices and order, Relative asset paths.
Trace a finished example
python -X utf8 demo.py --build 3
# Four pages with 6, 6, 6 and 5 frames.
# Page 4 ends with number 23, path clips/clip-23.mp4, caption clip-23.mp4.23 validated paths become globally numbered frames. Starting slices at 0, 6, 12 and 18 produces four pages. The last slice contains five frames; the caption uses the basename while the path keeps its folder.
The finished implementation is in collection_tools.py. Reading it is guided practice, not independent evidence.
Predict the partial page
How many six-up pages are needed for 23 clips?
Compare your answer · self-reviewed
Four: 6/6/6/5. Integer division gives three full pages, but the remaining five still need review.
Find the reset bug
What is wrong with numbering every page’s first frame 1?
Compare your answer · self-reviewed
It loses the frame’s identity in the whole collection. Page numbers restart a page context; frame numbers retain global positions.
Recall the side effect
Does PurePosixPath(path).name extract or render a video frame?
Compare your answer · self-reviewed
No. It returns a text basename. The plan does not open, decode or render the clip.
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.
The tutor button only prepares a question locally. Review it and choose Send yourself; no code is sent merely by running or opening a lesson.
Output
Errors and check feedback
Read the browser task briefs without running Python
Trace collection identity
Read the complete function, predict a changed case, then Run. Implement contact_plan(paths,page_size=6). Use the supplied path validator; require list and non-bool integer size 1–12. Return fresh {page,frames} pages with {number,path,caption} frames, global one-based numbering, original order/duplicates and basename captions. Keep partial pages; empty input gives []. Wrong types raise TypeError, refused paths/sizes ValueError. This plans instructions; it does not open or render files.
Preserve the changed collection independently
Implement contact_plan(paths,page_size=6). Use the supplied path validator; require list and non-bool integer size 1–12. Return fresh {page,frames} pages with {number,path,caption} frames, global one-based numbering, original order/duplicates and basename captions. Keep partial pages; empty input gives []. Wrong types raise TypeError, refused paths/sizes ValueError. This plans instructions; it does not open or render files.
Change it, then build your own
One controlled change
Change the page size to 4, then 12. Add the same path twice and an empty list. Predict the page sizes and global numbers before calling the function.
Your independent task
Implement contact_plan(paths, page_size=6) in practice.py. You may call the provided relative_asset_path validator. Return fresh pages {page, frames}, with each frame {number, path, caption}; preserve order and duplicates, number globally from 1, keep the final partial page and return [] for empty input. Wrong container/type is TypeError; refused size/path is ValueError.
What success looks like
Four contact-plan test methods pass for 23 clips, altered page sizes, duplicates, comma/Unicode captions, empty input, malformed paths, input preservation and fresh outputs. This checks instructions, not visual rendering.
Hint 1 · a question
Keep global frame identity separate from the local slot on a page.
Hint 2 · a concept cue
Use range(0, len(paths), page_size) for slice starts. Python safely returns the shorter final slice.
Hint 3 · a localized example
Create frame dictionaries from enumerate(paths, 1), then slice that new frame list into pages. Validate page_size before range so zero cannot become an accidental crash.
Need the complete worked solution?
Open collection_tools.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 frame 23 disappears, stop using only len(paths) // page_size full pages. If numbers reset, enumerate globally before grouping or add the page offset. If captions include folders, use PurePosixPath(path).name.
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
Plan a changed 23-path list at six-up and four-up sizes, including one repeated path. Flatten the pages and compare the original ordered paths and global numbers. Explain why the plan alone cannot prove image quality.
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
Batching should preserve identity and evidence. A partial page is still a complete instruction for the remaining items.