Separate parser and writer

This commit is contained in:
2017-04-21 12:42:23 +02:00
parent 92982fb042
commit 06af68bf5a

View File

@@ -66,42 +66,37 @@ class ITunesParser:
""" """
Parse an iTunes Library and produce JSON - for ELS Parse an iTunes Library and produce JSON - for ELS
""" """
def __init__(self, library_file): def __init__(self):
self._tracks = {}
self._albums = {} self._albums = {}
self._artists = {} self._artists = {}
self.library_file = library_file
def to_json(self): def _read_tracks(self, library_file):
""" """
Just do processSong() Read library file and return Tracks key of dict.
or do process_songs, then _write_artists and _write_albums. Dict may contains
Note: process_songs do a process_artists and process_albums... - Major Version
This method suck. - Minor Version
- Date
- Application Version
- Features
- Show Content Ratings
- Music Folder
- Library Persistent ID
- Tracks
- ...
""" """
ret = self._process_songs() plist = plistlib.load(open(library_file, 'rb'))
self._write_artists()
self._write_albums()
# return json.dumps(jsonObj, indent=indent, cls=SetEncoder)
return ret
def _read_tracks(self):
"""
Read library and return Tracks key of dict
"""
plist = plistlib.load(open(self.library_file, 'rb'))
return plist['Tracks'] return plist['Tracks']
def _process_songs(self): def parse(self, library_file):
""" """
Return an output JSON for an ELS Bulk request - Not a correct format Return an output JSON for an ELS Bulk request - Not a correct format
This method call process_album & process_artist This method call process_album & process_artist
TODO Just return a _correct_ JSON and treat in another place/class TODO Just return a _correct_ JSON and treat in another place/class
""" """
tracks = self._read_tracks() tracks = self._read_tracks(library_file)
ret = ""
for _, track in tracks.items(): for _, track in tracks.items():
# Filter out any non-music # Filter out any non-music
@@ -110,20 +105,19 @@ class ITunesParser:
if 'Podcast' in track or 'Has Video' in track: if 'Podcast' in track or 'Has Video' in track:
continue continue
persistent_id = track['Persistent ID'] # Each keeped track are stored
json_track_index = { self._tracks[track['Persistent ID']] = track
"index": {"_index": "itunessongs", "_type": "song", "_id": persistent_id}
}
# Retrieve for each track artist information # Retrieve for each track artist information
self._process_artist(track) self._process_artist(track)
# Retrieve for each track album information # Retrieve for each track album information
self._process_album(track) self._process_album(track)
ret += json.dumps(json_track_index, indent=None, cls=SetEncoder) ret = {
ret += "\n" 'songs': self._tracks,
ret += json.dumps(track, indent=None, cls=SetEncoder) 'albums': self._albums,
ret += "\n" 'artists': self._artists
}
return ret return ret
def _process_artist(self, track): def _process_artist(self, track):
@@ -138,6 +132,8 @@ class ITunesParser:
# Add artist # Add artist
if akey not in self._artists: if akey not in self._artists:
a_id = self.calc_id(akey) a_id = self.calc_id(akey)
# Key is used to increment/precise some information
# So we use artist name as a key to avoid calculating an ID for each track
self._artists[akey] = { self._artists[akey] = {
'Persistent ID': a_id, 'Persistent ID': a_id,
'Name': akey, 'Name': akey,
@@ -173,6 +169,8 @@ class ITunesParser:
akey = track['Album'] akey = track['Album']
if akey not in self._albums: if akey not in self._albums:
a_id = self.calc_id(akey) a_id = self.calc_id(akey)
# Key is used to increment/precise some information
# So we use album name as a key to avoid calculating an ID for each track
self._albums[akey] = { self._albums[akey] = {
'Persistent ID': a_id, 'Persistent ID': a_id,
'Name': akey, 'Name': akey,
@@ -205,42 +203,6 @@ class ITunesParser:
self._albums[akey]['Album Rating'] = track['Album Rating'] self._albums[akey]['Album Rating'] = track['Album Rating']
self._albums[akey]['Album Rating Computed'] = True self._albums[akey]['Album Rating Computed'] = True
def _write_artists(self):
"""
Write artists data to another JSON file
"""
file_artist = io.open('es-artist-data.json', 'wb')
for artist in self._artists:
persistent_id = self._artists[artist]['Persistent ID']
self._artists[artist]['Rating'] = round(self._artists[artist]['Rating'])
json_track_index = {
"index": {"_index": "itunessongs", "_type": "artist", "_id": persistent_id}
}
file_artist.write(bytes(json.dumps(json_track_index, indent=None, cls=SetEncoder), 'UTF-8'))
file_artist.write(bytes("\n", 'UTF-8'))
file_artist.write(bytes(json.dumps(self._artists[artist], indent=None, cls=SetEncoder), 'UTF-8'))
file_artist.write(bytes("\n", 'UTF-8'))
file_artist.close()
def _write_albums(self):
"""
Write albums data to another JSON file
"""
file_albums = io.open('es-albums-data.json', 'wb')
for album in self._albums:
persistent_id = self._albums[album]['Persistent ID']
self._albums[album]['Rating'] = round(self._albums[album]['Rating'])
json_track_index = {
"index": {"_index": "itunessongs", "_type": "album", "_id": persistent_id}
}
file_albums.write(bytes(json.dumps(json_track_index, indent=None, cls=SetEncoder), 'UTF-8'))
file_albums.write(bytes("\n", 'UTF-8'))
file_albums.write(bytes(json.dumps(self._albums[album], indent=None, cls=SetEncoder), 'UTF-8'))
file_albums.write(bytes("\n", 'UTF-8'))
file_albums.close()
@classmethod @classmethod
def calc_rating(cls, added_value, current_rating, count): def calc_rating(cls, added_value, current_rating, count):
""" """
@@ -257,6 +219,82 @@ class ITunesParser:
md5.update(key.encode('UTF-8')) md5.update(key.encode('UTF-8'))
return md5.hexdigest() return md5.hexdigest()
class WriteElsJson:
def to_json(self):
"""
Just do processSong()
or do process_songs, then _write_artists and _write_albums.
Note: process_songs do a process_artists and process_albums...
This method suck.
"""
ret = self._process_songs()
self._write_artists()
self._write_albums()
# return json.dumps(jsonObj, indent=indent, cls=SetEncoder)
return ret
@staticmethod
def write_artists(artists, output_file):
"""
Write artists data to another JSON file
"""
file_artist = io.open(output_file, 'wb')
for _, artist in artists.items():
persistent_id = artist['Persistent ID']
artist['Rating'] = round(artist['Rating'])
json_track_index = {
"index": {"_index": "itunessongs", "_type": "artist", "_id": persistent_id}
}
file_artist.write(bytes(json.dumps(json_track_index, indent=None, cls=SetEncoder), 'UTF-8'))
file_artist.write(bytes("\n", 'UTF-8'))
file_artist.write(bytes(json.dumps(artist, indent=None, cls=SetEncoder), 'UTF-8'))
file_artist.write(bytes("\n", 'UTF-8'))
file_artist.close()
@staticmethod
def write_albums(albums, output_file):
"""
Write albums data to another JSON file
"""
file_albums = io.open(output_file, 'wb')
for _, album in albums.items():
persistent_id = album['Persistent ID']
album['Rating'] = round(album['Rating'])
json_track_index = {
"index": {"_index": "itunessongs", "_type": "album", "_id": persistent_id}
}
file_albums.write(bytes(json.dumps(json_track_index, indent=None, cls=SetEncoder), 'UTF-8'))
file_albums.write(bytes("\n", 'UTF-8'))
file_albums.write(bytes(json.dumps(album, indent=None, cls=SetEncoder), 'UTF-8'))
file_albums.write(bytes("\n", 'UTF-8'))
file_albums.close()
@staticmethod
def write_songs(songs, output_file):
"""
Write songs to a JSON
"""
file = io.open(output_file, 'wb')
for persistent_id, song in songs.items():
json_track_index = {
"index": {"_index": "itunessongs", "_type": "album", "_id": persistent_id}
}
file.write(bytes(json.dumps(json_track_index, indent=None, cls=SetEncoder), 'UTF-8'))
file.write(bytes("\n", 'UTF-8'))
file.write(bytes(json.dumps(song, indent=None, cls=SetEncoder), 'UTF-8'))
file.write(bytes("\n", 'UTF-8'))
file.close()
#### main block #### #### main block ####
# Default input & output files # Default input & output files
@@ -279,15 +317,18 @@ parser.add_argument('-c', '--console', action='store_true',
if __name__ == '__main__': if __name__ == '__main__':
args = parser.parse_args() args = parser.parse_args()
itunes_parser = ITunesParser(args.file) itunes_parser = ITunesParser().parse(args.file)
output = itunes_parser.to_json()
if args.console: WriteElsJson.write_songs(itunes_parser['songs'], "es-songs.json")
print(output) WriteElsJson.write_artists(itunes_parser['artists'], "es-artists.json")
else: WriteElsJson.write_albums(itunes_parser['albums'], "es-albums.json")
with io.open(args.output, 'wb') as outfile:
if sys.version_info.major == 2: # if args.console:
outfile.write(bytes(output)) # print(output)
elif sys.version_info.major == 3: # else:
outfile.write(bytes(output, 'UTF-8')) # with io.open(args.output, 'wb') as outfile:
print('JSON data written to: ' + args.output) # if sys.version_info.major == 2:
# outfile.write(bytes(output))
# elif sys.version_info.major == 3:
# outfile.write(bytes(output, 'UTF-8'))
# print('JSON data written to: ' + args.output)