Skip to content

Commit

Permalink
added alphabetic ordering of unexpected keys. added --non_strict to a…
Browse files Browse the repository at this point in the history
…llow unexpected keys.
  • Loading branch information
lindt committed Mar 14, 2016
1 parent 66e874f commit c8a02bc
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 17 deletions.
7 changes: 5 additions & 2 deletions bin/compose_format
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ if __name__ == '__main__':
parser.add_argument(
'--ignore_changes', action='store_const', const=False,
help='ignore changes for return code', default=True)
parser.add_argument(
'--non_strict', action='store_const', const=True,
help='if this is provided, unknown keys errors are ignored', default=False)
parser.add_argument('files', nargs=argparse.REMAINDER)
args = parser.parse_args()
formatter = ComposeFormat()
Expand All @@ -22,14 +25,14 @@ if __name__ == '__main__':
assert args.replace is False, 'replace makes no sense when reading from stdin'

data = sys.stdin.read()
formatted = formatter.format_string(data)
formatted = formatter.format_string(data, strict=not args.non_strict)
print(formatted)
if not args.ignore_changes:
if data != formatted:
sys.exit(1)

for path in args.files:
if not formatter.format(path, args.replace):
if not formatter.format(path, replace=args.replace, strict=not args.non_strict):
if args.replace:
print('path {} has been changed'.format(path))
if not args.ignore_changes:
Expand Down
49 changes: 35 additions & 14 deletions compose_format/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,24 @@
class ComposeFormat:
TOPLEVEL_ORDER = ['version', 'services', 'volumes', 'networks']
SERVICE_ORDER = [
'image', 'command', 'links',
'volumes_from', 'volumes', 'expose', 'ports',
'extra_hosts', 'restart', 'ulimits', 'tty']
BUILD_ORDER = ['context', 'dockerfile']
'image', 'command', 'entrypoint', 'container_name',
'links', 'volumes_from', 'volumes', 'volume_driver',
'build',
'expose', 'ports',
'net', 'network_mode', 'networks',
'labels',
'devices',
'read_only',
'env_file', 'environment',
'cpu_shares', 'cpu_quota', 'cpuset', 'domainname', 'hostname', 'ipc',
'mac_address', 'mem_limit', 'memswap_limit', 'privileged',
'depends_on', 'extends', 'external_links',
'stdin_open', 'user', 'working_dir',
'extra_hosts', 'restart', 'ulimits', 'tty', 'dns', 'dns_search', 'pid',
'security_opt', 'cap_add', 'cap_drop', 'cgroup_parent', 'logging', 'log_driver', 'log_opt',
'stopsignal',
]
BUILD_ORDER = ['context', 'dockerfile', 'args']

ORDERS = {
'version': TOPLEVEL_ORDER,
Expand All @@ -21,11 +35,11 @@ class ComposeFormat:
def __init__(self):
pass

def format(self, path, replace=False):
def format(self, path, replace=False, strict=True):
with open(path, 'r') as file:
data = file.read()
original = data
formatted = self.format_string(data, replace=replace)
formatted = self.format_string(data, replace=replace, strict=strict)

if replace:
with open(path, 'w') as file:
Expand All @@ -34,8 +48,8 @@ def format(self, path, replace=False):
print(formatted)
return original == formatted

def format_string(self, data, replace=False):
data = self.reorder(load(data))
def format_string(self, data, replace=False, strict=True):
data = self.reorder(load(data), strict=strict)

def is_legacy_version(data):
if 'version' not in data:
Expand All @@ -48,7 +62,7 @@ def is_legacy_version(data):
return formatted.strip() + '\n'

@staticmethod
def reorder(data):
def reorder(data, strict=True):
if type(data) is dict or type(data) is OrderedDict:
for key in ComposeFormat.ORDERS.keys():
if key not in data.keys():
Expand All @@ -57,19 +71,26 @@ def reorder(data):

def order(item):
key, _ = item
assert key in current_order, 'key: {0} not known'.format(key)
if strict:
assert key in current_order, 'key: {0} not known'.format(key)

if key in current_order:
return current_order.index(key)
return len(current_order)
return len(current_order) + ComposeFormat.name_to_order(key)

result = {key: ComposeFormat.reorder(value) for key, value in data.items()}
result = {key: ComposeFormat.reorder(value, strict=strict) for key, value in data.items()}
result = OrderedDict(sorted(result.items(), key=order))

return result
return {key: ComposeFormat.reorder(value) for key, value in data.items()}
return {key: ComposeFormat.reorder(value, strict=strict) for key, value in data.items()}
if type(data) is list:
return sorted([ComposeFormat.reorder(item) for item in data])
return sorted([ComposeFormat.reorder(item, strict=strict) for item in data])
if len(str(data)) >= 1 and str(data)[0].isdigit():
return '\'{}\''.format(data)
return data

@staticmethod
def name_to_order(value):
from functools import reduce

return reduce(lambda left, right: (left * 256 + right), (ord(char) for char in value))
19 changes: 19 additions & 0 deletions features/format.feature
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,22 @@ Feature: Format
ports:
- '10000'
"""

Scenario: Alphabetic Order for unknown keys (--non_strict)
Given a file named "compose.yml" with:
"""
foo:
image: bar
aaa: unknown
ccc: unknown
bbb: unknown
"""
When I run `bin/compose_format --non_strict compose.yml`
Then it should pass with exactly:
"""
foo:
image: bar
aaa: unknown
bbb: unknown
ccc: unknown
"""
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ def readme():

setup(
name='compose_format',
version='0.1.4',
version='0.1.5',
description='format docker-compose files',
long_description=readme(),
url='http://github.com/funkwerk/compose_format',
Expand Down

0 comments on commit c8a02bc

Please sign in to comment.