Skip to content

feat: add phase 4 models#24

Open
Sivivatu wants to merge 42 commits intomasterfrom
03-18-feat_add_phase_4_models
Open

feat: add phase 4 models#24
Sivivatu wants to merge 42 commits intomasterfrom
03-18-feat_add_phase_4_models

Conversation

@Sivivatu
Copy link
Copy Markdown
Owner

No description provided.

Sivivatu and others added 30 commits March 18, 2026 13:14
- restructure tasks, add phases, and enhance documentation
* docs: record Phase 1 PR completion and update next steps

* feat: implement JobResource with run/status/output and polling helpers

* feat: add jobs resource property to sync client

* chore: export job resources from package __init__.py

* feat: add jobs resource property to async client

* test: add unit tests for JobResource with respx mocking

* docs: Phase 2 complete (9/9 tasks done)

* docs: add Pull Requests section and update Phase 2 status

* test: add quick test script for local testing
* Initial plan

* fix: guard raise last_exception against NoneType; fix import errors; add retry unit tests

Co-authored-by: Sivivatu <7496456+Sivivatu@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Sivivatu <7496456+Sivivatu@users.noreply.github.com>
Sivivatu added 12 commits March 18, 2026 14:07
## Summary

This PR completes the migration from Poetry to UV with final fixes and configuration updates.

### Changes
- ✅ Fix pyproject.toml schema violation (removed conflicting dynamic version)
- ✅ Complete branch-updates workflow migration from Poetry to UV
- ✅ Fix PRP prompt files (correct 'mode' to 'agent')

### Stack Structure
This PR is stacked on top of #4 and should be merged after Phase 1 & 2 are complete.

**Stack:**
- master ← #4 (agentic_process_updates) ← this PR (ci-uv-final-fixes)

### Related
- Builds on #7 (Migrate CI/CD pipelines from Poetry to UV)
- Part of the v0.2.0 development cycle
… handling

- Remove duplicate empty AlteryxClient class causing IndentationError
- Change AsyncJobResource.cancel() to catch NotFoundError by type
  instead of fragile string matching on exception message
- Update imports from old alteryx_gallery_api to alteryx_server_py
- Replace responses library mocks with respx/unittest.mock for httpx
- Align test fixtures with new client constructor (client_id/client_secret)
- Use resource-based API (client.workflows.list()) instead of removed methods
- Fix test_exceptions.py infinite recursion from Windows path handling
- Fix test_job_resource.py async/sync mismatch and respx mock patterns
- Correct test data to use valid ExecutionMode enum values
- Add None guard for _client before request calls in AlteryxClient
- Remove str from data parameter union (httpx doesn't accept str for data=)
- Remove unused Union import from client.py
- Type-narrow _client in JobResource and AsyncJobResource
- Use JobPriority enum conversion for priority parameter
- Use cast() for ambiguous return types in get_output methods
- Remove invalid message kwarg from JobNotFoundError calls
@Sivivatu Sivivatu mentioned this pull request Mar 18, 2026
Copy link
Copy Markdown
Owner Author

Sivivatu commented Mar 18, 2026

@Sivivatu Sivivatu marked this pull request as ready for review March 18, 2026 17:03
Copilot AI review requested due to automatic review settings March 18, 2026 17:03
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: df3a25e990

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +107 to +108
expiration_date: Optional[datetime] = Field(None, alias="expirationDate")
permissions: CollectionPermission
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Split user permission updates from group permission updates

CollectionPermissionUpdateRequest is the only update-permissions contract added here, but it makes expiration_date optional. In Alteryx's Collection endpoint docs, PUT /v3/collections/{collectionId}/users/{userId}/permissions requires expirationDate, while the user-group variant allows it to be omitted. With the shared optional field, callers can build a locally valid request for the user-permissions endpoint that will still be rejected by the server once this model is wired up.

Useful? React with 👍 / 👎.

Comment on lines +76 to +80
"""Flatten nested permissions to match form-encoded API contracts."""
data = super().model_dump(*args, **kwargs)
permissions = data.pop("permissions", None)
if permissions:
data.update(permissions)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Serialize expirationDate before flattening collection form payloads

These model_dump() overrides are intended to match the form-encoded collection contracts, but they only flatten permissions and never convert expiration_date. Alteryx documents expirationDate as an ISO8601 value for these collection share/update endpoints, so any caller that sets an expiration and posts this dumped dict as form data will end up sending Python's raw datetime representation instead of the documented wire format. The same issue is duplicated in the other two model_dump() overrides below.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds new Pydantic model definitions for additional Alteryx Server API surfaces (“phase 4”), expanding the client’s typed request/response layer and re-exporting them from models.__init__ for easier consumption.

Changes:

  • Added Collection models + request payload models (including permission-flattening model_dump() helpers).
  • Added Credential models + request payload models.
  • Added (currently schema-less) ServerInfo/ServerSettings response models and exported all new models in models/__init__.py.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.

File Description
src/alteryx_server_py/models/server.py Introduces ServerInfo/ServerSettings models (currently permissive “extra allow”).
src/alteryx_server_py/models/credentials.py Adds credential response + create/update/share request models.
src/alteryx_server_py/models/collections.py Adds collection response + create/update/share request models with permission flattening for form-encoded contracts.
src/alteryx_server_py/models/__init__.py Re-exports the new models for public package access.

user_ids: list[UserId] = Field(default_factory=list, alias="userIds")
user_group_ids: list[UserGroupId] = Field(default_factory=list, alias="userGroupIds")
workflow_ids: list[WorkflowId] = Field(default_factory=list, alias="workflowIds")
schedule_ids: list[str] = Field(default_factory=list, alias="scheduleIds")
Comment on lines +75 to +81
def model_dump(self, *args, **kwargs):
"""Flatten nested permissions to match form-encoded API contracts."""
data = super().model_dump(*args, **kwargs)
permissions = data.pop("permissions", None)
if permissions:
data.update(permissions)
return data
Comment on lines +13 to +18
model_config = ConfigDict(
str_strip_whitespace=True,
validate_assignment=True,
extra="allow",
populate_by_name=True,
)
Comment on lines +34 to +49
class CredentialCreateRequest(BaseModel):
"""Request model for creating a credential."""

model_config = ConfigDict(populate_by_name=True)

username: str
password: str


class CredentialUpdateRequest(BaseModel):
"""Request model for updating a credential password."""

model_config = ConfigDict(populate_by_name=True)

new_password: str = Field(..., alias="NewPassword")

model_config = ConfigDict(
str_strip_whitespace=True,
validate_assignment=True,
extra="allow",
model_config = ConfigDict(
str_strip_whitespace=True,
validate_assignment=True,
extra="allow",
Copy link
Copy Markdown
Owner Author

Sivivatu commented May 6, 2026

Merge activity

  • May 6, 12:05 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • May 6, 12:06 PM UTC: Graphite couldn't merge this pull request because a downstack PR removed comment section #22 failed to merge.
  • May 8, 9:29 AM UTC: A user started a stack merge that includes this pull request via Graphite.
  • May 8, 9:50 AM UTC: Graphite couldn't merge this pull request because a downstack PR removed comment section #22 failed to merge.
  • May 8, 10:58 AM UTC: A user started a stack merge that includes this pull request via Graphite.
  • May 8, 11:01 AM UTC: Graphite couldn't merge this PR because it had merge conflicts.

@Sivivatu Sivivatu changed the base branch from phase3-schedule-user-management to graphite-base/24 May 8, 2026 09:29
@Sivivatu Sivivatu changed the base branch from graphite-base/24 to master May 8, 2026 11:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants