Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ To install from pip:
pip install pydo
```

For async support, install with the `aio` extra:

```shell
pip install pydo[aio]
```

## **`pydo` Quickstart**

> A quick guide to getting started with the client.
Expand All @@ -36,6 +42,22 @@ from pydo import Client
client = Client(token=os.getenv("DIGITALOCEAN_TOKEN"))
```

For asynchronous operations, use the `AsyncClient`:

```python
import os
import asyncio
from pydo import AsyncClient

async def main():
client = AsyncClient(token=os.getenv("DIGITALOCEAN_TOKEN"))
# Use await for async operations
result = await client.ssh_keys.list()
print(result)

asyncio.run(main())
```

#### Example of Using `pydo` to Access DO Resources

Find below a working example for GETting a ssh_key ([per this http request](https://docs.digitalocean.com/reference/api/api-reference/#operation/sshKeys_list)) and printing the ID associated with the ssh key. If you'd like to try out this quick example, you can follow [these instructions](https://docs.digitalocean.com/products/droplets/how-to/add-ssh-keys/) to add ssh keys to your DO account.
Expand Down
3 changes: 2 additions & 1 deletion src/pydo/_patch.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

from pydo.custom_policies import CustomHttpLoggingPolicy
from pydo import GeneratedClient, _version
from pydo.aio import AsyncClient

if TYPE_CHECKING:
# pylint: disable=unused-import,ungrouped-imports
Expand Down Expand Up @@ -49,7 +50,7 @@ def __init__(self, token: str, *, timeout: int = 120, **kwargs):
)


__all__ = ["Client"]
__all__ = ["Client", "AsyncClient"]


def patch_sdk():
Expand Down
4 changes: 4 additions & 0 deletions src/pydo/aio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@
_patch_all = []
from ._patch import patch_sdk as _patch_sdk

# Alias Client as AsyncClient for easier access
AsyncClient = Client

__all__ = [
"GeneratedClient",
"AsyncClient",
]
__all__.extend([p for p in _patch_all if p not in __all__])

Expand Down
26 changes: 26 additions & 0 deletions src/pydo/operations/_patch.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
from typing import TYPE_CHECKING

from ._operations import DropletsOperations as Droplets
from ._operations import KubernetesOperations as Kubernetes
from ._operations import InvoicesOperations as Invoices

if TYPE_CHECKING:
# pylint: disable=unused-import,ungrouped-imports
Expand All @@ -25,3 +27,27 @@ def patch_sdk():
you can't accomplish using the techniques described in
https://aka.ms/azsdk/python/dpcodegen/python/customize
"""

# Fix kubernetes.get_kubeconfig to return raw YAML content instead of trying to parse as JSON
def _get_kubeconfig(self, cluster_id, **kwargs):
"""Get a Kubernetes config file for the specified cluster."""
# Call the original method but with raw response
response = self._client.get(
f"/v2/kubernetes/clusters/{cluster_id}/kubeconfig",
**kwargs
)
return response.content

Kubernetes.get_kubeconfig = _get_kubeconfig

# Fix invoices.get_pdf_by_uuid to return raw PDF content instead of trying to parse as JSON
def _get_pdf_by_uuid(self, invoice_uuid, **kwargs):
"""Get a PDF invoice by UUID."""
# Call the original method but with raw response
response = self._client.get(
f"/v2/customers/my/invoices/{invoice_uuid}/pdf",
**kwargs
)
return response.content

Invoices.get_pdf_by_uuid = _get_pdf_by_uuid
5 changes: 2 additions & 3 deletions tests/mocked/test_billing.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,12 +203,11 @@ def test_get_invoice_pdf_by_uuid(mock_client: Client, mock_client_url):
responses.add(
responses.GET,
f"{mock_client_url}/v2/customers/my/invoices/1/pdf",
json=expected,
body=expected,
)
invoices = mock_client.invoices.get_pdf_by_uuid(invoice_uuid=1)
list_in = list(invoices)

assert "group_description" in str(list_in)
assert "group_description" in str(invoices)


@responses.activate
Expand Down
3 changes: 0 additions & 3 deletions tests/mocked/test_kubernetes.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,9 +211,6 @@ def test_kubernetes_get_kubeconfig(mock_client: Client, mock_client_url):
)

config_resp = mock_client.kubernetes.get_kubeconfig(cluster_id)
pytest.skip("The operation currently fails to return content.")
# TODO: investigate why the generated client doesn't return the response content
# It seems to be something to do with the yaml content type.
assert config_resp.decode("utf-8") == expected


Expand Down