{"id":3727,"library":"oras","title":"ORAS Python SDK","description":"ORAS Python SDK (Open Container Initiative Registry as Storage) is a Python library that enables users to push and pull OCI Artifacts to and from OCI-conformant registries. The current version is 0.2.42, and the project maintains an active and rapid release cadence with frequent updates.","status":"active","version":"0.2.42","language":"en","source_language":"en","source_url":"https://github.com/oras-project/oras-py","tags":["oci","registry","container","storage","artifacts"],"install":[{"cmd":"pip install oras","lang":"bash","label":"Base Installation"},{"cmd":"pip install oras[ecr]","lang":"bash","label":"With AWS ECR Authentication"}],"dependencies":[{"reason":"Used for HTTP communication with registries.","package":"requests","optional":false},{"reason":"Used for OCI schema validation.","package":"jsonschema","optional":false},{"reason":"Required for AWS ECR specific authentication mechanisms.","package":"ecr","optional":true}],"imports":[{"note":"The primary client for interacting with OCI registries.","symbol":"OrasClient","correct":"from oras.client import OrasClient"},{"note":"Used for creating OCI manifest configuration objects.","symbol":"ManifestConfig","correct":"from oras.oci import ManifestConfig"}],"quickstart":{"code":"import os\nfrom oras.client import OrasClient\n\n# Prepare a dummy file to push\nwith open('artifact.txt', 'w') as f:\n    f.write('Hello, ORAS!')\n\nregistry_hostname = os.environ.get('ORAS_REGISTRY_HOSTNAME', 'localhost:5000')\nrepository_target = f\"{registry_hostname}/my/artifact:v1\"\nusername = os.environ.get('ORAS_USERNAME', '')\npassword = os.environ.get('ORAS_PASSWORD', '')\n\nclient = OrasClient(hostname=registry_hostname, insecure=True) # Use insecure=True for local registries without TLS\n\nif username and password:\n    print(f\"Attempting to login to {registry_hostname}...\")\n    try:\n        client.login(username=username, password=password)\n        print(\"Login successful.\")\n    except Exception as e:\n        print(f\"Login failed: {e}\")\n        # Depending on local setup, login might not be strictly necessary for insecure local registries\n\nprint(f\"Pushing artifact to {repository_target}...\")\ntry:\n    push_response = client.push(files=[\"artifact.txt\"], target=repository_target)\n    print(f\"Push successful: {push_response}\")\nexcept Exception as e:\n    print(f\"Push failed: {e}\")\n    print(\"Ensure a registry is running at and accessible from '\" + registry_hostname + \"'. For example: 'docker run -d -p 5000:5000 --name oras-quickstart ghcr.io/oras-project/registry:latest'\")\n\n# Clean up after push if successful\n# os.remove('artifact.txt') # Uncomment to clean up\n\n# For pulling, create a new directory to avoid conflicts if artifact.txt already exists\npull_dir = './pulled_artifacts'\nos.makedirs(pull_dir, exist_ok=True)\n\nprint(f\"Pulling artifact from {repository_target} into {pull_dir}...\")\ntry:\n    # Pulls into the current working directory by default, unless oras.utils.workdir is used\n    # For this example, we'll let it pull to current dir and specify path for clarity\n    pulled_files = client.pull(target=repository_target, output_dir=pull_dir)\n    print(f\"Pull successful. Files: {pulled_files}\")\n    # Verify content if needed\n    # with open(os.path.join(pull_dir, 'artifact.txt'), 'r') as f:\n    #     print(f.read())\nexcept Exception as e:\n    print(f\"Pull failed: {e}\")\n\n# Cleanup pulled files\n# import shutil\n# shutil.rmtree(pull_dir)\n# os.remove('artifact.txt') # If not removed after push\n","lang":"python","description":"This quickstart demonstrates how to initialize an `OrasClient`, log in (if necessary), and then push and pull a simple artifact to/from an OCI-compliant registry. It uses environment variables for registry hostname, username, and password for flexibility, falling back to a local insecure registry setup for ease of testing."},"warnings":[{"fix":"Ensure you install the `ecr` extra: `pip install oras[ecr]`.","message":"AWS ECR authentication support (`oras[ecr]`) was moved to an optional extra. If you were previously relying on ECR authentication without explicitly installing `oras[ecr]`, your setup will break.","severity":"breaking","affected_versions":"0.2.35 and earlier"},{"fix":"Upgrade to `oras>=0.2.39` or ensure your Python environment is 3.8+ if you encounter syntax errors related to type hints.","message":"Python 3.7+ compatibility was fixed, specifically regarding the use of union syntax (e.g., `list | None`). If you are using Python 3.7 or older, or if your environment relied on previous (potentially broken) behavior, this might affect you.","severity":"breaking","affected_versions":"0.2.38 and earlier"},{"fix":"Review your authentication setup and test with `oras>=0.2.36` to ensure credentials are resolved as expected. Debug authentication issues using the client's debug logs.","message":"The authentication priority for various credential sources (AWS-native, docker login, credHelpers, credsStore) has been explicitly fixed and re-ordered. If your environment relies on a specific order of credential resolution, this change might alter how your client authenticates.","severity":"gotcha","affected_versions":"0.2.35 and earlier"},{"fix":"Ensure you are on the latest `oras` version to benefit from `credsStore`/`credHelpers` bug fixes. Verify your Docker configuration (`~/.docker/config.json`) and the availability of helper binaries.","message":"There have been multiple fixes related to how Docker's `credsStore` and `credHelpers` binaries are located and used for authentication. Users relying on these Docker credential helpers might experience intermittent authentication failures or incorrect credential resolution.","severity":"gotcha","affected_versions":"Prior to 0.2.40 (and 0.2.37, 0.2.34)"},{"fix":"When pulling, consider using unique output directories or carefully inspect the pulled files if you suspect filename collisions. Monitor the GitHub issues for a resolution.","message":"An open issue indicates potential data loss where `oras-py` strips paths to basename during pull operations, leading to filename collisions if multiple artifacts share the same basename. This could result in one artifact overwriting another upon pulling.","severity":"gotcha","affected_versions":"All versions up to 0.2.42 (as of April 2026)"}],"env_vars":null,"last_verified":"2026-04-11T00:00:00.000Z","next_check":"2026-07-10T00:00:00.000Z"}