Skip to content

Commit fc466d1

Browse files
committed
Bring localization resources into the SC2Factory.
Renames DepotHash to a more accurate DepotFile. Adds a new Localization resource and methods to load them from the factory class. Allows resources to use their parent factory to load subresources.
1 parent 277a849 commit fc466d1

File tree

3 files changed

+42
-18
lines changed

3 files changed

+42
-18
lines changed

sc2reader/factories.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
from sc2reader import exceptions
1515
from sc2reader import utils
1616
from sc2reader import log_utils
17-
from sc2reader.resources import Resource, Replay, Map, GameSummary, MapInfo, MapHeader
17+
from sc2reader.objects import DepotFile
18+
from sc2reader.resources import Resource, Replay, Map, GameSummary, MapInfo, MapHeader, Localization
1819

1920
class SC2Factory(object):
2021
"""The SC2Factory class acts as a generic loader interface for all
@@ -69,6 +70,14 @@ def load_replays(self, sources, options=None, **new_options):
6970
"""Loads a collection of sc2replay files, returns a generator."""
7071
return self.load_all(Replay, sources, options, extension='SC2Replay', **new_options)
7172

73+
def load_localization(self, source, options=None, **new_options):
74+
"""Loads a single s2ml file. Accepts file path, url, or file object."""
75+
return self.load(Localization, source, options, **new_options)
76+
77+
def load_localizations(self, sources, options=None, **new_options):
78+
"""Loads a collection of s2ml files, returns a generator."""
79+
return self.load_all(Localization, sources, options, extension='s2ml', **new_options)
80+
7281
def load_map(self, source, options=None, **new_options):
7382
"""Loads a single s2ma file. Accepts file path, url, or file object."""
7483
return self.load(Map, source, options, **new_options)
@@ -134,7 +143,7 @@ def load_all(self, cls, sources, options=None, **new_options):
134143

135144
# Internal Functions
136145
def _load(self, cls, resource, filename, options):
137-
obj = cls(resource, filename=filename, **options)
146+
obj = cls(resource, filename=filename, factory=self, **options)
138147
for plugin in options.get('plugins',self._get_plugins(cls)):
139148
# TODO: What if you want to do a transform?
140149
plugin(obj)
@@ -170,6 +179,9 @@ def _load_resource(self, resource, options=None, **new_options):
170179
"""http links, filesystem locations, and file-like objects"""
171180
options = options or self._get_options(Resource, **new_options)
172181

182+
if isinstance(resource, DepotFile):
183+
resource = resource.url
184+
173185
if isinstance(resource, basestring):
174186
if re.match(r'https?://',resource):
175187
self.logger.info("Fetching remote resource: "+resource)

sc2reader/objects.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,24 @@
1414
ColorData = namedtuple('ColorData',['a','r','g','b'])
1515
BnetData = namedtuple('BnetData',['unknown1','unknown2','subregion','uid'])
1616

17-
class DepotHash(object):
17+
class DepotFile(object):
1818
url_template = 'http://{0}.depot.battle.net:1119/{1}.{2}'
1919

2020
def __init__(self, bytes):
2121
self.server = bytes[4:8].strip('\x00 ')
2222
self.hash = bytes[8:].encode('hex')
2323
self.type = bytes[0:4]
2424

25-
def __str__(self):
25+
@property
26+
def url(self):
2627
return self.url_template.format(self.server, self.hash, self.type)
2728

29+
def __hash__(self):
30+
return hash(self.url)
31+
32+
def __str__(self):
33+
return self.url
34+
2835

2936
class Team(object):
3037
"""

sc2reader/resources.py

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from sc2reader import utils
1616
from sc2reader import log_utils
1717
from sc2reader import readers, data
18-
from sc2reader.objects import Player, Observer, Team, PlayerSummary, Graph, DepotHash
18+
from sc2reader.objects import Player, Observer, Team, PlayerSummary, Graph, DepotFile
1919
from sc2reader.constants import REGIONS, LOCALIZED_RACES, GAME_SPEED_FACTOR, GAME_SPEED_CODES, RACE_CODES, PLAYER_TYPE_CODES, TEAM_COLOR_CODES, GAME_FORMAT_CODES, GAME_TYPE_CODES, DIFFICULTY_CODES
2020

2121

@@ -29,7 +29,8 @@ def real_type(teams):
2929

3030

3131
class Resource(object):
32-
def __init__(self, file_object, filename=None, **options):
32+
def __init__(self, file_object, filename=None, factory=None, **options):
33+
self.factory = factory
3334
self.opt = utils.AttributeDict(options)
3435
self.logger = log_utils.get_logger(self.__class__)
3536
self.filename = filename or getattr(file_object,'name','Unavailable')
@@ -619,6 +620,17 @@ def get_url(cls, gateway, map_hash):
619620
else:
620621
return None
621622

623+
class Localization(Resource):
624+
625+
def __init__(self, s2ml_file, **options):
626+
super(Localization, self).__init__(s2ml_file, **options)
627+
self.mapping = dict()
628+
xml = ElementTree.parse(s2ml_file)
629+
for entry in xml.findall('e'):
630+
self.mapping[int(entry.attrib['id'])] = entry.text
631+
632+
def __getitem__(self, key):
633+
return self.mapping[key]
622634

623635
class GameSummary(Resource):
624636

@@ -710,9 +722,7 @@ def __init__(self, summary_file, filename=None, **options):
710722
# The s2gs file also keeps reference to a series of s2mv files
711723
# Some of these appear to be encoded bytes and others appear to be
712724
# the preview images that authors may bundle with their maps.
713-
self.s2mv_urls = [str(DepotHash(file_hash)) for file_hash in self.parts[0][6][7]]
714-
715-
725+
self.s2mv_urls = [str(DepotFile(file_hash)) for file_hash in self.parts[0][6][7]]
716726

717727
def load_translations(self):
718728
# This section of the file seems to map numerical ids to their
@@ -758,7 +768,7 @@ def load_translations(self):
758768
files = list()
759769
for file_hash in localization[1]:
760770
if file_hash[:4] != '\x00\x00\x00\x00':
761-
files.append(DepotHash(file_hash))
771+
files.append(DepotFile(file_hash))
762772
self.localization_urls[language] = files
763773

764774
# Grab the gateway from the one of the files
@@ -772,15 +782,12 @@ def load_translations(self):
772782
# For now we'll only do this for english localizations.
773783
self.lang_sheets = dict()
774784
self.translations = dict()
775-
for lang,urls in self.localization_urls.items():
785+
for lang, files in self.localization_urls.items():
776786
if lang != 'enUS': continue
777787

778788
sheets = dict()
779-
for sheet, url in enumerate(urls):
780-
print "Opening ", str(url)
781-
xml = ElementTree.parse(urllib2.urlopen(str(url)))
782-
translation = dict((int(e.attrib['id']),e.text) for e in xml.findall('e'))
783-
sheets[sheet] = translation
789+
for sheet, depot_file in enumerate(files):
790+
sheets[sheet] = self.factory.load_localization(depot_file)
784791

785792
translation = dict()
786793
for uid, (sheet, item) in self.id_map.items():
@@ -917,8 +924,6 @@ def load_players(self):
917924
player = PlayerSummary(struct[0][0])
918925
stats = self.player_stats[index]
919926
settings = self.player_settings[index]
920-
print settings
921-
print stats
922927
player.is_ai = not isinstance(struct[0][1], dict)
923928
if not player.is_ai:
924929
player.region = self.region

0 commit comments

Comments
 (0)