Skip to content

Commit

Permalink
feat: adds bundle create and download
Browse files Browse the repository at this point in the history
  • Loading branch information
tdstein committed Apr 23, 2024
1 parent 90b6f83 commit 4e78efd
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 2 deletions.
54 changes: 53 additions & 1 deletion src/posit/connect/bundles.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import annotations

from typing import List
from typing import BinaryIO, List

from requests.sessions import Session as Session

Expand Down Expand Up @@ -99,6 +99,25 @@ def delete(self) -> None:
url = urls.append(self.config.url, path)
self.session.delete(url)

def download(self) -> bytes:
"""Download a bundle.
Returns
-------
bytes
Archive contents in bytes representation.
Examples
--------
>>> with open('archive.tar.gz', 'wb') as file:
>>> data = bundle.download()
>>> file.write(data)
"""
path = f"v1/content/{self.content_guid}/bundles/{self.id}/download"
url = urls.append(self.config.url, path)
response = self.session.get(url, stream=True)
return response.content


class Bundles(Resources):
def __init__(
Expand All @@ -107,6 +126,39 @@ def __init__(
super().__init__(config, session)
self.content_guid = content_guid

def create(self, data: BinaryIO | bytes) -> Bundle:
"""Create a bundle.
Create a bundle by upload via archive format.
Parameters
----------
data : BinaryIO | bytes
Archive contents in BinaryIO or bytes representation.
Returns
-------
Bundle
Examples
--------
Create a bundle using a file object.
>>> with open('bundle.tar.gz', 'rb') as file:
>>> bundle.create(file)
Create a bundle using bytes.
>>> with open('bundle.tar.gz', 'rb') as file:
>>> data = file.read()
>>> bundle.create(data)
"""
path = f"v1/content/{self.content_guid}/bundles"
url = urls.append(self.config.url, path)
response = self.session.post(url, data=data)
result = response.json()
return Bundle(self.config, self.session, **result)

def find(self) -> List[Bundle]:
path = f"v1/content/{self.content_guid}/bundles"
url = urls.append(self.config.url, path)
Expand Down
Binary file not shown.
4 changes: 4 additions & 0 deletions tests/posit/connect/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,7 @@ def load_mock(path: str) -> dict:
>>> data = load_mock("v1/example.jsonc")
"""
return json.loads((Path(__file__).parent / "__api__" / path).read_text())


def get_path(path: str) -> Path:
return Path(__file__).parent / "__api__" / path
81 changes: 80 additions & 1 deletion tests/posit/connect/test_bundles.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import requests
import responses

from responses import matchers

from posit.connect import Client
from posit.connect.config import Config
from posit.connect.bundles import Bundle

from .api import load_mock # type: ignore
from .api import load_mock, get_path # type: ignore


class TestBundleProperties:
Expand Down Expand Up @@ -119,6 +121,83 @@ def test(self):
assert mock_bundle_delete.call_count == 1


class TestBundleDownload:
@responses.activate
def test(self):
content_guid = "f2f37341-e21d-3d80-c698-a935ad614066"
bundle_id = "101"
path = get_path(
f"v1/content/{content_guid}/bundles/{bundle_id}/download/bundle.tar.gz"
)

# behavior
mock_content_get = responses.get(
f"https://connect.example/__api__/v1/content/{content_guid}",
json=load_mock(f"v1/content/{content_guid}.json"),
)

mock_bundle_get = responses.get(
f"https://connect.example/__api__/v1/content/{content_guid}/bundles/{bundle_id}",
json=load_mock(
f"v1/content/{content_guid}/bundles/{bundle_id}.json"
),
)

mock_bundle_download = responses.get(
f"https://connect.example/__api__/v1/content/{content_guid}/bundles/{bundle_id}/download",
body=path.read_bytes(),
)

# setup
c = Client("12345", "https://connect.example")
bundle = c.content.get(content_guid).bundles.get(bundle_id)

# invoke
data = bundle.download()

# assert
assert mock_content_get.call_count == 1
assert mock_bundle_get.call_count == 1
assert mock_bundle_download.call_count == 1
assert data == path.read_bytes()


class TestBundlesCreate:
@responses.activate
def test(self):
content_guid = "f2f37341-e21d-3d80-c698-a935ad614066"
bundle_id = "101"
path = get_path(
f"v1/content/{content_guid}/bundles/{bundle_id}/download/bundle.tar.gz"
)

# behavior
mock_content_get = responses.get(
f"https://connect.example/__api__/v1/content/{content_guid}",
json=load_mock(f"v1/content/{content_guid}.json"),
)

mock_bundle_post = responses.post(
f"https://connect.example/__api__/v1/content/{content_guid}/bundles",
json=load_mock(
f"v1/content/{content_guid}/bundles/{bundle_id}.json"
),
)

# setup
c = Client("12345", "https://connect.example")
content = c.content.get(content_guid)

# invoke
data = path.read_bytes()
bundle = content.bundles.create(data)

# # assert
assert bundle.id == "101"
assert mock_content_get.call_count == 1
assert mock_bundle_post.call_count == 1


class TestBundlesFind:
@responses.activate
def test(self):
Expand Down

0 comments on commit 4e78efd

Please sign in to comment.