Skip to content

Add ContainerTypes to openedx-core [FC-0117]#495

Open
bradenmacdonald wants to merge 11 commits intomainfrom
braden/container-type
Open

Add ContainerTypes to openedx-core [FC-0117]#495
bradenmacdonald wants to merge 11 commits intomainfrom
braden/container-type

Conversation

@bradenmacdonald
Copy link
Contributor

@bradenmacdonald bradenmacdonald commented Mar 3, 2026

Implements #412

  • Add a ContainerType concept and corresponding database table (ContainerTypeRecord). Now every container must have a corresponding type; plain Container instances cannot be saved on their own.
  • The test cases for Containers are now in the publishing app and don't depend on Unit, Subsection, etc. This consolidates the core container logic, and should also make it easier to extract to a separate containers app.
  • The Unit, Subsection, and Section classes, apps, and test cases are substantially simplified.
  • Because the container APIs are now type-aware you can use the generic APIs even with specific subclasses like Unit.
  • The create_next_container_version now accepts a Container object. Previously it only accepted a container PK, but passing the object is more convenient (also see next point)
  • If you pass a Container instance (or subclass instance) to create_next_container_version, it now automatically clears Django's internal field cache for accessing the latest draft version, so you don't have to remember to call refresh_from_db() before container.versioning.draft will be correct.
    • I didn't yet make the same change to soft_delete_draft() but I think we should.
    • We can't really do the same for publishing because there's no way to clear the cache for dependencies that are automatically published.

Corresponding openedx-platform PR: openedx/openedx-platform#38181

@openedx-webhooks openedx-webhooks added open-source-contribution PR author is not from Axim or 2U core contributor PR author is a Core Contributor (who may or may not have write access to this repo). labels Mar 3, 2026
@openedx-webhooks
Copy link

openedx-webhooks commented Mar 3, 2026

Thanks for the pull request, @bradenmacdonald!

This repository is currently maintained by @axim-engineering.

Once you've gone through the following steps feel free to tag them in a comment and let them know that your changes are ready for engineering review.

🔘 Get product approval

If you haven't already, check this list to see if your contribution needs to go through the product review process.

  • If it does, you'll need to submit a product proposal for your contribution, and have it reviewed by the Product Working Group.
    • This process (including the steps you'll need to take) is documented here.
  • If it doesn't, simply proceed with the next step.
🔘 Provide context

To help your reviewers and other members of the community understand the purpose and larger context of your changes, feel free to add as much of the following information to the PR description as you can:

  • Dependencies

    This PR must be merged before / after / at the same time as ...

  • Blockers

    This PR is waiting for OEP-1234 to be accepted.

  • Timeline information

    This PR must be merged by XX date because ...

  • Partner information

    This is for a course on edx.org.

  • Supporting documentation
  • Relevant Open edX discussion forum threads
🔘 Get a green build

If one or more checks are failing, continue working on your changes until this is no longer the case and your build turns green.

Details
Where can I find more information?

If you'd like to get more details on all aspects of the review process for open source pull requests (OSPRs), check out the following resources:

When can I expect my changes to be merged?

Our goal is to get community contributions seen and reviewed as efficiently as possible.

However, the amount of time that it takes to review and merge a PR can vary significantly based on factors such as:

  • The size and impact of the changes that it introduces
  • The need for product review
  • Maintenance status of the parent repository

💡 As a result it may take up to several weeks or months to complete a review and merge your PR.

@ormsbee
Copy link
Contributor

ormsbee commented Mar 14, 2026

So this is definitely not something that needs to roll into this work, but in case it's relevant: Now that everything is in applets and publishing dependencies are explicitly modeled, I think container models and logic can move out of publishing and into its own applet.

@bradenmacdonald bradenmacdonald force-pushed the braden/container-type branch 2 times, most recently from 7bed463 to 0c75f56 Compare March 16, 2026 20:54
@bradenmacdonald
Copy link
Contributor Author

@ormsbee As you expected it was quite easy to do, so I've included that change in this PR.

I just have to make the corresponding edx-platform changes, and clean up a few small loose ends, and this will be ready.

@bradenmacdonald bradenmacdonald force-pushed the braden/container-type branch 2 times, most recently from 37757d1 to 9430410 Compare March 16, 2026 21:52
Comment on lines 192 to 196
# If the version has a container version, add its children
container_table = tomlkit.table()
children = publishing_api.get_container_children_entities_keys(version.containerversion)
children = containers_api.get_container_children_entities_keys(version.containerversion)
container_table.add("children", children)
version_table.add("container", container_table)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that this if branch of toml_publishable_entity_version is not covered by any tests. I think we need a lot more test coverage of the backup/restore format.

@bradenmacdonald bradenmacdonald marked this pull request as ready for review March 17, 2026 00:52
@bradenmacdonald bradenmacdonald changed the title Add ContainerTypes to openedx-core Add ContainerTypes to openedx-core [FC-0117] Mar 17, 2026
@bradenmacdonald bradenmacdonald added the FC Relates to an Axim Funded Contribution project label Mar 17, 2026
Claude explanation: In `_create_side_effects_for_change_log`, `change_log.records.all()` has no `ORDER BY`. On SQLite, this returns records in insertion order (PK order) — which is root-first, since `publish_from_drafts` inserts the initial draft first, then its dependencies layer by layer. On MySQL/InnoDB, the query uses the `oel_plr_uniq_pl_publishable` unique index on (`publish_log`, `entity`) to service the `WHERE publish_log_id = ?` filter, which returns records in `entity_id` order — i.e. leaf-first, because `child_entity2` has a lower entity PK than `parent_of_two`, `grandparent`, etc.

The `processed_entity_ids` optimization on line 899–904 is order-sensitive: when you process leaf records first, `processed_entity_ids` isn't yet populated with their ancestors' IDs, so the while loop traverses all the way up the tree redundantly on each leaf
Copy link
Member

@kdmccormick kdmccormick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partial review.

So happy to see the containers applet factored out and the create_container_* APIs made DRYer and safer.

"""Raised when trying to modify a container whose implementation [plugin] is no longer available."""


class ContainerTypeRecord(models.Model):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'd rather call this just ContainerType, consistent with ComponentType.

The type alias you're calling ContainerType now, ie type[Container], could be ContainerSubclass, which is more precise from a Python standpoint. Or you could drop the alias altogether. You have several methods named along these lines, eg subclass_for_type_code, all_subclasses, etc., and I think it is very clear what all of those method do just by their names.

Comment on lines +51 to +53
# The "containers" app is built on top of publishing, and is a peer to
# "components" but they do not depend on each other.
openedx_content.applets.components | openedx_content.applets.containers
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did not know about this syntax. cool!

@bradenmacdonald
Copy link
Contributor Author

bradenmacdonald commented Mar 18, 2026

@kdmccormick @ormsbee It occurred to me (unfortunately rather late) that the ContainerType I'm adding here could also have been implemented more generically within publishing as a PublishableEntityType, providing all the same benefits and functionality to Containers, but also to all other publishable entities. Somewhat relevant in the context of the discussion about the key field and its purpose, especially given that PublishableEntity doesn't have the concept of "entity type" yet. (But we will have very similar ContainerType and ComponentType) I do wonder if we'll want it in the near future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core contributor PR author is a Core Contributor (who may or may not have write access to this repo). FC Relates to an Axim Funded Contribution project open-source-contribution PR author is not from Axim or 2U

Projects

Status: Waiting on Author

Development

Successfully merging this pull request may close these issues.

4 participants