Skip to content

Release v0.10.0: SDK modernization, structured exceptions, and expanded test coverage#58

Merged
LegendEvent merged 38 commits intomainfrom
dev
Apr 17, 2026
Merged

Release v0.10.0: SDK modernization, structured exceptions, and expanded test coverage#58
LegendEvent merged 38 commits intomainfrom
dev

Conversation

@LegendEvent
Copy link
Copy Markdown
Owner

Summary

This PR merges the dev branch into main, delivering the v0.10.0 release. It represents a comprehensive modernization of the Darktrace SDK — introducing a structured exception hierarchy, migrating the build system to pyproject.toml, enforcing ruff linting/formatting across the entire codebase, and significantly expanding test coverage.

34 commits · 49 files changed · +3,517 / −2,388 lines


Changes by Category

🏗️ Architecture & Core Infrastructure

Change Details
Structured exception hierarchy New darktrace/exceptions.py — all exceptions subclass requests.HTTPError for backward compatibility. Hierarchy: DarktraceErrorBadRequestError (400), AuthenticationError (401), ForbiddenError (403), NotFoundError (404), RateLimitError (429), ServerError (5xx), ConnectionError
_UNSET sentinel → typed class Replaced the _UNSET sentinel pattern in dt_utils.py with a properly typed _UnsetType class for better IDE support and type safety
Build system migration Replaced setup.py with pyproject.toml (104 lines) — ruff config, project metadata, build system declaration
BaseEndpoint modernization dt_utils.py expanded with logging, idiomatic helper methods (_get(), _post_json()), __repr__(), and structured error propagation

🔧 Refactoring (13 commits)

  • PEP 604 type annotations across all modules — Optional[X]X | None, Union[X, Y]X | Y
  • Idiomatic HTTP helpers — migrated manual _get_headers() + _make_request() pattern to self._get() / self._post_json() in dt_analyst, dt_breaches, and other modules
  • DRY consolidation — eliminated duplicated code patterns across endpoint modules
  • Removed anti-patterns — catch-log-reraise in dt_breaches, bare except: handlers, dead code, unused imports
  • __all__ exports added to all 27 endpoint modules for explicit public API declaration
  • __repr__ and class docstrings added to core modules
  • Removed unnecessary comments and docstring verbosity

🐛 Bug Fixes (5 commits)

Fix Details
activate_action restored Re-added missing activate_action method to dt_antigena.py that was accidentally removed
Antigena backwards-compatibility Restored and deprecated approve_action with proper deprecation warnings
Bare except: handlers Replaced with specific exception types across all modules
Silent error swallowing Fixed dt_similardevices.py silently catching and ignoring errors
Missing time default Restored missing time parameter default in advanced search GET path
Email test 403 handling Tests now gracefully skip when the email API returns 403 Forbidden
__all__ sort order Fixed __init__.py exports to be alphabetically sorted

🎨 Style & Formatting (3 commits)

  • Ruff linter/formatter config added (pyproject.toml [tool.ruff], line-length=120)
  • Codebase-wide ruff formatting applied to all 27+ modules
  • PEP 8 compliance — fixed import ordering, removed unused imports, added type hints to 22 remaining modules

🧪 Test Coverage (4 new/expanded test files)

File Lines Content
tests/test_auth.py 443 Comprehensive HMAC-SHA1 auth signing tests, parameter sorting, header generation
tests/test_exceptions.py 193 Exception hierarchy validation, status code mapping, backward compatibility with requests.HTTPError
tests/test_post_delete.py 708 Full POST and DELETE endpoint coverage — intelfeed, tags, modelbreaches, antigena, mbcomments
tests/test_mock.py Updated Refactored to follow idiomatic patterns
tests/test_sdk_readonly.py Restructured Simplified and cleaned up integration test structure

📦 Tooling & CI (1 feature + 5 chore commits)

  • Pre-commit hooks — added .pre-commit-config.yaml with ruff, trailing-whitespace, end-of-file-fixer
  • CI lint workflow — ruff check on push/PR (moved to local-only .github/)
  • Import-linter config — added coupling enforcement rules
  • GitNexus code intelligence — pre-commit hook for code indexing
  • .gitignore updates — sisyphus/state exclusions, hooks/ moved to local-only

