Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Event types #289

Merged
merged 9 commits into from
Jul 25, 2024
Merged

Add Event types #289

merged 9 commits into from
Jul 25, 2024

Conversation

tribble
Copy link

@tribble tribble commented Jul 24, 2024

Description

Initial PR to add two event types. It's most crucial to get feedback on the approach, then we can add more types in following PRs.

Documentation

Does this require changes to the WorkOS Docs? E.g. the API Reference or code snippets need updates.

[ ] Yes

If yes, link a related docs PR and add a docs maintainer as a reviewer. Their approval is required.

@tribble tribble requested a review from a team as a code owner July 24, 2024 19:08
@tribble tribble requested review from gcarvelli and mattgd and removed request for a team July 24, 2024 19:08
workos/events.py Outdated
Comment on lines 84 to 85
# TODO: This is a hack, and it's wrong. Events does not support before or order
"before": None,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit unclear - why do we need to define before here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our current list params typing forces it. We need to refactor but I'm kicking that can down the road to a future PR.

workos/events.py Outdated
Comment on lines 153 to 145
return WorkOsListResource(
list_method=self.list_events,
list_args=params,
**ListPage[Event](**response).model_dump(),
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh interesting. Does this work without issue for async? I may have to revisit this in my PR.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I doubt it. We probably need to parametrize the list resource to use an async client. But I haven't gotten there yet

@tribble
Copy link
Author

tribble commented Jul 24, 2024

@mattgd Switching this back to draft. Need to fix some tests and there may be some real work to make the auto paging iter async

@tribble tribble marked this pull request as draft July 24, 2024 19:26
@mattgd
Copy link
Contributor

mattgd commented Jul 24, 2024

@mattgd Switching this back to draft. Need to fix some tests and there may be some real work to make the auto paging iter async

@tribble Before you troubleshoot, I have an addition for that in my PR - let me know what you think: https://github.com/workos/workos-python/pull/288/files#diff-fd823a1e532828a74cb86c58012687832231229d0985952f4580c40ab33c3191R206-R225.

@tribble
Copy link
Author

tribble commented Jul 24, 2024

@mattgd OK, PR ready for review. Events has enough quirks this required some changes. Will comment inline.

@tribble tribble marked this pull request as ready for review July 24, 2024 23:41
@@ -153,7 +153,7 @@ def inner(
http_client: Union[SyncHTTPClient, AsyncHTTPClient],
data_list: list,
status_code: int = 200,
headers: Mapping[str, str] = None,
headers: Optional[Mapping[str, str]] = None,
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should point mypy at more of our files?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seemingly we should be able to open it up to all workos/ files. That's how I was running it locally. If we're having a mypy mismatch we should adjust settings to make sure it runs how we'd like in CI.

# We normalize this to 'active' in the SDK. This helper function
# does this conversion to make make assertions easier.
if directory["state"] == "linked":
return {**directory, "state": "active"}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I bit the bullet and just did this conversion instead of having two types.

@@ -73,7 +87,7 @@ def mock_group(self):

@pytest.fixture
def mock_directories(self):
directory_list = [MockDirectory(id=str(i)).to_dict() for i in range(20)]
directory_list = [MockDirectory(id=str(i)).to_dict() for i in range(10)]
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our list pages default to 10 anyway

@@ -8,8 +8,9 @@ def __init__(self, id):
self.object = "directory"
self.id = id
self.organization_id = "organization_id"
self.domain = "crashlanding.com"
self.name = "Ri Jeong Hyeok"
self.external_key = "ext_123"
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This external key is actually required. See our API ref (which isn't consistent, sigh) as well as our API JSON model and Event JSON model.

from workos.resources.base import WorkOSBaseResource


class MockDirectoryActivatedPayload(WorkOSBaseResource):
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was easier than mangling the existing MockDirectory model

from workos.resources.base import WorkOSBaseResource


class MockEvent(WorkOSBaseResource):
def __init__(self, id):
self.object = "event"
self.id = id
self.event = "dsync.user.created"
self.data = {"id": "event_01234ABCD", "organization_id": "org_1234"}
self.event = "dsync.activated"
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had to switch to an event that actually exists



def list_data_to_dicts(list_data: List):
def list_data_to_dicts(list_data: Sequence):
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use a more generic duck type?

@@ -4,7 +4,6 @@
from workos.utils.http_client import AsyncHTTPClient, SyncHTTPClient
from workos.utils.pagination_order import PaginationOrder
from workos.utils.request import REQUEST_METHOD_DELETE, REQUEST_METHOD_GET

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hates me rando newlines

"events": events,
"limit": limit,
"after": after,
"organization_id": organization_id,
"organization_id": organization,
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now our other API methods just use organization.

I'm conforming for consistency. Happy to have a cleanup PR sweep through and change all of those params to organization_id

return WorkOsListResource(
list_method=self.list_events,
list_args=params,
**ListPage[Event](**response).model_dump(exclude_unset=True),
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to use exclude_unset=True otherwise this would always serialize before in the list_metadata. I think it's because the resource can't tell the difference between ListAfterMetadata and ListMetadata.

The other option is to and a third generic parameter and explicitly pass in the ListMetadata shape. But, since python type hint generics don't set support default values for generics, every list resource would have to pass in the list metadata type.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realized there is another option. We could have separate WorkOsForwardListResource and WorkOsBidirectionalListResource.

Not sure how much benefit that will bring. It would almost definitely be more code.

from workos.typing.literals import LiteralOrUntyped

DirectoryState = Literal[
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extracted to a shared type which normalizes state

@@ -1,42 +0,0 @@
from workos.resources.base import WorkOSBaseResource
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wasn't used ¯\_(ツ)_/¯

Comment on lines +165 to +171
fixed_pagination_params = cast(
# Type hints consider this a mismatch because it assume the dictionary is dict[str, int]
Dict[str, Union[int, str, None]],
{
"limit": self.list_args["limit"],
},
)
Copy link
Author

@tribble tribble Jul 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type hints were a bit "too smart". Since self.list_args["limit"] is an int it considers the entire dictionary to be of type Dict[str, int].

"limit": self.list_args["limit"],
},
)
if "order" in self.list_args:
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Order isn't a thing for events.

Comment on lines +15 to +19
def convert_linked_to_active(value: Any, info: ValidationInfo) -> Any:
if isinstance(value, str) and value == "linked":
return "active"
else:
return value
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🙃

@@ -153,7 +153,7 @@ def inner(
http_client: Union[SyncHTTPClient, AsyncHTTPClient],
data_list: list,
status_code: int = 200,
headers: Mapping[str, str] = None,
headers: Optional[Mapping[str, str]] = None,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seemingly we should be able to open it up to all workos/ files. That's how I was running it locally. If we're having a mypy mismatch we should adjust settings to make sure it runs how we'd like in CI.

@mattgd mattgd merged commit f2ecb38 into beta-5.0 Jul 25, 2024
5 checks passed
@mattgd mattgd deleted the add-event-types branch July 25, 2024 16:29
tribble added a commit that referenced this pull request Jul 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants