diff options
author | Jenkins <jenkins@review.openstack.org> | 2014-12-14 22:48:28 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2014-12-14 22:48:28 +0000 |
commit | d6d5197f6eadad04a44b8c6e3f98f0574e442f52 (patch) | |
tree | 0680b46c3750004182924060e99cce6c6b115ed2 | |
parent | e3187cb25bc43bb903548406750bc82611aaaf3d (diff) | |
parent | 6ff27ccabf0580d57f48e607b21535f5475ff3fe (diff) | |
download | python-heatclient-d6d5197f6eadad04a44b8c6e3f98f0574e442f52.tar.gz |
Merge "Add transtlation markers for error messages"
-rw-r--r-- | heatclient/common/environment_format.py | 7 | ||||
-rw-r--r-- | heatclient/common/http.py | 22 | ||||
-rw-r--r-- | heatclient/common/template_format.py | 4 | ||||
-rw-r--r-- | heatclient/common/template_utils.py | 21 | ||||
-rw-r--r-- | heatclient/common/utils.py | 14 | ||||
-rw-r--r-- | heatclient/exc.py | 21 | ||||
-rw-r--r-- | heatclient/openstack/common/apiclient/exceptions.py | 4 | ||||
-rw-r--r-- | heatclient/openstack/common/apiclient/fake_client.py | 15 | ||||
-rw-r--r-- | heatclient/shell.py | 28 | ||||
-rw-r--r-- | heatclient/v1/shell.py | 64 |
10 files changed, 114 insertions, 86 deletions
diff --git a/heatclient/common/environment_format.py b/heatclient/common/environment_format.py index e00bb15..0b876b6 100644 --- a/heatclient/common/environment_format.py +++ b/heatclient/common/environment_format.py @@ -11,6 +11,7 @@ # under the License. from heatclient.common import template_format +from heatclient.openstack.common._i18n import _ import yaml @@ -33,12 +34,12 @@ def parse(env_str): if env is None: env = {} elif not isinstance(env, dict): - raise ValueError('The environment is not a valid ' - 'YAML mapping data type.') + raise ValueError(_('The environment is not a valid ' + 'YAML mapping data type.')) for param in env: if param not in SECTIONS: - raise ValueError('environment has wrong section "%s"' % param) + raise ValueError(_('environment has wrong section "%s"') % param) return env diff --git a/heatclient/common/http.py b/heatclient/common/http.py index 2089176..063bcfa 100644 --- a/heatclient/common/http.py +++ b/heatclient/common/http.py @@ -28,6 +28,7 @@ from oslo.utils import encodeutils from oslo.utils import importutils from heatclient import exc +from heatclient.openstack.common._i18n import _ LOG = logging.getLogger(__name__) USER_AGENT = 'python-heatclient' @@ -192,12 +193,12 @@ class HTTPClient(object): allow_redirects=allow_redirects, **kwargs) except socket.gaierror as e: - message = ("Error finding address for %(url)s: %(e)s" % + message = (_("Error finding address for %(url)s: %(e)s") % {'url': self.endpoint_url + url, 'e': e}) raise exc.InvalidEndpoint(message=message) except (socket.error, socket.timeout) as e: endpoint = self.endpoint - message = ("Error communicating with %(endpoint)s %(e)s" % + message = (_("Error communicating with %(endpoint)s %(e)s") % {'endpoint': endpoint, 'e': e}) raise exc.CommunicationError(message=message) @@ -206,11 +207,14 @@ class HTTPClient(object): if not 'X-Auth-Key' in kwargs['headers'] and \ (resp.status_code == 401 or (resp.status_code == 500 and "(HTTP 401)" in resp.content)): - raise exc.HTTPUnauthorized("Authentication failed. Please try" - " again with option " - "--include-password or export " - "HEAT_INCLUDE_PASSWORD=1\n%s" - % resp.content) + raise exc.HTTPUnauthorized(_("Authentication failed. Please try" + " again with option %(option)s or " + "export %(var)s\n%(content)s") % + { + 'option': '--include-password', + 'var': 'HEAT_INCLUDE_PASSWORD=1', + 'content': resp.content + }) elif 400 <= resp.status_code < 600: raise exc.from_response(resp) elif resp.status_code in (301, 302, 305): @@ -227,12 +231,12 @@ class HTTPClient(object): def strip_endpoint(self, location): if location is None: - message = "Location not returned with 302" + message = _("Location not returned with 302") raise exc.InvalidEndpoint(message=message) elif location.lower().startswith(self.endpoint.lower()): return location[len(self.endpoint):] else: - message = "Prohibited endpoint redirect %s" % location + message = _("Prohibited endpoint redirect %s") % location raise exc.InvalidEndpoint(message=message) def credentials_headers(self): diff --git a/heatclient/common/template_format.py b/heatclient/common/template_format.py index b29817b..2f4a91a 100644 --- a/heatclient/common/template_format.py +++ b/heatclient/common/template_format.py @@ -13,6 +13,8 @@ import json import yaml +from heatclient.openstack.common._i18n import _ + if hasattr(yaml, 'CSafeLoader'): yaml_loader = yaml.CSafeLoader else: @@ -57,5 +59,5 @@ def parse(tmpl_str): if not ('HeatTemplateFormatVersion' in tpl or 'heat_template_version' in tpl or 'AWSTemplateFormatVersion' in tpl): - raise ValueError("Template format version not found.") + raise ValueError(_("Template format version not found.")) return tpl diff --git a/heatclient/common/template_utils.py b/heatclient/common/template_utils.py index bf55c91..29dd3fc 100644 --- a/heatclient/common/template_utils.py +++ b/heatclient/common/template_utils.py @@ -26,6 +26,7 @@ from oslo.serialization import jsonutils from heatclient.common import environment_format from heatclient.common import template_format from heatclient import exc +from heatclient.openstack.common._i18n import _ def get_template_contents(template_file=None, template_url=None, @@ -44,12 +45,16 @@ def get_template_contents(template_file=None, template_url=None, tpl = object_request and object_request('GET', template_object) else: - raise exc.CommandError('Need to specify exactly one of ' - '--template-file, --template-url ' - 'or --template-object') + raise exc.CommandError(_('Need to specify exactly one of ' + '%(arg1)s, %(arg2)s or %(arg3)s') % + { + 'arg1': '--template-file', + 'arg2': '--template-url', + 'arg3': '--template-object' + }) if not tpl: - raise exc.CommandError('Could not fetch template from %s' + raise exc.CommandError(_('Could not fetch template from %s') % template_url) try: @@ -57,8 +62,8 @@ def get_template_contents(template_file=None, template_url=None, tpl = tpl.decode('utf-8') template = template_format.parse(tpl) except ValueError as e: - raise exc.CommandError( - 'Error parsing template %s %s' % (template_url, e)) + raise exc.CommandError(_('Error parsing template %(url)s %(error)s') % + {'url': template_url, 'error': e}) tmpl_base_url = base_url_for_url(template_url) if files is None: @@ -138,8 +143,8 @@ def read_url_content(url): try: content = request.urlopen(url).read() except error.URLError: - raise exc.CommandError('Could not fetch contents for %s' - % url) + raise exc.CommandError(_('Could not fetch contents for %s') % url) + if content: try: content.decode('utf-8') diff --git a/heatclient/common/utils.py b/heatclient/common/utils.py index efa3593..22a9059 100644 --- a/heatclient/common/utils.py +++ b/heatclient/common/utils.py @@ -25,6 +25,7 @@ from oslo.serialization import jsonutils from oslo.utils import importutils from heatclient import exc +from heatclient.openstack.common._i18n import _ from heatclient.openstack.common import cliutils supported_formats = { @@ -93,8 +94,12 @@ def find_resource(manager, name_or_id): try: return manager.find(name=name_or_id) except exc.NotFound: - msg = "No %s with a name or ID of '%s' exists." % \ - (manager.resource_class.__name__.lower(), name_or_id) + msg = _("No %(name)s with a name or ID of " + "'%(name_or_id)s' exists.") % \ + { + 'name': manager.resource_class.__name__.lower(), + 'name_or_id': name_or_id + } raise exc.CommandError(msg) @@ -127,8 +132,7 @@ def format_parameters(params): try: (n, v) = p.split(('='), 1) except ValueError: - msg = '%s(%s). %s.' % ('Malformed parameter', p, - 'Use the key=value format') + msg = _('Malformed parameter(%s). Use the key=value format.') % p raise exc.CommandError(msg) if n not in parameters: @@ -147,7 +151,7 @@ def format_output(output, format='yaml'): try: return supported_formats[output_format](output) except KeyError: - raise exc.HTTPUnsupported("The format(%s) is unsupported." + raise exc.HTTPUnsupported(_("The format(%s) is unsupported.") % output_format) diff --git a/heatclient/exc.py b/heatclient/exc.py index 1c9883d..4240d75 100644 --- a/heatclient/exc.py +++ b/heatclient/exc.py @@ -14,6 +14,8 @@ import sys from oslo.serialization import jsonutils +from heatclient.openstack.common._i18n import _ + verbose = 0 @@ -47,7 +49,7 @@ class HTTPException(BaseException): try: self.error = jsonutils.loads(message) if 'error' not in self.error: - raise KeyError('Key "error" not exists') + raise KeyError(_('Key "error" not exists')) except KeyError: # NOTE(jianingy): If key 'error' happens not exist, # self.message becomes no sense. In this case, we @@ -62,19 +64,24 @@ class HTTPException(BaseException): message = self.error['error'].get('message', 'Internal Error') if verbose: traceback = self.error['error'].get('traceback', '') - return 'ERROR: %s\n%s' % (message, traceback) + return (_('ERROR: %(message)s\n%(traceback)s') % + {'message': message, 'traceback': traceback}) else: - return 'ERROR: %s' % message + return _('ERROR: %s') % message class HTTPMultipleChoices(HTTPException): code = 300 def __str__(self): - self.details = ("Requested version of Heat API is not" - "available.") - return "%s (HTTP %s) %s" % (self.__class__.__name__, self.code, - self.details) + self.details = _("Requested version of Heat API is not" + "available.") + return (_("%(name)s (HTTP %(code)s) %(details)s") % + { + 'name': self.__class__.__name__, + 'code': self.code, + 'details': self.details + }) class BadRequest(HTTPException): diff --git a/heatclient/openstack/common/apiclient/exceptions.py b/heatclient/openstack/common/apiclient/exceptions.py index 745ad06..d151a15 100644 --- a/heatclient/openstack/common/apiclient/exceptions.py +++ b/heatclient/openstack/common/apiclient/exceptions.py @@ -115,9 +115,9 @@ class HttpError(ClientException): self.response = response self.url = url self.method = method - formatted_string = "%s (HTTP %s)" % (self.message, self.http_status) + formatted_string = _("%s (HTTP %s)") % (self.message, self.http_status) if request_id: - formatted_string += " (Request-ID: %s)" % request_id + formatted_string += _(" (Request-ID: %s)") % request_id super(HttpError, self).__init__(formatted_string) diff --git a/heatclient/openstack/common/apiclient/fake_client.py b/heatclient/openstack/common/apiclient/fake_client.py index 44ae68c..ed96459 100644 --- a/heatclient/openstack/common/apiclient/fake_client.py +++ b/heatclient/openstack/common/apiclient/fake_client.py @@ -30,6 +30,7 @@ import requests import six from six.moves.urllib import parse +from heatclient.openstack.common._i18n import _ from heatclient.openstack.common.apiclient import client @@ -41,7 +42,7 @@ def assert_has_keys(dct, required=None, optional=None): assert k in dct except AssertionError: extra_keys = set(dct.keys()).difference(set(required + optional)) - raise AssertionError("found unexpected keys: %s" % + raise AssertionError(_("found unexpected keys: %s") % list(extra_keys)) @@ -91,9 +92,9 @@ class FakeHTTPClient(client.HTTPClient): expected = (method, url) called = self.callstack[pos][0:2] assert self.callstack, \ - "Expected %s %s but no calls were made." % expected + _("Expected %s %s but no calls were made.") % expected - assert expected == called, 'Expected %s %s; got %s %s' % \ + assert expected == called, _('Expected %s %s; got %s %s') % \ (expected + called) if body is not None: @@ -107,7 +108,7 @@ class FakeHTTPClient(client.HTTPClient): expected = (method, url) assert self.callstack, \ - "Expected %s %s but no calls were made." % expected + _("Expected %s %s but no calls were made.") % expected found = False entry = None @@ -116,7 +117,7 @@ class FakeHTTPClient(client.HTTPClient): found = True break - assert found, 'Expected %s %s; got %s' % \ + assert found, _('Expected %s %s; got %s') % \ (method, url, self.callstack) if body is not None: assert entry[3] == body, "%s != %s" % (entry[3], body) @@ -158,8 +159,8 @@ class FakeHTTPClient(client.HTTPClient): callback = "%s_%s" % (method.lower(), munged_url) if not hasattr(self, callback): - raise AssertionError('Called unknown API method: %s %s, ' - 'expected fakes method name: %s' % + raise AssertionError(_('Called unknown API method: %s %s, ' + 'expected fakes method name: %s') % (method, url, callback)) resp = getattr(self, callback)(**kwargs) diff --git a/heatclient/shell.py b/heatclient/shell.py index 587aa92..eeaaeb2 100644 --- a/heatclient/shell.py +++ b/heatclient/shell.py @@ -511,9 +511,9 @@ class HeatShell(object): # support only v2 auth = self._get_keystone_v2_auth(v2_auth_url, **kwargs) else: - raise exc.CommandError('Unable to determine the Keystone version ' - 'to authenticate with using the given ' - 'auth_url.') + raise exc.CommandError(_('Unable to determine the Keystone ' + 'version to authenticate with using the ' + 'given auth_url.')) return auth @@ -547,23 +547,23 @@ class HeatShell(object): return 0 if not args.os_username and not args.os_auth_token: - raise exc.CommandError("You must provide a username via" + raise exc.CommandError(_("You must provide a username via" " either --os-username or env[OS_USERNAME]" " or a token via --os-auth-token or" - " env[OS_AUTH_TOKEN]") + " env[OS_AUTH_TOKEN]")) if not args.os_password and not args.os_auth_token: - raise exc.CommandError("You must provide a password via" + raise exc.CommandError(_("You must provide a password via" " either --os-password or env[OS_PASSWORD]" " or a token via --os-auth-token or" - " env[OS_AUTH_TOKEN]") + " env[OS_AUTH_TOKEN]")) if args.os_no_client_auth: if not args.heat_url: - raise exc.CommandError("If you specify --os-no-client-auth" + raise exc.CommandError(_("If you specify --os-no-client-auth" " you must also specify a Heat API URL" " via either --heat-url or" - " env[HEAT_URL]") + " env[HEAT_URL]")) else: # Tenant/project name or ID is needed to make keystoneclient # retrieve a service catalog, it's not required if @@ -571,7 +571,7 @@ class HeatShell(object): if not (args.os_tenant_id or args.os_tenant_name or args.os_project_id or args.os_project_name): - raise exc.CommandError("You must provide a tenant id via" + raise exc.CommandError(_("You must provide a tenant id via" " either --os-tenant-id or" " env[OS_TENANT_ID] or a tenant name" " via either --os-tenant-name or" @@ -579,12 +579,12 @@ class HeatShell(object): " via either --os-project-id or" " env[OS_PROJECT_ID] or a project" " name via either --os-project-name or" - " env[OS_PROJECT_NAME]") + " env[OS_PROJECT_NAME]")) if not args.os_auth_url: - raise exc.CommandError("You must provide an auth url via" + raise exc.CommandError(_("You must provide an auth url via" " either --os-auth-url or via" - " env[OS_AUTH_URL]") + " env[OS_AUTH_URL]")) kwargs = { 'insecure': args.insecure, @@ -705,7 +705,7 @@ def main(args=None): HeatShell().main(args) except KeyboardInterrupt: - print("... terminating heat client", file=sys.stderr) + print(_("... terminating heat client"), file=sys.stderr) sys.exit(130) except Exception as e: if '--debug' in args or '-d' in args: diff --git a/heatclient/v1/shell.py b/heatclient/v1/shell.py index 723a074..ee3328a 100644 --- a/heatclient/v1/shell.py +++ b/heatclient/v1/shell.py @@ -151,7 +151,8 @@ def do_stack_adopt(hc, args): env_path=args.environment_file) if not args.adopt_file: - raise exc.CommandError('Need to specify --adopt-file') + raise exc.CommandError(_('Need to specify %(arg)s') % + {'arg': '--adopt-file'}) adopt_url = template_utils.normalise_file_path_to_url(args.adopt_file) adopt_data = request.urlopen(adopt_url).read() @@ -256,8 +257,8 @@ def do_stack_delete(hc, args): failure_count += 1 print(e) if failure_count == len(args.id): - raise exc.CommandError("Unable to delete any of the specified " - "stacks.") + raise exc.CommandError(_("Unable to delete any of the specified " + "stacks.")) do_stack_list(hc) @@ -278,7 +279,7 @@ def do_stack_abandon(hc, args): try: stack = hc.stacks.abandon(**fields) except exc.HTTPNotFound: - raise exc.CommandError('Stack not found: %s' % args.id) + raise exc.CommandError(_('Stack not found: %s') % args.id) else: result = jsonutils.dumps(stack, indent=2) if args.output_file is not None: @@ -300,7 +301,7 @@ def do_action_suspend(hc, args): try: hc.actions.suspend(**fields) except exc.HTTPNotFound: - raise exc.CommandError('Stack not found: %s' % args.id) + raise exc.CommandError(_('Stack not found: %s') % args.id) else: do_stack_list(hc) @@ -313,7 +314,7 @@ def do_action_resume(hc, args): try: hc.actions.resume(**fields) except exc.HTTPNotFound: - raise exc.CommandError('Stack not found: %s' % args.id) + raise exc.CommandError(_('Stack not found: %s') % args.id) else: do_stack_list(hc) @@ -326,7 +327,7 @@ def do_action_check(hc, args): try: hc.actions.check(**fields) except exc.HTTPNotFound: - raise exc.CommandError('Stack not found: %s' % args.id) + raise exc.CommandError(_('Stack not found: %s') % args.id) else: do_stack_list(hc) @@ -347,7 +348,7 @@ def do_stack_show(hc, args): try: stack = hc.stacks.get(**fields) except exc.HTTPNotFound: - raise exc.CommandError('Stack not found: %s' % args.id) + raise exc.CommandError(_('Stack not found: %s') % args.id) else: formatters = { 'description': utils.text_wrap_formatter, @@ -503,7 +504,7 @@ def do_stack_cancel_update(hc, args): try: hc.actions.cancel_update(**fields) except exc.HTTPNotFound: - raise exc.CommandError('Stack not found: %s' % args.id) + raise exc.CommandError(_('Stack not found: %s') % args.id) else: do_stack_list(hc) @@ -563,7 +564,7 @@ def do_output_list(hc, args): try: stack = hc.stacks.get(stack_id=args.id) except exc.HTTPNotFound: - raise exc.CommandError('Stack not found: %s' % args.id) + raise exc.CommandError(_('Stack not found: %s') % args.id) else: outputs = stack.to_dict()['outputs'] fields = ['output_key', 'description'] @@ -584,12 +585,12 @@ def do_output_show(hc, args): try: stack = hc.stacks.get(stack_id=args.id) except exc.HTTPNotFound: - raise exc.CommandError('Stack not found: %s' % args.id) + raise exc.CommandError(_('Stack not found: %s') % args.id) else: for output in stack.to_dict().get('outputs', []): if output['output_key'] == args.output: if 'output_error' in output: - msg = "Error: %s" % output['output_error'] + msg = _("Error: %s") % output['output_error'] raise exc.CommandError(msg) else: value = output['output_value'] @@ -614,7 +615,7 @@ def do_resource_type_show(hc, args): resource_type = hc.resource_types.get(args.resource_type) except exc.HTTPNotFound: raise exc.CommandError( - 'Resource Type not found: %s' % args.resource_type) + _('Resource Type not found: %s') % args.resource_type) else: print(jsonutils.dumps(resource_type, indent=2)) @@ -631,7 +632,7 @@ def do_resource_type_template(hc, args): template = hc.resource_types.generate_template(**fields) except exc.HTTPNotFound: raise exc.CommandError( - 'Resource Type %s not found.' % args.resource_type) + _('Resource Type %s not found.') % args.resource_type) else: if args.format: print(utils.format_output(template, format=args.format)) @@ -655,7 +656,7 @@ def do_template_show(hc, args): try: template = hc.stacks.template(**fields) except exc.HTTPNotFound: - raise exc.CommandError('Stack not found: %s' % args.id) + raise exc.CommandError(_('Stack not found: %s') % args.id) else: if 'heat_template_version' in template: print(yaml.safe_dump(template, indent=2)) @@ -723,7 +724,7 @@ def do_resource_list(hc, args): try: resources = hc.resources.list(**fields) except exc.HTTPNotFound: - raise exc.CommandError('Stack not found: %s' % args.id) + raise exc.CommandError(_('Stack not found: %s') % args.id) else: fields = ['physical_resource_id', 'resource_type', 'resource_status', 'updated_time'] @@ -759,8 +760,9 @@ def do_resource_show(hc, args): try: resource = hc.resources.get(**fields) except exc.HTTPNotFound: - raise exc.CommandError('Stack or resource not found: %s %s' % - (args.id, args.resource)) + raise exc.CommandError(_('Stack or resource not found: ' + '%(id)s %(resource)s') % + {'id': args.id, 'resource': args.resource}) else: formatters = { 'links': utils.link_formatter, @@ -791,8 +793,9 @@ def do_resource_metadata(hc, args): try: metadata = hc.resources.metadata(**fields) except exc.HTTPNotFound: - raise exc.CommandError('Stack or resource not found: %s %s' % - (args.id, args.resource)) + raise exc.CommandError(_('Stack or resource not found: ' + '%(id)s %(resource)s') % + {'id': args.id, 'resource': args.resource}) else: print(jsonutils.dumps(metadata, indent=2)) @@ -812,7 +815,7 @@ def do_resource_signal(hc, args): data = args.data data_file = args.data_file if data and data_file: - raise exc.CommandError('Can only specify one of data and data-file') + raise exc.CommandError(_('Can only specify one of data and data-file')) if data_file: data_url = template_utils.normalise_file_path_to_url(data_file) data = request.urlopen(data_url).read() @@ -822,15 +825,16 @@ def do_resource_signal(hc, args): try: data = jsonutils.loads(data) except ValueError as ex: - raise exc.CommandError('Data should be in JSON format: %s' % ex) + raise exc.CommandError(_('Data should be in JSON format: %s') % ex) if not isinstance(data, dict): - raise exc.CommandError('Data should be a JSON dict') + raise exc.CommandError(_('Data should be a JSON dict')) fields['data'] = data try: hc.resources.signal(**fields) except exc.HTTPNotFound: - raise exc.CommandError('Stack or resource not found: %s %s' % - (args.id, args.resource)) + raise exc.CommandError(_('Stack or resource not found: ' + '%(id)s %(resource)s') % + {'id': args.id, 'resource': args.resource}) @utils.arg('id', metavar='<NAME or ID>', @@ -929,7 +933,7 @@ def do_stack_snapshot(hc, args): try: snapshot = hc.stacks.snapshot(**fields) except exc.HTTPNotFound: - raise exc.CommandError('Stack not found: %s' % args.id) + raise exc.CommandError(_('Stack not found: %s') % args.id) else: print(jsonutils.dumps(snapshot, indent=2, ensure_ascii=False)) @@ -944,7 +948,7 @@ def do_snapshot_show(hc, args): try: snapshot = hc.stacks.snapshot_show(**fields) except exc.HTTPNotFound: - raise exc.CommandError('Stack or snapshot not found') + raise exc.CommandError(_('Stack or snapshot not found')) else: print(jsonutils.dumps(snapshot, indent=2, ensure_ascii=False)) @@ -959,7 +963,7 @@ def do_snapshot_delete(hc, args): try: hc.stacks.snapshot_delete(**fields) except exc.HTTPNotFound: - raise exc.CommandError('Stack or snapshot not found') + raise exc.CommandError(_('Stack or snapshot not found')) @utils.arg('id', metavar='<NAME or ID>', @@ -972,7 +976,7 @@ def do_stack_restore(hc, args): try: hc.stacks.restore(**fields) except exc.HTTPNotFound: - raise exc.CommandError('Stack or snapshot not found') + raise exc.CommandError(_('Stack or snapshot not found')) @utils.arg('id', metavar='<NAME or ID>', @@ -983,7 +987,7 @@ def do_snapshot_list(hc, args): try: snapshots = hc.stacks.snapshot_list(**fields) except exc.HTTPNotFound: - raise exc.CommandError('Stack not found: %s' % args.id) + raise exc.CommandError(_('Stack not found: %s') % args.id) else: fields = ['id', 'name', 'status', 'status_reason', 'data', 'creation_time'] |