Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Placeholder Coverage in Planning item [STTNHUB-198] #40

Merged
merged 2 commits into from
Aug 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions server/stt/stt_planning_ml.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,18 @@ class STTPlanningMLParser(PlanningMLParser):
def parse(self, tree: Element, provider=None):
items = super(STTPlanningMLParser, self).parse(tree, provider)
items_to_ingest = []
planning_service = get_resource_service("planning")
for item in items:
if planning_xml_contains_remove_signal(tree):
unpost_or_spike_event_or_planning(item)
# If the item contains the ``sttinstruct:remove`` signal, no need to ingest this one
continue

planning_item = planning_service.find_one(req=None, _id=item["_id"])
self.check_coverage(
item, planning_item, tree
) if planning_item else self.set_placeholder_coverage(item, tree)

self.set_extra_fields(item, tree)
items_to_ingest.append(item)

Expand Down Expand Up @@ -148,6 +155,45 @@ def set_urgency(self, content_meta, item):

return item

def set_placeholder_coverage(self, item, tree):
"""
Set a Placeholder Coverage if no coverages are provided in the parsed item
"""
if not item.get("coverages"):
placeholder_coverage = [
{
"coverage_id": f"placeholder_{item.get('guid')}",
"workflow_status": "draft",
"firstcreated": item.get("firstcreated"),
"planning": {
"slugline": "Placeholder Coverage",
"g2_content_type": "text",
"scheduled": item.get("planning_date"),
},
"flags": {"placeholder": True},
}
]
item["coverages"] = placeholder_coverage

super(STTPlanningMLParser, self).parse_news_coverage_status(tree, item)

def check_coverage(self, item, planning_item, tree):
# if existing item is found in the db update coverage details of that item based on new item.
if not planning_item.get("coverages"):
# Existing: No Coverages | Ingest: No Coverages
self.set_placeholder_coverage(item, tree)
elif not item.get("coverages"):
# Existing: Coverages | Ingest: No Coverages
self.set_placeholder_coverage(item, tree)
else:
# Existing: Coverages | Ingest: Coverages
for existing_coverage in planning_item["coverages"]:
if existing_coverage.get("flags", {}).get("placeholder"):
# Existing: Placeholder Coverage | Ingest: Coverages
planning_item["coverages"].remove(existing_coverage)
# Update news_coverage_status for provided coverages
super(STTPlanningMLParser, self).parse_news_coverage_status(tree, item)


