Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aws
GitHub Repository: aws/aws-cli
Path: blob/develop/awscli/text.py
1566 views
1
# Copyright 2012-2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
3
# Licensed under the Apache License, Version 2.0 (the "License"). You
4
# may not use this file except in compliance with the License. A copy of
5
# the License is located at
6
7
# http://aws.amazon.com/apache2.0/
8
9
# or in the "license" file accompanying this file. This file is
10
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
# ANY KIND, either express or implied. See the License for the specific
12
# language governing permissions and limitations under the License.
13
14
15
def format_text(data, stream):
16
_format_text(data, stream)
17
18
19
def _format_text(item, stream, identifier=None, scalar_keys=None):
20
if isinstance(item, dict):
21
_format_dict(scalar_keys, item, identifier, stream)
22
elif isinstance(item, list):
23
_format_list(item, identifier, stream)
24
else:
25
# If it's not a list or a dict, we just write the scalar
26
# value out directly.
27
stream.write(str(item))
28
stream.write('\n')
29
30
31
def _format_list(item, identifier, stream):
32
if not item:
33
return
34
if any(isinstance(el, dict) for el in item):
35
all_keys = _all_scalar_keys(item)
36
for element in item:
37
_format_text(
38
element,
39
stream=stream,
40
identifier=identifier,
41
scalar_keys=all_keys,
42
)
43
elif any(isinstance(el, list) for el in item):
44
scalar_elements, non_scalars = _partition_list(item)
45
if scalar_elements:
46
_format_scalar_list(scalar_elements, identifier, stream)
47
for non_scalar in non_scalars:
48
_format_text(non_scalar, stream=stream, identifier=identifier)
49
else:
50
_format_scalar_list(item, identifier, stream)
51
52
53
def _partition_list(item):
54
scalars = []
55
non_scalars = []
56
for element in item:
57
if isinstance(element, (list, dict)):
58
non_scalars.append(element)
59
else:
60
scalars.append(element)
61
return scalars, non_scalars
62
63
64
def _format_scalar_list(elements, identifier, stream):
65
if identifier is not None:
66
for item in elements:
67
stream.write(f'{identifier.upper()}\t{item}\n')
68
else:
69
# For a bare list, just print the contents.
70
stream.write('\t'.join([str(item) for item in elements]))
71
stream.write('\n')
72
73
74
def _format_dict(scalar_keys, item, identifier, stream):
75
scalars, non_scalars = _partition_dict(item, scalar_keys=scalar_keys)
76
if scalars:
77
if identifier is not None:
78
scalars.insert(0, identifier.upper())
79
stream.write('\t'.join(scalars))
80
stream.write('\n')
81
for new_identifier, non_scalar in non_scalars:
82
_format_text(item=non_scalar, stream=stream, identifier=new_identifier)
83
84
85
def _all_scalar_keys(list_of_dicts):
86
keys_seen = set()
87
for item_dict in list_of_dicts:
88
for key, value in item_dict.items():
89
if not isinstance(value, (dict, list)):
90
keys_seen.add(key)
91
return list(sorted(keys_seen))
92
93
94
def _partition_dict(item_dict, scalar_keys):
95
# Given a dictionary, partition it into two list based on the
96
# values associated with the keys.
97
# {'foo': 'scalar', 'bar': 'scalar', 'baz': ['not, 'scalar']}
98
# scalar = [('foo', 'scalar'), ('bar', 'scalar')]
99
# non_scalar = [('baz', ['not', 'scalar'])]
100
scalar = []
101
non_scalar = []
102
if scalar_keys is None:
103
# scalar_keys can have more than just the keys in the item_dict,
104
# but if user does not provide scalar_keys, we'll grab the keys
105
# from the current item_dict
106
for key, value in sorted(item_dict.items()):
107
if isinstance(value, (dict, list)):
108
non_scalar.append((key, value))
109
else:
110
scalar.append(str(value))
111
else:
112
for key in scalar_keys:
113
scalar.append(str(item_dict.get(key, '')))
114
remaining_keys = sorted(set(item_dict.keys()) - set(scalar_keys))
115
for remaining_key in remaining_keys:
116
non_scalar.append((remaining_key, item_dict[remaining_key]))
117
return scalar, non_scalar
118
119