├── .gitignore ├── .dockerignore ├── Dockerfile ├── example_deployment ├── 03_pullsecret_test.yml ├── 01_aws_credentials.yml ├── 01_authorization.yml └── 02_deployment.yml ├── pyproject.toml ├── LICENSE ├── .github └── workflows │ └── ci.yml ├── README.md ├── ecrupdater.py └── uv.lock /.gitignore: -------------------------------------------------------------------------------- 1 | .venv 2 | .env 3 | .idea 4 | .vscode 5 | logging.json 6 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .venv 2 | .env 3 | .idea 4 | .vscode 5 | example_deployment 6 | README.md 7 | .github 8 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.13 2 | COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ 3 | WORKDIR /app 4 | COPY . . 5 | RUN uv sync --locked 6 | CMD ["uv", "run", "ecrupdater.py"] 7 | -------------------------------------------------------------------------------- /example_deployment/03_pullsecret_test.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: private-reg 5 | spec: 6 | containers: 7 | - name: private-reg-container 8 | image: YOUR_SECRIT_ECR/YOUR_SECRIT_IMAGE 9 | imagePullSecrets: 10 | - name: ecr -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "ecr-updater" 3 | version = "0.1.0" 4 | description = "Add your description here" 5 | readme = "README.md" 6 | requires-python = ">=3.13" 7 | dependencies = [ 8 | "boto3>=1.40.63", 9 | "kubernetes>=34.1.0", 10 | "loguru>=0.7.3", 11 | "python-json-logger>=4.0.0", 12 | ] 13 | -------------------------------------------------------------------------------- /example_deployment/01_aws_credentials.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: ecr-aws-credentials 5 | data: 6 | AWS_ACCESS_KEY_ID: 'PUT_BASE64_ENCODED_ACCESS_KEY_HERE' #base-64 encoded aws access key with ecr access, run echo -n "PUT_ACCESSKEY_HERE" | base64 7 | AWS_SECRET_ACCESS_KEY: 'PUT_BASE64_ENCODED_SECRET_KEY_HERE' #base-64 encoded aws access key with ecr access, echo -n "PUT_SECRETKEY_HERE" | base64 -------------------------------------------------------------------------------- /example_deployment/01_authorization.yml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: ClusterRole 3 | apiVersion: rbac.authorization.k8s.io/v1beta1 4 | metadata: 5 | name: ecr-updater 6 | rules: 7 | - apiGroups: 8 | - "" 9 | resources: 10 | - secrets 11 | - configmaps 12 | verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] 13 | # The rule below is only needed when auto-creating pull secrets in all namespaces 14 | # See ECR_CREATE_MISSING in README.md 15 | - apiGroups: 16 | - "" 17 | resources: 18 | - namespaces 19 | verbs: ["get", "list"] 20 | --- 21 | kind: ClusterRoleBinding 22 | apiVersion: rbac.authorization.k8s.io/v1beta1 23 | metadata: 24 | name: ecr-updater 25 | roleRef: 26 | apiGroup: rbac.authorization.k8s.io 27 | kind: ClusterRole 28 | name: ecr-updater 29 | subjects: 30 | - kind: ServiceAccount 31 | name: ecr-updater 32 | namespace: default -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Trond Hindenes 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Docker Build with Autoversion 2 | 3 | on: 4 | push: 5 | 6 | permissions: 7 | contents: write 8 | 9 | jobs: 10 | get-version: 11 | name: Get Version 12 | runs-on: ubuntu-latest 13 | outputs: 14 | version: ${{ steps.get_version.outputs.semverWithPrefix }} 15 | versionWithPrefix: ${{ steps.get_version.outputs.semverWithPrefix }} 16 | is-release: ${{ steps.get_version.outputs.isRelease }} 17 | steps: 18 | - name: Checkout code 19 | uses: actions/checkout@v4 20 | with: 21 | fetch-depth: 0 22 | 23 | - name: Calculate version 24 | id: get_version 25 | uses: trondhindenes/autoversion-action@v1 26 | 27 | docker: 28 | name: Build and push Docker image 29 | needs: 30 | - get-version 31 | runs-on: ubuntu-latest 32 | permissions: 33 | contents: read 34 | packages: write 35 | 36 | steps: 37 | - name: Checkout code 38 | uses: actions/checkout@v4 39 | 40 | - name: Set up Docker Buildx 41 | uses: docker/setup-buildx-action@v3 42 | 43 | - name: Log in to GitHub Container Registry 44 | uses: docker/login-action@v3 45 | with: 46 | registry: ghcr.io 47 | username: ${{ github.actor }} 48 | password: ${{ secrets.GITHUB_TOKEN }} 49 | 50 | - name: Extract metadata 51 | id: meta 52 | uses: docker/metadata-action@v5 53 | with: 54 | images: ghcr.io/${{ github.repository }} 55 | tags: | 56 | type=semver,pattern={{version}},value=${{ needs.get-version.outputs.version }} 57 | type=raw,value=latest,enable=${{ needs.get-version.outputs.is-release == 'true' }} 58 | type=raw,value=release,enable=${{ needs.get-version.outputs.is-release == 'true' }} 59 | 60 | - name: Build and push Docker image 61 | uses: docker/build-push-action@v5 62 | with: 63 | push: true 64 | tags: ${{ steps.meta.outputs.tags }} 65 | labels: ${{ steps.meta.outputs.labels }} 66 | platforms: linux/amd64,linux/arm64 67 | provenance: false 68 | -------------------------------------------------------------------------------- /example_deployment/02_deployment.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: ecr-updater 6 | --- 7 | apiVersion: v1 8 | kind: ConfigMap 9 | metadata: 10 | name: log-configuration 11 | data: 12 | logging.json: | 13 | { 14 | "version": 1, 15 | "disable_existing_loggers": false, 16 | "formatters": { 17 | "json": { 18 | "format": "%(asctime)s %(levelname)s %(message)s %(pathname)s %(lineno)d %(threadName)s", 19 | "class": "pythonjsonlogger.jsonlogger.JsonFormatter" 20 | } 21 | }, 22 | "handlers": { 23 | "json": { 24 | "class": "logging.StreamHandler", 25 | "formatter": "json" 26 | } 27 | }, 28 | "loggers": { 29 | "": { 30 | "handlers": [ "json" ], 31 | "level": "INFO" 32 | } 33 | } 34 | } 35 | --- 36 | kind: Deployment 37 | apiVersion: apps/v1 38 | metadata: 39 | name: ecr-updater 40 | labels: 41 | k8s-app: ecr-updater 42 | spec: 43 | replicas: 1 44 | selector: 45 | matchLabels: 46 | k8s-app: ecr-updater 47 | template: 48 | metadata: 49 | labels: 50 | k8s-app: ecr-updater 51 | name: ecr-updater 52 | spec: 53 | serviceAccountName: ecr-updater 54 | containers: 55 | - image: trondhindenes/k8s-ecrupdater 56 | name: ecrupdater 57 | env: 58 | - name: K8S_PULL_SECRET_NAME 59 | value: ecr 60 | - name: AWS_DEFAULT_REGION 61 | value: eu-west-1 62 | - name: AWS_ACCESS_KEY_ID 63 | valueFrom: 64 | secretKeyRef: 65 | name: ecr-aws-credentials 66 | key: AWS_ACCESS_KEY_ID 67 | - name: AWS_SECRET_ACCESS_KEY 68 | valueFrom: 69 | secretKeyRef: 70 | name: ecr-aws-credentials 71 | key: AWS_SECRET_ACCESS_KEY 72 | - name: LOG_CONFIG 73 | value: /etc/log-configuration/logging.json 74 | volumeMounts: 75 | - mountPath: /etc/log-configuration 76 | name: log-configuration 77 | - image: palmstonegames/kubectl-proxy 78 | name: kubectl-proxy 79 | volumes: 80 | - name: log-configuration 81 | configMap: 82 | name: log-configuration 83 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # K8s-Ecrupdater 2 | Because of the way AWS ECR docker registries work, the credentials have to be refreshed. 3 | This image pulls credentials from ECR every hour, and injects them into Kubernetes so that images can be pulled from a private repo. 4 | 5 | This allows the use of AWS ECR registries also when your Kubernetes cluster is running in another cloud provider, or you don't want to set up EC2 roles for it. 6 | 7 | Grab container images from: https://github.com/trondhindenes/ecr-updater/pkgs/container/ecr-updater 8 | 9 | ## Configuration 10 | Configure with the following environment variables: 11 | ``` 12 | K8S_PULL_SECRET_NAME: Name of the Kubernetes pull secret to update 13 | ECR_UPDATE_INTERVAL: (optional, time in seconds) 14 | ECR_CREATE_MISSING: if this envvar is set to `true`, missing pull secrets will be created in all namespaces 15 | (there's a good chance this will fail on older (pre 1.11) clusters. 16 | ECR_SKIP_NAMESPACES: Comma-separated list of namespaces to skip when creating missing secrets 17 | AWS_DEFAULT_REGION: (set to your region) 18 | AWS_ACCESS_KEY_ID: aws creds 19 | AWS_SECRET_ACCESS_KEY: aws creds 20 | LOG_CONFIG: optional log config file (defaults to ./logging.json) 21 | LOG_LEVEL: Applies only if no log config file has been found (defaults to INFO) 22 | ``` 23 | 24 | Note that if you're using alternate methods of providing the pod with AWS credentials (such as kube2iam or similar) you can skip the `AWS_ACCESS_KEY_ID`/`AWS_SECRET_ACCESS_KEY` configuration items. 25 | 26 | ## Example deployment 27 | It is assumed that you already have ECR setup, an IAM user with access to it, and that you have `kubectl` configured to communicate with your Kubernetes cluster. 28 | 29 | You can also run it locally using `kubectl proxy` on your computer if you want to test things out. In that case, make sure the proxy listens on `localhost:8001` 30 | 31 | 1. (this step is only required if `ECR_CREATE_MISSING` is not set to true) Create a secret called ecr. This is the secret that this pod will update regularly. It doesn't matter what you put in here, as ecrupdater will update it, it just needs to exist.: 32 | `kubectl create secret docker-registry ecr --docker-username=smash --docker-password=lol --docker-email lol@lol.com` 33 | NOTE: `ecrupdater` will look for the secrets with the specified name across all your namespaces if you're using the authorization template below. So in this example any secret named `ecr` across all namespaces will be updated. If you want to separate them you can run multiple instances of `ecrupdater`, optionally with tighter (namespaces-isolated) security. 34 | 35 | 2. Create the authorization stuff that lets kubectl-proxy (running in the same pod as the ecr-updater) interact with kubernetes: 36 | `kubectl apply -f example_deployment/01_authorization.yml` 37 | 38 | 3. Create a IAM user that has read access to your registries. The access key and secret key need to be base64-encoded (remember to use the `-n` option): 39 | `echo -n "PUT_ACCESSKEY_HERE" | base64` 40 | `echo -n "PUT_SECRETKEY_HERE" | base64` 41 | Put this info in the file `example_deployment/01_aws_credentials.yml.yml` in this repo. 42 | Now you can create a secret that will hold this info. This is how the ecr updater will log on to AWS: 43 | `kubectl apply -f example_deployment/01_aws_credentials.yml` 44 | 45 | 4. Deploy the pod. This contains both the ecr-updater and a "sidecar" container running kubectl-proxy. The proxy allows communication with the kubernetes api in a simple manner. 46 | Make sure to set your correct aws region in `example_deployment/02_deployment.yml` before deploying! 47 | `kubectl apply -f example_deployment/02_deployment.yml` 48 | 49 | 5. Test a deployment. Replace the containerimage with one from your own ecr registry, deploy it and prosper! (note that the ecrupdater initially pauses for 60 seconds, so make sure time has passed between the ecr updater pod coming online, and you run the next command) 50 | `kubectl apply -f example_deployment/03_pullsecret_test.yml` 51 | 52 | ## Logging 53 | By default, the service logs using the built in python logging package and the python-json-logger package for the json formatting. 54 | In order to change the log configuration, the service expects a log config file 'logging.json' in the working directory. 55 | Alternatively, this log config file path can be configured via the ENV variable `LOG_CONFIG` using a configMap. 56 | 57 | ### Logger config docs 58 | * https://docs.python.org/3/library/logging.config.html 59 | 60 | example log config file to enable JSON logging on INFO level. 61 | ``` 62 | { 63 | "version": 1, 64 | "disable_existing_loggers": false, 65 | "formatters": { 66 | "json": { 67 | "format": "%(asctime)s %(levelname)s %(message)s %(pathname)s %(lineno)d %(threadName)s", 68 | "class": "pythonjsonlogger.jsonlogger.JsonFormatter" 69 | } 70 | }, 71 | "handlers": { 72 | "json": { 73 | "class": "logging.StreamHandler", 74 | "formatter": "json" 75 | } 76 | }, 77 | "loggers": { 78 | "": { 79 | "handlers": ["json"], 80 | "level": "INFO" 81 | } 82 | } 83 | } 84 | ``` 85 | -------------------------------------------------------------------------------- /ecrupdater.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | import json 4 | import time 5 | import base64 6 | import boto3 7 | import logging 8 | import logging.config 9 | from kubernetes import client as k8sclient 10 | from kubernetes.client import Configuration, ApiClient, ApiException 11 | 12 | 13 | def setup_logging( 14 | log_config_file=os.environ.get('LOG_CONFIG', './logging.json'), 15 | # fallback if no logger config file has been configured 16 | default_level=os.environ.get('LOG_LEVEL', 'INFO') 17 | ): 18 | if os.path.exists(log_config_file): 19 | print("Loading log configuration file from path '{}'...".format(log_config_file)) 20 | with open(log_config_file, 'rt') as f: 21 | config = json.load(f) 22 | logging.config.dictConfig(config) 23 | else: 24 | print("No Log config file provided, loading default configuration.") 25 | logging.basicConfig(level=default_level) 26 | setup_logging() 27 | logger = logging.getLogger(__name__) 28 | 29 | 30 | print('Starting ECR-updater ..') 31 | pull_secret_name = os.getenv('K8S_PULL_SECRET_NAME', None) 32 | env_update_interval = os.getenv('ECR_UPDATE_INTERVAL', '3600') 33 | create_missing_pull_secrets_str = os.getenv('ECR_CREATE_MISSING', 'false') 34 | skip_namespaces = os.getenv('ECR_SKIP_NAMESPACES', '') 35 | # Allows the kubernetes python clients to talk to k8s via the kubectl-proxy sidecar container 36 | kubernetes_api_endpoint = os.getenv('KUBERNETES_API_ENDPOINT', 'http://localhost:8001') 37 | 38 | try: 39 | update_interval = int(env_update_interval) 40 | except: 41 | raise ValueError(f'unable to parse {env_update_interval} into seconds, exiting') 42 | 43 | if pull_secret_name is None: 44 | raise ValueError('Specify name of secret in env variable K8S_PULL_SECRET_NAME') 45 | 46 | 47 | def create_pull_secrets(): 48 | if create_missing_pull_secrets_str.lower() != 'true': 49 | return None 50 | 51 | skip_namespaces_list = [] 52 | if skip_namespaces: 53 | skip_namespaces_list = [x.strip() for x in skip_namespaces.split(',')] 54 | 55 | 56 | k8s_config = Configuration() 57 | k8s_config.host = kubernetes_api_endpoint 58 | k8s_api_client = ApiClient(configuration=k8s_config) 59 | v1 = k8sclient.CoreV1Api(api_client=k8s_api_client) 60 | namespaces = v1.list_namespace() 61 | for namespace in namespaces.items: 62 | if namespace.metadata.name in skip_namespaces_list: 63 | logger.info('Skipping namespace %s as it is in the skip list', namespace.metadata.name) 64 | continue 65 | ns_secrets = v1.list_namespaced_secret(namespace.metadata.name) 66 | has_ecr_secret = [x for x in ns_secrets.items if x.metadata.name == pull_secret_name] 67 | if not has_ecr_secret: 68 | k8s_secret = { 69 | 'server': 70 | { 71 | 'username': 'temp', 72 | 'password': 'temp' 73 | } 74 | } 75 | b64_k8s_secret = base64.b64encode(json.dumps(k8s_secret).encode('utf-8')).decode('utf-8') 76 | secret_body = { 77 | 'kind': 'Secret', 78 | 'apiVersion': 'v1', 79 | 'metadata': { 80 | 'name': pull_secret_name, 81 | 'creationTimestamp': None 82 | }, 83 | 'data': { 84 | '.dockerconfigjson': b64_k8s_secret 85 | }, 86 | 'type': 'kubernetes.io/dockerconfigjson' 87 | } 88 | logger.info('Creating secret %s in namespace %s', pull_secret_name, namespace.metadata.name) 89 | try: 90 | v1.create_namespaced_secret(namespace.metadata.name, secret_body) 91 | except ApiException: 92 | logger.exception('Could not create secret %s in namespace %s', 93 | pull_secret_name, 94 | namespace.metadata.name) 95 | 96 | 97 | def update_ecr(): 98 | logger.info('Starting ECR secret update loop ..') 99 | client = boto3.client('ecr') 100 | response = client.get_authorization_token() 101 | token = response['authorizationData'][0]['authorizationToken'] 102 | server = response['authorizationData'][0]['proxyEndpoint'] 103 | bare_server = server.replace('https://', '') 104 | decoded_token = base64.b64decode(token).decode('utf-8') 105 | registry_username = decoded_token.split(':')[0] 106 | registry_password = decoded_token.split(':')[1] 107 | 108 | k8s_config = Configuration() 109 | k8s_config.host = kubernetes_api_endpoint 110 | k8s_api_client = ApiClient(configuration=k8s_config) 111 | v1 = k8sclient.CoreV1Api(api_client=k8s_api_client) 112 | secrets = v1.list_secret_for_all_namespaces() 113 | 114 | registry_secrets = [x for x in secrets.items if x.metadata.name == pull_secret_name] 115 | logger.info('Found %s registry_secrets matching name %s', len(registry_secrets), pull_secret_name) 116 | for secret in registry_secrets: 117 | secret_name = secret.metadata.name 118 | if secret.type == 'kubernetes.io/dockercfg': 119 | logger.info('Updating secret %s (type kubernetes.io/dockercfg) in namespace %s', 120 | secret_name, 121 | secret.metadata.namespace) 122 | k8s_secret = { 123 | server: 124 | { 125 | 'username': registry_username, 126 | 'password': registry_password 127 | } 128 | } 129 | 130 | b64_k8s_secret = base64.b64encode(json.dumps(k8s_secret).encode('utf-8')).decode('utf-8') 131 | body = { 132 | 'kind': 'Secret', 133 | 'apiVersion': 'v1', 134 | 'metadata': { 135 | 'name': pull_secret_name, 136 | 'creationTimestamp': None 137 | }, 138 | 'data': { 139 | '.dockercfg': b64_k8s_secret 140 | }, 141 | 'type': 'kubernetes.io/dockercfg' 142 | } 143 | res = v1.patch_namespaced_secret(secret.metadata.name, secret.metadata.namespace, body) 144 | elif secret.type == 'kubernetes.io/dockerconfigjson': 145 | logger.info('Updating secret %s (type kubernetes.io/dockerconfigjson) in namespace %s', 146 | secret_name, 147 | secret.metadata.namespace) 148 | k8s_secret = { 149 | 'auths': { 150 | bare_server: { 151 | 'username': registry_username, 152 | 'password': registry_password 153 | } 154 | } 155 | } 156 | b64_k8s_secret = base64.b64encode(json.dumps(k8s_secret).encode('utf-8')).decode('utf-8') 157 | body = { 158 | 'kind': 'Secret', 159 | 'apiVersion': 'v1', 160 | 'metadata': { 161 | 'name': pull_secret_name, 162 | 'creationTimestamp': None 163 | }, 164 | 'data': { 165 | '.dockerconfigjson': b64_k8s_secret 166 | }, 167 | 'type': 'kubernetes.io/dockerconfigjson' 168 | } 169 | res = v1.patch_namespaced_secret(secret.metadata.name, secret.metadata.namespace, body) 170 | else: 171 | logger.warning('Unknown secret type for secret name %s: %s'.format(secret_name, secret.type)) 172 | 173 | 174 | if __name__ == '__main__': 175 | while True: 176 | logger.info('Running credentials update loop ..') 177 | create_pull_secrets() 178 | update_ecr() 179 | logger.info(f'...done. Waiting %s seconds', update_interval) 180 | time.sleep(update_interval) 181 | -------------------------------------------------------------------------------- /uv.lock: -------------------------------------------------------------------------------- 1 | version = 1 2 | revision = 3 3 | requires-python = ">=3.13" 4 | 5 | [[package]] 6 | name = "boto3" 7 | version = "1.40.63" 8 | source = { registry = "https://pypi.org/simple" } 9 | dependencies = [ 10 | { name = "botocore" }, 11 | { name = "jmespath" }, 12 | { name = "s3transfer" }, 13 | ] 14 | sdist = { url = "https://files.pythonhosted.org/packages/5d/fb/db063c9600cbe2c52009edd436262c696b18bafaf49835a7f17ba1679a84/boto3-1.40.63.tar.gz", hash = "sha256:3bf4b034900c87a6a9b3b3b44c4aec26e96fc73bff2505f0766224b7295178ce", size = 111541, upload-time = "2025-10-30T19:32:52.081Z" } 15 | wheels = [ 16 | { url = "https://files.pythonhosted.org/packages/c6/d4/d977f678c60e05c19c857ad896f838152dc68e0cc28f0f026e224879d8ca/boto3-1.40.63-py3-none-any.whl", hash = "sha256:f15d4abf1a6283887c336f660cdfc2162a210d2d8f4d98dbcbcef983371c284d", size = 139322, upload-time = "2025-10-30T19:32:49.876Z" }, 17 | ] 18 | 19 | [[package]] 20 | name = "botocore" 21 | version = "1.40.63" 22 | source = { registry = "https://pypi.org/simple" } 23 | dependencies = [ 24 | { name = "jmespath" }, 25 | { name = "python-dateutil" }, 26 | { name = "urllib3" }, 27 | ] 28 | sdist = { url = "https://files.pythonhosted.org/packages/a2/08/62f4d332dd729d14190073eaf6db63803a5bc2d9b8f1248ae3cbc6c9cb64/botocore-1.40.63.tar.gz", hash = "sha256:0324552c3c800e258cbcb8c22b495a2e2e0260a7408d08016196e46fa0d1b587", size = 14400022, upload-time = "2025-10-30T19:32:40.81Z" } 29 | wheels = [ 30 | { url = "https://files.pythonhosted.org/packages/45/b0/17c1e8fa8617c588da33f6724909eef56e1745ddfe2f87972d9a8e9e6ca2/botocore-1.40.63-py3-none-any.whl", hash = "sha256:83657b3ee487268fccc9ba022cba572ba657b9ece8cddd1fa241e2c6a49c8c14", size = 14061984, upload-time = "2025-10-30T19:32:36.945Z" }, 31 | ] 32 | 33 | [[package]] 34 | name = "cachetools" 35 | version = "6.2.1" 36 | source = { registry = "https://pypi.org/simple" } 37 | sdist = { url = "https://files.pythonhosted.org/packages/cc/7e/b975b5814bd36faf009faebe22c1072a1fa1168db34d285ef0ba071ad78c/cachetools-6.2.1.tar.gz", hash = "sha256:3f391e4bd8f8bf0931169baf7456cc822705f4e2a31f840d218f445b9a854201", size = 31325, upload-time = "2025-10-12T14:55:30.139Z" } 38 | wheels = [ 39 | { url = "https://files.pythonhosted.org/packages/96/c5/1e741d26306c42e2bf6ab740b2202872727e0f606033c9dd713f8b93f5a8/cachetools-6.2.1-py3-none-any.whl", hash = "sha256:09868944b6dde876dfd44e1d47e18484541eaf12f26f29b7af91b26cc892d701", size = 11280, upload-time = "2025-10-12T14:55:28.382Z" }, 40 | ] 41 | 42 | [[package]] 43 | name = "certifi" 44 | version = "2025.10.5" 45 | source = { registry = "https://pypi.org/simple" } 46 | sdist = { url = "https://files.pythonhosted.org/packages/4c/5b/b6ce21586237c77ce67d01dc5507039d444b630dd76611bbca2d8e5dcd91/certifi-2025.10.5.tar.gz", hash = "sha256:47c09d31ccf2acf0be3f701ea53595ee7e0b8fa08801c6624be771df09ae7b43", size = 164519, upload-time = "2025-10-05T04:12:15.808Z" } 47 | wheels = [ 48 | { url = "https://files.pythonhosted.org/packages/e4/37/af0d2ef3967ac0d6113837b44a4f0bfe1328c2b9763bd5b1744520e5cfed/certifi-2025.10.5-py3-none-any.whl", hash = "sha256:0f212c2744a9bb6de0c56639a6f68afe01ecd92d91f14ae897c4fe7bbeeef0de", size = 163286, upload-time = "2025-10-05T04:12:14.03Z" }, 49 | ] 50 | 51 | [[package]] 52 | name = "charset-normalizer" 53 | version = "3.4.4" 54 | source = { registry = "https://pypi.org/simple" } 55 | sdist = { url = "https://files.pythonhosted.org/packages/13/69/33ddede1939fdd074bce5434295f38fae7136463422fe4fd3e0e89b98062/charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", size = 129418, upload-time = "2025-10-14T04:42:32.879Z" } 56 | wheels = [ 57 | { url = "https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794", size = 208091, upload-time = "2025-10-14T04:41:13.346Z" }, 58 | { url = "https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed", size = 147936, upload-time = "2025-10-14T04:41:14.461Z" }, 59 | { url = "https://files.pythonhosted.org/packages/89/c5/adb8c8b3d6625bef6d88b251bbb0d95f8205831b987631ab0c8bb5d937c2/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72", size = 144180, upload-time = "2025-10-14T04:41:15.588Z" }, 60 | { url = "https://files.pythonhosted.org/packages/91/ed/9706e4070682d1cc219050b6048bfd293ccf67b3d4f5a4f39207453d4b99/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328", size = 161346, upload-time = "2025-10-14T04:41:16.738Z" }, 61 | { url = "https://files.pythonhosted.org/packages/d5/0d/031f0d95e4972901a2f6f09ef055751805ff541511dc1252ba3ca1f80cf5/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede", size = 158874, upload-time = "2025-10-14T04:41:17.923Z" }, 62 | { url = "https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894", size = 153076, upload-time = "2025-10-14T04:41:19.106Z" }, 63 | { url = "https://files.pythonhosted.org/packages/75/1e/5ff781ddf5260e387d6419959ee89ef13878229732732ee73cdae01800f2/charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1", size = 150601, upload-time = "2025-10-14T04:41:20.245Z" }, 64 | { url = "https://files.pythonhosted.org/packages/d7/57/71be810965493d3510a6ca79b90c19e48696fb1ff964da319334b12677f0/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490", size = 150376, upload-time = "2025-10-14T04:41:21.398Z" }, 65 | { url = "https://files.pythonhosted.org/packages/e5/d5/c3d057a78c181d007014feb7e9f2e65905a6c4ef182c0ddf0de2924edd65/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44", size = 144825, upload-time = "2025-10-14T04:41:22.583Z" }, 66 | { url = "https://files.pythonhosted.org/packages/e6/8c/d0406294828d4976f275ffbe66f00266c4b3136b7506941d87c00cab5272/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133", size = 162583, upload-time = "2025-10-14T04:41:23.754Z" }, 67 | { url = "https://files.pythonhosted.org/packages/d7/24/e2aa1f18c8f15c4c0e932d9287b8609dd30ad56dbe41d926bd846e22fb8d/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3", size = 150366, upload-time = "2025-10-14T04:41:25.27Z" }, 68 | { url = "https://files.pythonhosted.org/packages/e4/5b/1e6160c7739aad1e2df054300cc618b06bf784a7a164b0f238360721ab86/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e", size = 160300, upload-time = "2025-10-14T04:41:26.725Z" }, 69 | { url = "https://files.pythonhosted.org/packages/7a/10/f882167cd207fbdd743e55534d5d9620e095089d176d55cb22d5322f2afd/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc", size = 154465, upload-time = "2025-10-14T04:41:28.322Z" }, 70 | { url = "https://files.pythonhosted.org/packages/89/66/c7a9e1b7429be72123441bfdbaf2bc13faab3f90b933f664db506dea5915/charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac", size = 99404, upload-time = "2025-10-14T04:41:29.95Z" }, 71 | { url = "https://files.pythonhosted.org/packages/c4/26/b9924fa27db384bdcd97ab83b4f0a8058d96ad9626ead570674d5e737d90/charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14", size = 107092, upload-time = "2025-10-14T04:41:31.188Z" }, 72 | { url = "https://files.pythonhosted.org/packages/af/8f/3ed4bfa0c0c72a7ca17f0380cd9e4dd842b09f664e780c13cff1dcf2ef1b/charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2", size = 100408, upload-time = "2025-10-14T04:41:32.624Z" }, 73 | { url = "https://files.pythonhosted.org/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd", size = 207746, upload-time = "2025-10-14T04:41:33.773Z" }, 74 | { url = "https://files.pythonhosted.org/packages/10/9a/97c8d48ef10d6cd4fcead2415523221624bf58bcf68a802721a6bc807c8f/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb", size = 147889, upload-time = "2025-10-14T04:41:34.897Z" }, 75 | { url = "https://files.pythonhosted.org/packages/10/bf/979224a919a1b606c82bd2c5fa49b5c6d5727aa47b4312bb27b1734f53cd/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e", size = 143641, upload-time = "2025-10-14T04:41:36.116Z" }, 76 | { url = "https://files.pythonhosted.org/packages/ba/33/0ad65587441fc730dc7bd90e9716b30b4702dc7b617e6ba4997dc8651495/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14", size = 160779, upload-time = "2025-10-14T04:41:37.229Z" }, 77 | { url = "https://files.pythonhosted.org/packages/67/ed/331d6b249259ee71ddea93f6f2f0a56cfebd46938bde6fcc6f7b9a3d0e09/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191", size = 159035, upload-time = "2025-10-14T04:41:38.368Z" }, 78 | { url = "https://files.pythonhosted.org/packages/67/ff/f6b948ca32e4f2a4576aa129d8bed61f2e0543bf9f5f2b7fc3758ed005c9/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838", size = 152542, upload-time = "2025-10-14T04:41:39.862Z" }, 79 | { url = "https://files.pythonhosted.org/packages/16/85/276033dcbcc369eb176594de22728541a925b2632f9716428c851b149e83/charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6", size = 149524, upload-time = "2025-10-14T04:41:41.319Z" }, 80 | { url = "https://files.pythonhosted.org/packages/9e/f2/6a2a1f722b6aba37050e626530a46a68f74e63683947a8acff92569f979a/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e", size = 150395, upload-time = "2025-10-14T04:41:42.539Z" }, 81 | { url = "https://files.pythonhosted.org/packages/60/bb/2186cb2f2bbaea6338cad15ce23a67f9b0672929744381e28b0592676824/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c", size = 143680, upload-time = "2025-10-14T04:41:43.661Z" }, 82 | { url = "https://files.pythonhosted.org/packages/7d/a5/bf6f13b772fbb2a90360eb620d52ed8f796f3c5caee8398c3b2eb7b1c60d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090", size = 162045, upload-time = "2025-10-14T04:41:44.821Z" }, 83 | { url = "https://files.pythonhosted.org/packages/df/c5/d1be898bf0dc3ef9030c3825e5d3b83f2c528d207d246cbabe245966808d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152", size = 149687, upload-time = "2025-10-14T04:41:46.442Z" }, 84 | { url = "https://files.pythonhosted.org/packages/a5/42/90c1f7b9341eef50c8a1cb3f098ac43b0508413f33affd762855f67a410e/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828", size = 160014, upload-time = "2025-10-14T04:41:47.631Z" }, 85 | { url = "https://files.pythonhosted.org/packages/76/be/4d3ee471e8145d12795ab655ece37baed0929462a86e72372fd25859047c/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec", size = 154044, upload-time = "2025-10-14T04:41:48.81Z" }, 86 | { url = "https://files.pythonhosted.org/packages/b0/6f/8f7af07237c34a1defe7defc565a9bc1807762f672c0fde711a4b22bf9c0/charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9", size = 99940, upload-time = "2025-10-14T04:41:49.946Z" }, 87 | { url = "https://files.pythonhosted.org/packages/4b/51/8ade005e5ca5b0d80fb4aff72a3775b325bdc3d27408c8113811a7cbe640/charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c", size = 107104, upload-time = "2025-10-14T04:41:51.051Z" }, 88 | { url = "https://files.pythonhosted.org/packages/da/5f/6b8f83a55bb8278772c5ae54a577f3099025f9ade59d0136ac24a0df4bde/charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2", size = 100743, upload-time = "2025-10-14T04:41:52.122Z" }, 89 | { url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" }, 90 | ] 91 | 92 | [[package]] 93 | name = "colorama" 94 | version = "0.4.6" 95 | source = { registry = "https://pypi.org/simple" } 96 | sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } 97 | wheels = [ 98 | { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, 99 | ] 100 | 101 | [[package]] 102 | name = "durationpy" 103 | version = "0.10" 104 | source = { registry = "https://pypi.org/simple" } 105 | sdist = { url = "https://files.pythonhosted.org/packages/9d/a4/e44218c2b394e31a6dd0d6b095c4e1f32d0be54c2a4b250032d717647bab/durationpy-0.10.tar.gz", hash = "sha256:1fa6893409a6e739c9c72334fc65cca1f355dbdd93405d30f726deb5bde42fba", size = 3335, upload-time = "2025-05-17T13:52:37.26Z" } 106 | wheels = [ 107 | { url = "https://files.pythonhosted.org/packages/b0/0d/9feae160378a3553fa9a339b0e9c1a048e147a4127210e286ef18b730f03/durationpy-0.10-py3-none-any.whl", hash = "sha256:3b41e1b601234296b4fb368338fdcd3e13e0b4fb5b67345948f4f2bf9868b286", size = 3922, upload-time = "2025-05-17T13:52:36.463Z" }, 108 | ] 109 | 110 | [[package]] 111 | name = "ecr-updater" 112 | version = "0.1.0" 113 | source = { virtual = "." } 114 | dependencies = [ 115 | { name = "boto3" }, 116 | { name = "kubernetes" }, 117 | { name = "loguru" }, 118 | { name = "python-json-logger" }, 119 | ] 120 | 121 | [package.metadata] 122 | requires-dist = [ 123 | { name = "boto3", specifier = ">=1.40.63" }, 124 | { name = "kubernetes", specifier = ">=34.1.0" }, 125 | { name = "loguru", specifier = ">=0.7.3" }, 126 | { name = "python-json-logger", specifier = ">=4.0.0" }, 127 | ] 128 | 129 | [[package]] 130 | name = "google-auth" 131 | version = "2.42.1" 132 | source = { registry = "https://pypi.org/simple" } 133 | dependencies = [ 134 | { name = "cachetools" }, 135 | { name = "pyasn1-modules" }, 136 | { name = "rsa" }, 137 | ] 138 | sdist = { url = "https://files.pythonhosted.org/packages/25/6b/22a77135757c3a7854c9f008ffed6bf4e8851616d77faf13147e9ab5aae6/google_auth-2.42.1.tar.gz", hash = "sha256:30178b7a21aa50bffbdc1ffcb34ff770a2f65c712170ecd5446c4bef4dc2b94e", size = 295541, upload-time = "2025-10-30T16:42:19.381Z" } 139 | wheels = [ 140 | { url = "https://files.pythonhosted.org/packages/92/05/adeb6c495aec4f9d93f9e2fc29eeef6e14d452bba11d15bdb874ce1d5b10/google_auth-2.42.1-py2.py3-none-any.whl", hash = "sha256:eb73d71c91fc95dbd221a2eb87477c278a355e7367a35c0d84e6b0e5f9b4ad11", size = 222550, upload-time = "2025-10-30T16:42:17.878Z" }, 141 | ] 142 | 143 | [[package]] 144 | name = "idna" 145 | version = "3.11" 146 | source = { registry = "https://pypi.org/simple" } 147 | sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" } 148 | wheels = [ 149 | { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, 150 | ] 151 | 152 | [[package]] 153 | name = "jmespath" 154 | version = "1.0.1" 155 | source = { registry = "https://pypi.org/simple" } 156 | sdist = { url = "https://files.pythonhosted.org/packages/00/2a/e867e8531cf3e36b41201936b7fa7ba7b5702dbef42922193f05c8976cd6/jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe", size = 25843, upload-time = "2022-06-17T18:00:12.224Z" } 157 | wheels = [ 158 | { url = "https://files.pythonhosted.org/packages/31/b4/b9b800c45527aadd64d5b442f9b932b00648617eb5d63d2c7a6587b7cafc/jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980", size = 20256, upload-time = "2022-06-17T18:00:10.251Z" }, 159 | ] 160 | 161 | [[package]] 162 | name = "kubernetes" 163 | version = "34.1.0" 164 | source = { registry = "https://pypi.org/simple" } 165 | dependencies = [ 166 | { name = "certifi" }, 167 | { name = "durationpy" }, 168 | { name = "google-auth" }, 169 | { name = "python-dateutil" }, 170 | { name = "pyyaml" }, 171 | { name = "requests" }, 172 | { name = "requests-oauthlib" }, 173 | { name = "six" }, 174 | { name = "urllib3" }, 175 | { name = "websocket-client" }, 176 | ] 177 | sdist = { url = "https://files.pythonhosted.org/packages/ef/55/3f880ef65f559cbed44a9aa20d3bdbc219a2c3a3bac4a30a513029b03ee9/kubernetes-34.1.0.tar.gz", hash = "sha256:8fe8edb0b5d290a2f3ac06596b23f87c658977d46b5f8df9d0f4ea83d0003912", size = 1083771, upload-time = "2025-09-29T20:23:49.283Z" } 178 | wheels = [ 179 | { url = "https://files.pythonhosted.org/packages/ca/ec/65f7d563aa4a62dd58777e8f6aa882f15db53b14eb29aba0c28a20f7eb26/kubernetes-34.1.0-py2.py3-none-any.whl", hash = "sha256:bffba2272534e224e6a7a74d582deb0b545b7c9879d2cd9e4aae9481d1f2cc2a", size = 2008380, upload-time = "2025-09-29T20:23:47.684Z" }, 180 | ] 181 | 182 | [[package]] 183 | name = "loguru" 184 | version = "0.7.3" 185 | source = { registry = "https://pypi.org/simple" } 186 | dependencies = [ 187 | { name = "colorama", marker = "sys_platform == 'win32'" }, 188 | { name = "win32-setctime", marker = "sys_platform == 'win32'" }, 189 | ] 190 | sdist = { url = "https://files.pythonhosted.org/packages/3a/05/a1dae3dffd1116099471c643b8924f5aa6524411dc6c63fdae648c4f1aca/loguru-0.7.3.tar.gz", hash = "sha256:19480589e77d47b8d85b2c827ad95d49bf31b0dcde16593892eb51dd18706eb6", size = 63559, upload-time = "2024-12-06T11:20:56.608Z" } 191 | wheels = [ 192 | { url = "https://files.pythonhosted.org/packages/0c/29/0348de65b8cc732daa3e33e67806420b2ae89bdce2b04af740289c5c6c8c/loguru-0.7.3-py3-none-any.whl", hash = "sha256:31a33c10c8e1e10422bfd431aeb5d351c7cf7fa671e3c4df004162264b28220c", size = 61595, upload-time = "2024-12-06T11:20:54.538Z" }, 193 | ] 194 | 195 | [[package]] 196 | name = "oauthlib" 197 | version = "3.3.1" 198 | source = { registry = "https://pypi.org/simple" } 199 | sdist = { url = "https://files.pythonhosted.org/packages/0b/5f/19930f824ffeb0ad4372da4812c50edbd1434f678c90c2733e1188edfc63/oauthlib-3.3.1.tar.gz", hash = "sha256:0f0f8aa759826a193cf66c12ea1af1637f87b9b4622d46e866952bb022e538c9", size = 185918, upload-time = "2025-06-19T22:48:08.269Z" } 200 | wheels = [ 201 | { url = "https://files.pythonhosted.org/packages/be/9c/92789c596b8df838baa98fa71844d84283302f7604ed565dafe5a6b5041a/oauthlib-3.3.1-py3-none-any.whl", hash = "sha256:88119c938d2b8fb88561af5f6ee0eec8cc8d552b7bb1f712743136eb7523b7a1", size = 160065, upload-time = "2025-06-19T22:48:06.508Z" }, 202 | ] 203 | 204 | [[package]] 205 | name = "pyasn1" 206 | version = "0.6.1" 207 | source = { registry = "https://pypi.org/simple" } 208 | sdist = { url = "https://files.pythonhosted.org/packages/ba/e9/01f1a64245b89f039897cb0130016d79f77d52669aae6ee7b159a6c4c018/pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034", size = 145322, upload-time = "2024-09-10T22:41:42.55Z" } 209 | wheels = [ 210 | { url = "https://files.pythonhosted.org/packages/c8/f1/d6a797abb14f6283c0ddff96bbdd46937f64122b8c925cab503dd37f8214/pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629", size = 83135, upload-time = "2024-09-11T16:00:36.122Z" }, 211 | ] 212 | 213 | [[package]] 214 | name = "pyasn1-modules" 215 | version = "0.4.2" 216 | source = { registry = "https://pypi.org/simple" } 217 | dependencies = [ 218 | { name = "pyasn1" }, 219 | ] 220 | sdist = { url = "https://files.pythonhosted.org/packages/e9/e6/78ebbb10a8c8e4b61a59249394a4a594c1a7af95593dc933a349c8d00964/pyasn1_modules-0.4.2.tar.gz", hash = "sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6", size = 307892, upload-time = "2025-03-28T02:41:22.17Z" } 221 | wheels = [ 222 | { url = "https://files.pythonhosted.org/packages/47/8d/d529b5d697919ba8c11ad626e835d4039be708a35b0d22de83a269a6682c/pyasn1_modules-0.4.2-py3-none-any.whl", hash = "sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a", size = 181259, upload-time = "2025-03-28T02:41:19.028Z" }, 223 | ] 224 | 225 | [[package]] 226 | name = "python-dateutil" 227 | version = "2.9.0.post0" 228 | source = { registry = "https://pypi.org/simple" } 229 | dependencies = [ 230 | { name = "six" }, 231 | ] 232 | sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } 233 | wheels = [ 234 | { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, 235 | ] 236 | 237 | [[package]] 238 | name = "python-json-logger" 239 | version = "4.0.0" 240 | source = { registry = "https://pypi.org/simple" } 241 | sdist = { url = "https://files.pythonhosted.org/packages/29/bf/eca6a3d43db1dae7070f70e160ab20b807627ba953663ba07928cdd3dc58/python_json_logger-4.0.0.tar.gz", hash = "sha256:f58e68eb46e1faed27e0f574a55a0455eecd7b8a5b88b85a784519ba3cff047f", size = 17683, upload-time = "2025-10-06T04:15:18.984Z" } 242 | wheels = [ 243 | { url = "https://files.pythonhosted.org/packages/51/e5/fecf13f06e5e5f67e8837d777d1bc43fac0ed2b77a676804df5c34744727/python_json_logger-4.0.0-py3-none-any.whl", hash = "sha256:af09c9daf6a813aa4cc7180395f50f2a9e5fa056034c9953aec92e381c5ba1e2", size = 15548, upload-time = "2025-10-06T04:15:17.553Z" }, 244 | ] 245 | 246 | [[package]] 247 | name = "pyyaml" 248 | version = "6.0.3" 249 | source = { registry = "https://pypi.org/simple" } 250 | sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } 251 | wheels = [ 252 | { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, 253 | { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, 254 | { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, 255 | { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, 256 | { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, 257 | { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, 258 | { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, 259 | { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, 260 | { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, 261 | { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, 262 | { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, 263 | { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, 264 | { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, 265 | { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, 266 | { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, 267 | { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, 268 | { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, 269 | { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, 270 | { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, 271 | { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, 272 | { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, 273 | { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, 274 | { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, 275 | { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, 276 | { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, 277 | { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, 278 | { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, 279 | { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, 280 | ] 281 | 282 | [[package]] 283 | name = "requests" 284 | version = "2.32.5" 285 | source = { registry = "https://pypi.org/simple" } 286 | dependencies = [ 287 | { name = "certifi" }, 288 | { name = "charset-normalizer" }, 289 | { name = "idna" }, 290 | { name = "urllib3" }, 291 | ] 292 | sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } 293 | wheels = [ 294 | { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, 295 | ] 296 | 297 | [[package]] 298 | name = "requests-oauthlib" 299 | version = "2.0.0" 300 | source = { registry = "https://pypi.org/simple" } 301 | dependencies = [ 302 | { name = "oauthlib" }, 303 | { name = "requests" }, 304 | ] 305 | sdist = { url = "https://files.pythonhosted.org/packages/42/f2/05f29bc3913aea15eb670be136045bf5c5bbf4b99ecb839da9b422bb2c85/requests-oauthlib-2.0.0.tar.gz", hash = "sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9", size = 55650, upload-time = "2024-03-22T20:32:29.939Z" } 306 | wheels = [ 307 | { url = "https://files.pythonhosted.org/packages/3b/5d/63d4ae3b9daea098d5d6f5da83984853c1bbacd5dc826764b249fe119d24/requests_oauthlib-2.0.0-py2.py3-none-any.whl", hash = "sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36", size = 24179, upload-time = "2024-03-22T20:32:28.055Z" }, 308 | ] 309 | 310 | [[package]] 311 | name = "rsa" 312 | version = "4.9.1" 313 | source = { registry = "https://pypi.org/simple" } 314 | dependencies = [ 315 | { name = "pyasn1" }, 316 | ] 317 | sdist = { url = "https://files.pythonhosted.org/packages/da/8a/22b7beea3ee0d44b1916c0c1cb0ee3af23b700b6da9f04991899d0c555d4/rsa-4.9.1.tar.gz", hash = "sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75", size = 29034, upload-time = "2025-04-16T09:51:18.218Z" } 318 | wheels = [ 319 | { url = "https://files.pythonhosted.org/packages/64/8d/0133e4eb4beed9e425d9a98ed6e081a55d195481b7632472be1af08d2f6b/rsa-4.9.1-py3-none-any.whl", hash = "sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762", size = 34696, upload-time = "2025-04-16T09:51:17.142Z" }, 320 | ] 321 | 322 | [[package]] 323 | name = "s3transfer" 324 | version = "0.14.0" 325 | source = { registry = "https://pypi.org/simple" } 326 | dependencies = [ 327 | { name = "botocore" }, 328 | ] 329 | sdist = { url = "https://files.pythonhosted.org/packages/62/74/8d69dcb7a9efe8baa2046891735e5dfe433ad558ae23d9e3c14c633d1d58/s3transfer-0.14.0.tar.gz", hash = "sha256:eff12264e7c8b4985074ccce27a3b38a485bb7f7422cc8046fee9be4983e4125", size = 151547, upload-time = "2025-09-09T19:23:31.089Z" } 330 | wheels = [ 331 | { url = "https://files.pythonhosted.org/packages/48/f0/ae7ca09223a81a1d890b2557186ea015f6e0502e9b8cb8e1813f1d8cfa4e/s3transfer-0.14.0-py3-none-any.whl", hash = "sha256:ea3b790c7077558ed1f02a3072fb3cb992bbbd253392f4b6e9e8976941c7d456", size = 85712, upload-time = "2025-09-09T19:23:30.041Z" }, 332 | ] 333 | 334 | [[package]] 335 | name = "six" 336 | version = "1.17.0" 337 | source = { registry = "https://pypi.org/simple" } 338 | sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } 339 | wheels = [ 340 | { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, 341 | ] 342 | 343 | [[package]] 344 | name = "urllib3" 345 | version = "2.3.0" 346 | source = { registry = "https://pypi.org/simple" } 347 | sdist = { url = "https://files.pythonhosted.org/packages/aa/63/e53da845320b757bf29ef6a9062f5c669fe997973f966045cb019c3f4b66/urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d", size = 307268, upload-time = "2024-12-22T07:47:30.032Z" } 348 | wheels = [ 349 | { url = "https://files.pythonhosted.org/packages/c8/19/4ec628951a74043532ca2cf5d97b7b14863931476d117c471e8e2b1eb39f/urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", size = 128369, upload-time = "2024-12-22T07:47:28.074Z" }, 350 | ] 351 | 352 | [[package]] 353 | name = "websocket-client" 354 | version = "1.9.0" 355 | source = { registry = "https://pypi.org/simple" } 356 | sdist = { url = "https://files.pythonhosted.org/packages/2c/41/aa4bf9664e4cda14c3b39865b12251e8e7d239f4cd0e3cc1b6c2ccde25c1/websocket_client-1.9.0.tar.gz", hash = "sha256:9e813624b6eb619999a97dc7958469217c3176312b3a16a4bd1bc7e08a46ec98", size = 70576, upload-time = "2025-10-07T21:16:36.495Z" } 357 | wheels = [ 358 | { url = "https://files.pythonhosted.org/packages/34/db/b10e48aa8fff7407e67470363eac595018441cf32d5e1001567a7aeba5d2/websocket_client-1.9.0-py3-none-any.whl", hash = "sha256:af248a825037ef591efbf6ed20cc5faa03d3b47b9e5a2230a529eeee1c1fc3ef", size = 82616, upload-time = "2025-10-07T21:16:34.951Z" }, 359 | ] 360 | 361 | [[package]] 362 | name = "win32-setctime" 363 | version = "1.2.0" 364 | source = { registry = "https://pypi.org/simple" } 365 | sdist = { url = "https://files.pythonhosted.org/packages/b3/8f/705086c9d734d3b663af0e9bb3d4de6578d08f46b1b101c2442fd9aecaa2/win32_setctime-1.2.0.tar.gz", hash = "sha256:ae1fdf948f5640aae05c511ade119313fb6a30d7eabe25fef9764dca5873c4c0", size = 4867, upload-time = "2024-12-07T15:28:28.314Z" } 366 | wheels = [ 367 | { url = "https://files.pythonhosted.org/packages/e1/07/c6fe3ad3e685340704d314d765b7912993bcb8dc198f0e7a89382d37974b/win32_setctime-1.2.0-py3-none-any.whl", hash = "sha256:95d644c4e708aba81dc3704a116d8cbc974d70b3bdb8be1d150e36be6e9d1390", size = 4083, upload-time = "2024-12-07T15:28:26.465Z" }, 368 | ] 369 | --------------------------------------------------------------------------------