t*: normalize docs (#9339)

* t*: normalize docs

* Apply suggestions from code review

Co-authored-by: Felix Fontein <felix@fontein.de>

* break long line to regain sanity

---------

Co-authored-by: Felix Fontein <felix@fontein.de>
pull/9371/head
Alexei Znamensky 2024-12-24 23:59:56 +13:00 committed by GitHub
parent c141f86883
commit 6e84c1375e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 109 additions and 134 deletions

View File

@ -9,8 +9,7 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type __metaclass__ = type
DOCUMENTATION = ''' DOCUMENTATION = r"""
---
module: taiga_issue module: taiga_issue
short_description: Creates/deletes an issue in a Taiga Project Management Platform short_description: Creates/deletes an issue in a Taiga Project Management Platform
description: description:
@ -89,10 +88,11 @@ options:
author: Alejandro Guirao (@lekum) author: Alejandro Guirao (@lekum)
requirements: [python-taiga] requirements: [python-taiga]
notes: notes:
- The authentication is achieved either by the environment variable TAIGA_TOKEN or by the pair of environment variables TAIGA_USERNAME and TAIGA_PASSWORD - The authentication is achieved either by the environment variable E(TAIGA_TOKEN) or by the pair
''' of environment variables E(TAIGA_USERNAME) and E(TAIGA_PASSWORD).
"""
EXAMPLES = ''' EXAMPLES = r"""
- name: Create an issue in the my hosted Taiga environment and attach an error log - name: Create an issue in the my hosted Taiga environment and attach an error log
community.general.taiga_issue: community.general.taiga_issue:
taiga_host: https://mytaigahost.example.com taiga_host: https://mytaigahost.example.com
@ -117,9 +117,9 @@ EXAMPLES = '''
subject: An error has been found subject: An error has been found
issue_type: Bug issue_type: Bug
state: absent state: absent
''' """
RETURN = '''# ''' RETURN = """# """
import traceback import traceback
from os import getenv from os import getenv

View File

@ -9,22 +9,21 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type __metaclass__ = type
DOCUMENTATION = ''' DOCUMENTATION = r"""
module: telegram module: telegram
author: author:
- "Artem Feofanov (@tyouxa)" - "Artem Feofanov (@tyouxa)"
- "Nikolai Lomov (@lomserman)" - "Nikolai Lomov (@lomserman)"
short_description: Send notifications via telegram short_description: Send notifications via telegram
description: description:
- Send notifications via telegram bot, to a verified group or user. - Send notifications via telegram bot, to a verified group or user.
- Also, the user may try to use any other telegram bot API method, if you specify O(api_method) argument. - Also, the user may try to use any other telegram bot API method, if you specify O(api_method) argument.
notes: notes:
- You will require a telegram account and create telegram bot to use this module. - You will require a telegram account and create telegram bot to use this module.
extends_documentation_fragment: extends_documentation_fragment:
- community.general.attributes - community.general.attributes
attributes: attributes:
check_mode: check_mode:
support: full support: full
@ -49,11 +48,9 @@ options:
- Any parameters for the method. - Any parameters for the method.
- For reference to default method, V(SendMessage), see U(https://core.telegram.org/bots/api#sendmessage). - For reference to default method, V(SendMessage), see U(https://core.telegram.org/bots/api#sendmessage).
version_added: 2.0.0 version_added: 2.0.0
"""
''' EXAMPLES = r"""
EXAMPLES = """
- name: Send notify to Telegram - name: Send notify to Telegram
community.general.telegram: community.general.telegram:
token: '9999999:XXXXXXXXXXXXXXXXXXXXXXX' token: '9999999:XXXXXXXXXXXXXXXXXXXXXXX'
@ -75,15 +72,14 @@ EXAMPLES = """
message_id: '{{ saved_msg_id }}' message_id: '{{ saved_msg_id }}'
""" """
RETURN = """ RETURN = r"""
msg: msg:
description: The message you attempted to send description: The message you attempted to send.
returned: success returned: success
type: str type: str
sample: "Ansible task finished" sample: "Ansible task finished"
telegram_error: telegram_error:
description: Error message gotten from Telegram API description: Error message gotten from Telegram API.
returned: failure returned: failure
type: str type: str
sample: "Bad Request: message text is empty" sample: "Bad Request: message text is empty"

View File

@ -8,13 +8,11 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type __metaclass__ = type
DOCUMENTATION = r''' DOCUMENTATION = r"""
---
module: terraform module: terraform
short_description: Manages a Terraform deployment (and plans) short_description: Manages a Terraform deployment (and plans)
description: description:
- Provides support for deploying resources with Terraform and pulling - Provides support for deploying resources with Terraform and pulling resource information back into Ansible.
resource information back into Ansible.
extends_documentation_fragment: extends_documentation_fragment:
- community.general.attributes - community.general.attributes
attributes: attributes:
@ -27,18 +25,16 @@ options:
state: state:
choices: ['planned', 'present', 'absent'] choices: ['planned', 'present', 'absent']
description: description:
- Goal state of given stage/project - Goal state of given stage/project.
type: str type: str
default: present default: present
binary_path: binary_path:
description: description:
- The path of a terraform binary to use, relative to the 'service_path' - The path of a C(terraform) binary to use, relative to the 'service_path' unless you supply an absolute path.
unless you supply an absolute path.
type: path type: path
project_path: project_path:
description: description:
- The path to the root of the Terraform directory with the - The path to the root of the Terraform directory with the C(vars.tf)/C(main.tf)/etc to use.
vars.tf/main.tf/etc to use.
type: path type: path
required: true required: true
plugin_paths: plugin_paths:
@ -48,88 +44,80 @@ options:
- When set, the plugin discovery and auto-download behavior of Terraform is disabled. - When set, the plugin discovery and auto-download behavior of Terraform is disabled.
- The directory structure in the plugin path can be tricky. The Terraform docs - The directory structure in the plugin path can be tricky. The Terraform docs
U(https://learn.hashicorp.com/tutorials/terraform/automate-terraform#pre-installed-plugins) U(https://learn.hashicorp.com/tutorials/terraform/automate-terraform#pre-installed-plugins)
show a simple directory of files, but actually, the directory structure show a simple directory of files, but actually, the directory structure has to follow the same structure you would see if Terraform auto-downloaded
has to follow the same structure you would see if Terraform auto-downloaded the plugins. the plugins. See the examples below for a tree output of an example plugin directory.
See the examples below for a tree output of an example plugin directory.
type: list type: list
elements: path elements: path
version_added: 3.0.0 version_added: 3.0.0
workspace: workspace:
description: description:
- The terraform workspace to work with. This sets the E(TF_WORKSPACE) environmental variable - The terraform workspace to work with. This sets the E(TF_WORKSPACE) environmental variable that is used to override workspace selection.
that is used to override workspace selection. For more information about workspaces For more information about workspaces have a look at U(https://developer.hashicorp.com/terraform/language/state/workspaces).
have a look at U(https://developer.hashicorp.com/terraform/language/state/workspaces).
type: str type: str
default: default default: default
purge_workspace: purge_workspace:
description: description:
- Only works with state = absent - Only works with state = absent.
- If true, the workspace will be deleted after the "terraform destroy" action. - If true, the workspace will be deleted after the "terraform destroy" action.
- The 'default' workspace will not be deleted. - The 'default' workspace will not be deleted.
default: false default: false
type: bool type: bool
plan_file: plan_file:
description: description:
- The path to an existing Terraform plan file to apply. If this is not - The path to an existing Terraform plan file to apply. If this is not specified, Ansible will build a new TF plan and execute it. Note
specified, Ansible will build a new TF plan and execute it. that this option is required if 'state' has the 'planned' value.
Note that this option is required if 'state' has the 'planned' value.
type: path type: path
state_file: state_file:
description: description:
- The path to an existing Terraform state file to use when building plan. - The path to an existing Terraform state file to use when building plan. If this is not specified, the default C(terraform.tfstate) will
If this is not specified, the default C(terraform.tfstate) will be used. be used.
- This option is ignored when plan is specified. - This option is ignored when plan is specified.
type: path type: path
variables_files: variables_files:
description: description:
- The path to a variables file for Terraform to fill into the TF - The path to a variables file for Terraform to fill into the TF configurations. This can accept a list of paths to multiple variables files.
configurations. This can accept a list of paths to multiple variables files.
type: list type: list
elements: path elements: path
aliases: [ 'variables_file' ] aliases: ['variables_file']
variables: variables:
description: description:
- A group of key-values pairs to override template variables or those in variables files. - A group of key-values pairs to override template variables or those in variables files. By default, only string and number values are
By default, only string and number values are allowed, which are passed on unquoted. allowed, which are passed on unquoted.
- Support complex variable structures (lists, dictionaries, numbers, and booleans) to reflect terraform variable syntax when O(complex_vars=true). - Support complex variable structures (lists, dictionaries, numbers, and booleans) to reflect terraform variable syntax when O(complex_vars=true).
- Ansible integers or floats are mapped to terraform numbers. - Ansible integers or floats are mapped to terraform numbers.
- Ansible strings are mapped to terraform strings. - Ansible strings are mapped to terraform strings.
- Ansible dictionaries are mapped to terraform objects. - Ansible dictionaries are mapped to terraform objects.
- Ansible lists are mapped to terraform lists. - Ansible lists are mapped to terraform lists.
- Ansible booleans are mapped to terraform booleans. - Ansible booleans are mapped to terraform booleans.
- "B(Note) passwords passed as variables will be visible in the log output. Make sure to use C(no_log=true) in production!" - B(Note) passwords passed as variables will be visible in the log output. Make sure to use C(no_log=true) in production!.
type: dict type: dict
complex_vars: complex_vars:
description: description:
- Enable/disable capability to handle complex variable structures for C(terraform). - Enable/disable capability to handle complex variable structures for C(terraform).
- If V(true) the O(variables) also accepts dictionaries, lists, and booleans to be passed to C(terraform). - If V(true) the O(variables) also accepts dictionaries, lists, and booleans to be passed to C(terraform). Strings that are passed are correctly
Strings that are passed are correctly quoted. quoted.
- When disabled, supports only simple variables (strings, integers, and floats), and passes them on unquoted. - When disabled, supports only simple variables (strings, integers, and floats), and passes them on unquoted.
type: bool type: bool
default: false default: false
version_added: 5.7.0 version_added: 5.7.0
targets: targets:
description: description:
- A list of specific resources to target in this plan/application. The - A list of specific resources to target in this plan/application. The resources selected here will also auto-include any dependencies.
resources selected here will also auto-include any dependencies.
type: list type: list
elements: str elements: str
default: [] default: []
lock: lock:
description: description:
- Enable statefile locking, if you use a service that accepts locks (such - Enable statefile locking, if you use a service that accepts locks (such as S3+DynamoDB) to store your statefile.
as S3+DynamoDB) to store your statefile.
type: bool type: bool
default: true default: true
lock_timeout: lock_timeout:
description: description:
- How long to maintain the lock on the statefile, if you use a service - How long to maintain the lock on the statefile, if you use a service that accepts locks (such as S3+DynamoDB).
that accepts locks (such as S3+DynamoDB).
type: int type: int
force_init: force_init:
description: description:
- To avoid duplicating infra, if a state file can't be found this will - To avoid duplicating infra, if a state file can't be found this will force a C(terraform init). Generally, this should be turned off unless
force a C(terraform init). Generally, this should be turned off unless
you intend to provision an entirely new Terraform deployment. you intend to provision an entirely new Terraform deployment.
default: false default: false
type: bool type: bool
@ -145,8 +133,8 @@ options:
type: dict type: dict
backend_config_files: backend_config_files:
description: description:
- The path to a configuration file to provide at init state to the -backend-config parameter. - The path to a configuration file to provide at init state to the -backend-config parameter. This can accept a list of paths to multiple
This can accept a list of paths to multiple configuration files. configuration files.
type: list type: list
elements: path elements: path
version_added: '0.2.0' version_added: '0.2.0'
@ -164,8 +152,8 @@ options:
version_added: '1.3.0' version_added: '1.3.0'
check_destroy: check_destroy:
description: description:
- Apply only when no resources are destroyed. Note that this only prevents "destroy" actions, - Apply only when no resources are destroyed. Note that this only prevents "destroy" actions, but not "destroy and re-create" actions. This
but not "destroy and re-create" actions. This option is ignored when O(state=absent). option is ignored when O(state=absent).
type: bool type: bool
default: false default: false
version_added: '3.3.0' version_added: '3.3.0'
@ -175,12 +163,12 @@ options:
type: int type: int
version_added: '3.8.0' version_added: '3.8.0'
notes: notes:
- To just run a C(terraform plan), use check mode. - To just run a C(terraform plan), use check mode.
requirements: [ "terraform" ] requirements: ["terraform"]
author: "Ryan Scott Brown (@ryansb)" author: "Ryan Scott Brown (@ryansb)"
''' """
EXAMPLES = """ EXAMPLES = r"""
- name: Basic deploy of a service - name: Basic deploy of a service
community.general.terraform: community.general.terraform:
project_path: '{{ project_dir }}' project_path: '{{ project_dir }}'
@ -248,7 +236,7 @@ EXAMPLES = """
# └── terraform-provider-vsphere_v1.26.0_x4 # └── terraform-provider-vsphere_v1.26.0_x4
""" """
RETURN = """ RETURN = r"""
outputs: outputs:
type: complex type: complex
description: A dictionary of all the TF outputs by their assigned name. Use RV(ignore:outputs.MyOutputName.value) to access the value. description: A dictionary of all the TF outputs by their assigned name. Use RV(ignore:outputs.MyOutputName.value) to access the value.
@ -258,18 +246,18 @@ outputs:
sensitive: sensitive:
type: bool type: bool
returned: always returned: always
description: Whether Terraform has marked this value as sensitive description: Whether Terraform has marked this value as sensitive.
type: type:
type: str type: str
returned: always returned: always
description: The type of the value (string, int, etc) description: The type of the value (string, int, etc).
value: value:
type: str type: str
returned: always returned: always
description: The value of the output as interpolated by Terraform description: The value of the output as interpolated by Terraform.
stdout: stdout:
type: str type: str
description: Full C(terraform) command stdout, in case you want to display it or examine the event log description: Full C(terraform) command stdout, in case you want to display it or examine the event log.
returned: always returned: always
sample: '' sample: ''
command: command:

View File

@ -8,20 +8,18 @@
from __future__ import absolute_import, division, print_function from __future__ import absolute_import, division, print_function
__metaclass__ = type __metaclass__ = type
DOCUMENTATION = r''' DOCUMENTATION = r"""
---
module: timezone module: timezone
short_description: Configure timezone setting short_description: Configure timezone setting
description: description:
- This module configures the timezone setting, both of the system clock and of the hardware clock. - This module configures the timezone setting, both of the system clock and of the hardware clock. If you want to set up the NTP, use
If you want to set up the NTP, use M(ansible.builtin.service) module. M(ansible.builtin.service) module.
- It is recommended to restart C(crond) after changing the timezone, otherwise the jobs may run at the wrong time. - It is recommended to restart C(crond) after changing the timezone, otherwise the jobs may run at the wrong time.
- Several different tools are used depending on the OS/Distribution involved. - Several different tools are used depending on the OS/Distribution involved. For Linux it can use C(timedatectl) or edit C(/etc/sysconfig/clock)
For Linux it can use C(timedatectl) or edit C(/etc/sysconfig/clock) or C(/etc/timezone) and C(hwclock). or C(/etc/timezone) and C(hwclock). On SmartOS, C(sm-set-timezone), for macOS, C(systemsetup), for BSD, C(/etc/localtime) is modified. On
On SmartOS, C(sm-set-timezone), for macOS, C(systemsetup), for BSD, C(/etc/localtime) is modified. AIX, C(chtz) is used.
On AIX, C(chtz) is used. - Make sure that the zoneinfo files are installed with the appropriate OS package, like C(tzdata) (usually always installed, when not using
- Make sure that the zoneinfo files are installed with the appropriate OS package, like C(tzdata) (usually always installed, a minimal installation like Alpine Linux).
when not using a minimal installation like Alpine Linux).
- Windows and HPUX are not supported, please let us know if you find any other OS/distro in which this fails. - Windows and HPUX are not supported, please let us know if you find any other OS/distro in which this fails.
extends_documentation_fragment: extends_documentation_fragment:
- community.general.attributes - community.general.attributes
@ -35,51 +33,49 @@ options:
description: description:
- Name of the timezone for the system clock. - Name of the timezone for the system clock.
- Default is to keep current setting. - Default is to keep current setting.
- B(At least one of name and hwclock are required.) - B(At least one) of O(name) and O(hwclock) are required.
type: str type: str
hwclock: hwclock:
description: description:
- Whether the hardware clock is in UTC or in local timezone. - Whether the hardware clock is in UTC or in local timezone.
- Default is to keep current setting. - Default is to keep current setting.
- Note that this option is recommended not to change and may fail - Note that this option is recommended not to change and may fail to configure, especially on virtual environments such as AWS.
to configure, especially on virtual environments such as AWS. - B(At least one) of O(name) and O(hwclock) are required.
- B(At least one of name and hwclock are required.) - I(Only used on Linux).
- I(Only used on Linux.)
type: str type: str
aliases: [ rtc ] aliases: [rtc]
choices: [ local, UTC ] choices: [local, UTC]
notes: notes:
- On Ubuntu 24.04 the C(util-linux-extra) package is required to provide the C(hwclock) command. - On Ubuntu 24.04 the C(util-linux-extra) package is required to provide the C(hwclock) command.
- On SmartOS the C(sm-set-timezone) utility (part of the smtools package) is required to set the zone timezone. - On SmartOS the C(sm-set-timezone) utility (part of the smtools package) is required to set the zone timezone.
- On AIX only Olson/tz database timezones are usable (POSIX is not supported). - On AIX only Olson/tz database timezones are usable (POSIX is not supported). An OS reboot is also required on AIX for the new timezone setting
An OS reboot is also required on AIX for the new timezone setting to take effect. to take effect. Note that AIX 6.1+ is needed (OS level 61 or newer).
Note that AIX 6.1+ is needed (OS level 61 or newer).
author: author:
- Shinichi TAMURA (@tmshn) - Shinichi TAMURA (@tmshn)
- Jasper Lievisse Adriaanse (@jasperla) - Jasper Lievisse Adriaanse (@jasperla)
- Indrajit Raychaudhuri (@indrajitr) - Indrajit Raychaudhuri (@indrajitr)
''' """
RETURN = r''' RETURN = r"""
diff: diff:
description: The differences about the given arguments. description: The differences about the given arguments.
returned: success returned: success
type: complex type: complex
contains: contains:
before: before:
description: The values before change description: The values before change.
type: dict type: dict
after: after:
description: The values after change description: The values after change.
type: dict type: dict
''' """
EXAMPLES = r''' EXAMPLES = r"""
- name: Set timezone to Asia/Tokyo - name: Set timezone to Asia/Tokyo
become: true become: true
community.general.timezone: community.general.timezone:
name: Asia/Tokyo name: Asia/Tokyo
''' """
import errno import errno
import os import os

View File

@ -9,20 +9,17 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type __metaclass__ = type
DOCUMENTATION = ''' DOCUMENTATION = r"""
---
module: twilio module: twilio
short_description: Sends a text message to a mobile phone through Twilio short_description: Sends a text message to a mobile phone through Twilio
description: description:
- Sends a text message to a phone number through the Twilio messaging API. - Sends a text message to a phone number through the Twilio messaging API.
notes: notes:
- This module is non-idempotent because it sends an email through the - This module is non-idempotent because it sends an email through the external API. It is idempotent only in the case that the module fails.
external API. It is idempotent only in the case that the module fails. - Like the other notification modules, this one requires an external dependency to work. In this case, you'll need a Twilio account with a purchased
- Like the other notification modules, this one requires an external or verified phone number to send the text message.
dependency to work. In this case, you'll need a Twilio account with
a purchased or verified phone number to send the text message.
extends_documentation_fragment: extends_documentation_fragment:
- community.general.attributes - community.general.attributes
attributes: attributes:
check_mode: check_mode:
support: full support: full
@ -50,7 +47,7 @@ options:
description: description:
- One or more phone numbers to send the text message to, format C(+15551112222). - One or more phone numbers to send the text message to, format C(+15551112222).
required: true required: true
aliases: [ to_number ] aliases: [to_number]
from_number: from_number:
type: str type: str
description: description:
@ -59,14 +56,13 @@ options:
media_url: media_url:
type: str type: str
description: description:
- A URL with a picture, video or sound clip to send with an MMS - A URL with a picture, video or sound clip to send with an MMS (multimedia message) instead of a plain SMS.
(multimedia message) instead of a plain SMS.
required: false required: false
author: "Matt Makai (@makaimc)" author: "Matt Makai (@makaimc)"
''' """
EXAMPLES = ''' EXAMPLES = r"""
# send an SMS about the build status to (555) 303 5681 # send an SMS about the build status to (555) 303 5681
# note: replace account_sid and auth_token values with your credentials # note: replace account_sid and auth_token values with your credentials
# and you have to have the 'from_number' on your Twilio account # and you have to have the 'from_number' on your Twilio account
@ -75,8 +71,8 @@ EXAMPLES = '''
msg: All servers with webserver role are now configured. msg: All servers with webserver role are now configured.
account_sid: ACXXXXXXXXXXXXXXXXX account_sid: ACXXXXXXXXXXXXXXXXX
auth_token: ACXXXXXXXXXXXXXXXXX auth_token: ACXXXXXXXXXXXXXXXXX
from_number: +15552014545 from_number: "+15552014545"
to_number: +15553035681 to_number: "+15553035681"
delegate_to: localhost delegate_to: localhost
# send an SMS to multiple phone numbers about the deployment # send an SMS to multiple phone numbers about the deployment
@ -87,11 +83,11 @@ EXAMPLES = '''
msg: This server configuration is now complete. msg: This server configuration is now complete.
account_sid: ACXXXXXXXXXXXXXXXXX account_sid: ACXXXXXXXXXXXXXXXXX
auth_token: ACXXXXXXXXXXXXXXXXX auth_token: ACXXXXXXXXXXXXXXXXX
from_number: +15553258899 from_number: "+15553258899"
to_numbers: to_numbers:
- +15551113232 - "+15551113232"
- +12025551235 - "+12025551235"
- +19735559010 - "+19735559010"
delegate_to: localhost delegate_to: localhost
# send an MMS to a single recipient with an update on the deployment # send an MMS to a single recipient with an update on the deployment
@ -103,11 +99,11 @@ EXAMPLES = '''
msg: Deployment complete! msg: Deployment complete!
account_sid: ACXXXXXXXXXXXXXXXXX account_sid: ACXXXXXXXXXXXXXXXXX
auth_token: ACXXXXXXXXXXXXXXXXX auth_token: ACXXXXXXXXXXXXXXXXX
from_number: +15552014545 from_number: "+15552014545"
to_number: +15553035681 to_number: "+15553035681"
media_url: https://demo.twilio.com/logo.png media_url: https://demo.twilio.com/logo.png
delegate_to: localhost delegate_to: localhost
''' """
# ======================================= # =======================================
# twilio module support methods # twilio module support methods

View File

@ -9,12 +9,11 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type __metaclass__ = type
DOCUMENTATION = ''' DOCUMENTATION = r"""
---
module: typetalk module: typetalk
short_description: Send a message to typetalk short_description: Send a message to typetalk
description: description:
- Send a message to typetalk using typetalk API - Send a message to typetalk using typetalk API.
extends_documentation_fragment: extends_documentation_fragment:
- community.general.attributes - community.general.attributes
attributes: attributes:
@ -26,35 +25,35 @@ options:
client_id: client_id:
type: str type: str
description: description:
- OAuth2 client ID - OAuth2 client ID.
required: true required: true
client_secret: client_secret:
type: str type: str
description: description:
- OAuth2 client secret - OAuth2 client secret.
required: true required: true
topic: topic:
type: int type: int
description: description:
- topic id to post message - Topic id to post message.
required: true required: true
msg: msg:
type: str type: str
description: description:
- message body - Message body.
required: true required: true
requirements: [ json ] requirements: [json]
author: "Takashi Someda (@tksmd)" author: "Takashi Someda (@tksmd)"
''' """
EXAMPLES = ''' EXAMPLES = r"""
- name: Send a message to typetalk - name: Send a message to typetalk
community.general.typetalk: community.general.typetalk:
client_id: 12345 client_id: 12345
client_secret: 12345 client_secret: 12345
topic: 1 topic: 1
msg: install completed msg: install completed
''' """
import json import json