stt_planning_ml_parser = STTPlanningMLParser()
register_feed_parser(STTPlanningMLParser.NAME, stt_planning_ml_parser)
61 changes: 61 additions & 0 deletions server/tests/fixtures/stt_planning_ml_placeholder-2.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<planningItem xmlns="http://iptc.org/std/nar/2006-10-01/" xmlns:stt="http://www.stt-lehtikuva.fi/NewsML" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://iptc.org/std/nar/2006-10-01/ http://www.iptc.org/std/NewsML-G2/2.12/specification/NewsML-G2_2.12-spec-All-Power.xsd http://www.stt-lehtikuva.fi/NewsML http://www.stt-lehtikuva.fi/newsml/schema/STT-Lehtikuva_NewsML_G2.xsd" guid="urn:newsml:stt.fi:20230529:620121" version="1" standard="NewsML-G2" standardversion="2.12" conformance="power" xml:lang="fi">
<catalogRef href="http://www.iptc.org/std/catalog/catalog.IPTC-G2-Standards_18.xml"/>
<catalogRef href="http://www.stt-lehtikuva.fi/newsml/doc/stt-NewsCodesCatalog_1.xml"/>
<itemMeta>
<itemClass qcode="plinat:newscoverage"/>
<provider literal="STT"/>
<versionCreated>2023-05-15T14:50:03+02:00</versionCreated>
<pubStatus qcode="stat:usable"/>
</itemMeta>
<contentMeta>
<contentCreated>2023-05-15T14:50:03+02:00</contentCreated>
<contentModified>2023-05-15T14:50:03+02:00</contentModified>
<headline>Karelian Lock 23 -taisteluharjoituksen mediapäivä</headline>
<description role="drol:summary">Maavoimien alueellinen taisteluharjoitus Karelian Lock 23 järjestetään Kouvolan, Luumäen ja Haminan alueilla 26.5–2.6.2023. Harjoituksessa kehitetään johtamisvalmiuksia ja yhteistoimintaa muiden puolustushaarojen kanssa. Harjoituksessa on mukana kansainvälisiä joukkoja Yhdysvaltojen maavoimista.
Harjoituksen kokonaisvahvuus on yhteensä noin 7000 henkilöä ja 720 ajoneuvoa. Harjoitukseen osallistuu palkatun henkilökunnan lisäksi varusmiehiä ja reserviläisiä. Kansainvälisten joukkojen vahvuus harjoituksessa on noin 450 henkilöä.
Mediatilaisuudessa on mahdollisuus tutustua harjoitukseen ja haastatella harjoitukseen osallistuvia joukkoja. </description>
<subject qcode="stt-topics:620121">
<related rel="sttrel:assigneddate" value="2023-05-29" valuedatatype="Date"/>
</subject>
<subject type="cpnat:department" qcode="sttdepartment:3">
<name>Kotimaa</name>
</subject>
</contentMeta>
<assert qcode="stt-topics:620121">
<newsCoverageStatus qcode="ncostat:notint"/>
</assert>
<newsCoverageSet>
<newsCoverage id="ID_TEXT_120844691">
<planning>
<g2contentType>application/vnd.iptc.g2.newsitem+xml</g2contentType>
<itemClass qcode="ninat:text"/>
<scheduled>2023-06-01T19:30:00+02:00</scheduled>
<headline>Sudanissa taistelut jatkuvat</headline>
<description/>
<subject qcode="stt-topics:621576" type="cpnat:abstract"/>
<genre qcode="sttgenre:1">
<name>Pääjuttu</name>
<narrower qcode="sttversion:3"/>
<narrower qcode="sttversion:4"/>
<narrower qcode="sttversion:6"/>
<related rel="sttrel:plannedlength" value="1900"/>
</genre>
</planning>
<delivery>
<deliveredItemRef guidref="urn:newsml:stt.fi:20230601:105610660">
<modified>2023-06-01T08:36:57+02:00</modified>
</deliveredItemRef>
<deliveredItemRef guidref="urn:newsml:stt.fi:20230601:105610662">
<modified>2023-06-01T09:08:12+02:00</modified>
</deliveredItemRef>
<deliveredItemRef guidref="urn:newsml:stt.fi:20230601:105610660">
<modified>2023-06-01T09:09:01+02:00</modified>
</deliveredItemRef>
<deliveredItemRef guidref="urn:newsml:stt.fi:20230601:105610641">
<modified>2023-06-01T08:35:30+02:00</modified>
</deliveredItemRef>
</delivery>
</newsCoverage>
</newsCoverageSet>
</planningItem>
28 changes: 28 additions & 0 deletions server/tests/fixtures/stt_planning_ml_placeholder.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<planningItem xmlns="http://iptc.org/std/nar/2006-10-01/" xmlns:stt="http://www.stt-lehtikuva.fi/NewsML" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://iptc.org/std/nar/2006-10-01/ http://www.iptc.org/std/NewsML-G2/2.12/specification/NewsML-G2_2.12-spec-All-Power.xsd http://www.stt-lehtikuva.fi/NewsML http://www.stt-lehtikuva.fi/newsml/schema/STT-Lehtikuva_NewsML_G2.xsd" guid="urn:newsml:stt.fi:20230529:620121" version="1" standard="NewsML-G2" standardversion="2.12" conformance="power" xml:lang="fi">
<catalogRef href="http://www.iptc.org/std/catalog/catalog.IPTC-G2-Standards_18.xml"/>
<catalogRef href="http://www.stt-lehtikuva.fi/newsml/doc/stt-NewsCodesCatalog_1.xml"/>
<itemMeta>
<itemClass qcode="plinat:newscoverage"/>
<provider literal="STT"/>
<versionCreated>2023-05-15T14:50:03+02:00</versionCreated>
<pubStatus qcode="stat:usable"/>
</itemMeta>
<contentMeta>
<contentCreated>2023-05-15T14:50:03+02:00</contentCreated>
<contentModified>2023-05-15T14:50:03+02:00</contentModified>
<headline>Karelian Lock 23 -taisteluharjoituksen mediapäivä</headline>
<description role="drol:summary">Maavoimien alueellinen taisteluharjoitus Karelian Lock 23 järjestetään Kouvolan, Luumäen ja Haminan alueilla 26.5–2.6.2023. Harjoituksessa kehitetään johtamisvalmiuksia ja yhteistoimintaa muiden puolustushaarojen kanssa. Harjoituksessa on mukana kansainvälisiä joukkoja Yhdysvaltojen maavoimista.
Harjoituksen kokonaisvahvuus on yhteensä noin 7000 henkilöä ja 720 ajoneuvoa. Harjoitukseen osallistuu palkatun henkilökunnan lisäksi varusmiehiä ja reserviläisiä. Kansainvälisten joukkojen vahvuus harjoituksessa on noin 450 henkilöä.
Mediatilaisuudessa on mahdollisuus tutustua harjoitukseen ja haastatella harjoitukseen osallistuvia joukkoja. </description>
<subject qcode="stt-topics:620121">
<related rel="sttrel:assigneddate" value="2023-05-29" valuedatatype="Date"/>
</subject>
<subject type="cpnat:department" qcode="sttdepartment:3">
<name>Kotimaa</name>
</subject>
</contentMeta>
<assert qcode="stt-topics:620121">
<newsCoverageStatus qcode="ncostat:notint"/>
</assert>
</planningItem>
131 changes: 131 additions & 0 deletions server/tests/stt_planning_ml_test.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
from tests import TestCase
from stt.stt_planning_ml import STTPlanningMLParser
from datetime import datetime, timedelta
from dateutil.tz import tzoffset, tzutc
from superdesk.io.commands.update_ingest import ingest_item
from superdesk import get_resource_service
from bson import ObjectId


