Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Simplify project upsert creation without changing persisted fields

Open
#455 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
35/100
Issue type
Refactor
Clarity
Clearly specified
Activity status
Active
Tech stack
python
Domain
api, backend, testing

Research direction

Read the native AGENTS.md, _docs/PROCESS.md, and the frozen ownership notes first, then inspect api/views/project_upsert_persistence.py and its create_project_from_upsert entrypoint. Run the unchanged-source characterization in api/tests/test_json_body_shapes.py, reusing the existing project update and authentication fixtures. Done means the direct construction preserves the stated endpoint, persistence, validation, defaults, and identity behavior while the DTO and builder are removed and all native verification gates pass.

Written by the indexing model from the issue text.

Description

courses enhancement P2

Goal

Delete the unnecessary project upsert dataclass/dictionary round trip. Preserve the existing HTTP contract, persisted project identity and values, permissions, validation, save ordering, defaults, visible UI and features. This is one behavior-preserving constructor simplification, not a project/model adoption.

Authority

  • Native AGENTS.md, _docs/PROCESS.md, .claude/agents/product-manager.md and _docs/ci/change-selective-ci.md.
  • _docs/specs/04-courses-and-cohorts.md, _docs/specs/06-studio-and-admin-api.md (existing compatibility endpoints retain their contracts), _docs/specs/07-security-privacy-operations.md, _docs/specs/10-verification-strategy.md and _docs/architecture/app-boundaries.md.
  • User-required protected /home/alexey/git/dtc-website/coding-standard.md, SHA c043aedb9c48076e7c24374d21075d8d823bf134f7ddfbba9194c5178c112b48, read-only authority absent from the committed source baseline. Follow all required practices; native executable verification commands govern actual gates.
  • Other-author audit .tmp/dtc-next-code-simplification/REPORT.md, SHA 6f95db95bfe244872de409944b73528f158b317e5809c9c6469ff4e18f3b2ee4, at committed main d8c6ff6ade741608cee6b318774358fe5aad82bb.

The raw audit incorrectly counted nine constructor fields. Actual source has eight supplied fields: course, slug, title, description, instructions_url, submission_due_date, peer_review_due_date, state. Generated database id is an additional persisted identity assertion, not a ninth constructor argument. Project.course currently references the site's Cohort, not a package Course model.

Status and ownership prerequisite

Groomed. The initial ownership prerequisite is resolved for isolated implementation by the root disposition in comment5970014430, following the owner reply. Authorized source worktree: agent-455-project-create-simplification, branch worktree-agent-455, committed remote/main d8c6ff6ade741608cee6b318774358fe5aad82bb; owned paths are only api/views/project_upsert_persistence.py and api/tests/test_json_body_shapes.py. No permission to alter or publish the foreign coding wave is granted.

The proposed source path api/views/project_upsert_persistence.py also differs in protected unpushed coding commit 257273d4abf92e53c751416e446a7a06c04f4849 (Advisory lint remediation in api). Its direct-return edits intersect the exact DTO builder and constructor; its save_project_upsert response/default cleanup is outside the deletion and must survive unchanged. Clean worktrees, absent/idle native sessions and an unavailable historical owner do not release that work. The orchestrator has frozen the isolated base and preservation agreement: style-only direct returns in the removed DTO/builder become redundant; later composition must retain the unrelated save cleanup unchanged; do not modify shared main, copy mixed WIP, discard or publish the foreign wave.

The second proposed path, api/tests/test_json_body_shapes.py, is byte-identical on committed d8c6ff6a, 257273d4 and protected local main. A bounded read-only inventory found 43 worktrees, zero exact dirty-path overlaps and zero unavailable statuses for both paths. This observation does not release the constructor overlap or any archived ownership.

No artificial dependency on package402, C5.3, homework validators, #439/#55 or book #410. Existing operational CI/Dev gates remain required, not waived by this small scope.

Scope after allocation

  1. In api/views/project_upsert_persistence.py, retain the existing create_project_from_upsert(course, project_slug, data) entrypoint and replace only its DTO→vars→dictionary-copy→ORM construction with the same direct Project.objects.create keyword values. Remove ProjectUpsertCreateData, the unused project_upsert_create_data builder and the dataclass import after independently confirming no other caller/dynamic patch/public export contract. No forwarding facade, new DTO or replacement construction framework.
  2. Preserve project_by_slug, apply_project_instructions_url, apply_project_data, save_project_upsert and their behavior; preserve the foreign approved advisory forms when composing onto its owner-approved base. Do not substitute the bulk-create service: it has different slug/title/error policies.
  3. Use existing opted-in api/tests/test_json_body_shapes.py for a cohesive ProjectUpsertBodyContract characterization of accepted JSON body→persisted project/response. It already owns actual project create/detail body contracts and imports ProjectAPITestBase; baseline size is 163 lines. Keep the complete final module<=300 and every added/materially changed function<=30, with no arbitrary split or waiver. Retain existing body-shape/security tests. If a meaningful full contract cannot fit this owner, STOP and obtain a narrow reviewed test/gate allocation before adding tests; do not add excluded tests or silently expand configuration/seals.

Only the named persistence source slice and named existing test-module addition are proposed. Exact source/test ownership is now frozen by the orchestrator for isolated uncommitted implementation; independent Tester and final PM remain required. No model fields, migrations, serializers, URLs, decorators, validation rules, pins/lock/seals, templates, UI, deployment or infrastructure changes.

