Skip to content

Commit

Permalink
Pushing latest fixes and features to dev (#46)
Browse files Browse the repository at this point in the history
* Adding 2017 to LICENSE

* Adding inital test suite

* Fix incorrect header argument

* Adding game metadata support (MMR, etc)
  • Loading branch information
jrepp authored Feb 25, 2017
1 parent da26adb commit 734953f
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 30 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

*.swp
*.swo
*~

*.SC2Replay

Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (c) 2013 Blizzard Entertainment
Copyright (c) 2013, 2017 Blizzard Entertainment

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
1 change: 1 addition & 0 deletions s2protocol/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
__author__ = 'Blizzard Entertainment'
__version__ = (1, 0, 1, 'dev')
__all__ = [ 'versions', 'diff', 's2_cli' ]
30 changes: 9 additions & 21 deletions s2protocol/s2_cli.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,4 @@
#!/usr/bin/env python
#
# Copyright (c) 2013 Blizzard Entertainment
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

import sys
import argparse
Expand Down Expand Up @@ -52,6 +32,7 @@ def process(self, event):
print >> self._output, json.dumps(event, encoding='ISO-8859-1', ensure_ascii=True, indent=4)
return event


class NDJSONOutputFilter(EventFilter):
""" Added as a filter will format the event into NDJSON """
def __init__(self, output):
Expand Down Expand Up @@ -171,6 +152,8 @@ def main():
action="store_true")
parser.add_argument("--header", help="print protocol header",
action="store_true")
parser.add_argument("--metadata", help="print game metadata",
action="store_true")
parser.add_argument("--details", help="print protocol details",
action="store_true")
parser.add_argument("--initdata", help="print protocol initdata",
Expand Down Expand Up @@ -249,7 +232,7 @@ def process_event(event):
contents = archive.header['user_data_header']['content']
header = versions.latest().decode_replay_header(contents)
if args.header:
process_event(args.header)
process_event(header)

# The header's baseBuild determines which protocol to use
baseBuild = header['m_version']['m_baseBuild']
Expand All @@ -259,6 +242,11 @@ def process_event(event):
print >> sys.stderr, 'Unsupported base build: %d' % baseBuild
sys.exit(1)

# Process game metadata
if args.all or args.metadata:
contents = archive.read_file('replay.gamemetadata.json')
process_event(json.loads(contents))

# Print protocol details
if args.all or args.details:
contents = archive.read_file('replay.details')
Expand Down
19 changes: 11 additions & 8 deletions s2protocol/versions/__init__.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@

import os
import re
import imp
import sys


def import_protocol(base_path, module_name):
def _import_protocol(base_path, protocol_module_name):
"""
Import a module from a base path, used to import protocol modules.
"""

# Try to return the module if it's been loaded already
try:
return sys.modules[module_name]
return sys.modules[protocol_module_name]
except KeyError:
pass

# print 'importing', module_name, 'from', base_path
# If any of the following calls raises an exception,
# there's a problem we can't handle -- let the caller handle it.
fp, pathname, description = imp.find_module(module_name, [base_path])
#
# Without the full module name in the load, the 'import decoders' will fail
#
fp, pathname, description = imp.find_module(protocol_module_name, [base_path])
try:
return imp.load_module(module_name, fp, pathname, description)
return imp.load_module('s2protocol.versions.' + protocol_module_name, fp, pathname, description)
finally:
# Since we may exit via an exception, close fp explicitly.
if fp:
Expand All @@ -29,7 +32,7 @@ def import_protocol(base_path, module_name):

def list_all(base_path=None):
"""
Returns a list of the current protocol version file names in the versions module.
Returns a list of the current protocol version file names in the versions module sorted by name.
"""
if base_path is None:
base_path = os.path.dirname(__file__)
Expand Down Expand Up @@ -58,7 +61,7 @@ def latest():
module_name = latest_version.split('.')[0]

# Perform the import
return import_protocol(base_path, module_name)
return _import_protocol(base_path, module_name)



Expand All @@ -67,5 +70,5 @@ def build(build_version):
Get the module for a specific build version
"""
base_path = os.path.dirname(__file__)
return import_protocol(base_path, 'protocol{0}'.format(build_version))
return _import_protocol(base_path, 'protocol{0}'.format(build_version))

68 changes: 68 additions & 0 deletions tests/suite.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#!/usr/bin/python

import sys
import unittest
import os
import inspect
import re

from optparse import OptionParser

#
# Fix up import path if running directly
#
if __name__ == '__main__':
filename = os.path.abspath(inspect.getfile(inspect.currentframe()))
thispath = os.path.dirname(filename)
normpath = os.path.normpath(os.path.join(thispath, os.pardir))
sys.path.insert(0, normpath)

import s2protocol
import test_versions


def run():
parser = OptionParser()
parser.add_option('-l', '--list', dest='list', action='store_true',
help='List all test cases')
parser.add_option('-r', '--requests', dest='requests', action='store_true',
help='Enable logging of requests')
parser.add_option('-v', '--verbose', dest='verbose', action='store_true',
help='Enable verbose logging')
parser.add_option('-f', '--filter', dest='filter', type='string', action='store',
help='Filter test cases with a regular expression')
options, args = parser.parse_args()

all_tests = [
test_versions.suite(),
]

if options.list:
for suite in all_tests:
for t in suite:
print t.id()
return

if options.filter:
pattern = re.compile(options.filter)
def expand_tests():
for suite in all_tests:
for t in suite:
yield t

def pattern_match(test):
name = test.id()
return pattern.match(name) is not None
all_tests = unittest.TestSuite(filter(pattern_match, expand_tests()))
else:
all_tests = unittest.TestSuite(all_tests)

test_verbosity = 1
if options.verbose:
test_verbosity = 3

unittest.TextTestRunner(verbosity=test_verbosity, failfast=True).run(all_tests)

if __name__ == '__main__':
run()

18 changes: 18 additions & 0 deletions tests/test_versions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import unittest
from s2protocol import versions as _versions

class VersionsTestCase(unittest.TestCase):
def test_latest(self):
p = _versions.latest()
self.assertIsNotNone(p)

def test_specific(self):
p = _versions.build(49716)
self.assertIsNotNone(p)

def test_missing(self):
self.assertRaises(ImportError, lambda: _versions.build(42))


def suite():
return unittest.TestLoader().loadTestsFromTestCase(VersionsTestCase)

0 comments on commit 734953f

Please sign in to comment.