-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Updated to enable return of JSON structures
Also return Python objects through use of classes for Media control informatiom, EPG and Programme/Recording
- Loading branch information
1 parent
4413ad4
commit a17df4f
Showing
8 changed files
with
397 additions
and
112 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,85 @@ | ||
"""Structure of a standard EPG prorgramme.""" | ||
|
||
from dataclasses import dataclass, field | ||
from datetime import datetime | ||
import json | ||
|
||
class Programme: | ||
"""SkyQ Programme Class.""" | ||
|
||
def __init__( | ||
self, programmeuuid, starttime, endtime, title, season, episode, imageUrl | ||
): | ||
"""Programme structure for SkyQ.""" | ||
self.progammeuuid = programmeuuid | ||
self.starttime = starttime | ||
self.endtime = endtime | ||
self.title = title | ||
self.season = season | ||
self.episode = episode | ||
self.imageUrl = imageUrl | ||
from .programme import Programme | ||
|
||
|
||
@dataclass | ||
class Channel: | ||
"""SkyQ Channel Class.""" | ||
|
||
sid: str = field( | ||
init=True, repr=True, compare=False, | ||
) | ||
channelno: str = field( | ||
init=True, repr=True, compare=False, | ||
) | ||
channelname: str = field( | ||
init=True, repr=True, compare=False, | ||
) | ||
channelImageUrl: str = field( | ||
init=True, repr=True, compare=False, | ||
) | ||
programmes: set = field( | ||
init=True, repr=True, compare=False, | ||
) | ||
|
||
def as_json(self) -> str: | ||
"""Return a JSON string respenting this Channel.""" | ||
return json.dumps(self, cls=_ChannelJSONEncoder) | ||
|
||
|
||
def ChannelDecoder(obj): | ||
"""Decode channel object from json.""" | ||
channel = json.loads(obj, object_hook=_json_decoder_hook) | ||
if "__type__" in channel and channel["__type__"] == "__channel__": | ||
return Channel(programmes=channel["programmes"], **channel["attributes"]) | ||
return channel | ||
|
||
|
||
def _json_decoder_hook(obj): | ||
"""Decode JSON into appropriate types used in this library.""" | ||
if "starttime" in obj: | ||
obj["starttime"] = datetime.strptime(obj["starttime"], "%Y-%m-%dT%H:%M:%SZ") | ||
if "endtime" in obj: | ||
obj["endtime"] = datetime.strptime(obj["endtime"], "%Y-%m-%dT%H:%M:%SZ") | ||
if "__type__" in obj and obj["__type__"] == "__programme__": | ||
obj = Programme(**obj["attributes"]) | ||
return obj | ||
|
||
|
||
class _ChannelJSONEncoder(json.JSONEncoder): | ||
def default(self, obj): | ||
if isinstance(obj, Channel): | ||
type_ = "__channel__" | ||
programmes = obj.programmes | ||
attributes = {} | ||
for k, v in vars(obj).items(): | ||
if k not in {"programmes"}: | ||
attributes.update({k: v}) | ||
return { | ||
"__type__": type_, | ||
"attributes": attributes, | ||
"programmes": programmes, | ||
} | ||
|
||
if isinstance(obj, set): | ||
return list(obj) | ||
|
||
if isinstance(obj, Programme): | ||
attributes = {} | ||
for k, v in vars(obj).items(): | ||
if type(v) is datetime: | ||
v = v.strftime("%Y-%m-%dT%H:%M:%SZ") | ||
attributes.update({k: v}) | ||
|
||
result = { | ||
"__type__": "__programme__", | ||
"attributes": attributes, | ||
} | ||
return result | ||
|
||
json.JSONEncoder.default(self, obj) # pragma: no cover |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
"""Structure of a media information.""" | ||
|
||
from dataclasses import dataclass, field | ||
import json | ||
from datetime import datetime | ||
|
||
|
||
@dataclass | ||
class Media: | ||
"""SkyQ Programme Class.""" | ||
|
||
channel: str = field( | ||
init=True, repr=True, compare=False, | ||
) | ||
imageUrl: str = field( | ||
init=True, repr=True, compare=False, | ||
) | ||
sid: str = field( | ||
init=True, repr=True, compare=False, | ||
) | ||
pvrId: str = field( | ||
init=True, repr=True, compare=False, | ||
) | ||
live: bool = field( | ||
init=True, repr=True, compare=False, | ||
) | ||
|
||
def as_json(self) -> str: | ||
"""Return a JSON string respenting this media info.""" | ||
return json.dumps(self, cls=_MediaJSONEncoder) | ||
|
||
|
||
def MediaDecoder(obj): | ||
"""Decode programme object from json.""" | ||
media = json.loads(obj) | ||
if "__type__" in media and media["__type__"] == "__media__": | ||
return Media(**media["attributes"]) | ||
return media | ||
|
||
|
||
class _MediaJSONEncoder(json.JSONEncoder): | ||
def default(self, obj): | ||
if isinstance(obj, Media): | ||
attributes = {} | ||
for k, v in vars(obj).items(): | ||
if type(v) is datetime: | ||
v = v.strftime("%Y-%m-%dT%H:%M:%SZ") | ||
attributes.update({k: v}) | ||
|
||
result = { | ||
"__type__": "__media__", | ||
"attributes": attributes, | ||
} | ||
return result |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
"""Structure of a standard EPG prorgramme.""" | ||
|
||
from dataclasses import dataclass, field | ||
from datetime import datetime | ||
import json | ||
|
||
|
||
@dataclass(order=True) | ||
class Programme: | ||
"""SkyQ Programme Class.""" | ||
|
||
programmeuuid: str = field( | ||
init=True, repr=True, compare=False, | ||
) | ||
starttime: datetime = field( | ||
init=True, repr=True, compare=True, | ||
) | ||
endtime: datetime = field( | ||
init=True, repr=True, compare=False, | ||
) | ||
title: str = field( | ||
init=True, repr=True, compare=False, | ||
) | ||
season: str = field( | ||
init=True, repr=True, compare=False, | ||
) | ||
episode: str = field( | ||
init=True, repr=True, compare=False, | ||
) | ||
imageUrl: str = field( | ||
init=True, repr=True, compare=False, | ||
) | ||
|
||
def __hash__(self): | ||
"""Calculate the hash of this object.""" | ||
return hash(self.starttime) | ||
|
||
def as_json(self) -> str: | ||
"""Return a JSON string respenting this Programmel.""" | ||
return json.dumps(self, cls=_ProgrammeJSONEncoder) | ||
|
||
|
||
@dataclass | ||
class RecordedProgramme(Programme): | ||
"""SkyQ Programme Class.""" | ||
|
||
channel: str = field( | ||
init=True, repr=True, compare=False, | ||
) | ||
|
||
def as_json(self) -> str: | ||
"""Return a JSON string respenting this recording.""" | ||
return json.dumps(self, cls=_RecordingJSONEncoder) | ||
|
||
|
||
def ProgrammeDecoder(obj): | ||
"""Decode programme object from json.""" | ||
programme = json.loads(obj, object_hook=_json_decoder_hook) | ||
if "__type__" in programme and programme["__type__"] == "__programme__": | ||
return Programme(**programme["attributes"]) | ||
return programme | ||
|
||
|
||
def RecordedProgrammeDecoder(obj): | ||
"""Decode recorded programme object from json.""" | ||
recording = json.loads(obj, object_hook=_json_decoder_hook) | ||
if "__type__" in recording and recording["__type__"] == "__recording__": | ||
return RecordedProgramme(**recording["attributes"]) | ||
return recording | ||
|
||
|
||
def _json_decoder_hook(obj): | ||
"""Decode JSON into appropriate types used in this library.""" | ||
if "starttime" in obj: | ||
obj["starttime"] = datetime.strptime(obj["starttime"], "%Y-%m-%dT%H:%M:%SZ") | ||
if "endtime" in obj: | ||
obj["endtime"] = datetime.strptime(obj["endtime"], "%Y-%m-%dT%H:%M:%SZ") | ||
return obj | ||
|
||
|
||
class _ProgrammeJSONEncoder(json.JSONEncoder): | ||
def default(self, obj): | ||
if isinstance(obj, Programme): | ||
attributes = {} | ||
for k, v in vars(obj).items(): | ||
if type(v) is datetime: | ||
v = v.strftime("%Y-%m-%dT%H:%M:%SZ") | ||
attributes.update({k: v}) | ||
|
||
result = { | ||
"__type__": "__programme__", | ||
"attributes": attributes, | ||
} | ||
return result | ||
|
||
|
||
class _RecordingJSONEncoder(json.JSONEncoder): | ||
def default(self, obj): | ||
if isinstance(obj, Programme): | ||
attributes = {} | ||
for k, v in vars(obj).items(): | ||
if type(v) is datetime: | ||
v = v.strftime("%Y-%m-%dT%H:%M:%SZ") | ||
attributes.update({k: v}) | ||
|
||
result = { | ||
"__type__": "__recording__", | ||
"attributes": attributes, | ||
} | ||
return result |
Oops, something went wrong.