-
Notifications
You must be signed in to change notification settings - Fork 12
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
Refactor and streamline organization and set base for SDK typing #284
Conversation
Removed deprecated organization methods and updated organization tests. Also, migrated organization.py to Pydantic models, and added mypy typing for more strict type checking. Additionally, enhance auto-paging to work with new models and restructured fixtures for organization tests.
b6fc19d
to
e9a1274
Compare
workos/organizations.py
Outdated
order=None, | ||
): | ||
domains: Optional[List[str]] = None, | ||
limit: Optional[int] = None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If limit
has a default value of RESPONSE_LIMIT
below, any reason not to make that the default value here?
limit: Optional[int] = None, | |
limit: Optional[int] = RESPONSE_LIMIT, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... and remove the default_limit = True
below. It doesn't seem to do anything.
…oughts on the approach
…s to a typing directory
@@ -45,7 +47,7 @@ def inner(method, response_dict, status_code, headers=None): | |||
def mock(*args, **kwargs): | |||
return MockResponse(response_dict, status_code, headers=headers) | |||
|
|||
monkeypatch.setattr(requests, method, mock) | |||
monkeypatch.setattr(requests, "request", mock) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed how we call requests
, rather than using get_attr
to retrieve the function by name, always wall request.request
and pass in the method
|
||
|
||
@pytest.fixture | ||
def mock_pagination_request(monkeypatch): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like how complex this test function is, but we need to roughly emulate the behavior of a pagination endpoint and return different pages of data in successive calls.
@@ -18,110 +22,19 @@ def mock_users(self): | |||
return { | |||
"data": user_list, | |||
"list_metadata": {"before": None, "after": None}, | |||
"metadata": { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of this no longer used/needed
limit: int = RESPONSE_LIMIT, | ||
before: Optional[str] = None, | ||
after: Optional[str] = None, | ||
order: PaginationOrder = "desc", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optional[PaginationOrder] = "desc"
is not what we want here. That allows None
as a possible value. This disallows None
and does not require order
to be specified.
token=workos.api_key, | ||
return WorkOsListResource( | ||
list_method=self.list_users, | ||
# TODO: Should we even bother with this validation? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My current opinion is no. But want to constrain scope of this PR and fix later
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Loaded up the page before you posted this, but down to omit. Better to be consistent everywhere IMO, and I think on Friday we decided against explicit input validation like this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Will remove in a follow-on PR
"""Delete one existing Directory. | ||
|
||
Args: | ||
directory (str): The ID of the directory to be deleted. (Required) | ||
|
||
Returns: | ||
dict: Directories response from WorkOS. | ||
None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah. Our doc here was a lie. We return an empty 202
workos/typing/enums.py
Outdated
|
||
EnumType = TypeVar("EnumType", bound=Enum) | ||
|
||
# Identical to the literal or strings path, except meant for a literal of enum values. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I just delete this from the PR? Not being used at the moment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, can delete.
|
||
params = { | ||
"domains": domains, | ||
"limit": limit, | ||
"before": before, | ||
"after": after, | ||
"order": order or "desc", | ||
"order": order, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With order
previously being passed as None
, this doesn't change the default ordering at all, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously if order
was not passed in, the value would fall back to "desc"
. Instead that default moves to the function signature: order: PaginationOrder = "desc"
workos/resources/directory_sync.py
Outdated
# Toying around with the differences in type hinting or deserialization for enums vs literals. In the end pretty equivalent, | ||
# it's a question of whether we want to present strings or DirectoryState.ACTIVE to the user | ||
# leaving both options here for now until we settle on a preference |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this comment be removed now?
workos/resources/organizations.py
Outdated
class OrganizationDomain(WorkOSModel): | ||
id: str | ||
organization_id: str | ||
object: Literal["organization"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be Literal["organization_domain"]
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It sure should
# These fields end up exposed in the types. Does we care? | ||
list_method: Callable = Field(exclude=True) | ||
list_args: ListArgs = Field(exclude=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where do these fields this show up in types exactly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
workos/resources/list.py
Outdated
# add all possible generics of List Resource | ||
T = TypeVar("T", Organization, Directory, DirectoryGroup, DirectoryUser) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like we could name this something better like "ListableResource".
# TODO: Should we even bother with this validation? | ||
list_args=ListArgs.model_validate(params), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like the call made Friday was that we wouldn't focus on inbound param validation. I'm okay with either, but we should probably be consistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will remove in a follow-up.
* Refactor and streamline organization tests and resources Removed deprecated organization methods and updated organization tests. Also, migrated organization.py to Pydantic models, and added mypy typing for more strict type checking. Additionally, enhance auto-paging to work with new models and restructured fixtures for organization tests. * Switch directories over to new list resources and add typing * Mark version as alpha * Formatting and some type fixes * Add defaults for all optional fields * Type dsync getters * Possible path forward for unknown literal values * Move comments * Export the untyped type and a type guard. Leave a comment about my thoughts on the approach * Test out literals of strings vs enums and factor out types and helpers to a typing directory * Settled on an approach for untyped literals * A little refactoring * More accurate validation for UntypedLiteral * Comments reminding us to clean up * Add typing to the rest of the dsync methods * Just some formattin' * A little more cleanup to unify organizations and dsync * Fix organizations test * DirectorySync tests passing, but still need some cleanup * Do not bump version yet * Formatting * Clean up by removing the enum paths * Small fixed for compat * More formatting and compat * Start fixing dsync tests * Fix another dsync test * Fix more dsync tests * Fix params, optional allows None, instead can force default * Directory sync tests are green * Fix audit logs test * Fix organizations test * Fix auto paging iter tests * Remove debugging print * Fix user management tests * Switch override to typing_extensions * Build fixes. Proper dict override and remove duplicate model key * Add directory sync resource to mypy.ini * Pantera can't spell * Fix type and delete unused fixtures * Remove unused import * Update dsync tests to new pagination helper * Delete unused fixtures * Remove some unneeded comments * PR feedback * Remove trailing comma in mypy.ini --------- Co-authored-by: Peter Arzhintar <[email protected]>
WorkOsListResource
to fix.auto_pagination_iter()
for list methodspydandic
for setting new resource classes forOrganization
and other entities (come later)types-requests
as mypy complained for typingrequests
libmypy
(initially scoping toworkos/organizations.py
)workos/organizations.py
- methods returnpydandic
models.list_organizations_v2()
method since they were meant to work with.auto_pagination_iter()
, but it wasn't functional