📚 Documentation

  • Improved example docs and docstrings across all modules
  • Updated examples/README.md
  • Enhanced conftest.py with better pytest CLI option handling

Breaking Changes

⚠️ setup.py removed

The build system has migrated to pyproject.toml. Projects installing via pip install -e . will continue to work without changes (pip supports pyproject.toml natively since pip 21.3).

⚠️ Exception types changed

Methods now raise structured exceptions from darktrace.exceptions instead of raw requests.HTTPError. Existing except requests.HTTPError handlers remain compatible — all new exceptions subclass it.

⚠️ approve_action deprecated in Antigena

Use activate_action instead. approve_action still works but emits a DeprecationWarning.


Files Changed (49)

Click to expand full file list

New files:

  • darktrace/exceptions.py — Exception hierarchy
  • tests/test_auth.py — Auth unit tests
  • tests/test_exceptions.py — Exception unit tests
  • tests/test_post_delete.py — POST/DELETE integration tests
  • pyproject.toml — Build config (replaces setup.py)

Removed files:

  • setup.py — Migrated to pyproject.toml
  • tests/real/test_devicesearch_real.py — Consolidated

Modified (all 27 endpoint modules + core):

  • darktrace/__init__.py, darktrace/auth.py, darktrace/client.py, darktrace/dt_utils.py
  • darktrace/dt_advanced_search.py, darktrace/dt_analyst.py, darktrace/dt_antigena.py, darktrace/dt_breaches.py, darktrace/dt_components.py, darktrace/dt_cves.py, darktrace/dt_details.py, darktrace/dt_deviceinfo.py, darktrace/dt_devices.py, darktrace/dt_devicesearch.py, darktrace/dt_devicesummary.py, darktrace/dt_email.py, darktrace/dt_endpointdetails.py, darktrace/dt_enums.py, darktrace/dt_filtertypes.py, darktrace/dt_intelfeed.py, darktrace/dt_mbcomments.py, darktrace/dt_metricdata.py, darktrace/dt_metrics.py, darktrace/dt_models.py, darktrace/dt_network.py, darktrace/dt_pcaps.py, darktrace/dt_similardevices.py, darktrace/dt_status.py, darktrace/dt_subnets.py, darktrace/dt_summarystatistics.py, darktrace/dt_tags.py
  • darktrace/_version.py — 0.9.0 → 0.10.0
  • conftest.py, README.md, .gitignore
  • examples/README.md, examples/intelfeed_example.py, examples/threat_intelligence.py, examples/tor_exit_nodes.py
  • tests/test_compilation.py, tests/test_mock.py, tests/test_sdk_readonly.py

Commit Breakdown

Type Count Description
feat 1 GitNexus code intelligence pre-commit hook
fix 5 Antigena restore, bare except, error swallowing, email tests, all sort
refactor 13 Type annotations, DRY, idiomatic helpers, anti-pattern removal, dead code
style 3 Ruff formatting, PEP 8, import ordering
test 1 Antigena backwards-compatibility and deprecation tests
docs 1 Example docs, test robustness, docstrings
chore 10 Build config, gitignore, hooks, allowlists, version bump

Checklist

  • All 27 endpoint modules updated
  • New exception hierarchy is backward-compatible with requests.HTTPError
  • pyproject.toml replaces setup.py for modern Python packaging
  • Ruff linting passes across entire codebase
  • Test coverage expanded from 3 to 7 test files
  • Version bumped to 0.10.0
  • __all__ exports added for explicit public API surface
  • Deprecated approve_action with DeprecationWarning (backwards-compat preserved)

LegendEvent and others added 30 commits March 31, 2026 13:07
Apply consistent PEP 8 style transformations to all remaining Python files, matching the pattern already applied to 11 files in a previous commit.

Changes are purely mechanical with zero logic modifications:
- Single to double quotes for all string literals
- PEP 8 import ordering (stdlib > third-party > local)
- Remove unused `import requests` from endpoint modules
- Trailing commas on multi-line function signatures
- Multi-line `_make_request` call formatting
- Remove trailing whitespace, ensure trailing newlines
- Type hint improvements (`int = None` to `Optional[int] = None`)

Files changed:
  darktrace/__init__.py, auth.py
  darktrace/dt_antigena.py, dt_breaches.py, dt_components.py, dt_cves.py,
  dt_details.py, dt_deviceinfo.py, dt_devicesearch.py, dt_email.py,
  dt_endpointdetails.py, dt_enums.py, dt_intelfeed.py, dt_mbcomments.py,
  dt_metrics.py, dt_models.py, dt_pcaps.py, dt_status.py,
  dt_summarystatistics.py
  examples/intelfeed_example.py, threat_intelligence.py

Verified: all 22 files pass py_compile, package imports OK (v0.9.0),
90 tests pass / 0 fail, scope fidelity confirmed (style-only changes).

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
- Add [tool.ruff] config: target-version py37, line-length 120
- Configure lint rules: E, F, W, I, UP (ignore E501 for docstrings)
- Configure format: double quotes, space indentation
- Configure isort: known-first-party darktrace
- Add [project.optional-dependencies] dev group: ruff, pytest, pre-commit
- Exclude examples/ from ruff checks
- Replace _UNSET = object() with _Unset singleton class in dt_utils.py
- _Unset has __repr__ ('<UNSET>'), __bool__ (False), singleton via __new__
- Add _InternalTimeoutType = Union[_Unset, None, float, Tuple[float, float]]
- Update _resolve_timeout to use _InternalTimeoutType (no type: ignore needed)
- Remove 24 _UNSET-related # type: ignore[assignment] across 19 modules
- Preserve all return-type # type: ignore[assignment] (unrelated to _UNSET)
- Fix missing Dict/Any imports in dt_subnets.py (F821 bug)
- Add # noqa: F401 to __version__ import in __init__.py
- Update test files for ruff formatting compatibility
- One-time ruff format pass on all darktrace/ and root Python files
- Import sorting (isort), consistent quote style, whitespace normalization
- No logic changes — formatting only
- conftest.py: add # noqa: E402 for post-function imports
- setup.py: quote style normalization, remove unused os import
- Add .pre-commit-config.yaml with ruff (--fix) and ruff-format hooks
- Add .github/workflows/lint.yml with parallel lint + test jobs
- Lint job: ruff check + ruff format --check (Python 3.12)
- Test job: pip install -e .[dev] + pytest
- Triggers on push/PR to main branch
3-phase architecture:
- Phase 1: Refresh GitNexus index with embeddings (skippable)
- Phase 2: Run 4 Cypher detection checks + allowlist filtering
- Phase 3: Dynamic deep investigation for actionable issues

Features:
- Allowlist for false positives (30 orphaned SDK classes)
- LLM-consumable output with rich context
- Dynamic investigation queries per issue type
- Sisyphus ulw mode trigger for complex issues
- Remove deprecated approve_action method from dt_antigena.py
- Remove corresponding test from test_mock.py
- Replace bare except Exception with specific exception types
  (requests.exceptions.RequestException, json.JSONDecodeError)
  in add_comment, acknowledge, unacknowledge methods

Code smells detected by GitNexus code intelligence hook.
Add real activate_action() method that POSTs to /antigena with activate:true.
Fix approve_action() deprecation message to no longer reference the
previously missing activate_action method.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Restore approve_action and activate_action assertions in test_antigena_methods.
Restore TestDeprecations class with test_approve_action_deprecated.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
refactor: codebase modernization, quality tooling, and API correctness fixes
…s, and expanded tests

- Migrate all 27 endpoint modules to use idiomatic BaseEndpoint helpers
  (_get, _post_json, _post_form, _delete) instead of manual header/request calls
- Add structured exception hierarchy (darktrace/exceptions.py) with 8
  purpose-built HTTP error classes wrapping requests.HTTPError
- Add _raise_for_status() to BaseEndpoint for consistent error handling
- Expand CI matrix to Python 3.8-3.12 in lint workflow
- Add 28 HMAC signature tests (tests/test_auth.py)
- Add 47 POST/DELETE mock tests (tests/test_post_delete.py)
- Remove legacy setup.py (pyproject.toml is sole build config)
- Fix README: remove false async-ready claim, add exceptions docs
- Full backward compatibility maintained: no public API signature changes
refactor: modernize SDK with idiomatic patterns, structured exceptions, and expanded tests
- Migrate all 27 endpoint modules to use idiomatic BaseEndpoint helpers
  (_get, _post_json, _post_form, _delete) instead of manual header/request calls
