Skip to content

Commit 42e8c59

Browse files
authored
Add Manufacturing topic; update upserter to make adding child topics easier (#1364)
* Add Manufacturing topic; update upserter to make adding child topics easier * Updating the rollback to match on the topic's own uuid
1 parent 5ef8945 commit 42e8c59

File tree

4 files changed

+181
-1
lines changed

4 files changed

+181
-1
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
"""
2+
Update the topics; add Manufacturing under Engineering
3+
This is intended to fix https://github.com/mitodl/hq/issues/5076 - no additional
4+
mappings since the topics for Principals of Manufacturing include "Manufacturing"
5+
so it should match on name directly.
6+
"""
7+
8+
from django.db import migrations
9+
10+
from channels.constants import ChannelType
11+
from learning_resources.utils import upsert_topic_data_string
12+
13+
map_changes = """
14+
---
15+
topics:
16+
- icon:
17+
id: 4176e385-92c5-4e02-b3cc-4f34d9a4bf40
18+
mappings: []
19+
name: Manufacturing
20+
children: []
21+
parent: 952604ab-ae23-45b3-a040-0e5f26fe42df
22+
"""
23+
24+
25+
def add_new_mapping(apps, schema_editor):
26+
"""Upsert the map_changes data above."""
27+
28+
upsert_topic_data_string(map_changes)
29+
30+
31+
def rollback_new_mapping(apps, schema_editor):
32+
"""Remove the Manufacturing topic."""
33+
34+
LearningResourceTopic = apps.get_model(
35+
"learning_resources", "LearningResourceTopic"
36+
)
37+
Channel = apps.get_model("channels", "Channel")
38+
39+
topic = LearningResourceTopic.objects.filter(
40+
topic_uuid="4176e385-92c5-4e02-b3cc-4f34d9a4bf40",
41+
).get()
42+
43+
Channel.objects.filter(
44+
channel_type=ChannelType.topic.name,
45+
topic_detail__topic=topic,
46+
).all().delete()
47+
48+
topic.delete()
49+
50+
51+
class Migration(migrations.Migration):
52+
dependencies = [
53+
(
54+
"data_fixtures",
55+
"0007_topic_mappings_edx_add_programming_coding_to_computer_science",
56+
),
57+
]
58+
59+
operations = [migrations.RunPython(add_new_mapping, rollback_new_mapping)]

learning_resources/data/README-topics.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,16 @@ topics:
2929
- offeror topic
3030
- other offeror topic
3131
children: []
32+
parent: optional ID for the parent (read the Updating section before using this)
3233
```
3334

34-
Children use the same format as the items under `topics`.
35+
Children use the same format as the items under `topics`. Topic IDs are UUIDs.
36+
37+
## Updating topics (and the `parent` element)
38+
39+
A given topic's parent/child relationship is usually defined by their position in the yaml file. Children are in the parent's `children` list and the upsert function uses this when it creates the topics in the database.
40+
41+
There is a slight problem with this - if you want to _modify_ a topic, you now have to specify the whole tree, or the upsert code won't know what they belong to. This is where the `parent` element comes in. You can set this to the UUID of the parent that it should have, and the upserter will load that topic and use it as the parent so you don't have to specify the whole tree.
3542

3643
## Transforming topic maps
3744

learning_resources/utils.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,7 @@ def _walk_topic_map(topics: list, parent: None | LearningResourceTopic = None) -
487487
- icon - the icon we should display for the topic (a Remixicon, generally)
488488
- mappings - mappings for topics found in offeror data
489489
- children - child topics (records in this same format)
490+
- parent - specific parent for the topic
490491
A more detailed definition of this is in data/README-topics.md.
491492
492493
Args:
@@ -503,6 +504,22 @@ def _walk_topic_map(topics: list, parent: None | LearningResourceTopic = None) -
503504
"icon": topic["icon"] or "",
504505
}
505506

507+
if not parent and "parent" in topic:
508+
# Topic specifies a parent, so let's try to grab it.
509+
try:
510+
defaults["parent"] = LearningResourceTopic.objects.filter(
511+
topic_uuid=topic["parent"]
512+
).get()
513+
except LearningResourceTopic.DoesNotExist:
514+
log.warning(
515+
(
516+
"_walk_topic_map: topic %s specified a parent %s but"
517+
" the parent did not exist"
518+
),
519+
topic["name"],
520+
topic["parent"],
521+
)
522+
506523
if topic["id"]:
507524
defaults["topic_uuid"] = topic["id"]
508525

learning_resources/utils_test.py

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,103 @@ def test_modify_topic_data_string(mocker):
388388
)
389389

390390

391+
def test_modify_topic_with_parent(mocker):
392+
"""Test that the parent option is processed correctly when upserting topics"""
393+
394+
mock_pluggy = mocker.patch("learning_resources.utils.topic_upserted_actions")
395+
396+
base_topic_file = """
397+
---
398+
topics:
399+
- icon: RiRobot2Line
400+
id: c06109bf-cff8-4873-b04b-f5e66e3e1764
401+
mappings:
402+
mitx:
403+
- Electronics
404+
ocw:
405+
- Technology
406+
name: Data Science, Analytics & Computer Technology
407+
children:
408+
- children: []
409+
icon: RiRobot2Line
410+
id: 4cd6156e-51a0-4da4-add4-6f81e106cd43
411+
mappings:
412+
ocw:
413+
- Programming Languages
414+
- Software Design and Engineering
415+
mitx:
416+
- Computer Science
417+
name: Programming & Coding
418+
"""
419+
420+
new_topic_file = """
421+
---
422+
topics:
423+
- children: []
424+
icon: RiRobot2Line
425+
id: d335c250-1292-4391-a7cb-3181f803e0f3
426+
mappings: []
427+
name: Debugging
428+
parent: 4cd6156e-51a0-4da4-add4-6f81e106cd43
429+
"""
430+
431+
new_topic_nested_parent_file = """
432+
topics:
433+
- icon: RiRobot2Line
434+
id: c06109bf-cff8-4873-b04b-f5e66e3e1764
435+
mappings:
436+
mitx:
437+
- Electronics
438+
ocw:
439+
- Technology
440+
name: Data Science, Analytics & Computer Technology
441+
children:
442+
- children: []
443+
icon: RiRobot2Line
444+
id: ea647bfc-cc83-42c7-b685-b5c2088b30af
445+
mappings: []
446+
name: Google Analytics
447+
"""
448+
449+
upsert_topic_data_string(base_topic_file)
450+
451+
assert mock_pluggy.called
452+
453+
main_topic = LearningResourceTopic.objects.filter(
454+
topic_uuid="c06109bf-cff8-4873-b04b-f5e66e3e1764"
455+
)
456+
457+
assert main_topic.exists()
458+
main_topic = main_topic.get()
459+
460+
sub_topic = LearningResourceTopic.objects.filter(parent=main_topic)
461+
462+
assert sub_topic.exists()
463+
sub_topic = sub_topic.get()
464+
465+
upsert_topic_data_string(new_topic_file)
466+
467+
new_topic = LearningResourceTopic.objects.filter(
468+
topic_uuid="d335c250-1292-4391-a7cb-3181f803e0f3"
469+
)
470+
471+
assert new_topic.exists()
472+
assert new_topic.get().parent == sub_topic
473+
474+
upsert_topic_data_string(new_topic_nested_parent_file)
475+
476+
main_topic.refresh_from_db()
477+
478+
sub_topic = LearningResourceTopic.objects.filter(parent=main_topic)
479+
assert sub_topic.count() == 2
480+
481+
for topic in sub_topic.all():
482+
assert str(topic.topic_uuid) in [
483+
"ea647bfc-cc83-42c7-b685-b5c2088b30af",
484+
"4cd6156e-51a0-4da4-add4-6f81e106cd43",
485+
]
486+
487+
391488
def test_add_parent_topics_to_learning_resource(fixture_resource):
392489
"""Ensure the parent topics get added to the resource."""
393490

0 commit comments

Comments
 (0)