Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions src/hcl/api.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -42,30 +42,33 @@ def isHcl(s):
raise ValueError("No HCL object could be decoded")


def load(fp):
def load(fp, object_pairs_hook=None):
'''
Deserializes a file-pointer like object into a python dictionary.
The contents of the file must either be JSON or HCL.

:param fp: An object that has a read() function

:param object_pairs_hook: is an optional function that behaves just like the json.load parameter does but only supports OrderedDict
:returns: Dictionary
'''
return loads(fp.read())
return loads(fp.read(), object_pairs_hook=object_pairs_hook)


def loads(s):
def loads(s, object_pairs_hook=None):
'''
Deserializes a string and converts it to a dictionary. The contents
of the string must either be JSON or HCL.


:param object_pairs_hook: is an optional function that behaves just like the json.load parameter does but only supports OrderedDict

:returns: Dictionary
'''
s = u(s)
if isHcl(s):
return HclParser().parse(s)
hcl_out = HclParser(object_pairs_hook=object_pairs_hook)
return hcl_out.parse(s)
else:
return json.loads(s)
return json.loads(s, object_pairs_hook=object_pairs_hook)


def dumps(*args, **kwargs):
Expand Down
10 changes: 8 additions & 2 deletions src/hcl/parser.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from .lexer import Lexer
from ply import lex, yacc
from collections import OrderedDict

import inspect

Expand Down Expand Up @@ -74,7 +75,11 @@ def objectlist_flat(self, lt, replace):

from object.go: there's a flattened list structure
'''
d = {}

if self.object_pairs_hook == OrderedDict:
d = OrderedDict()
else:
d = {}

for k, v in lt:
if k in d.keys() and not replace:
Expand Down Expand Up @@ -317,10 +322,11 @@ def p_error(self, p):

raise ValueError(msg)

def __init__(self):
def __init__(self, object_pairs_hook=None):
self.yacc = yacc.yacc(
module=self, debug=False, optimize=1, picklefile=pickle_file
)
self.object_pairs_hook = object_pairs_hook

def parse(self, s):
return self.yacc.parse(s, lexer=Lexer())
30 changes: 23 additions & 7 deletions tests/test_parser.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from os.path import join, dirname
import hcl
import json
from collections import OrderedDict

import pytest

Expand Down Expand Up @@ -64,28 +65,43 @@

@pytest.mark.parametrize("hcl_fname,invalid", PARSE_FIXTURES)
def test_parser_bytes(hcl_fname, invalid):

with open(join(PARSE_FIXTURE_DIR, hcl_fname), 'rb') as fp:

input = fp.read()
print(input)

if not invalid:
hcl.loads(input)
else:
with pytest.raises(ValueError):
hcl.loads(input)

@pytest.mark.parametrize("hcl_fname,invalid", PARSE_FIXTURES)
def test_parser_str(hcl_fname, invalid):

with open(join(PARSE_FIXTURE_DIR, hcl_fname), 'r') as fp:

input = fp.read()
print(input)

if not invalid:
hcl.loads(input)
else:
with pytest.raises(ValueError):
hcl.loads(input)

@pytest.mark.parametrize("hcl_fname,invalid", PARSE_FIXTURES)
def test_parser_object_pairs_hook(hcl_fname, invalid):
with open(join(PARSE_FIXTURE_DIR, hcl_fname), 'r') as fp:

input = fp.read()
print(input)

if not invalid:
output = hcl.loads(input, object_pairs_hook=OrderedDict)
dummy = OrderedDict([])
assert type(output) == type(dummy)
else:
with pytest.raises(ValueError):
hcl.loads(input)