- Add structured exception hierarchy (darktrace/exceptions.py) with 8
  purpose-built HTTP error classes wrapping requests.HTTPError
- Add _raise_for_status() to BaseEndpoint for consistent error handling
- Expand CI matrix to Python 3.8-3.12 in lint workflow
- Add 28 HMAC signature tests (tests/test_auth.py)
- Add 47 POST/DELETE mock tests (tests/test_post_delete.py)
- Remove legacy setup.py (pyproject.toml is sole build config)
- Fix README: remove false async-ready claim, add exceptions docs
- Full backward compatibility maintained: no public API signature changes
… wiring, modernize annotations

- Replace all -> Any return types with dict | list, bytes, dict, or None across 27 endpoint modules
- Wrap connection/timeout errors in darktrace.ConnectionError with exception chaining
- Replace 5 raw response.raise_for_status() calls with _raise_for_status()
- Add from __future__ import annotations to all endpoint modules
- Modernize type annotations (Optional[X] -> X | None, Dict -> dict, etc.)
- Add 12 tests for exception wiring, HTTP status mapping, and backward compatibility
- Update .gitignore for local tooling files
… wiring, modernize annotations

- Replace all -> Any return types with dict | list, bytes, dict, or None across 27 endpoint modules
- Wrap connection/timeout errors in darktrace.ConnectionError with exception chaining
- Replace 5 raw response.raise_for_status() calls with _raise_for_status()
- Add from __future__ import annotations to all endpoint modules
- Modernize type annotations (Optional[X] -> X | None, Dict -> dict, etc.)
- Add 12 tests for exception wiring, HTTP status mapping, and backward compatibility
- Update .gitignore for local tooling files
- Remove unreachable comment after return in dt_tags.py
- Delete tests/real/test_devicesearch_real.py (3 zero-value stub tests)
- Remove empty test_email_decode_link stub from test_sdk_readonly.py
- Note: import json in dt_breaches.py retained (still used by except blocks, Task 6 will handle)
- Remove 3 try/except blocks that catch-log-reraise (add_comment, acknowledge, unacknowledge)
- Remove now-unused imports: import json, import requests
- Fix test anti-pattern: replace assert True with pass in except blocks
- Exceptions now propagate naturally through _post_json() → _make_request()
- Convert 4 manual GET methods in dt_analyst.py to use self._get()
- Remove now-unused _raise_for_status import from dt_analyst.py
- Add from __future__ import annotations to client.py
- Remove unnecessary quotes from type annotations (UP037)
- Extract _dashboard_get() helper in dt_email.py
- 4 dashboard GET methods now delegate to shared helper
- Public API signatures and docstrings preserved exactly
- dt_breaches.py with_comment methods left as-is (differ in called method)
- Test boilerplate left as-is (explicitness preferred)
- Add from __future__ import annotations to __init__.py and auth.py
- Replace Dict/Optional/Union/Tuple with PEP 604 syntax (dict, | None, |, tuple)
- Modernize TimeoutType and _InternalTimeoutType aliases
- Add [tool.mypy] config section to pyproject.toml
- Zero legacy typing imports remain in darktrace/ source
- Add TYPE_CHECKING guard for DarktraceClient in dt_utils.py
- Type BaseEndpoint.__init__ client as DarktraceClient
- Type __exit__ with proper stdlib types (type, BaseException, TracebackType)
- Remove unused typing.Any from client.py
- No circular imports
- Add import-linter>=2.0 as dev dependency
- Configure hub-and-spoke independence contract (dt_* modules)
- Configure infrastructure isolation contract (dt_utils)
- Full coupling analysis report in evidence files
- Remove 25 trivial __init__ overrides (just super().__init__(client))
- Clean 14 'future-proofing' / 'forward compatibility' phrases
- Remove 7 redundant inline comments (code is self-explanatory)
- Preserve all helpful documentation: docstrings, IMPORTANT, backwards compat notes
Email module tests now skip instead of failing when the Darktrace/Email
sub-product is not licensed on the appliance (returns 403 Forbidden).
@LegendEvent LegendEvent merged commit 62541da into main Apr 17, 2026
@LegendEvent LegendEvent deleted the dev branch April 17, 2026 15:13
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.

1 participant