How-to guide
This section is a series of helpful recipes for how to do things and solve particular problems with mosromgr.
Note
For simplicity, these examples deal with MOS messages read from local files,
but MosFile
and
MosCollection
objects can also be
constructed using from_string
and
from_s3
. Refer to MOS Types
and MOS Collection for more information.
Merging MOS files
When dealing with merging MosFile
objects, this is
done by “adding” each file to the RunningOrder
object by using the +
operator:
>>> from mosromgr.mostypes import RunningOrder, StoryInsert
>>> ro = RunningOrder.from_file('123456-roCreate.mos.xml')
>>> si = StoryInsert.from_file('123457-roStoryInsert.mos.xml')
>>> len(ro.stories)
10
>>> ro += si
>>> len(ro.stories)
11
To parse and merge a collection of MOS files, you could create a list of files
(or use glob()
), let MosFile
classify
each file, then merge each of them into the
RunningOrder
:
from mosromgr.mostypes import MosFile
from glob import glob
files = glob('*.mos.xml')
ro, *mosfiles = sorted(MosFile.from_file(f) for f in files)
for mf in mosfiles:
ro += mf
To access the final XML, simply print the
RunningOrder
object or access the
__str__
:
>>> print(ro)
<mos>
<mosID>MOS ID</mosID>
<messageID>1234567</messageID>
...
>>> s = str(ro)
>>> s
<mos>
<mosID>MOS ID</mosID>
<messageID>1234567</messageID>
...
Merging MOS files using MOSCollection
The MosCollection
class provides a wrapper for
operations dealing with a collection of MOS files as part of one programme. So
to merge files like in the previous example, you could do the following
instead:
from mosromgr.moscollection import MosCollection
from glob import glob
files = glob('*.mos.xml')
mc = MosCollection.from_files(files)
mc.merge()
To access the final XML, simply print the
MosCollection
object or access the
__str__
:
>>> print(mc)
<mos>
<mosID>MOS ID</mosID>
<messageID>1234567</messageID>
...
>>> s = str(mc)
>>> s
<mos>
<mosID>MOS ID</mosID>
<messageID>1234567</messageID>
...
Accessing the properties of a running order
For example, a RunningOrder
object could contain
several Story
objects, each containing a number
of Item
objects:
>>> from mosromgr.mostypes import RunningOrder
>>> ro = RunningOrder.from_file('roCreate.mos.xml')
>>> ro.stories
[<Story 1234>, <Story 1235>, <Story 1236>]
>>> [story.duration for story in ro.stories]
[10, 20, 30]
>>> ro.duration
60
>>> story = ro.stories[0]
>>> story.slug
'Some story'
>>> story.items
[<Item ITEM1>, <Item ITEM2>, <Item ITEM3>]
>>> item = story.items[0]
>>> item.slug
'Some item'
In the case of a StoryAppend
object, this would
contain a single story:
>>> from mosromgr.mostypes import StoryAppend
>>> sa = StoryAppend.from_file('roStoryAppend.mos.xml')
>>> sa.story
<Story STORY1>
>>> sa.duration
20
If this StoryAppend
object was merged with a
RunningOrder
object, the new story would be
accessible in the RunningOrder
stories
property:
>>> from mosromgr.mostypes import RunningOrder, StoryAppend
>>> ro = RunningOrder.from_file('roCreate.mos.xml')
>>> sa = StoryAppend.from_file('roStoryAppend.mos.xml')
>>> len(ro.stories)
3
>>> ro += sa
>>> len(ro.stories)
4
Additional information may be contained within the XML, and not exposed by
properties the way slug
and
object_id
are. In the sprit of
escape hatches and ejector seats, the original XML in which the element was
found is accessible as an xml.etree.ElementTree.Element
object for
further introspection.
For example, if you knew some of the <item>
tags in a running order
contained an <areaID>
field, and you wanted to access its value, you could
do so by inspecting the xml
property:
tag = item.xml.find('areaID')
if tag is not None:
print(tag.text)
Handling Exceptions
This can be useful for handling exceptions in your own code. For example, to
handle any exception generated by the library, you can catch the library’s base
exception MosRoMgrException
:
try:
main()
except MosRoMgrException as e:
print(e)
To catch a specific exception known to be raised under certain circumstances, each exception can be imported and handled separately if required:
from mosromgr.mostypes import MosFile
from mosromgr.exc import MosInvalidXML, UnknownMosFileType
try:
ro = MosFile.from_file(mosfile)
except MosInvalidXML as e:
print("Invalid in", mosfile)
except UnknownMosFileType as e:
print("Unknown MOS file type", mosfile)
In some cases, a warning is raised rather than an exception. This means that
execution is continued but a warning is output, which can be suppressed using
the warnings
module.
Capturing warnings
If you want to catch warnings and log them (for example, during a merge), you
can use warnings.catch_warnings
:
with warnings.catch_warnings(record=True) as warns:
mc.merge()
warning_messages = [str(w.message) for w in warns]
Suppressing warnings
If you are not interested in seeing or capturing warnings, you can either use a
warning filter or use warnings.catch_warnings
:
with warnings.catch_warnings() as warns:
mc.merge()