Skip to content

Commit

Permalink
Add full support for VDF_VERSION 0x07564427 (fixes #5)
Browse files Browse the repository at this point in the history
 - Support loading / dumping both formats without additional user code
 - Add test cases for new format
  • Loading branch information
leovp committed Aug 17, 2017
1 parent 6d2f3d7 commit 13d9bb5
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 29 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ coverage:
coverage html

test:
py.test
py.test -v

test-all:
tox
51 changes: 30 additions & 21 deletions steamfiles/appinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,22 +124,26 @@ def decode(self):
header=app,
))

app['sections'] = self.wrapper()
while True:
section_id = self.read_byte()
if not section_id:
break
# The newest VDF format is a bit simpler to parse.
if header['version'] == 0x07564427:
app['sections'] = self.parse_subsections()
else:
app['sections'] = self.wrapper()
while True:
section_id = self.read_byte()
if not section_id:
break

# Skip the 0x00 byte before section name.
self.offset += 1
# Skip the 0x00 byte before section name.
self.offset += 1

section_name = self.read_string()
app['sections'][section_name] = self.parse_subsections(root_section=True)
section_name = self.read_string()
app['sections'][section_name] = self.parse_subsections(root_section=True)

# New Section ID's could be added in the future, or changes could be made to
# existing ones, so instead of maintaining a table of section names and their
# corresponding IDs, we are going to store the IDs with all the data.
app['sections'][section_name][b'__steamfiles_section_id'] = section_id
# New Section ID's could be added in the future, or changes could be made to
# existing ones, so instead of maintaining a table of section names and their
# corresponding IDs, we are going to store the IDs with all the data.
app['sections'][section_name][b'__steamfiles_section_id'] = section_id

parsed[app_id] = app

Expand Down Expand Up @@ -216,6 +220,7 @@ class AppinfoEncoder:

def __init__(self, data):
self.data = data
self.version = self.data[b'__vdf_version']

def iter_encode(self):
# VDF Header
Expand All @@ -232,16 +237,20 @@ def iter_encode(self):
app_data['last_update'], app_data['access_token'],
app_data['checksum'], app_data['change_number'])

for section_name, section_data in app_data['sections'].items():
# Delete '_section_id' from the dictionary, as it was placed there by
# the decoding class only to preserve the section id number.
section_id = section_data[b'__steamfiles_section_id']
# Once again, new VDF format is much simpler.
if self.version == 0x07564427:
yield from self.iter_encode_section(app_data['sections'])
else:
for section_name, section_data in app_data['sections'].items():
# Delete '_section_id' from the dictionary, as it was placed there by
# the decoding class only to preserve the section id number.
section_id = section_data[b'__steamfiles_section_id']

yield struct.pack('<H', section_id)
yield self.encode_string(section_name)
yield from self.iter_encode_section(section_data, root_section=True)
yield struct.pack('<H', section_id)
yield self.encode_string(section_name)
yield from self.iter_encode_section(section_data, root_section=True)

yield LAST_SECTION
yield LAST_SECTION

yield LAST_APP

Expand Down
17 changes: 10 additions & 7 deletions tests/test_appinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@
from steamfiles import appinfo
from . import sort_dict

test_file_name = os.path.join(os.path.dirname(__file__), 'test_data/appinfo.vdf')

@pytest.fixture(name='vdf_path', params=['appinfo_4426.vdf', 'appinfo_4427.vdf'])
def _vdf_path(request):
return os.path.join(os.path.dirname(__file__), 'test_data/' + request.param)


@pytest.fixture(name='vdf_data')
def _vdf_data():
with open(test_file_name, 'rb') as f:
def _vdf_data(vdf_path):
with open(vdf_path, 'rb') as f:
yield f.read()


Expand All @@ -33,8 +36,8 @@ def test_loads_dumps_with_wrapper(vdf_data):
assert appinfo.dumps(loaded) == vdf_data


def test_load_dump(vdf_data):
with open(test_file_name, 'rb') as in_file:
def test_load_dump(vdf_data, vdf_path):
with open(vdf_path, 'rb') as in_file:
out_file = io.BytesIO()
loaded = appinfo.load(in_file)

Expand All @@ -52,8 +55,8 @@ def test_load_dump(vdf_data):
assert out_file.read() == vdf_data


def test_load_dump_with_wrapper(vdf_data):
with open(test_file_name, 'rb') as in_file:
def test_load_dump_with_wrapper(vdf_data, vdf_path):
with open(vdf_path, 'rb') as in_file:
out_file = io.BytesIO()
loaded = appinfo.load(in_file, wrapper=OrderedDict)
appinfo.dump(loaded, out_file)
Expand Down
File renamed without changes.
Binary file added tests/test_data/appinfo_4427.vdf
Binary file not shown.

0 comments on commit 13d9bb5

Please sign in to comment.