text:
# This file is auto-generated by AWSMetadata.jl
using AWS
using AWS.AWSServices: ecr
using AWS.Compat
using AWS.UUIDs

"""
    batch_check_layer_availability(layer_digests, repository_name)
    batch_check_layer_availability(layer_digests, repository_name, params::Dict{String,<:Any})

Checks the availability of one or more image layers in a repository. When an image is
pushed to a repository, each image layer is checked to verify if it has been uploaded
before. If it has been uploaded, then the image layer is skipped.  This operation is used
by the Amazon ECR proxy and is not generally used by customers for pulling and pushing
images. In most cases, you should use the docker CLI to pull, tag, and push images.

# Arguments
- `layer_digests`: The digests of the image layers to check.
- `repository_name`: The name of the repository that is associated with the image layers to
  check.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"registryId"`: The Amazon Web Services account ID associated with the registry that
  contains the image layers to check. If you do not specify a registry, the default registry
  is assumed.
"""
function batch_check_layer_availability(
    layerDigests, repositoryName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "BatchCheckLayerAvailability",
        Dict{String,Any}(
            "layerDigests" => layerDigests, "repositoryName" => repositoryName
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function batch_check_layer_availability(
    layerDigests,
    repositoryName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "BatchCheckLayerAvailability",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "layerDigests" => layerDigests, "repositoryName" => repositoryName
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    batch_delete_image(image_ids, repository_name)
    batch_delete_image(image_ids, repository_name, params::Dict{String,<:Any})

Deletes a list of specified images within a repository. Images are specified with either an
imageTag or imageDigest. You can remove a tag from an image by specifying the image's tag
in your request. When you remove the last tag from an image, the image is deleted from your
repository. You can completely delete an image (and all of its tags) by specifying the
image's digest in your request.

# Arguments
- `image_ids`: A list of image ID references that correspond to images to delete. The
  format of the imageIds reference is imageTag=tag or imageDigest=digest.
- `repository_name`: The repository that contains the image to delete.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"registryId"`: The Amazon Web Services account ID associated with the registry that
  contains the image to delete. If you do not specify a registry, the default registry is
  assumed.
"""
function batch_delete_image(
    imageIds, repositoryName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "BatchDeleteImage",
        Dict{String,Any}("imageIds" => imageIds, "repositoryName" => repositoryName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function batch_delete_image(
    imageIds,
    repositoryName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "BatchDeleteImage",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "imageIds" => imageIds, "repositoryName" => repositoryName
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    batch_get_image(image_ids, repository_name)
    batch_get_image(image_ids, repository_name, params::Dict{String,<:Any})

Gets detailed information for an image. Images are specified with either an imageTag or
imageDigest. When an image is pulled, the BatchGetImage API is called once to retrieve the
image manifest.

# Arguments
- `image_ids`: A list of image ID references that correspond to images to describe. The
  format of the imageIds reference is imageTag=tag or imageDigest=digest.
- `repository_name`: The repository that contains the images to describe.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"acceptedMediaTypes"`: The accepted media types for the request. Valid values:
  application/vnd.docker.distribution.manifest.v1+json |
  application/vnd.docker.distribution.manifest.v2+json |
  application/vnd.oci.image.manifest.v1+json
- `"registryId"`: The Amazon Web Services account ID associated with the registry that
  contains the images to describe. If you do not specify a registry, the default registry is
  assumed.
"""
function batch_get_image(
    imageIds, repositoryName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "BatchGetImage",
        Dict{String,Any}("imageIds" => imageIds, "repositoryName" => repositoryName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function batch_get_image(
    imageIds,
    repositoryName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "BatchGetImage",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "imageIds" => imageIds, "repositoryName" => repositoryName
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    batch_get_repository_scanning_configuration(repository_names)
    batch_get_repository_scanning_configuration(repository_names, params::Dict{String,<:Any})

Gets the scanning configuration for one or more repositories.

# Arguments
- `repository_names`: One or more repository names to get the scanning configuration for.

"""
function batch_get_repository_scanning_configuration(
    repositoryNames; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "BatchGetRepositoryScanningConfiguration",
        Dict{String,Any}("repositoryNames" => repositoryNames);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function batch_get_repository_scanning_configuration(
    repositoryNames,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "BatchGetRepositoryScanningConfiguration",
        Dict{String,Any}(
            mergewith(
                _merge, Dict{String,Any}("repositoryNames" => repositoryNames), params
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    complete_layer_upload(layer_digests, repository_name, upload_id)
    complete_layer_upload(layer_digests, repository_name, upload_id, params::Dict{String,<:Any})

Informs Amazon ECR that the image layer upload has completed for a specified registry,
repository name, and upload ID. You can optionally provide a sha256 digest of the image
layer for data validation purposes. When an image is pushed, the CompleteLayerUpload API is
called once per each new image layer to verify that the upload has completed.  This
operation is used by the Amazon ECR proxy and is not generally used by customers for
pulling and pushing images. In most cases, you should use the docker CLI to pull, tag, and
push images.

# Arguments
- `layer_digests`: The sha256 digest of the image layer.
- `repository_name`: The name of the repository to associate with the image layer.
- `upload_id`: The upload ID from a previous InitiateLayerUpload operation to associate
  with the image layer.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"registryId"`: The Amazon Web Services account ID associated with the registry to which
  to upload layers. If you do not specify a registry, the default registry is assumed.
"""
function complete_layer_upload(
    layerDigests,
    repositoryName,
    uploadId;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "CompleteLayerUpload",
        Dict{String,Any}(
            "layerDigests" => layerDigests,
            "repositoryName" => repositoryName,
            "uploadId" => uploadId,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function complete_layer_upload(
    layerDigests,
    repositoryName,
    uploadId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "CompleteLayerUpload",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "layerDigests" => layerDigests,
                    "repositoryName" => repositoryName,
                    "uploadId" => uploadId,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    create_pull_through_cache_rule(ecr_repository_prefix, upstream_registry_url)
    create_pull_through_cache_rule(ecr_repository_prefix, upstream_registry_url, params::Dict{String,<:Any})

Creates a pull through cache rule. A pull through cache rule provides a way to cache images
from an external public registry in your Amazon ECR private registry.

# Arguments
- `ecr_repository_prefix`: The repository name prefix to use when caching images from the
  source registry.
- `upstream_registry_url`: The registry URL of the upstream public registry to use as the
  source for the pull through cache rule.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"registryId"`: The Amazon Web Services account ID associated with the registry to create
  the pull through cache rule for. If you do not specify a registry, the default registry is
  assumed.
"""
function create_pull_through_cache_rule(
    ecrRepositoryPrefix,
    upstreamRegistryUrl;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "CreatePullThroughCacheRule",
        Dict{String,Any}(
            "ecrRepositoryPrefix" => ecrRepositoryPrefix,
            "upstreamRegistryUrl" => upstreamRegistryUrl,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_pull_through_cache_rule(
    ecrRepositoryPrefix,
    upstreamRegistryUrl,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "CreatePullThroughCacheRule",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "ecrRepositoryPrefix" => ecrRepositoryPrefix,
                    "upstreamRegistryUrl" => upstreamRegistryUrl,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    create_repository(repository_name)
    create_repository(repository_name, params::Dict{String,<:Any})

Creates a repository. For more information, see Amazon ECR repositories in the Amazon
Elastic Container Registry User Guide.

# Arguments
- `repository_name`: The name to use for the repository. The repository name may be
  specified on its own (such as nginx-web-app) or it can be prepended with a namespace to
  group the repository into a category (such as project-a/nginx-web-app).

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"encryptionConfiguration"`: The encryption configuration for the repository. This
  determines how the contents of your repository are encrypted at rest.
- `"imageScanningConfiguration"`: The image scanning configuration for the repository. This
  determines whether images are scanned for known vulnerabilities after being pushed to the
  repository.
- `"imageTagMutability"`: The tag mutability setting for the repository. If this parameter
  is omitted, the default setting of MUTABLE will be used which will allow image tags to be
  overwritten. If IMMUTABLE is specified, all image tags within the repository will be
  immutable which will prevent them from being overwritten.
- `"registryId"`: The Amazon Web Services account ID associated with the registry to create
  the repository. If you do not specify a registry, the default registry is assumed.
- `"tags"`: The metadata that you apply to the repository to help you categorize and
  organize them. Each tag consists of a key and an optional value, both of which you define.
  Tag keys can have a maximum character length of 128 characters, and tag values can have a
  maximum length of 256 characters.
"""
function create_repository(
    repositoryName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "CreateRepository",
        Dict{String,Any}("repositoryName" => repositoryName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_repository(
    repositoryName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "CreateRepository",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("repositoryName" => repositoryName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_lifecycle_policy(repository_name)
    delete_lifecycle_policy(repository_name, params::Dict{String,<:Any})

Deletes the lifecycle policy associated with the specified repository.

# Arguments
- `repository_name`: The name of the repository.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"registryId"`: The Amazon Web Services account ID associated with the registry that
  contains the repository. If you do not specify a registry, the default registry is assumed.
"""
function delete_lifecycle_policy(
    repositoryName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "DeleteLifecyclePolicy",
        Dict{String,Any}("repositoryName" => repositoryName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_lifecycle_policy(
    repositoryName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "DeleteLifecyclePolicy",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("repositoryName" => repositoryName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_pull_through_cache_rule(ecr_repository_prefix)
    delete_pull_through_cache_rule(ecr_repository_prefix, params::Dict{String,<:Any})

Deletes a pull through cache rule.

# Arguments
- `ecr_repository_prefix`: The Amazon ECR repository prefix associated with the pull
  through cache rule to delete.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"registryId"`: The Amazon Web Services account ID associated with the registry that
  contains the pull through cache rule. If you do not specify a registry, the default
  registry is assumed.
"""
function delete_pull_through_cache_rule(
    ecrRepositoryPrefix; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "DeletePullThroughCacheRule",
        Dict{String,Any}("ecrRepositoryPrefix" => ecrRepositoryPrefix);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_pull_through_cache_rule(
    ecrRepositoryPrefix,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "DeletePullThroughCacheRule",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}("ecrRepositoryPrefix" => ecrRepositoryPrefix),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_registry_policy()
    delete_registry_policy(params::Dict{String,<:Any})

Deletes the registry permissions policy.

"""
function delete_registry_policy(; aws_config::AbstractAWSConfig=global_aws_config())
    return ecr(
        "DeleteRegistryPolicy"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end
function delete_registry_policy(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "DeleteRegistryPolicy",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_repository(repository_name)
    delete_repository(repository_name, params::Dict{String,<:Any})

Deletes a repository. If the repository contains images, you must either delete all images
in the repository or use the force option to delete the repository.

# Arguments
- `repository_name`: The name of the repository to delete.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"force"`:  If a repository contains images, forces the deletion.
- `"registryId"`: The Amazon Web Services account ID associated with the registry that
  contains the repository to delete. If you do not specify a registry, the default registry
  is assumed.
"""
function delete_repository(
    repositoryName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "DeleteRepository",
        Dict{String,Any}("repositoryName" => repositoryName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_repository(
    repositoryName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "DeleteRepository",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("repositoryName" => repositoryName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_repository_policy(repository_name)
    delete_repository_policy(repository_name, params::Dict{String,<:Any})

Deletes the repository policy associated with the specified repository.

# Arguments
- `repository_name`: The name of the repository that is associated with the repository
  policy to delete.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"registryId"`: The Amazon Web Services account ID associated with the registry that
  contains the repository policy to delete. If you do not specify a registry, the default
  registry is assumed.
"""
function delete_repository_policy(
    repositoryName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "DeleteRepositoryPolicy",
        Dict{String,Any}("repositoryName" => repositoryName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_repository_policy(
    repositoryName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "DeleteRepositoryPolicy",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("repositoryName" => repositoryName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    describe_image_replication_status(image_id, repository_name)
    describe_image_replication_status(image_id, repository_name, params::Dict{String,<:Any})

Returns the replication status for a specified image.

# Arguments
- `image_id`:
- `repository_name`: The name of the repository that the image is in.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"registryId"`: The Amazon Web Services account ID associated with the registry. If you
  do not specify a registry, the default registry is assumed.
"""
function describe_image_replication_status(
    imageId, repositoryName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "DescribeImageReplicationStatus",
        Dict{String,Any}("imageId" => imageId, "repositoryName" => repositoryName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function describe_image_replication_status(
    imageId,
    repositoryName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "DescribeImageReplicationStatus",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}("imageId" => imageId, "repositoryName" => repositoryName),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    describe_image_scan_findings(image_id, repository_name)
    describe_image_scan_findings(image_id, repository_name, params::Dict{String,<:Any})

Returns the scan findings for the specified image.

# Arguments
- `image_id`:
- `repository_name`: The repository for the image for which to describe the scan findings.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of image scan results returned by
  DescribeImageScanFindings in paginated output. When this parameter is used,
  DescribeImageScanFindings only returns maxResults results in a single page along with a
  nextToken response element. The remaining results of the initial request can be seen by
  sending another DescribeImageScanFindings request with the returned nextToken value. This
  value can be between 1 and 1000. If this parameter is not used, then
  DescribeImageScanFindings returns up to 100 results and a nextToken value, if applicable.
- `"nextToken"`: The nextToken value returned from a previous paginated
  DescribeImageScanFindings request where maxResults was used and the results exceeded the
  value of that parameter. Pagination continues from the end of the previous results that
  returned the nextToken value. This value is null when there are no more results to return.
- `"registryId"`: The Amazon Web Services account ID associated with the registry that
  contains the repository in which to describe the image scan findings for. If you do not
  specify a registry, the default registry is assumed.
"""
function describe_image_scan_findings(
    imageId, repositoryName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "DescribeImageScanFindings",
        Dict{String,Any}("imageId" => imageId, "repositoryName" => repositoryName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function describe_image_scan_findings(
    imageId,
    repositoryName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "DescribeImageScanFindings",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}("imageId" => imageId, "repositoryName" => repositoryName),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    describe_images(repository_name)
    describe_images(repository_name, params::Dict{String,<:Any})

Returns metadata about the images in a repository.  Beginning with Docker version 1.9, the
Docker client compresses image layers before pushing them to a V2 Docker registry. The
output of the docker images command shows the uncompressed image size, so it may return a
larger image size than the image sizes returned by DescribeImages.

# Arguments
- `repository_name`: The repository that contains the images to describe.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"filter"`: The filter key and value with which to filter your DescribeImages results.
- `"imageIds"`: The list of image IDs for the requested repository.
- `"maxResults"`: The maximum number of repository results returned by DescribeImages in
  paginated output. When this parameter is used, DescribeImages only returns maxResults
  results in a single page along with a nextToken response element. The remaining results of
  the initial request can be seen by sending another DescribeImages request with the returned
  nextToken value. This value can be between 1 and 1000. If this parameter is not used, then
  DescribeImages returns up to 100 results and a nextToken value, if applicable. This option
  cannot be used when you specify images with imageIds.
- `"nextToken"`: The nextToken value returned from a previous paginated DescribeImages
  request where maxResults was used and the results exceeded the value of that parameter.
  Pagination continues from the end of the previous results that returned the nextToken
  value. This value is null when there are no more results to return. This option cannot be
  used when you specify images with imageIds.
- `"registryId"`: The Amazon Web Services account ID associated with the registry that
  contains the repository in which to describe images. If you do not specify a registry, the
  default registry is assumed.
"""
function describe_images(repositoryName; aws_config::AbstractAWSConfig=global_aws_config())
    return ecr(
        "DescribeImages",
        Dict{String,Any}("repositoryName" => repositoryName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function describe_images(
    repositoryName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "DescribeImages",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("repositoryName" => repositoryName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    describe_pull_through_cache_rules()
    describe_pull_through_cache_rules(params::Dict{String,<:Any})

Returns the pull through cache rules for a registry.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"ecrRepositoryPrefixes"`: The Amazon ECR repository prefixes associated with the pull
  through cache rules to return. If no repository prefix value is specified, all pull through
  cache rules are returned.
- `"maxResults"`: The maximum number of pull through cache rules returned by
  DescribePullThroughCacheRulesRequest in paginated output. When this parameter is used,
  DescribePullThroughCacheRulesRequest only returns maxResults results in a single page along
  with a nextToken response element. The remaining results of the initial request can be seen
  by sending another DescribePullThroughCacheRulesRequest request with the returned nextToken
  value. This value can be between 1 and 1000. If this parameter is not used, then
  DescribePullThroughCacheRulesRequest returns up to 100 results and a nextToken value, if
  applicable.
- `"nextToken"`: The nextToken value returned from a previous paginated
  DescribePullThroughCacheRulesRequest request where maxResults was used and the results
  exceeded the value of that parameter. Pagination continues from the end of the previous
  results that returned the nextToken value. This value is null when there are no more
  results to return.
- `"registryId"`: The Amazon Web Services account ID associated with the registry to return
  the pull through cache rules for. If you do not specify a registry, the default registry is
  assumed.
"""
function describe_pull_through_cache_rules(;
    aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "DescribePullThroughCacheRules";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function describe_pull_through_cache_rules(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "DescribePullThroughCacheRules",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    describe_registry()
    describe_registry(params::Dict{String,<:Any})

Describes the settings for a registry. The replication configuration for a repository can
be created or updated with the PutReplicationConfiguration API action.

"""
function describe_registry(; aws_config::AbstractAWSConfig=global_aws_config())
    return ecr("DescribeRegistry"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET)
end
function describe_registry(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "DescribeRegistry", params; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end

"""
    describe_repositories()
    describe_repositories(params::Dict{String,<:Any})

Describes image repositories in a registry.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of repository results returned by DescribeRepositories
  in paginated output. When this parameter is used, DescribeRepositories only returns
  maxResults results in a single page along with a nextToken response element. The remaining
  results of the initial request can be seen by sending another DescribeRepositories request
  with the returned nextToken value. This value can be between 1 and 1000. If this parameter
  is not used, then DescribeRepositories returns up to 100 results and a nextToken value, if
  applicable. This option cannot be used when you specify repositories with repositoryNames.
- `"nextToken"`: The nextToken value returned from a previous paginated
  DescribeRepositories request where maxResults was used and the results exceeded the value
  of that parameter. Pagination continues from the end of the previous results that returned
  the nextToken value. This value is null when there are no more results to return. This
  option cannot be used when you specify repositories with repositoryNames.  This token
  should be treated as an opaque identifier that is only used to retrieve the next items in a
  list and not for other programmatic purposes.
- `"registryId"`: The Amazon Web Services account ID associated with the registry that
  contains the repositories to be described. If you do not specify a registry, the default
  registry is assumed.
- `"repositoryNames"`: A list of repositories to describe. If this parameter is omitted,
  then all repositories in a registry are described.
"""
function describe_repositories(; aws_config::AbstractAWSConfig=global_aws_config())
    return ecr(
        "DescribeRepositories"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end
function describe_repositories(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "DescribeRepositories",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_authorization_token()
    get_authorization_token(params::Dict{String,<:Any})

Retrieves an authorization token. An authorization token represents your IAM authentication
credentials and can be used to access any Amazon ECR registry that your IAM principal has
access to. The authorization token is valid for 12 hours. The authorizationToken returned
is a base64 encoded string that can be decoded and used in a docker login command to
authenticate to a registry. The CLI offers an get-login-password command that simplifies
the login process. For more information, see Registry authentication in the Amazon Elastic
Container Registry User Guide.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"registryIds"`: A list of Amazon Web Services account IDs that are associated with the
  registries for which to get AuthorizationData objects. If you do not specify a registry,
  the default registry is assumed.
"""
function get_authorization_token(; aws_config::AbstractAWSConfig=global_aws_config())
    return ecr(
        "GetAuthorizationToken"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end
function get_authorization_token(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "GetAuthorizationToken",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_download_url_for_layer(layer_digest, repository_name)
    get_download_url_for_layer(layer_digest, repository_name, params::Dict{String,<:Any})

Retrieves the pre-signed Amazon S3 download URL corresponding to an image layer. You can
only get URLs for image layers that are referenced in an image. When an image is pulled,
the GetDownloadUrlForLayer API is called once per image layer that is not already cached.
This operation is used by the Amazon ECR proxy and is not generally used by customers for
pulling and pushing images. In most cases, you should use the docker CLI to pull, tag, and
push images.

# Arguments
- `layer_digest`: The digest of the image layer to download.
- `repository_name`: The name of the repository that is associated with the image layer to
  download.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"registryId"`: The Amazon Web Services account ID associated with the registry that
  contains the image layer to download. If you do not specify a registry, the default
  registry is assumed.
"""
function get_download_url_for_layer(
    layerDigest, repositoryName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "GetDownloadUrlForLayer",
        Dict{String,Any}("layerDigest" => layerDigest, "repositoryName" => repositoryName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_download_url_for_layer(
    layerDigest,
    repositoryName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "GetDownloadUrlForLayer",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "layerDigest" => layerDigest, "repositoryName" => repositoryName
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_lifecycle_policy(repository_name)
    get_lifecycle_policy(repository_name, params::Dict{String,<:Any})

Retrieves the lifecycle policy for the specified repository.

# Arguments
- `repository_name`: The name of the repository.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"registryId"`: The Amazon Web Services account ID associated with the registry that
  contains the repository. If you do not specify a registry, the default registry is assumed.
"""
function get_lifecycle_policy(
    repositoryName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "GetLifecyclePolicy",
        Dict{String,Any}("repositoryName" => repositoryName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_lifecycle_policy(
    repositoryName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "GetLifecyclePolicy",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("repositoryName" => repositoryName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_lifecycle_policy_preview(repository_name)
    get_lifecycle_policy_preview(repository_name, params::Dict{String,<:Any})

Retrieves the results of the lifecycle policy preview request for the specified repository.

# Arguments
- `repository_name`: The name of the repository.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"filter"`: An optional parameter that filters results based on image tag status and all
  tags, if tagged.
- `"imageIds"`: The list of imageIDs to be included.
- `"maxResults"`: The maximum number of repository results returned by
  GetLifecyclePolicyPreviewRequest in
 paginated output. When this parameter is used,
  GetLifecyclePolicyPreviewRequest only returns
 maxResults results in a single page
  along with a nextToken
 response element. The remaining results of the initial
  request can be seen by sending
 another GetLifecyclePolicyPreviewRequest request
  with the returned nextToken
 value. This value can be between 1 and 1000. If
  this
 parameter is not used, then GetLifecyclePolicyPreviewRequest returns up
  to
 100 results and a nextToken value, if
 applicable. This option cannot be
  used when you specify images with imageIds.
- `"nextToken"`: The nextToken value returned from a previous paginated

  GetLifecyclePolicyPreviewRequest request where maxResults was used and the
 results
  exceeded the value of that parameter. Pagination continues from the end of the

  previous results that returned the nextToken value. This value is
 null when there
  are no more results to return. This option cannot be used when you specify images with
  imageIds.
- `"registryId"`: The Amazon Web Services account ID associated with the registry that
  contains the repository. If you do not specify a registry, the default registry is assumed.
"""
function get_lifecycle_policy_preview(
    repositoryName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "GetLifecyclePolicyPreview",
        Dict{String,Any}("repositoryName" => repositoryName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_lifecycle_policy_preview(
    repositoryName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "GetLifecyclePolicyPreview",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("repositoryName" => repositoryName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_registry_policy()
    get_registry_policy(params::Dict{String,<:Any})

Retrieves the permissions policy for a registry.

"""
function get_registry_policy(; aws_config::AbstractAWSConfig=global_aws_config())
    return ecr("GetRegistryPolicy"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET)
end
function get_registry_policy(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "GetRegistryPolicy", params; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end

"""
    get_registry_scanning_configuration()
    get_registry_scanning_configuration(params::Dict{String,<:Any})

Retrieves the scanning configuration for a registry.

"""
function get_registry_scanning_configuration(;
    aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "GetRegistryScanningConfiguration";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_registry_scanning_configuration(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "GetRegistryScanningConfiguration",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_repository_policy(repository_name)
    get_repository_policy(repository_name, params::Dict{String,<:Any})

Retrieves the repository policy for the specified repository.

# Arguments
- `repository_name`: The name of the repository with the policy to retrieve.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"registryId"`: The Amazon Web Services account ID associated with the registry that
  contains the repository. If you do not specify a registry, the default registry is assumed.
"""
function get_repository_policy(
    repositoryName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "GetRepositoryPolicy",
        Dict{String,Any}("repositoryName" => repositoryName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_repository_policy(
    repositoryName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "GetRepositoryPolicy",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("repositoryName" => repositoryName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    initiate_layer_upload(repository_name)
    initiate_layer_upload(repository_name, params::Dict{String,<:Any})

Notifies Amazon ECR that you intend to upload an image layer. When an image is pushed, the
InitiateLayerUpload API is called once per image layer that has not already been uploaded.
Whether or not an image layer has been uploaded is determined by the
BatchCheckLayerAvailability API action.  This operation is used by the Amazon ECR proxy and
is not generally used by customers for pulling and pushing images. In most cases, you
should use the docker CLI to pull, tag, and push images.

# Arguments
- `repository_name`: The name of the repository to which you intend to upload layers.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"registryId"`: The Amazon Web Services account ID associated with the registry to which
  you intend to upload layers. If you do not specify a registry, the default registry is
  assumed.
"""
function initiate_layer_upload(
    repositoryName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "InitiateLayerUpload",
        Dict{String,Any}("repositoryName" => repositoryName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function initiate_layer_upload(
    repositoryName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "InitiateLayerUpload",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("repositoryName" => repositoryName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_images(repository_name)
    list_images(repository_name, params::Dict{String,<:Any})

Lists all the image IDs for the specified repository. You can filter images based on
whether or not they are tagged by using the tagStatus filter and specifying either TAGGED,
UNTAGGED or ANY. For example, you can filter your results to return only UNTAGGED images
and then pipe that result to a BatchDeleteImage operation to delete them. Or, you can
filter your results to return only TAGGED images to list all of the tags in your repository.

# Arguments
- `repository_name`: The repository with image IDs to be listed.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"filter"`: The filter key and value with which to filter your ListImages results.
- `"maxResults"`: The maximum number of image results returned by ListImages in paginated
  output. When this parameter is used, ListImages only returns maxResults results in a single
  page along with a nextToken response element. The remaining results of the initial request
  can be seen by sending another ListImages request with the returned nextToken value. This
  value can be between 1 and 1000. If this parameter is not used, then ListImages returns up
  to 100 results and a nextToken value, if applicable.
- `"nextToken"`: The nextToken value returned from a previous paginated ListImages request
  where maxResults was used and the results exceeded the value of that parameter. Pagination
  continues from the end of the previous results that returned the nextToken value. This
  value is null when there are no more results to return.  This token should be treated as an
  opaque identifier that is only used to retrieve the next items in a list and not for other
  programmatic purposes.
- `"registryId"`: The Amazon Web Services account ID associated with the registry that
  contains the repository in which to list images. If you do not specify a registry, the
  default registry is assumed.
"""
function list_images(repositoryName; aws_config::AbstractAWSConfig=global_aws_config())
    return ecr(
        "ListImages",
        Dict{String,Any}("repositoryName" => repositoryName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_images(
    repositoryName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "ListImages",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("repositoryName" => repositoryName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_tags_for_resource(resource_arn)
    list_tags_for_resource(resource_arn, params::Dict{String,<:Any})

List the tags for an Amazon ECR resource.

# Arguments
- `resource_arn`: The Amazon Resource Name (ARN) that identifies the resource for which to
  list the tags. Currently, the only supported resource is an Amazon ECR repository.

"""
function list_tags_for_resource(
    resourceArn; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "ListTagsForResource",
        Dict{String,Any}("resourceArn" => resourceArn);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_tags_for_resource(
    resourceArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "ListTagsForResource",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("resourceArn" => resourceArn), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    put_image(image_manifest, repository_name)
    put_image(image_manifest, repository_name, params::Dict{String,<:Any})

Creates or updates the image manifest and tags associated with an image. When an image is
pushed and all new image layers have been uploaded, the PutImage API is called once to
create or update the image manifest and the tags associated with the image.  This operation
is used by the Amazon ECR proxy and is not generally used by customers for pulling and
pushing images. In most cases, you should use the docker CLI to pull, tag, and push images.

# Arguments
- `image_manifest`: The image manifest corresponding to the image to be uploaded.
- `repository_name`: The name of the repository in which to put the image.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"imageDigest"`: The image digest of the image manifest corresponding to the image.
- `"imageManifestMediaType"`: The media type of the image manifest. If you push an image
  manifest that does not contain the mediaType field, you must specify the
  imageManifestMediaType in the request.
- `"imageTag"`: The tag to associate with the image. This parameter is required for images
  that use the Docker Image Manifest V2 Schema 2 or Open Container Initiative (OCI) formats.
- `"registryId"`: The Amazon Web Services account ID associated with the registry that
  contains the repository in which to put the image. If you do not specify a registry, the
  default registry is assumed.
"""
function put_image(
    imageManifest, repositoryName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "PutImage",
        Dict{String,Any}(
            "imageManifest" => imageManifest, "repositoryName" => repositoryName
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function put_image(
    imageManifest,
    repositoryName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "PutImage",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "imageManifest" => imageManifest, "repositoryName" => repositoryName
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    put_image_scanning_configuration(image_scanning_configuration, repository_name)
    put_image_scanning_configuration(image_scanning_configuration, repository_name, params::Dict{String,<:Any})

Updates the image scanning configuration for the specified repository.

# Arguments
- `image_scanning_configuration`: The image scanning configuration for the repository. This
  setting determines whether images are scanned for known vulnerabilities after being pushed
  to the repository.
- `repository_name`: The name of the repository in which to update the image scanning
  configuration setting.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"registryId"`: The Amazon Web Services account ID associated with the registry that
  contains the repository in which to update the image scanning configuration setting. If you
  do not specify a registry, the default registry is assumed.
"""
function put_image_scanning_configuration(
    imageScanningConfiguration,
    repositoryName;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "PutImageScanningConfiguration",
        Dict{String,Any}(
            "imageScanningConfiguration" => imageScanningConfiguration,
            "repositoryName" => repositoryName,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function put_image_scanning_configuration(
    imageScanningConfiguration,
    repositoryName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "PutImageScanningConfiguration",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "imageScanningConfiguration" => imageScanningConfiguration,
                    "repositoryName" => repositoryName,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    put_image_tag_mutability(image_tag_mutability, repository_name)
    put_image_tag_mutability(image_tag_mutability, repository_name, params::Dict{String,<:Any})

Updates the image tag mutability settings for the specified repository. For more
information, see Image tag mutability in the Amazon Elastic Container Registry User Guide.

# Arguments
- `image_tag_mutability`: The tag mutability setting for the repository. If MUTABLE is
  specified, image tags can be overwritten. If IMMUTABLE is specified, all image tags within
  the repository will be immutable which will prevent them from being overwritten.
- `repository_name`: The name of the repository in which to update the image tag mutability
  settings.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"registryId"`: The Amazon Web Services account ID associated with the registry that
  contains the repository in which to update the image tag mutability settings. If you do not
  specify a registry, the default registry is assumed.
"""
function put_image_tag_mutability(
    imageTagMutability, repositoryName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "PutImageTagMutability",
        Dict{String,Any}(
            "imageTagMutability" => imageTagMutability, "repositoryName" => repositoryName
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function put_image_tag_mutability(
    imageTagMutability,
    repositoryName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "PutImageTagMutability",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "imageTagMutability" => imageTagMutability,
                    "repositoryName" => repositoryName,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    put_lifecycle_policy(lifecycle_policy_text, repository_name)
    put_lifecycle_policy(lifecycle_policy_text, repository_name, params::Dict{String,<:Any})

Creates or updates the lifecycle policy for the specified repository. For more information,
see Lifecycle policy template.

# Arguments
- `lifecycle_policy_text`: The JSON repository policy text to apply to the repository.
- `repository_name`: The name of the repository to receive the policy.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"registryId"`: The Amazon Web Services account ID associated with the registry that
  contains the repository. If you do
 not specify a registry, the default registry is
  assumed.
"""
function put_lifecycle_policy(
    lifecyclePolicyText, repositoryName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "PutLifecyclePolicy",
        Dict{String,Any}(
            "lifecyclePolicyText" => lifecyclePolicyText, "repositoryName" => repositoryName
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function put_lifecycle_policy(
    lifecyclePolicyText,
    repositoryName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "PutLifecyclePolicy",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "lifecyclePolicyText" => lifecyclePolicyText,
                    "repositoryName" => repositoryName,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    put_registry_policy(policy_text)
    put_registry_policy(policy_text, params::Dict{String,<:Any})

Creates or updates the permissions policy for your registry. A registry policy is used to
specify permissions for another Amazon Web Services account and is used when configuring
cross-account replication. For more information, see Registry permissions in the Amazon
Elastic Container Registry User Guide.

# Arguments
- `policy_text`: The JSON policy text to apply to your registry. The policy text follows
  the same format as IAM policy text. For more information, see Registry permissions in the
  Amazon Elastic Container Registry User Guide.

"""
function put_registry_policy(policyText; aws_config::AbstractAWSConfig=global_aws_config())
    return ecr(
        "PutRegistryPolicy",
        Dict{String,Any}("policyText" => policyText);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function put_registry_policy(
    policyText,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "PutRegistryPolicy",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("policyText" => policyText), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    put_registry_scanning_configuration()
    put_registry_scanning_configuration(params::Dict{String,<:Any})

Creates or updates the scanning configuration for your private registry.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"rules"`: The scanning rules to use for the registry. A scanning rule is used to
  determine which repository filters are used and at what frequency scanning will occur.
- `"scanType"`: The scanning type to set for the registry. By default, the BASIC scan type
  is used. When basic scanning is set, you may specify filters to determine which individual
  repositories, or all repositories, are scanned when new images are pushed. Alternatively,
  you can do manual scans of images with basic scanning. When the ENHANCED scan type is set,
  Amazon Inspector provides automated, continuous scanning of all repositories in your
  registry.
"""
function put_registry_scanning_configuration(;
    aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "PutRegistryScanningConfiguration";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function put_registry_scanning_configuration(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "PutRegistryScanningConfiguration",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    put_replication_configuration(replication_configuration)
    put_replication_configuration(replication_configuration, params::Dict{String,<:Any})

Creates or updates the replication configuration for a registry. The existing replication
configuration for a repository can be retrieved with the DescribeRegistry API action. The
first time the PutReplicationConfiguration API is called, a service-linked IAM role is
created in your account for the replication process. For more information, see Using
service-linked roles for Amazon ECR in the Amazon Elastic Container Registry User Guide.
When configuring cross-account replication, the destination account must grant the source
account permission to replicate. This permission is controlled using a registry permissions
policy. For more information, see PutRegistryPolicy.

# Arguments
- `replication_configuration`: An object representing the replication configuration for a
  registry.

"""
function put_replication_configuration(
    replicationConfiguration; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "PutReplicationConfiguration",
        Dict{String,Any}("replicationConfiguration" => replicationConfiguration);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function put_replication_configuration(
    replicationConfiguration,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "PutReplicationConfiguration",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}("replicationConfiguration" => replicationConfiguration),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    set_repository_policy(policy_text, repository_name)
    set_repository_policy(policy_text, repository_name, params::Dict{String,<:Any})

Applies a repository policy to the specified repository to control access permissions. For
more information, see Amazon ECR Repository policies in the Amazon Elastic Container
Registry User Guide.

# Arguments
- `policy_text`: The JSON repository policy text to apply to the repository. For more
  information, see Amazon ECR repository policies in the Amazon Elastic Container Registry
  User Guide.
- `repository_name`: The name of the repository to receive the policy.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"force"`: If the policy you are attempting to set on a repository policy would prevent
  you from setting another policy in the future, you must force the SetRepositoryPolicy
  operation. This is intended to prevent accidental repository lock outs.
- `"registryId"`: The Amazon Web Services account ID associated with the registry that
  contains the repository. If you do not specify a registry, the default registry is assumed.
"""
function set_repository_policy(
    policyText, repositoryName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "SetRepositoryPolicy",
        Dict{String,Any}("policyText" => policyText, "repositoryName" => repositoryName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function set_repository_policy(
    policyText,
    repositoryName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "SetRepositoryPolicy",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "policyText" => policyText, "repositoryName" => repositoryName
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    start_image_scan(image_id, repository_name)
    start_image_scan(image_id, repository_name, params::Dict{String,<:Any})

Starts an image vulnerability scan. An image scan can only be started once per 24 hours on
an individual image. This limit includes if an image was scanned on initial push. For more
information, see Image scanning in the Amazon Elastic Container Registry User Guide.

# Arguments
- `image_id`:
- `repository_name`: The name of the repository that contains the images to scan.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"registryId"`: The Amazon Web Services account ID associated with the registry that
  contains the repository in which to start an image scan request. If you do not specify a
  registry, the default registry is assumed.
"""
function start_image_scan(
    imageId, repositoryName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "StartImageScan",
        Dict{String,Any}("imageId" => imageId, "repositoryName" => repositoryName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function start_image_scan(
    imageId,
    repositoryName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "StartImageScan",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}("imageId" => imageId, "repositoryName" => repositoryName),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    start_lifecycle_policy_preview(repository_name)
    start_lifecycle_policy_preview(repository_name, params::Dict{String,<:Any})

Starts a preview of a lifecycle policy for the specified repository. This allows you to see
the results before associating the lifecycle policy with the repository.

# Arguments
- `repository_name`: The name of the repository to be evaluated.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"lifecyclePolicyText"`: The policy to be evaluated against. If you do not specify a
  policy, the current policy for the repository is used.
- `"registryId"`: The Amazon Web Services account ID associated with the registry that
  contains the repository. If you do not specify a registry, the default registry is assumed.
"""
function start_lifecycle_policy_preview(
    repositoryName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "StartLifecyclePolicyPreview",
        Dict{String,Any}("repositoryName" => repositoryName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function start_lifecycle_policy_preview(
    repositoryName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "StartLifecyclePolicyPreview",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("repositoryName" => repositoryName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    tag_resource(resource_arn, tags)
    tag_resource(resource_arn, tags, params::Dict{String,<:Any})

Adds specified tags to a resource with the specified ARN. Existing tags on a resource are
not changed if they are not specified in the request parameters.

# Arguments
- `resource_arn`: The Amazon Resource Name (ARN) of the the resource to which to add tags.
  Currently, the only supported resource is an Amazon ECR repository.
- `tags`: The tags to add to the resource. A tag is an array of key-value pairs. Tag keys
  can have a maximum character length of 128 characters, and tag values can have a maximum
  length of 256 characters.

"""
function tag_resource(resourceArn, tags; aws_config::AbstractAWSConfig=global_aws_config())
    return ecr(
        "TagResource",
        Dict{String,Any}("resourceArn" => resourceArn, "tags" => tags);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function tag_resource(
    resourceArn,
    tags,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "TagResource",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}("resourceArn" => resourceArn, "tags" => tags),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    untag_resource(resource_arn, tag_keys)
    untag_resource(resource_arn, tag_keys, params::Dict{String,<:Any})

Deletes specified tags from a resource.

# Arguments
- `resource_arn`: The Amazon Resource Name (ARN) of the resource from which to remove tags.
  Currently, the only supported resource is an Amazon ECR repository.
- `tag_keys`: The keys of the tags to be removed.

"""
function untag_resource(
    resourceArn, tagKeys; aws_config::AbstractAWSConfig=global_aws_config()
)
    return ecr(
        "UntagResource",
        Dict{String,Any}("resourceArn" => resourceArn, "tagKeys" => tagKeys);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function untag_resource(
    resourceArn,
    tagKeys,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "UntagResource",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}("resourceArn" => resourceArn, "tagKeys" => tagKeys),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    upload_layer_part(layer_part_blob, part_first_byte, part_last_byte, repository_name, upload_id)
    upload_layer_part(layer_part_blob, part_first_byte, part_last_byte, repository_name, upload_id, params::Dict{String,<:Any})

Uploads an image layer part to Amazon ECR. When an image is pushed, each new image layer is
uploaded in parts. The maximum size of each image layer part can be 20971520 bytes (or
about 20MB). The UploadLayerPart API is called once per each new image layer part.  This
operation is used by the Amazon ECR proxy and is not generally used by customers for
pulling and pushing images. In most cases, you should use the docker CLI to pull, tag, and
push images.

# Arguments
- `layer_part_blob`: The base64-encoded layer part payload.
- `part_first_byte`: The position of the first byte of the layer part witin the overall
  image layer.
- `part_last_byte`: The position of the last byte of the layer part within the overall
  image layer.
- `repository_name`: The name of the repository to which you are uploading layer parts.
- `upload_id`: The upload ID from a previous InitiateLayerUpload operation to associate
  with the layer part upload.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"registryId"`: The Amazon Web Services account ID associated with the registry to which
  you are uploading layer parts. If you do not specify a registry, the default registry is
  assumed.
"""
function upload_layer_part(
    layerPartBlob,
    partFirstByte,
    partLastByte,
    repositoryName,
    uploadId;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "UploadLayerPart",
        Dict{String,Any}(
            "layerPartBlob" => layerPartBlob,
            "partFirstByte" => partFirstByte,
            "partLastByte" => partLastByte,
            "repositoryName" => repositoryName,
            "uploadId" => uploadId,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function upload_layer_part(
    layerPartBlob,
    partFirstByte,
    partLastByte,
    repositoryName,
    uploadId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return ecr(
        "UploadLayerPart",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "layerPartBlob" => layerPartBlob,
                    "partFirstByte" => partFirstByte,
                    "partLastByte" => partLastByte,
                    "repositoryName" => repositoryName,
                    "uploadId" => uploadId,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end


text:
using Test

@testset "C API" begin
  global ns = 400
  global nd = 100
  include(joinpath(dirname(@__FILE__), "..", "example", "ex4.jl"))
  @test nlp.obj_val ≈ -4.999509728895e+01
end

@testset "MathOptInterface" begin
    include("MOI_wrapper.jl")
end

@testset "ACOPF" begin
    include("acopf.jl")
end

ext: jl


text:
using PkgDeps
using Test
using UUIDs

depot = joinpath(@__DIR__, "resources")

@testset "internal functions" begin
    @testset "_get_pkg_name" begin
        @testset "uuid to name" begin
            expected = "Case1"
            pkg_name = PkgDeps._get_pkg_name(UUID("00000000-1111-2222-3333-444444444444"); depots=depot)

            @test expected == pkg_name
        end

        @testset "exception" begin
            @test_throws NoUUIDMatch PkgDeps._get_pkg_name(UUID("00000000-0000-0000-0000-000000000000"); depots=depot)
        end
    end

    @testset "_get_pkg_uuid" begin
        @testset "name to uuid" begin
            expected = UUID("00000000-1111-2222-3333-444444444444")
            pkg_uuid = PkgDeps._get_pkg_uuid("Case1", "Foobar"; depots=depot)

            @test expected == pkg_uuid
        end

        @testset "exception" begin
            @test_throws PackageNotInRegistry PkgDeps._get_pkg_uuid("FakePackage", "Foobar"; depots=depot)
        end
    end

    @testset "_get_latest_version" begin
        expected = v"0.2.0"
        path = joinpath("resources", "registries", "General", "Case4")
        result = PkgDeps._get_latest_version(path)

        @test expected == result
    end
end

@testset "reachable_registries" begin
    @testset "specfic registry -- $(typeof(v))" for v in ("Foobar", ["Foobar"])
        registry = reachable_registries("Foobar"; depots=depot)

        @test registry.name == "Foobar"
    end

    @testset "all registries" begin
        registries = reachable_registries(; depots=depot)

        @test length(registries) == 2
    end
end

@testset "users" begin
    foobar_registry = reachable_registries("Foobar"; depots=depot)
    all_registries = reachable_registries(; depots=depot)

    @testset "specific registry" begin
        dependents = users("DownDep"; pkg_registry_name="Foobar", depots=depot, registries=[foobar_registry])

        @test length(dependents) == 2
        [@test case in dependents for case in ["Case1", "Case2"]]
    end

    @testset "all registries" begin
        dependents = users("DownDep"; pkg_registry_name="Foobar", depots=depot, registries=all_registries)

        @test length(dependents) == 3
        @test !("Case4" in dependents)
        [@test case in dependents for case in ["Case1", "Case2", "Case3"]]
    end
end


text:
function hammingsequence(N)
    if N < 1
        throw("Hamming sequence exponent must be a positive integer")
    end
    ham = N > 4000 ? Vector{BigInt}([1]) : Vector{Int}([1])
    base2, base3, base5 = (1, 1, 1)
    for i in 1:N-1
        x = min(2ham[base2], 3ham[base3], 5ham[base5])
        push!(ham, x)
        if 2ham[base2] <= x
            base2 += 1
        end
        if 3ham[base3] <= x
            base3 += 1
        end
        if 5ham[base5] <= x
            base5 += 1
        end
    end
    ham
end

println(hammingsequence(20))
println(hammingsequence(1691)[end])
println(hammingsequence(1000000)[end])

max_stars_repo_name: ethansaxenian/RosettaDecode

max_issues_repo_name: ethansaxenian/RosettaDecode

max_forks_repo_name: ethansaxenian/RosettaDecode


text:
function filter_desc{T}(a::CuArray{T}, format=CUDNN_TENSOR_NCHW)
  csize = Cint[size(a,i) for i=ndims(a):-1:1]
  #csize = Cint[size(a,i) for i=1:ndims(a)]
  p = Ptr{Void}[0]
  cudnnCreateFilterDescriptor(p)
  cudnnSetFilterNdDescriptor(p[1], datatype(T), format, ndims(a), csize)
  fd = new(p[1])
  finalizer(fd, cudnnDestroyFilterDescriptor)
  fd
end


text:
function Scarf.Instance(is::InventorySystem, gamma = 1.)
    @assert only(is.bom) isa EndProduct
    @assert only(only(is.bom).sources) isa Supplier
    ep = only(is.bom)
    inv = ep.inventory
    supplier = only(ep.sources)
    market = ep.market
    leadtime = supplier.leadtime.leadtime
    Scarf.Instance(inv.holding_cost.h, market.stockout_cost.b, supplier.order_cost.K,
        supplier.order_cost.c, cv(market.demand_dist), leadtime, rand.(market.forecast_reset[1].itr.xs), gamma,
        backlog = !market.lostsales)
end


text:
using LinearSearch
using Test

tests = [
]

@testset "LinearSearch.jl" begin
    for t in tests
        include("$(t).jl")
    end
end


text:
# adapted from https://github.com/chaaland/EllipseFit.jl by Casey Haaland

using LinearAlgebra

export ParametricFormEllipse, ConicFormEllipse, parametric2conic, conic2parametric

abstract type EllipseForm end

struct ParametricFormEllipse{T<:Real, U<:Real, V<:Real}
    axis_lengths::Array{T}
    center::Array{U}
    ccw_angle::V

    function ParametricFormEllipse(axis_lengths::Array{T}, center::Array{U}, ccw_angle::V) where {T<:Real, U<:Real, V<:Real}
        axis_lengths = vec(axis_lengths)
        center = vec(center)

        if size(center)[1] != 2
            error("Parameter 'center' must be vector of length 2")
        elseif size(axis_lengths)[1] != 2
            error("Parameter 'axis_lengths' must be vector of length 2")
        elseif sum(axis_lengths .< 0) > 0
            error("Parameter 'axis_lengths' must be nonnegative")
        else
            new{T,U,V}(axis_lengths, center, ccw_angle)
        end
    end
end

function parametric2conic(ellipse::ParametricFormEllipse)
    # inputs
    a = ellipse.axis_lengths[1] / 2
    b = ellipse.axis_lengths[2] / 2
    x₀ = ellipse.center[1]
    y₀ = ellipse.center[2]
    θ = deg2rad(ellipse.ccw_angle)

    # outputs
    A = a^2 * sin(θ)^2 + b^2 * cos(θ)^2
    B = 2 * (b^2 - a^2) * sin(θ) * cos(θ)
    C = a^2 * cos(θ)^2 + b^2 * sin(θ)^2
    D = -2 * A * x₀ - B * y₀
    E = -B * x₀ - 2 * C * y₀
    F = A * x₀^2 + B * x₀ * y₀ + C * y₀^2 - a^2 * b^2

    return ConicFormEllipse(A, B, C, D, E, F)
end

struct ConicFormEllipse{T<:Real} <: EllipseForm
    A::T
    B::T
    C::T
    D::T
    E::T
    F::T
    function ConicFormEllipse(A::T, B::T, C::T, D::T, E::T, F::T) where {T<:Real}
        if B ^2 - 4 * A * C >= 0
            error("Discriminant is non-negative. Input does not denote an ellipse")
        end
        new{T}(A, B, C, D, E, F)
    end
end

ConicFormEllipse(A::Real, B::Real, C::Real, D::Real, E::Real, F::Real) = ConicFormEllipse(promote(A, B, C, D, E, F)...)

function conic2parametric(ellipse::ConicFormEllipse)
    # TODO reference the different equations properly

    # mostly from here: https://en.wikipedia.org/wiki/Ellipse#General_ellipse

    #=
    Helper for converting from conic form to parametric form of ellipse
    Given an ellipse in standard conic section form
            A * x^2 + B * x * y + C * y^2 + D * x + E * y + F = 0
    convert it to parametric form
            [x_c y_c] + rot_mat2d(ccw_angle) * [a*cos(theta) b*sin(theta)]
    Args :

    Returns :
        axis_lengths : array of the form [2*a 2*b] where a is half the width
                          and b is half the height (before rotation)
        center : array of the x and y coordinates of the center of the ellipse
        ccw_angle : The counter clockwise angle (in degrees) to rotate the ellipse wrt
                    the positive x-axis
    =#

    A = ellipse.A; B = ellipse.B; C = ellipse.C; D = ellipse.D; E = ellipse.E; F = ellipse.F

    A_Q = [A B/2 D/2; B/2 C E/2; D/2 E/2 F]
    Δ = det(A_Q) # -1/4 * (AE² + CD² + FB² -BDE - 4 * ACF)

    A_33 = [A B/2; B/2 C]
    J = det(A_33) # -1/4 * (B² - 4 * AC)

    I = tr(A_33)

    sq = sqrt((A - C)^2 + B^2)

    #=
    now write the equations (21) and (22) at http://mathworld.wolfram.com/Ellipse.html
    in terms of Δ, J, I and sq --> semiaxes a and b
    =#

    a = sqrt(-2 * Δ * (I + sq)) / (2*J)
    b = sqrt(-2 * Δ * (I - sq)) / (2*J)

    axis_lengths = [2*a 2*b]

    x₀, y₀ = inv(A_33) * [-D/2; -E/2]

    center = [x₀ y₀]

    # all of the angles are mapped onto [-90,90]
    # as the system has a period of 180°
    # i.e. [-280, -100, 80, 260, etc] → 80

    if B == 0
        if A <= C
            θ = 0
        else
            θ = π/2
        end
    else
        θ = atan(1/B * (C - A - sq))
    end

    ccw_angle = rad2deg(θ)

    return ParametricFormEllipse(axis_lengths, center, ccw_angle)
end


text:
#!/usr/bin/env julia
#=
generate a random date (month and day) in a year.
Michael Hirsch, Ph.D.
=#

using Dates

function randomdate(year::Int)
  t = DateTime(year)
  t += Day(rand(0:daysinyear(t)-1))
end

t = randomdate(parse(Int,ARGS[1]))

println(Dates.format(t,"yyyy-mm-dd"))

max_stars_repo_name: scienceopen/sciencedates

max_issues_repo_name: geospace-code/sciencedates

max_forks_repo_name: geospace-code/sciencedates


text:
# # HOMEWORK: Packages
#
#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__notebooks/08_Packages_Homework.ipynb)
#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__notebooks/08_Packages_Homework.ipynb)
#
# Modules and packages are a nice way to organize code. You can read about how
# to deal with packages from the Julia manual
# [Modules](https://pkg.julialang.org/docs/julia/THl1k/1.1.0/manual/modules.html)
# and [Pkg](https://pkg.julialang.org/docs/julia/THl1k/1.1.0/stdlib/Pkg.html#Pkg-1)
# sections and from the
# [package manager documentation.](https://julialang.github.io/Pkg.jl/v1/)
#
# ## PkgTemplates
#
# The quickest and simplest way to create a package is using
# [PkgTemplates](https://github.com/invenia/PkgTemplates.jl). For example,
# this Julia package was generated using the `interactive_template` and
# `generate` functions of `PkgTemplates`.
#
# Also, this package website/documentation and jupyter notebooks are generated
# using [Documenter](https://github.com/JuliaDocs/Documenter.jl)
# and [Literate](https://github.com/fredrikekre/Literate.jl).
#
# #### Homework
#
# Use *PkgTemplates* to create a small *PersonalUtils.jl* package. Include your
# function to read fasta files from the previous homework in your package module
# and add unit tests for it.
#

max_stars_repo_name: diegozea/JuliaForBioinformatics

max_issues_repo_name: diegozea/JuliaForBioinformatics

max_forks_repo_name: diegozea/JuliaForBioinformatics


text:
# Configuration for running simple neutral copy error simulation
#=
Recommended command line to run:
> julia -p 4 -L NeutralEvolution.jl nrun.jl examples/example1
=#
global simtype
@everywhere simtype = 3
export simtype
@everywhere const N = 4        # population size
const mutstddev = 0.04
const ngens = 5
const initial_value = 1.0
const num_trials=3
const record_interval = 1
const use_population = true  # try this both with and without
#const use_population = false
const log_error = false
const wright_fisher_copy = false
const neutral = true


text:
# # `QuantumOps` performance intro

# This notebook introduces some of `QuantumOps` with an emphasis on performance aspects.

import Pkg
Pkg.activate("/home/lapeyre/.julia/gjl-quantum/QuantumOps")

## import all default symbols for interactive demo
using QuantumOps
using BenchmarkTools
import LinearAlgebra
import SparseArrays

## We also import I, X, Y, Z for convenience
using QuantumOps.Paulis: I, X, Y, Z
#----------------------------------------------------------------------------

# ### Pauli
#
# These, `I, X, Y, Z`, are bound to instances of the `Pauli` type, representing single-qubit operators.

(I, X, Y, Z) == Pauli.((0, 1, 2, 3)) ## The '.' broadcasts over the following elements.
#----------------------------------------------------------------------------

# Julia has a large number of standard interfaces and functions for numeric and algebraic types. I follow these when possible. For example, `Matrix` is used to construct a dense, heap-allocated matrix from an object. So I defined a method for it.

print(Matrix.(Pauli.(0:3)))
#----------------------------------------------------------------------------

# `Pauli` is in this type hierarchy.
# #### NOTE: I have removed `AbstractPauli <: AbstractMatrix` because of the danger mentioned below.

Pauli <: AbstractPauli <: AbstractMatrix
#----------------------------------------------------------------------------

# Only a very small amount of code depends on the internals of `Pauli`. Almost everything is coded against `AbstractPauli`. The developer almost never encounters the implementation of `Pauli`, and the user never does.
# But, if you want, you can see it this way.

dump(X)
#----------------------------------------------------------------------------

# #### `AbstractMatrix` danger
# Making `Pauli` an `AbstractMatrix` caused a performance regression found in this notebook. This is very common. Inside some of your code, a fallback method is called rather than what you intended and it converts the object to a dense matrix. It's not clear that using `Pauli <: AbstractMatrix` is worth much in any case.

# The notation `X[i, j]` calls `getindex(X, i, j)` which, for `AbstractPauli`, looks up the elements in stack allocated arrays. This is faster than indexing into a heap allocated (that is, every-day, dynamic) array:

m = rand(2, 2)
@btime $m[1, 1];
#----------------------------------------------------------------------------

@btime X[1, 1];  ## This includes time to look up what matrix corresponds to `X`
#----------------------------------------------------------------------------

# Above, I said that I implemented a method for `Matrix`. But this is only for efficiency. Because `Pauli <: AbstractMatrix`, the fallback method for `Matrix` that constructs the dense matrix using `getindex` would be called if I had not implemented a method.

# Libraries such as `LinearAlgebra` and `SparseArrays` accept `X` because it is an `AbstractMatrix` and implements a bit of the interface, such as `getindex`. For example:

Y * rand(2, 2)
#----------------------------------------------------------------------------

## The following fails because it is no longer true that AbstractPauli <: AbstractMatrix
## LinearAlgebra.eigen(Y)
#----------------------------------------------------------------------------

## Same here. We would need to define a method
## SparseArrays.sparse(X)
#----------------------------------------------------------------------------

# These are more efficient than for heap-allocated arrays (except for BLAS), but still not the best, since we know the answers. It would be a good idea to hard code the result for `sparse` and return an copy. As an example I did implement methods for a few functions, for example, `ishermitian`, and `eigvals`:

@btime LinearAlgebra.eigvals(Z)
#----------------------------------------------------------------------------

# `20`ns is the time required to copy the array of eigenvalues.

# Most importantly, I have implemented operations such as multiplication and Kroncker product rather than relying on fallback methods.
#
# Here is an example of multiplication.

a = rand(Pauli, 1000); ## A sampler for Paui supports the entire `rand` interface.
a_matrix = Matrix.(a); ## convert to heap-allocated matrices
#----------------------------------------------------------------------------

@btime reduce(*, $a)  ## `*` ignores the phase
#----------------------------------------------------------------------------

@btime reduce(*, $a_matrix)
#----------------------------------------------------------------------------

# ### `PauliTerm`
#
# `PauliTerm` represents a tensor product of Pauli operators (or a single one) and keeps track of a coefficient, including a phase. The following should give the same result as for `a_matrix` above, including the phase.

PauliTerm("XX").ops
#----------------------------------------------------------------------------

a_terms = [PauliTerm([x]) for x in a]
@btime reduce(*, $a_terms)
#----------------------------------------------------------------------------

# Note that this is 50-100 times slower than reducing an array of `Pauli`s. This is likely mostly because each `PauliTerm` and each reduction requires allocating an array, which is very expensive. This could likely be optimized a bit.
#
# We can easily get a bit of improvement by using stack-allocated vectors. This is easy because we have a parametric type system, and a lot of generic code:

using StaticArrays
x = rand(Pauli, 10);  ## dynamic vector
xs = SVector{10, Pauli}(x); ## copy to static vector, the length is encoded in the type.
tx = PauliTerm(x); ## convert to `PauliTerm`
txs = PauliTerm(xs);

@btime $tx * $tx;
@btime $txs * $txs;
#----------------------------------------------------------------------------

# This is only a modest improvement, because the algorithms are not well suited to static vectors. Static vectors are also not efficient for large vectors. But, this illustrates parametric types.

# ### Compare `PauliTerm` with qiskit

Pkg.activate("/home/lapeyre/.julia/gjl-quantum/QuantumOps/Dev")
using PyCall
Pkg.activate("/home/lapeyre/.julia/gjl-quantum/QuantumOps")

qi = pyimport("qiskit.quantum_info");
#----------------------------------------------------------------------------

# Here, we compare multiplication of two Pauli strings with both libraries. We see how the time scales with string length.

function get_julia_python_terms(n_qubits)
    xj = PauliTerm(rand(Pauli, n_qubits))
    yj = PauliTerm(rand(Pauli, n_qubits))
    xp = qi.random_pauli(n_qubits)
    yp = qi.random_pauli(n_qubits)
    return (xj, yj, xp, yp)
end

n_qubits = 10
(xj, yj, xp, yp) = get_julia_python_terms(n_qubits)

## `QuantumOps`
@btime $xj * $yj
#----------------------------------------------------------------------------

## qiskit
@btime $xp * $yp   ## @btime gives same times as %timeit in python cli
#----------------------------------------------------------------------------

# #### For mulitplying 10-qubit Pauli strings, `QuantumOps` is about 300 times faster than qiskit.

julia_time = @belapsed $xj * $xj
qiskit_time = @belapsed $xp * $yp

qiskit_time / julia_time
#----------------------------------------------------------------------------

# Asymptotically, qiskit is about three times faster than `QuantumOps`. But, it takes a while to get there. For 1000-qubit strings `QuantumOps` is still eight times faster. I have some ideas regarding why python is faster than Julia here, but I am not at all sure. Also, there is a big, ~12 micro-s constant term in the python times. It might be worth trying to reduce this.

n_qubits = 1000
(xj, yj, xp, yp) = get_julia_python_terms(n_qubits)

julia_time = @belapsed $xj * $xj
qiskit_time = @belapsed $xp * $yp

qiskit_time / julia_time
#----------------------------------------------------------------------------

# Here are $10^4$ qubits. Julia is still faster, but they are comparable.

n_qubits = 10^4
(xj, yj, xp, yp) = get_julia_python_terms(n_qubits)

julia_time = @belapsed $xj * $xj
qiskit_time = @belapsed $xp * $yp

qiskit_time / julia_time
#----------------------------------------------------------------------------

# ### `PauliSum`

# A `PauliSum` represents a sum of `PauliTerm`s, sorted in a canonical order.

n_qubits = 10
n_terms = 10
ps = PauliSum(rand(Pauli, (n_terms, n_qubits)), randn(n_terms))
#----------------------------------------------------------------------------

# It makes no mathematical sense, but you can check performance by reducing the terms with `*`. We can see that there is no additional overhead compared to multiplying `PauliTerm`s.

@btime reduce(*, $ps)
#----------------------------------------------------------------------------

x = ps[5]
(x, typeof(x))
#----------------------------------------------------------------------------

# `add!` adds a `PauliTerm` in place. It does a sorted search to find the correct location.

add!(ps, -x)  ## add the additive inverse of a term
#----------------------------------------------------------------------------

# The length of the sum is now 9 rather than 10.

length(ps)
#----------------------------------------------------------------------------

n_qubits = 10
n_terms = 10
ps = PauliSum(rand(Pauli, (n_terms, n_qubits)), randn(n_terms));
size(ps)
#----------------------------------------------------------------------------

x = copy(ps[1])
#----------------------------------------------------------------------------

@btime add!($ps, $x);
#----------------------------------------------------------------------------

# That seems a bit slow.

# #### Pauli decomposition
#
# Construct the Pauli decomposition of a matrix.

m = rand(4, 4)
s = PauliSum(m)
#----------------------------------------------------------------------------

# Check that the decomposition is correct.

m ≈ Matrix(s)
#----------------------------------------------------------------------------

# Doing this decomposition is exponentially expensive. Here we compare the performance of Qiskit QI vs. QuantumOps.

n = 7
m = rand(2^n, 2^n);
julia_time = @belapsed PauliSum($m)
#----------------------------------------------------------------------------

qi_op = qi.Operator(m)
qi_time = @elapsed qi.SparsePauliOp.from_operator(qi_op)
#----------------------------------------------------------------------------

# Ratio of times to do Pauli decomposition for random 7-qubit matrix

qi_time / julia_time
#----------------------------------------------------------------------------

# ### Parametric types and composability

# #### Z4Group
#
# I implemented a type `Z4Group` that represents `(i, -1, -i, 1)`. This can be used to represent the Pauli group. The type `Z4Group` becomes part of the type of the term, which aids the compiler in devirtualizing and inlining.

t = PauliTerm(:XXY, Z4Group(im))
(t, typeof(t))
#----------------------------------------------------------------------------

v = PauliTerm(:ZXZ, Z4Group(1))
#----------------------------------------------------------------------------

t * v
#----------------------------------------------------------------------------

# #### Z4Group0
#
# More interesting is `Z4Group0` which is `Z4Group` augmented by another `Bool` representing zero. This can represent `(0, im, -im, 1, -1)`. It supports multiplication of elements, but is only closed under addition where at least one operand is `0`. It will error if you don't respect this. This quasi-algebra is enough to represent and compute kronecker products of Pauli matrices. The structure is this

dump(Z4Group0(1))
#----------------------------------------------------------------------------

# Note that this is a nested composite type. Nontheless an array of these is packed, with each element taking three bytes. Here is a packed two-dimensional array of `Z4Group0`.

a = rand(Z4Group0, (3,5))
a
#----------------------------------------------------------------------------

sizeof(a)  ## (3 x 5) x 3 bytes
#----------------------------------------------------------------------------

# We see that computation with `Z4Group0` can be as fast as or faster than `Complex{Int}`.

a = rand(Z4Group0, 10^5);
@btime reduce(*, a)
#----------------------------------------------------------------------------

anum = [convert(Complex{Int}, x) for x in a];
@btime reduce(*, anum)
#----------------------------------------------------------------------------

# I use `Z4Group0` in Kronecker products.

kron([Z4Group0.(m) for m in Matrix.([X, Y, Z])]...)
#----------------------------------------------------------------------------

operators = rand(Pauli, 4)
print(operators)
#----------------------------------------------------------------------------

mats = Matrix.(operators)
z40mats = [Z4Group0.(m) for m in mats];

size(kron(mats...))
#----------------------------------------------------------------------------

@btime kron($mats...);
#----------------------------------------------------------------------------

@btime kron($z40mats...);
#----------------------------------------------------------------------------

# Here, the time to do the calcuations with usual 16-byte complex numbers is the same. But, when converting a `PauliSum` to a matrix I use `ThreadsX.sum` over the terms, which is a dropin replacement for `sum` that does intelligent threading. When I use `Z4Group0` I get a significant improvement in performance, perhaps because of fewer cache misses.

# ### sympy

@pyimport sympy
(x, t) = sympy.symbols("x t")
#----------------------------------------------------------------------------

# We use a symbolic coefficient

term = PauliTerm("XXYZ", x + t)
#----------------------------------------------------------------------------

term^3
#----------------------------------------------------------------------------

# The type of coefficient is encoded in the type of the `PauliTerm`.

typeof(term)
#----------------------------------------------------------------------------

# #### `Symbolics`
#
# This is another symbolic libarary.

Pkg.activate("/home/lapeyre/.julia/gjl-quantum/QuantumOps/Dev")
using Symbolics
Pkg.activate("/home/lapeyre/.julia/gjl-quantum/QuantumOps")
#----------------------------------------------------------------------------

@variables a b c;
#----------------------------------------------------------------------------

# Create a `PauliSum` with symbolic coefficients

term1 = PauliTerm("XZ", a + b)
term2 = PauliTerm("ZX", b + c)

psum = term1^3 + term2
#----------------------------------------------------------------------------

# We convert the `PauliSum` with symbolic coefficients to a `Matrix`.
# No additional code is necessary to support this feature.

symmat = Matrix(psum)
#----------------------------------------------------------------------------


text:
export current_context, with_context

using UUIDs: uuid4

const CONTEXT_KEY = :OPEN_TELEMETRY_CONTEXT

# ??? performace issue with NamedTuple
struct Context{T<:NamedTuple}
    kv::T
end

Context() = Context(NamedTuple())

Base.merge(c1::Context, c2::Context) = Context(merge(c1.kv, c2.kv))

create_key(s) = Symbol(s, '-', uuid4())

for f in (:getindex, :haskey, :get)
    @eval Base.$f(ctx::Context, args...) = $f(ctx.kv, args...)
end

with_context(f; kv...) = with_context(f, current_context(); kv...)

"""
    with_context(f, [context]; kv...)

Run function `f` in the `context`. If extra `kv` pairs are provided, they will be merged with the `context` to form a new context. When `context` is not provided, the [`current_context`](@ref) will be used.
"""
with_context(f, ctx::Context; kw...) =
    task_local_storage(f, CONTEXT_KEY, merge(ctx, Context(values(kw))))

"""
Return the `Context` associated with the caller's current execution unit.
"""
current_context() = get(task_local_storage(), CONTEXT_KEY, Context())::Context


text:
function unpack(states_history::Vector{<:State};
    dims::Vector{Int}=Vector{Int}())
    # set default to condense all dimensions
    if length(dims) == 0
        dims = collect(1:length(states_history[1].x))
    end
    # set output sizes
    μ = zeros(typeof(states_history[1].x[1]),
        length(states_history), length(dims))
    Σ = zeros(typeof(states_history[1].x[1]),
        length(states_history), length(dims), length(dims))
    # iterate over belief_history and place elements appropriately
    for (i, state) in enumerate(states_history)
        μ[i,:] = state.x[dims]
        Σ[i,:,:] = state.P[dims,dims]
    end
    return μ, Σ
end


text:
Network = SimpleNet

netparams = SimpleNetHP(
    width = 200,
    depth_common = 8,
    use_batch_norm = true,
    batch_norm_momentum = 1.0,
)

self_play = SelfPlayParams(
    num_games = 2000,
    mcts = MctsParams(
        use_gpu = true,
        num_workers = 1,
        num_iters_per_turn = 200,
        cpuct = 1.0,
        temperature = ConstSchedule(1.0),
        dirichlet_noise_ϵ = 0.2,
        dirichlet_noise_α = 1.0,
    ),
)

arena = ArenaParams(
    num_games = 10,
    reset_mcts_every = 1,
    update_threshold = 0.00,
    flip_probability = 0.5,
    mcts = MctsParams(
        self_play.mcts,
        temperature = ConstSchedule(0.3),
        dirichlet_noise_ϵ = 0.1,
    ),
)

learning = LearningParams(
    samples_weighing_policy = LOG_WEIGHT,
    l2_regularization = 1e-4,
    optimiser = CyclicNesterov(
        lr_base = 1e-3,
        lr_high = 1e-2,
        lr_low = 1e-3,
        momentum_high = 0.9,
        momentum_low = 0.8,
    ),
    batch_size = 24,
    loss_computation_batch_size = 1024,
    nonvalidity_penalty = 1.0,
    min_checkpoints_per_epoch = 0,
    max_batches_per_checkpoint = 5_000,
    num_checkpoints = 1,
)

params = Params(
    arena = arena,
    self_play = self_play,
    learning = learning,
    num_iters = 10,
    memory_analysis = MemAnalysisParams(num_game_stages = 5),
    ternary_rewards = true,
    use_symmetries = false,
    mem_buffer_size = PLSchedule(80_000),
)
benchMcts = MctsParams(
    use_gpu = false,
    num_workers = 1,
    num_iters_per_turn = 100,
    cpuct = 0.9,
    temperature = ConstSchedule(1.0),
    dirichlet_noise_ϵ = 0.2,
    dirichlet_noise_α = 1.0,
)
benchmark = [
    Benchmark.Duel(
        Benchmark.NetworkOnly(),
        Benchmark.MctsRollouts(benchMcts),
        num_games = 20,
        flip_probability = 0.5,
    ),
    Benchmark.Duel(
        Benchmark.Full(self_play.mcts),
        Benchmark.MctsRollouts(self_play.mcts),
        num_games = 20,
        flip_probability = 0.4,
    ),
]