Skip to content
Merged
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
24 changes: 17 additions & 7 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ Contents

* `Return all resources across all pages as a list`_

* `Interacting with Multiple Workspaces`_
* `Requests without a Workspace in Scope`_

* `Personal Access Token without a Workspace`_

* `Webhooks`_

Expand Down Expand Up @@ -367,20 +369,28 @@ Return all resources across all pages as a list

all_devices = paginator.flatten_to_list()

Interacting with Multiple Workspaces
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Requests without a Workspace in Scope
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Some Seam API endpoints interact with multiple workspaces. The ``SeamMultiWorkspace`` client is not bound to a specific workspace and may use those endpoints with a personal access token authentication method.
Some Seam API endpoints do not require a workspace in scope.
The ``SeamWithoutWorkspace`` client is not bound to a specific workspace
and may use those endpoints with an appropriate authentication method.

A Personal Access Token is scoped to a Seam Console user. Obtain one from the Seam Console.
Personal Access Token without a Workspace
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

A Personal Access Token is scoped to a Seam Console user.
Obtain one from the Seam Console.

.. code-block:: python

from seam import SeamWithoutWorkspace

# Pass as an option to the constructor
seam = SeamMultiWorkspace(personal_access_token="your-personal-access-token")
seam = SeamWithoutWorkspace(personal_access_token="your-personal-access-token")

# Use the factory method
seam = SeamMultiWorkspace.from_personal_access_token("your-personal-access-token")
seam = SeamWithoutWorkspace.from_personal_access_token("your-personal-access-token")

# List workspaces authorized for this Personal Access Token
workspaces = seam.workspaces.list()
Expand Down
2 changes: 1 addition & 1 deletion seam/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# type: ignore

