learningequality / learningequality/le-utils
Migrate format_presets.py to spec + code generation
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 7
- Forks
- 36
- PR merge metrics
- No merged PRs in 30d
Description
❌ This issue is not open for contribution. Visit Contributing guidelines to learn about the contributing process and how to find suitable issues.
Overview
Migrate le_utils/constants/format_presets.py from the legacy JSON-as-data approach to the modern spec + code generation system. This is the most complex module with 10+ fields per preset and references to content kinds and file formats.
This module references constants from both file_formats and content_kinds, so both must be migrated first.
Context
Currently, le_utils/constants/format_presets.py uses the legacy approach:
- Loads
resources/presetlookup.jsonat runtime - Manual Python constants (
VIDEO_HIGH_RES = "high_res_video", etc.) - Complex namedtuple with many fields
- No JavaScript export available
Current Structure
File: le_utils/resources/presetlookup.json
{
"high_res_video": {
"readable_name": "High Resolution",
"multi_language": false,
"supplementary": false,
"thumbnail": false,
"subtitle": false,
"display": true,
"order": 1,
"kind": "video",
"allowed_formats": ["mp4", "webm"],
"convertible_formats": ["avi", "mov", "mpg", "wmv", "mkv", "flv", "ogv", "m4v"]
},
...
}
Python module has:
- Namedtuple:
class Preset(namedtuple("Preset", ["id", "readable_name", "multi_language", "supplementary", "thumbnail", "subtitle", "display", "order", "kind_id", "allowed_formats", "convertible_formats"])): pass - Manual constants for each preset
PRESETLISTwith Preset namedtupleschoicestuple
Target Spec Format
Create spec/constants-format_presets.json with all preset data:
{
"namedtuple": {
"name": "Preset",
"fields": ["id", "readable_name", "multi_language", "supplementary", "thumbnail", "subtitle", "display", "order", "kind_id", "allowed_formats", "convertible_formats"]
},
"constants": {
"high_res_video": {
"readable_name": "High Resolution",
"multi_language": false,
"supplementary": false,
"thumbnail": false,
"subtitle": false,
"display": true,
"order": 1,
"kind_id": "video",
"allowed_formats": ["mp4", "webm"],
"convertible_formats": ["avi", "mov", "mpg", "wmv", "mkv", "flv", "ogv", "m4v"]
},
"low_res_video": {
"readable_name": "Low Resolution",
"multi_language": false,
"supplementary": false,
"thumbnail": false,
"subtitle": false,
"display": true,
"order": 2,
"kind_id": "video",
"allowed_formats": ["mp4", "webm"],
"convertible_formats": ["avi", "mov", "mpg", "wmv", "mkv", "flv", "ogv", "m4v"]
}
}
}
Copy all presets from presetlookup.json, changing "kind" to "kind_id" to match the namedtuple field name.
Generated Output Example
Python (le_utils/constants/format_presets.py):
# Generated by scripts/generate_from_specs.py
from collections import namedtuple
class Preset(namedtuple("Preset", ["id", "readable_name", "multi_language", "supplementary", "thumbnail", "subtitle", "display", "order", "kind_id", "allowed_formats", "convertible_formats"])):
pass
VIDEO_HIGH_RES = "high_res_video"
VIDEO_LOW_RES = "low_res_video"
# ...
choices = (
(VIDEO_HIGH_RES, "Video High Res"),
(VIDEO_LOW_RES, "Video Low Res"),
# ...
)
PRESETLIST = [
Preset(
id="high_res_video",
readable_name="High Resolution",
multi_language=False,
supplementary=False,
thumbnail=False,
subtitle=False,
display=True,
order=1,
kind_id="video",
allowed_formats=["mp4", "webm"],
convertible_formats=["avi", "mov", "mpg", "wmv", "mkv", "flv", "ogv", "m4v"]
),
# ...
]
JavaScript (js/FormatPresets.js):
// Generated by scripts/generate_from_specs.py
export default {
VIDEO_HIGH_RES: "high_res_video",
VIDEO_LOW_RES: "low_res_video",
// ...
};
export const PresetsList = [
{
id: "high_res_video",
readable_name: "High Resolution",
multi_language: false,
supplementary: false,
thumbnail: false,
subtitle: false,
display: true,
order: 1,
kind_id: "video",
allowed_formats: ["mp4", "webm"],
convertible_formats: ["avi", "mov", "mpg", "wmv", "mkv", "flv", "ogv", "m4v"]
},
// ...
];
export const PresetsMap = new Map(
PresetsList.map(preset => [preset.id, preset])
);
Testing Updates
File: tests/test_presets.py
Update to test against spec:
spec_path = os.path.join(os.path.dirname(__file__), "..", "spec", "constants-format_presets.json")
with open(spec_path) as f:
spec = json.load(f)
presetlookup = spec["constants"]
# Verify all presets generated correctly
# Verify array fields (allowed_formats, convertible_formats) handled properly
How to Run Tests
pytest tests/test_presets.py -v
pytest tests/ -v
Acceptance Criteria
-
spec/constants-format_presets.jsoncreated with all preset data - Changed
"kind"to"kind_id"in spec to match namedtuple field -
make buildsuccessfully generates Python and JavaScript files - Generated
le_utils/constants/format_presets.pyhas:- Preset namedtuple with 11 fields
- Uppercase constants (VIDEO_HIGH_RES, etc.)
-
choicestuple -
PRESETLISTwith Preset namedtuples - Array fields (allowed_formats, convertible_formats) as lists
- Generated
js/FormatPresets.jshas:- Default export with constants
-
PresetsListwith full preset data -
PresetsMapfor lookups - Array fields properly exported
-
tests/test_presets.pyupdated to test against spec - All tests pass
-
resources/presetlookup.jsondeleted
Disclosure
🤖 This issue was written by Claude Code, under supervision, review and final edits by @rtibbles 🤖
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with le_utils/constants/format_presets.py, resources/presetlookup.json, and the existing spec-based generator; note that file_formats and content_kinds must be migrated first. Create spec/constants-format_presets.json, update tests/test_presets.py, and run pytest tests/test_presets.py -v, pytest tests/ -v, and make build. Done means generated Python and JavaScript outputs, updated tests, and removal of resources/presetlookup.json.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, python
- Domain
- build-system, tooling
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 25/100