Existing public contract

PUT /api/courses/<course_slug>/projects/by-slug/<project_slug>/ retains token authentication, allowed-method wrapper and the current require_staff_token authority boundary. Ordinary learner/nonstaff credentials must not gain write authority. Preserve current error/status/body behavior, including missing Cohort404 and malformed/nonobject body rejection.

  • Create: missing title falls back to name; an explicitly present title wins. Explicit null/empty title is not replaced with name and fails the existing required-create validation. description defaults to empty only when absent. instructions_url defaults to None when absent; admitted explicit None versus empty string keeps the current value. Do not normalize invalid or unsupported explicit values into a new success.
  • Both required dates use unchanged api.utils.parse_date: replace Z with +00:00, then datetime.fromisoformat; preserve clock/offset semantics, current database timezone behavior and serialized ISO values. No new date parser or chronology rule.
  • Constructor state is explicitly ProjectState.CLOSED.value (CL), even though the model default is collecting submissions (CS). The existing apply/save phase still applies an admitted requested state afterward. Missing state leaves CL.
  • Preserve all eight arguments, existing other model defaults, one actual create insert followed by the current apply/save path, and existing transaction/autocommit boundaries. Do not introduce/relocate validation, atomic blocks, catches or side effects.
  • Successful create returns201 through unchanged project_to_dict; subsequent PUT to the same Cohort/slug updates that same row and returns200 with the same PK. Another Cohort's same slug remains independent. Omitted update fields retain existing values as they do today.
  • Preserve validation order: missing create requirements, instructions URL, dates, then state. Invalid state/date/instructions must not create a project; invalid update preserves existing row values through the current boundary. No new behavior promise for previously unsupported explicit values.

Acceptance criteria

  • Explicit foreign-owner/base disposition is recorded before source edits; protected257273d4 changes and all foreign WIP remain preserved.
  • Meaningful admitted-body characterization passes on unchanged authorized source before simplification and on the final candidate afterward. It asserts all eight supplied fields and generated PK through the real endpoint and refreshed local Project instance, not DTO/dictionary structure.
  • Create201/update200, same-row identity, other-Cohort isolation, title/name precedence, absent defaults/admitted explicit null-or-empty instructions, both timezone-bearing dates and missing-state CL are preserved. Response fields and database values agree.
  • Existing malformed/nonobject request, missing required fields, permission denial and invalid date/instructions/state tests retain their exact status/code and zero-create/unchanged-update assertions. No permission, serializer, URL or validation changes.
  • A narrowly reversible intentional field-loss or wrong-date/state mutant reaches the owning persistence assertion and fails; a legitimate positive create/update control prevents a disabled-writes false positive. Mutation restoration is hash-proven before final gates; no production/test mutation remains in the frozen candidate.
  • The unused DTO/builder/import and round-trip operations are deleted without a facade, schema/package adoption or new abstraction. Final actual diff reports net production line deletion rather than relocation; initial audit estimated about23 lines, not a guaranteed budget.
  • Final test file<=300/functions<=30; persistence file shrinks; all user coding rules and native blocking/advisory checks hold. The existing opted-in test receives strict checking, not an ignored test claim.
  • SWE freezes the exact diff-derived native verification plan/evidence/four-bucket report; distinct Tester independently recomputes and validates it; distinct PM accepts. No required skip or pending screenshot can satisfy acceptance.
  • Ordinary local approved merge/push and sole OnCall exact-head CI+Dev succeed before operational completion. No existing non-green Dev result is relabelled as unrelated green.

Verification and browser disposition

No tests were run during PM grooming. The future engineer first adds the missing contract in the named admitted test owner and demonstrates the unchanged-source baseline, preserving any actual failed attempts under native process. Reuse existing api.tests.test_project_updates, project authentication/staff-authority and JSON-body fixtures rather than adding a second synthetic renderer or fake persistence owner.

Generate and execute the actual versioned plan through native commands:

uv run --frozen python scripts/ci.py verification-plan
uv run --frozen python scripts/ci.py verification-run
uv run --frozen python scripts/ci.py verification-evidence-check
uv run --frozen python scripts/ci.py verification-report-check

The api owner closure is api; actual final graph selection determines fresh components, quality/container/full backstops and reuse eligibility. Tester independently uses the documented VERIFY_CONSUMER=tester/role/phase commands. Do not hand-select fewer gates or borrow prior #453/package/site greens. Record exact base/head/tree, graph/policy/plan/environment digests, executed counts, commands, artifacts and all four dispositions. Existing registry/pin/seals remain unchanged.

No rendered product page is intentionally changed. Do not invent new browser pages or screenshots merely for this refactor. Native backend-only selection uses smoke; if the actual graph classifies the changed view slice as render impact, satisfy its derived core/screenshots gate or report a concrete mapping disposition through normal review, never force a backend override. Browser/API negatives preserve current authentication and state behavior, and no template changes enter this issue.

Deferred and excluded

Homework upsert validation deletion, rubric validators, scoring, #439/#55, #454 STOP, book #410 STOP, projection/history/template425/coding-wave integration, package release/adoption, data import/reset and cloud/provider operations remain separate and protected. This issue does not authorize reopening them.

Dominant language
Python
Stars
0
Forks
0
PR merge metrics
No merged PRs in 30d

Getting set up

  • Ships a Dockerfile or Docker Compose file
  • No pull request template
  • No contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from DataTalksClub/website

All issues in DataTalksClub/website

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.