from .seam import Seam
from .seam_multi_workspace import SeamMultiWorkspace
from .seam_without_workspace import SeamWithoutWorkspace
from .options import SeamInvalidOptionsError
from .auth import SeamInvalidTokenError
from .exceptions import (
Expand Down
2 changes: 1 addition & 1 deletion seam/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def get_auth_headers_for_personal_access_token(
}


def get_auth_headers_for_multi_workspace_personal_access_token(
def get_auth_headers_for_without_workspace_personal_access_token(
personal_access_token: str,
) -> dict:
if is_jwt(personal_access_token):
Expand Down
4 changes: 2 additions & 2 deletions seam/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def from_personal_access_token(
raise NotImplementedError


class AbstractSeamMultiWorkspaceWorkspaces(abc.ABC):
class AbstractSeamWithoutWorkspaceWorkspaces(abc.ABC):
@abc.abstractmethod
def create(
self,
Expand All @@ -65,7 +65,7 @@ def list(
raise NotImplementedError()


class AbstractSeamMultiWorkspace:
class AbstractSeamWithoutWorkspace:
lts_version: str
wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]]

Expand Down
22 changes: 11 additions & 11 deletions seam/seam_multi_workspace.py → seam/seam_without_workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
from typing_extensions import Self
from urllib3.util import Retry

from .auth import get_auth_headers_for_multi_workspace_personal_access_token
from .auth import get_auth_headers_for_without_workspace_personal_access_token
from .constants import DEFAULT_TIMEOUT, LTS_VERSION
from .options import get_endpoint
from .client import SeamHttpClient
from .models import AbstractSeamMultiWorkspace
from .models import AbstractSeamWithoutWorkspace
from .routes.workspaces import Workspaces


Expand All @@ -24,7 +24,7 @@ def create(self, **kwargs):
return self._workspaces.create(**kwargs)


class SeamMultiWorkspace(AbstractSeamMultiWorkspace):
class SeamWithoutWorkspace(AbstractSeamWithoutWorkspace):
"""
Seam class used to interact with Seam API without being scoped to a specific workspace.

Expand Down Expand Up @@ -56,9 +56,9 @@ def __init__(
niquests_options: Optional[Dict[str, Any]] = None,
):
"""
Initialize a SeamMultiWorkspace client instance.
Initialize a SeamWithoutWorkspace client instance.

This method sets up the SeamMultiWorkspace client with the provided personal access token
This method sets up the SeamWithoutWorkspace client with the provided personal access token
and configuration options.

:param personal_access_token: A personal access token for
Expand All @@ -83,9 +83,9 @@ def __init__(
:raises SeamInvalidTokenError: If the provided personal access token format is invalid
"""

self.lts_version = SeamMultiWorkspace.lts_version
self.lts_version = SeamWithoutWorkspace.lts_version
self.wait_for_action_attempt = wait_for_action_attempt
auth_headers = get_auth_headers_for_multi_workspace_personal_access_token(
auth_headers = get_auth_headers_for_without_workspace_personal_access_token(
personal_access_token
)
endpoint = get_endpoint(endpoint)
Expand Down Expand Up @@ -115,9 +115,9 @@ def from_personal_access_token(
niquests_options: Optional[Dict[str, Any]] = None,
) -> Self:
"""
Create a SeamMultiWorkspace instance using a personal access token.
Create a SeamWithoutWorkspace instance using a personal access token.

This class method is a convenience constructor for creating a SeamMultiWorkspace instance
This class method is a convenience constructor for creating a SeamWithoutWorkspace instance
authenticated with a personal access token.

:param personal_access_token: The personal access token for authenticating with Seam
Expand All @@ -130,13 +130,13 @@ def from_personal_access_token(
:type wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]]
:param retries: Configuration for retry behavior on failed requests
:type retries: Optional[urllib3.util.Retry]
:return: A new instance of the SeamMultiWorkspace class
:return: A new instance of the SeamWithoutWorkspace class
authenticated with the provided personal access token
:rtype: Self

:Example:

>>> seam = SeamMultiWorkspace.from_personal_access_token("your-personal-access-token-here")
>>> seam = SeamWithoutWorkspace.from_personal_access_token("your-personal-access-token-here")
"""

return cls(
Expand Down
26 changes: 13 additions & 13 deletions test/personal_access_token_test.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from seam import Seam, SeamMultiWorkspace
from seam import Seam, SeamWithoutWorkspace
from seam.auth import SeamInvalidTokenError

# UPSTREAM: The fake rejects a personal access token on /devices/list, so these
Expand Down Expand Up @@ -57,11 +57,11 @@ def test_seam_checks_personal_access_token_format():
Seam.from_personal_access_token("seam_pk_token", workspace_id)


def test_seam_multi_workspace_from_personal_access_token_returns_authorized_instance(
def test_seam_without_workspace_from_personal_access_token_returns_authorized_instance(
server,
):
endpoint, seed = server
seam = SeamMultiWorkspace.from_personal_access_token(
seam = SeamWithoutWorkspace.from_personal_access_token(
seed["seam_at1_token"], endpoint=endpoint
)

Expand All @@ -70,9 +70,9 @@ def test_seam_multi_workspace_from_personal_access_token_returns_authorized_inst
assert len(workspaces) > 0


def test_seam_multi_workspace_constructor_returns_authorized_instance(server):
def test_seam_without_workspace_constructor_returns_authorized_instance(server):
endpoint, seed = server
seam = SeamMultiWorkspace(
seam = SeamWithoutWorkspace(
personal_access_token=seed["seam_at1_token"], endpoint=endpoint
)

Expand All @@ -81,9 +81,9 @@ def test_seam_multi_workspace_constructor_returns_authorized_instance(server):
assert len(workspaces) > 0


def test_seam_multi_workspace_creates_a_workspace(server):
def test_seam_without_workspace_creates_a_workspace(server):
endpoint, seed = server
seam = SeamMultiWorkspace(
seam = SeamWithoutWorkspace(
personal_access_token=seed["seam_at1_token"], endpoint=endpoint
)

Expand All @@ -96,18 +96,18 @@ def test_seam_multi_workspace_creates_a_workspace(server):
assert workspace.workspace_id is not None


def test_seam_multi_workspace_checks_personal_access_token_format():
def test_seam_without_workspace_checks_personal_access_token_format():
with pytest.raises(SeamInvalidTokenError, match=r"Unknown"):
SeamMultiWorkspace.from_personal_access_token("some-invalid-key-format")
SeamWithoutWorkspace.from_personal_access_token("some-invalid-key-format")

with pytest.raises(SeamInvalidTokenError, match=r"Unknown"):
SeamMultiWorkspace.from_personal_access_token("seam_apikey_token")
SeamWithoutWorkspace.from_personal_access_token("seam_apikey_token")

with pytest.raises(SeamInvalidTokenError, match=r"Client Session Token"):
SeamMultiWorkspace.from_personal_access_token("seam_cst")
SeamWithoutWorkspace.from_personal_access_token("seam_cst")

with pytest.raises(SeamInvalidTokenError, match=r"JWT"):
SeamMultiWorkspace.from_personal_access_token("ey")
SeamWithoutWorkspace.from_personal_access_token("ey")

with pytest.raises(SeamInvalidTokenError, match=r"Publishable Key"):
SeamMultiWorkspace.from_personal_access_token("seam_pk_token")
SeamWithoutWorkspace.from_personal_access_token("seam_pk_token")
Loading