Skip to content

refactor: convert to proper open-source Python SDK package#3

Merged
ds-brandao merged 1 commit intomainfrom
claude/python-sdk-setup-lqW5v
Mar 5, 2026
Merged

refactor: convert to proper open-source Python SDK package#3
ds-brandao merged 1 commit intomainfrom
claude/python-sdk-setup-lqW5v

Conversation

@ds-brandao
Copy link
Owner

No description provided.

- Restructure as installable package (src layout, pyproject.toml with hatchling)
- Add full type annotations on all public methods and parameters
- Add custom exception hierarchy (HelpdeskError, APIError, ConfigurationError)
- Add TicketState and NoteType enums with PEP 561 py.typed marker
- Replace print() with logging, remove pretty_print_response
- Rename type params to note_type/ticket_type (avoid builtin shadowing)
- Rename search_ticket to search_tickets with snake_case keyword-only params
- Make cert_path optional (defaults to standard verification)
- Add comprehensive test suite (25 tests, 93% coverage)
- Add CI pipeline (GitHub Actions: pytest, ruff, mypy across Python 3.10-3.13)
- Add PyPI publish workflow via trusted publishers (OIDC)
- Rewrite README with badges, API reference, and install instructions
- Add CONTRIBUTING.md and CHANGELOG.md

https://claude.ai/code/session_012jDYBKYfKc83cBjHEjh51n
@ds-brandao ds-brandao requested a review from Copilot March 5, 2026 07:47
@ds-brandao ds-brandao merged commit e4d66f6 into main Mar 5, 2026
6 checks passed
@ds-brandao ds-brandao deleted the claude/python-sdk-setup-lqW5v branch March 5, 2026 07:50
Copy link

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

This PR refactors the original single-file helpdesk.py script into a properly structured, installable Python SDK package (lansweeper-helpdesk). It adds type annotations, a proper exception hierarchy, enums, tests, CI/CD workflows, and packaging configuration, while removing anti-patterns (bare print() calls, rate-limiting delays, etc.).

Changes:

  • Restructures the code into an installable src/lansweeper_helpdesk/ package with separate modules for the client, exceptions, and types.
  • Adds a comprehensive test suite (tests/) using pytest and responses, along with conftest.py fixtures.
  • Introduces packaging infrastructure (pyproject.toml, README.md, CHANGELOG.md, CONTRIBUTING.md, CI/publish workflows).

Reviewed changes

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

Show a summary per file
File Description
src/lansweeper_helpdesk/client.py Core API client, refactored with full type annotations, proper exception raising, and logging
src/lansweeper_helpdesk/exceptions.py Custom exception hierarchy (HelpdeskError, APIError, ConfigurationError, TicketNotFoundError)
src/lansweeper_helpdesk/types.py StrEnum enums for TicketState/NoteType and APIResponse type alias
src/lansweeper_helpdesk/__init__.py Package public surface (__all__, version, top-level imports)
src/lansweeper_helpdesk/py.typed PEP 561 marker for typed package
tests/test_client.py Tests for all public API methods and _request edge cases
tests/test_types.py Tests for enum values and string behaviour
tests/conftest.py Shared fixtures for HelpdeskAPI instances and temporary cert file
tests/__init__.py Makes tests/ a package
pyproject.toml Hatch-based build config, dependencies, dev extras, ruff/mypy settings
README.md New user-facing README replacing the old readme.md
CHANGELOG.md Structured changelog documenting breaking changes from the old API
CONTRIBUTING.md Developer contribution guide
helpdesk.py Deleted (replaced by the src/ package)
requirements.txt Deleted (replaced by pyproject.toml dependencies)
readme.md Deleted (replaced by README.md)
config/config.example.json Added example config file
.gitignore Standard Python .gitignore
.github/workflows/ci.yml CI pipeline across Python 3.10–3.13
.github/workflows/publish.yml OIDC-based PyPI publish workflow

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +32 to +34

class TicketNotFoundError(APIError):
"""Raised when a requested ticket does not exist."""
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

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

TicketNotFoundError is exported in all and documented in the README error-handling table as "Raised when a requested ticket does not exist," but it is never raised anywhere in the client code. This makes the documentation misleading — callers who catch TicketNotFoundError will never see it triggered.

Either the client should raise TicketNotFoundError in get_ticket() when the API returns a 404 (or an equivalent "not found" response), or the exception and its documentation should be removed until the raising logic is implemented.

Suggested change
class TicketNotFoundError(APIError):
"""Raised when a requested ticket does not exist."""

Copilot uses AI. Check for mistakes.
ticket_id: str,
text: str,
email: str,
note_type: str = "Public",
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

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

The add_note() method's note_type parameter defaults to the plain string "Public" rather than NoteType.PUBLIC. Since the NoteType enum was introduced specifically to represent the valid values for this parameter, using NoteType.PUBLIC as the default would be more consistent and would self-document the accepted values directly in the signature.

Copilot uses AI. Check for mistakes.
Comment on lines +15 to +16


Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

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

The StrEnum backport for Python 3.10 (line 13) does not override generate_next_value. The real StrEnum in Python 3.11+ returns the member name lowercased when auto() is used. Without overriding generate_next_value, using auto() on Python 3.10 with this backport would silently produce integer values instead of lowercase strings. While the current enums use explicit string values and are not affected, adding a generate_next_value override would make the backport a more complete and safer substitute to prevent subtle bugs if auto() is ever used in the future.

Suggested change
def _generate_next_value_(self, name, start, count, last_values):
"""Return the member name lowercased when using auto()."""
return name.lower()

Copilot uses AI. Check for mistakes.
Comment on lines +18 to +27
__all__ = [
"HelpdeskAPI",
"APIError",
"ConfigurationError",
"HelpdeskError",
"TicketNotFoundError",
"NoteType",
"TicketState",
"__version__",
]
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

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

APIResponse is the return type of every public method in the SDK (create_ticket, get_ticket, search_tickets, etc.), so users who want to type-annotate their own code using the SDK's return types need this alias. It is defined in types.py but not included in init.py's all or imported there, requiring users to do from lansweeper_helpdesk.types import APIResponse instead of from lansweeper_helpdesk import APIResponse. Exporting it alongside TicketState and NoteType would make the public API surface complete for typed consumers.

Copilot uses AI. Check for mistakes.
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