class STTPlanningMLParserTest(TestCase):
Expand Down Expand Up @@ -36,3 +41,129 @@ def test_stt_metadata(self):
},
self.item["subject"],
)

def test_placeholder_coverage(self):
# Case 1 : If Ingest Item does not contain any Coverage

self.fixture = "stt_planning_ml_placeholder.xml"
self.parse_source_content()
self.assertEqual(self.item["guid"], "urn:newsml:stt.fi:20230529:620121")
self.assertEqual(self.item["state"], "ingested")
self.assertEqual(len(self.item["coverages"]), 1)
self.assertEqual(
self.item["versioncreated"],
datetime(2023, 5, 15, 14, 50, 3, tzinfo=tzoffset(None, 7200)),
)
self.assertEqual(
self.item["firstcreated"],
datetime(2023, 5, 15, 14, 50, 3, tzinfo=tzoffset(None, 7200)),
)
self.assertEqual(
self.item["name"], "Karelian Lock 23 -taisteluharjoituksen mediapäivä"
)
self.assertEqual(
self.item["coverages"][0],
{
"coverage_id": "placeholder_urn:newsml:stt.fi:20230529:620121",
"workflow_status": "draft",
"firstcreated": datetime(
2023, 5, 15, 14, 50, 3, tzinfo=tzoffset(None, 7200)
),
"planning": {
"slugline": "Placeholder Coverage",
"g2_content_type": "text",
"scheduled": datetime(2023, 5, 28, 21, 0, tzinfo=tzutc()),
},
"flags": {"placeholder": True},
"news_coverage_status": {
"qcode": "ncostat:notint",
"name": "coverage not intended",
"label": "Not planned",
},
},
)

# Case 2 : If ingest item contain coverage.

self.fixture = "stt_planning_ml_placeholder-2.xml"
self.parse_source_content()
print(self.item["coverages"])
self.assertEqual(self.item["guid"], "urn:newsml:stt.fi:20230529:620121")
self.assertEqual(len(self.item["coverages"]), 1)
self.assertEqual(
self.item["coverages"][0],
{
"coverage_id": "ID_TEXT_120844691",
"workflow_status": "draft",
"firstcreated": datetime(
2023, 5, 15, 14, 50, 3, tzinfo=tzoffset(None, 7200)
),
"versioncreated": datetime(
2023, 5, 15, 14, 50, 3, tzinfo=tzoffset(None, 7200)
),
"planning": {
"slugline": "Sudanissa taistelut jatkuvat",
"g2_content_type": "text",
"scheduled": datetime(
2023, 6, 1, 19, 30, tzinfo=tzoffset(None, 7200)
),
"genre": [{"qcode": "sttgenre:1", "name": "Pääjuttu"}],
},
"news_coverage_status": {
"qcode": "ncostat:notint",
"name": "coverage not intended",
"label": "Not planned",
},
},
)

def test_update_planning(self):
service = get_resource_service("planning")
self.fixture = "stt_planning_ml_placeholder.xml"
self.parse_source_content()
source = self.item
provider = {
"_id": ObjectId(),
"source": "sf",
"name": "STT-PlanningML Ingest",
}

# Case 3 : Ingest Item with no coverage data
ingested, ids = ingest_item(source, provider=provider, feeding_service={})

self.assertTrue(ingested)
self.assertIn(source["guid"], ids)
dest = list(service.get_from_mongo(req=None, lookup={"guid": source["guid"]}))[
0
]
self.assertEqual(len(dest["coverages"]), 1)
coverage = dest["coverages"][0]
self.assertEqual(
coverage["coverage_id"], "placeholder_urn:newsml:stt.fi:20230529:620121"
)
self.assertEqual(
coverage["news_coverage_status"],
{
"qcode": "ncostat:notint",
"name": "coverage not intended",
"label": "Not planned",
},
)
self.assertEqual(
coverage["flags"], {"placeholder": True, "no_content_linking": False}
)

# Case 4 : Remove Placeholder Coverage if item updates has coverage
self.fixture = "stt_planning_ml_placeholder-2.xml"
self.parse_source_content()
source = self.item
source["versioncreated"] += timedelta(hours=1)
ingested, ids = ingest_item(source, provider=provider, feeding_service={})
dest = list(service.get_from_mongo(req=None, lookup={"guid": source["guid"]}))[
0
]
self.assertEqual(len(dest["coverages"]), 1)
self.assertNotIn(
"placeholder_urn:newsml:stt.fi:20230529:620121",
dest["coverages"][0]["coverage_id"],
)
Loading