Skip to content

Refactored and fixed crossplane.build #59

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 8, 2019
Merged
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
105 changes: 42 additions & 63 deletions crossplane/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,75 +74,54 @@ def _enquote(arg):

def build(payload, indent=4, tabs=False, header=False):
padding = '\t' if tabs else ' ' * indent
state = {
'prev_obj': None,
'depth': -1
}

def _put_line(line, obj):
margin = padding * state['depth']

# don't need put \n on first line and after comment
if state['prev_obj'] is None:
return margin + line

# trailing comments have to be without \n
if obj['directive'] == '#' and obj['line'] == state['prev_obj']['line']:
return ' ' + line

return '\n' + margin + line
head = ''
if header:
head += '# This config was built from JSON using NGINX crossplane.\n'
head += '# If you encounter any bugs please report them here:\n'
head += '# https://github.com/nginxinc/crossplane/issues\n'
head += '\n'

def _build_lines(objs):
state['depth'] = state['depth'] + 1
def _build_block(output, block, depth, last_line):
margin = padding * depth

for obj in objs:
directive = _enquote(obj['directive'])
for stmt in block:
directive = _enquote(stmt['directive'])
line = stmt.get('line', 0)

if directive in EXTERNAL_BUILDERS:
external_builder = EXTERNAL_BUILDERS[directive]
built = external_builder(obj, padding, state, indent, tabs)
yield _put_line(built, obj)
if directive == '#' and line == last_line:
output += ' #' + stmt['comment']
continue

if directive == '#':
yield _put_line('#' + obj['comment'], obj)
continue

args = [_enquote(arg) for arg in obj['args']]

if directive == 'if':
line = 'if (' + ' '.join(args) + ')'
elif args:
line = directive + ' ' + ' '.join(args)
else:
line = directive

if obj.get('block') is None:
yield _put_line(line + ';', obj)
elif directive == '#':
built = '#' + stmt['comment']
elif directive in EXTERNAL_BUILDERS:
external_builder = EXTERNAL_BUILDERS[directive]
built = external_builder(stmt, padding, indent, tabs)
else:
yield _put_line(line + ' {', obj)

# set prev_obj to propper indentation in block
state['prev_obj'] = obj
for line in _build_lines(obj['block']):
yield line
yield _put_line('}', obj)

state['prev_obj'] = obj
state['depth'] = state['depth'] - 1

if header:
lines = [
'# This config was built from JSON using NGINX crossplane.\n',
'# If you encounter any bugs please report them here:\n',
'# https://github.com/nginxinc/crossplane/issues\n',
'\n'
]
else:
lines = []

lines += _build_lines(payload)
return ''.join(lines)
args = [_enquote(arg) for arg in stmt['args']]

if directive == 'if':
built = 'if (' + ' '.join(args) + ')'
elif args:
built = directive + ' ' + ' '.join(args)
else:
built = directive

if stmt.get('block') is None:
built += ';'
else:
built += ' {'
built = _build_block(built, stmt['block'], depth+1, line)
built += '\n' + margin + '}'

output += ('\n' if output else '') + margin + built
last_line = line

return output

body = ''
body = _build_block(body, payload, 0, 0)
return head + body


def build_files(payload, dirname=None, indent=4, tabs=False, header=False):
Expand Down
2 changes: 1 addition & 1 deletion crossplane/ext/lua.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def lex(self, char_iterator, directive):
def parse(self, stmt, parsing, tokens, ctx=(), consume=False):
pass

def build(self, stmt, padding, state, indent=4, tabs=False):
def build(self, stmt, padding, indent=4, tabs=False):
built = stmt['directive']
if built == 'set_by_lua_block':
block = stmt['args'][1]
Expand Down
24 changes: 18 additions & 6 deletions tests/test_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,7 @@ def test_build_nested_and_multiple_args():
]
}
]

built = crossplane.build(payload, indent=4, tabs=False)

assert built == '\n'.join([
'events {',
' worker_connections 1024;',
Expand Down Expand Up @@ -148,9 +146,7 @@ def test_build_with_comments():
]
}
]

built = crossplane.build(payload, indent=4, tabs=False)

assert built == '\n'.join([
'events {',
' worker_connections 1024;',
Expand All @@ -170,6 +166,24 @@ def test_build_with_comments():
])


def test_build_starts_with_comments():
payload = [
{
"directive": "#",
"line": 1,
"args": [],
"comment": " foo"
},
{
"directive": "user",
"line": 5,
"args": ["root"]
}
]
built = crossplane.build(payload, indent=4, tabs=False)
assert built == '# foo\nuser root;'


def test_build_with_quoted_unicode():
payload = [
{
Expand All @@ -178,9 +192,7 @@ def test_build_with_quoted_unicode():
"args": ["русский текст"],
}
]

built = crossplane.build(payload, indent=4, tabs=False)

assert built == u"env 'русский текст';"


Expand Down