targetprocess-py 0.2.1__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/.coderabbit.yaml +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/.github/workflows/ci.yml +2 -2
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/.github/workflows/release.yml +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/CHANGELOG.md +58 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/CODEOWNERS +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/CONTRIBUTING.md +2 -2
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/PKG-INFO +4 -4
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/README.md +3 -3
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/SECURITY.md +2 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/SPEC.md +20 -17
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/docs/USAGE.md +6 -6
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/examples/bulk_updates.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/examples/create_bug.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/examples/list_user_stories.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/examples/readonly_reporting.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/pyproject.toml +4 -4
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/scripts/check_model_coverage.py +2 -2
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/scripts/live_smoke.py +1 -1
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/__init__.py +9 -9
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/_assignables.py +4 -4
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/_base.py +3 -3
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/_content.py +4 -4
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/_dates.py +1 -1
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/_generals.py +5 -5
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/_joins.py +47 -25
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/_lookups.py +7 -7
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/_nested.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/_observability.py +10 -10
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/client.py +5 -5
- targetprocess_py-0.3.0/src/targetprocess_py/models.py +121 -0
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/request_handler.py +5 -5
- targetprocess_py-0.3.0/src/targetprocess_py/resources/__init__.py +78 -0
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/_verify.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/assignables.py +5 -5
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/assignments.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/attachments.py +4 -4
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/base.py +33 -24
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/bugs.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/comments.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/custom_activities.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/custom_fields.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/custom_rules.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/entities.py +57 -22
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/entity_states.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/entity_types.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/epics.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/features.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/iterations.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/priorities.py +3 -3
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/processes.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/projects.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/relation_types.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/relations.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/releases.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/requests.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/role_efforts.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/roles.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/severities.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/tasks.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/team_assignments.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/team_iterations.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/teams.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/terms.py +3 -3
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/test_cases.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/times.py +9 -7
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/user_stories.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/users.py +5 -5
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/workflows.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/response_parser.py +2 -2
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/transport.py +1 -1
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/types.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/_support/request_handler.py +2 -2
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/conftest.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/integration/conftest.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/integration/test_live_readonly.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/integration/test_live_readwrite.py +2 -2
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/integration/test_live_readwrite_surfaces.py +3 -3
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_assignment.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_attachment.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_bug.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_cassette_guard.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_client.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_comment.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_custom_activity.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_custom_field.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_custom_field_value.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_custom_rule.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_entity_extras.py +5 -5
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_entity_ref.py +4 -4
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_entity_state.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_entity_type.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_epic.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_exceptions.py +17 -17
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_feature.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_integration_request_response.py +5 -5
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_iteration.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_model_field_coverage.py +5 -5
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_models.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_observability.py +32 -30
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_priority.py +2 -2
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_process.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_project.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_query_parameters.py +4 -4
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_relation.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_relation_type.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_release.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_request.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_request_handler.py +6 -6
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_request_handler_bulk.py +3 -3
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_request_handler_logged_user.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_assignable_state.py +13 -13
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_assignments.py +4 -4
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_attachments.py +5 -5
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_base_resource.py +6 -6
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_bugs.py +3 -3
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_comments.py +3 -3
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_custom_activities.py +3 -3
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_custom_field_writes.py +3 -3
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_custom_fields.py +3 -3
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_custom_rules.py +3 -3
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_entities.py +13 -13
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_entity_states.py +6 -6
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_entity_types.py +3 -3
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_epics.py +3 -3
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_features.py +3 -3
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_ignored_filter_paths.py +104 -23
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_iterations.py +3 -3
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_lookup_resolvers.py +9 -9
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_priorities.py +6 -6
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_processes.py +3 -3
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_projects.py +3 -3
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_relation_types.py +6 -6
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_relations.py +4 -4
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_releases.py +3 -3
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_requests.py +3 -3
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_role_efforts.py +4 -4
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_roles.py +6 -6
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_server_capability.py +6 -6
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_severities.py +3 -3
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_tasks.py +3 -3
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_team_assignments.py +4 -4
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_team_iterations.py +3 -3
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_teams.py +3 -3
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_terms.py +3 -3
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_test_cases.py +3 -3
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_times.py +6 -6
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_user_stories.py +3 -3
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_users.py +6 -6
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_verified_writes.py +4 -4
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_resources/test_workflows.py +3 -3
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_response_parser.py +3 -3
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_role.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_role_effort.py +20 -5
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_severity.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_task.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_team.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_team_assignment.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_team_iteration.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_term.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_test_case.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_time.py +21 -7
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_transport.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_types.py +3 -3
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_uploaded_attachment.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_user.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_user_story.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_workflow.py +1 -1
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/uv.lock +30 -19
- targetprocess_py-0.2.1/src/targetprocess/models.py +0 -121
- targetprocess_py-0.2.1/src/targetprocess/resources/__init__.py +0 -78
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/.commitlintrc.json +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/.env.example +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/.github/dependabot.yml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/.github/labels.yml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/.github/pull_request_template.md +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/.github/workflows/commit-message.yml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/.gitignore +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/.jscpd.json +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/.pre-commit-config.yaml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/.python-version +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/.tool-versions +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/CODE_OF_CONDUCT.md +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/LICENSE +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/docs/testing.md +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/examples/README.md +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/scripts/apply_labels.sh +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/scripts/check_commit_message.py +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/scripts/check_internal_refs.py +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/scripts/check_large_files.py +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/scripts/check_todos.py +0 -0
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/_entity_types.py +0 -0
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/exceptions.py +0 -0
- {targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/py.typed +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/__init__.py +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/_support/__init__.py +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/integration/__init__.py +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readonly/test_entity_states_scoped_to_a_workflow.yaml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readonly/test_entity_types_catalogue_parses.yaml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readonly/test_find_for_day_matches_a_real_entry.yaml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readonly/test_generic_entities_comment.yaml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readonly/test_get_single_with_include.yaml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readonly/test_list_user_stories_parses.yaml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readonly/test_logged_user_resolves_the_acting_user.yaml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readonly/test_pagination_crosses_page_boundary.yaml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readonly/test_priorities_scoped_to_an_entity_type.yaml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readonly/test_severities_rank_the_bug_set.yaml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readwrite/test_bulk_create_and_update_tasks_under_a_story.yaml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readwrite/test_custom_field_set_and_clear_round_trip.yaml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readwrite/test_request_create_update_delete_round_trip.yaml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readwrite/test_user_story_create_update_delete_round_trip.yaml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readwrite/test_verified_update_returns_the_re_read.yaml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readwrite_surfaces/test_assignment_create_and_delete.yaml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readwrite_surfaces/test_attachment_upload_list_download_and_delete.yaml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readwrite_surfaces/test_comment_create_update_delete_round_trip.yaml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readwrite_surfaces/test_relation_create_and_delete.yaml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readwrite_surfaces/test_relation_inbound_outbound_create_and_filter.yaml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readwrite_surfaces/test_role_effort_create_update_delete_round_trip.yaml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readwrite_surfaces/test_team_assignment_create_and_delete.yaml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readwrite_surfaces/test_two_level_advance_moves_both_levels.yaml +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/live_payloads.py +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_cassette_sanitiser.py +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_commit_message.py +0 -0
- {targetprocess_py-0.2.1 → targetprocess_py-0.3.0}/tests/test_internal_refs.py +0 -0
|
@@ -95,7 +95,7 @@ reviews:
|
|
|
95
95
|
- "!**/uv.lock"
|
|
96
96
|
|
|
97
97
|
path_instructions:
|
|
98
|
-
- path: "src/
|
|
98
|
+
- path: "src/targetprocess_py/**"
|
|
99
99
|
instructions: >
|
|
100
100
|
Async Python library for the TargetProcess v1 REST API. TP facts that are
|
|
101
101
|
correct and must not be "fixed": tokens are sent as an access_token query
|
|
@@ -32,7 +32,7 @@ jobs:
|
|
|
32
32
|
- run: uv run ruff check .
|
|
33
33
|
- run: uv run ruff format --check .
|
|
34
34
|
- run: uv run mypy --strict src
|
|
35
|
-
- run: uv run pytest -q --cov=
|
|
35
|
+
- run: uv run pytest -q --cov=targetprocess_py --cov-report=term --cov-fail-under=90
|
|
36
36
|
|
|
37
37
|
# Runs the same hooks a developer gets locally from `pre-commit install`, so a
|
|
38
38
|
# contributor who skipped the install still meets the same bar, and the hook
|
|
@@ -103,4 +103,4 @@ jobs:
|
|
|
103
103
|
set -euo pipefail
|
|
104
104
|
wheel=$(ls dist/*.whl)
|
|
105
105
|
uv run --isolated --no-project --with "$wheel" python -c \
|
|
106
|
-
"import
|
|
106
|
+
"import targetprocess_py; print(targetprocess_py.__version__)"
|
|
@@ -47,7 +47,7 @@ jobs:
|
|
|
47
47
|
- run: uvx twine==7.0.0 check --strict dist/*
|
|
48
48
|
# The version is read from the package, not the tag (see
|
|
49
49
|
# [tool.hatch.version] in pyproject.toml), so a tag that disagrees with
|
|
50
|
-
#
|
|
50
|
+
# targetprocess_py.__version__ would publish a release whose files carry a
|
|
51
51
|
# different version from the tag that produced them. Refuse it.
|
|
52
52
|
- name: Assert the tag matches the package version
|
|
53
53
|
env:
|
|
@@ -7,6 +7,62 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.3.0] - 2026-09-20
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- **BREAKING:** the import package is renamed from `targetprocess` to
|
|
15
|
+
`targetprocess_py`, the PEP 503 normalisation of the distribution name. The
|
|
16
|
+
distribution is still `targetprocess-py` on PyPI and the repository keeps its
|
|
17
|
+
name; only the import name changes. An import name that did not match the
|
|
18
|
+
distribution name made every tool that infers a dependency from a top-level
|
|
19
|
+
import ask PyPI for a package called `targetprocess`, which does not exist, so
|
|
20
|
+
such a consumer needed a hand-written override to install this library at all.
|
|
21
|
+
There is deliberately no compatibility shim: a `targetprocess` module
|
|
22
|
+
re-exporting the new package would keep alive exactly the import that cannot be
|
|
23
|
+
resolved. **Migration:** rewrite each `import targetprocess` as
|
|
24
|
+
`import targetprocess_py`, and each `from targetprocess.<module>` as
|
|
25
|
+
`from targetprocess_py.<module>`; nothing else about the public surface
|
|
26
|
+
changes.
|
|
27
|
+
- **BREAKING:** the library's logger namespace is renamed from `targetprocess` to
|
|
28
|
+
`targetprocess_py`, following the package, so records no longer arrive under a
|
|
29
|
+
namespace naming a module that does not exist. This fails differently from the
|
|
30
|
+
import rename and needs its own attention: an import that no longer resolves
|
|
31
|
+
raises at startup, while logging configuration that no longer matches simply
|
|
32
|
+
goes silent, with nothing raised to say so. **Migration:** rename
|
|
33
|
+
`targetprocess` to `targetprocess_py` in every handler, level, filter and
|
|
34
|
+
`dictConfig` entry that names this library's logger.
|
|
35
|
+
- `list()` refuses a `where=` filter naming the `Assignments` collection on four
|
|
36
|
+
further collections - `PortfolioEpics`, `TestPlanRuns`, `InboundAssignables`
|
|
37
|
+
and `OutboundAssignables` - raising `ValueError` before any request is sent,
|
|
38
|
+
as it already did for the six typed assignable collections. TargetProcess
|
|
39
|
+
answers such a filter with HTTP 200 and the *unfiltered* rows, so code that
|
|
40
|
+
appeared to narrow one of these collections by assignee was in fact receiving
|
|
41
|
+
every row; it now raises rather than returning silently-wrong results. Each
|
|
42
|
+
collection was confirmed against an unfiltered control on the same collection
|
|
43
|
+
before being added. Only `list()`'s `where=` is affected - reading
|
|
44
|
+
`InboundAssignables` or `OutboundAssignables` through `include=` is unchanged.
|
|
45
|
+
- The refusal's message states both ways a path under `Assignments` fails: a
|
|
46
|
+
filter on one of the collection's fields is accepted and ignored (HTTP 200),
|
|
47
|
+
while `Assignments.Count` is rejected by the query parser (HTTP 400).
|
|
48
|
+
|
|
49
|
+
### Fixed
|
|
50
|
+
|
|
51
|
+
- The eight numeric fields on the `RoleEffort` and `Time` read models no longer
|
|
52
|
+
carry a `ge=0` bound - `InitialEstimate`, `Effort`, `EffortCompleted`,
|
|
53
|
+
`EffortToDo`, `TimeSpent` and `TimeRemain` on `RoleEffort`, and `Spent` and
|
|
54
|
+
`Remain` on `Time`. Each is supplied by the server, and a constraint on a
|
|
55
|
+
server-supplied value fails the *whole entity* rather than the field, so one
|
|
56
|
+
out-of-range record would have aborted an entire `list()` page with a
|
|
57
|
+
`ParseError` - the rule `AssignableEntity` already stated and these two models
|
|
58
|
+
broke. A consumer relying on `ValidationError` for a negative value on these
|
|
59
|
+
fields, including on assignment, no longer receives one; `times.upsert` keeps
|
|
60
|
+
its write-side check, where a range error is actionable.
|
|
61
|
+
- `Time`'s class docstring and its `project` field description say what a
|
|
62
|
+
custom-activity entry's `project` holds. Such an entry has no `Assignable`,
|
|
63
|
+
and the field is populated all the same, matching that activity's own project
|
|
64
|
+
on every entry observed.
|
|
65
|
+
|
|
10
66
|
## [0.2.1] - 2026-09-18
|
|
11
67
|
|
|
12
68
|
### Fixed
|
|
@@ -175,7 +231,8 @@ The first public release.
|
|
|
175
231
|
- Log scrubbing redacts the `access_token` query parameter and `Authorization`
|
|
176
232
|
header values from the library's own log records.
|
|
177
233
|
|
|
178
|
-
[Unreleased]: https://github.com/man8/targetprocess-py/compare/v0.
|
|
234
|
+
[Unreleased]: https://github.com/man8/targetprocess-py/compare/v0.3.0...HEAD
|
|
235
|
+
[0.3.0]: https://github.com/man8/targetprocess-py/compare/v0.2.1...v0.3.0
|
|
179
236
|
[0.2.1]: https://github.com/man8/targetprocess-py/compare/v0.2.0...v0.2.1
|
|
180
237
|
[0.2.0]: https://github.com/man8/targetprocess-py/compare/v0.1.0...v0.2.0
|
|
181
238
|
[0.1.0]: https://github.com/man8/targetprocess-py/releases/tag/v0.1.0
|
|
@@ -9,6 +9,6 @@
|
|
|
9
9
|
# specific approval — not merely any review — is mandatory.
|
|
10
10
|
#
|
|
11
11
|
# If additional maintainers or team-based ownership are added later, split this
|
|
12
|
-
# into per-path rules (e.g. `src/
|
|
12
|
+
# into per-path rules (e.g. `src/targetprocess_py/ @man8 @someone`, `.github/ @man8`).
|
|
13
13
|
|
|
14
14
|
* @man8
|
|
@@ -46,7 +46,7 @@ package build run in CI.
|
|
|
46
46
|
| Lint | `uv run ruff check .` |
|
|
47
47
|
| Format | `uv run ruff format --check .` |
|
|
48
48
|
| Types | `uv run mypy --strict src` |
|
|
49
|
-
| Tests and coverage | `uv run pytest -q --cov=
|
|
49
|
+
| Tests and coverage | `uv run pytest -q --cov=targetprocess_py --cov-report=term --cov-fail-under=90` |
|
|
50
50
|
| Hook suite, commit stage | `uv run pre-commit run --all-files --hook-stage pre-commit` |
|
|
51
51
|
| Hook suite, push stage | `uv run pre-commit run --all-files --hook-stage pre-push` |
|
|
52
52
|
| Commit message | `uv run pre-commit run --hook-stage commit-msg --commit-msg-filename <file>` (CI runs it over the pull request title) |
|
|
@@ -297,7 +297,7 @@ feat!: require an explicit mode on the client
|
|
|
297
297
|
|
|
298
298
|
A release is a pull request followed by a tag.
|
|
299
299
|
|
|
300
|
-
1. In a pull request, set `__version__` in `src/
|
|
300
|
+
1. In a pull request, set `__version__` in `src/targetprocess_py/__init__.py`
|
|
301
301
|
(the only version string; the build reads it). Move the `[Unreleased]`
|
|
302
302
|
entries in `CHANGELOG.md` under a `## [X.Y.Z] - YYYY-MM-DD` heading dated
|
|
303
303
|
the release day, and update the link references at its foot. When the minor
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: targetprocess-py
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: A Python library for the TargetProcess v1 REST API
|
|
5
5
|
Project-URL: Homepage, https://github.com/man8/targetprocess-py
|
|
6
6
|
Project-URL: Repository, https://github.com/man8/targetprocess-py
|
|
@@ -75,7 +75,7 @@ For an environment-only install with no project, use `uv pip install targetproce
|
|
|
75
75
|
```python
|
|
76
76
|
import asyncio
|
|
77
77
|
|
|
78
|
-
from
|
|
78
|
+
from targetprocess_py import ClientMode, TargetProcessClient
|
|
79
79
|
|
|
80
80
|
|
|
81
81
|
async def main() -> None:
|
|
@@ -273,7 +273,7 @@ Every library error subclasses `TargetProcessError`, so you can catch a
|
|
|
273
273
|
specific failure or the base class:
|
|
274
274
|
|
|
275
275
|
```python
|
|
276
|
-
from
|
|
276
|
+
from targetprocess_py import (
|
|
277
277
|
AuthenticationError,
|
|
278
278
|
NotFoundError,
|
|
279
279
|
RateLimitError,
|
|
@@ -341,7 +341,7 @@ minor releases; every change is recorded in [CHANGELOG.md](CHANGELOG.md).
|
|
|
341
341
|
request has been resolved: the library refuses it before sending, verifies it
|
|
342
342
|
after the write, or SPEC.md documents it as a limitation.
|
|
343
343
|
3. The public surface is frozen: SPEC.md's Public API Surface matches
|
|
344
|
-
`
|
|
344
|
+
`targetprocess_py.__all__`, a Semantic Versioning promise for that surface is
|
|
345
345
|
stated, and a deprecation policy is written.
|
|
346
346
|
4. Documentation and the recorded test cassettes are current: every public
|
|
347
347
|
resource manager is documented in [docs/USAGE.md](docs/USAGE.md), the
|
|
@@ -36,7 +36,7 @@ For an environment-only install with no project, use `uv pip install targetproce
|
|
|
36
36
|
```python
|
|
37
37
|
import asyncio
|
|
38
38
|
|
|
39
|
-
from
|
|
39
|
+
from targetprocess_py import ClientMode, TargetProcessClient
|
|
40
40
|
|
|
41
41
|
|
|
42
42
|
async def main() -> None:
|
|
@@ -234,7 +234,7 @@ Every library error subclasses `TargetProcessError`, so you can catch a
|
|
|
234
234
|
specific failure or the base class:
|
|
235
235
|
|
|
236
236
|
```python
|
|
237
|
-
from
|
|
237
|
+
from targetprocess_py import (
|
|
238
238
|
AuthenticationError,
|
|
239
239
|
NotFoundError,
|
|
240
240
|
RateLimitError,
|
|
@@ -302,7 +302,7 @@ minor releases; every change is recorded in [CHANGELOG.md](CHANGELOG.md).
|
|
|
302
302
|
request has been resolved: the library refuses it before sending, verifies it
|
|
303
303
|
after the write, or SPEC.md documents it as a limitation.
|
|
304
304
|
3. The public surface is frozen: SPEC.md's Public API Surface matches
|
|
305
|
-
`
|
|
305
|
+
`targetprocess_py.__all__`, a Semantic Versioning promise for that surface is
|
|
306
306
|
stated, and a deprecation policy is written.
|
|
307
307
|
4. Documentation and the recorded test cassettes are current: every public
|
|
308
308
|
resource manager is documented in [docs/USAGE.md](docs/USAGE.md), the
|
|
@@ -85,12 +85,12 @@ itself.
|
|
|
85
85
|
local `skip` counter, since that can silently skip or repeat records if TP
|
|
86
86
|
ever returns a non-linear continuation URL.
|
|
87
87
|
- **Unrecognised query input**: TP answers a query parameter it does not
|
|
88
|
-
recognise, and a `where=` naming a nested collection path it does not
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
`
|
|
88
|
+
recognise, and a `where=` naming a nested collection path it does not filter
|
|
89
|
+
on, with HTTP 200 and the unfiltered, unsorted rows - indistinguishable from
|
|
90
|
+
success. The confirmed case is a filter on the `Assignments` collection of an
|
|
91
|
+
assignable, which returns the same rows as the unfiltered request, while the
|
|
92
|
+
`Assignment` entity's own `GeneralUser.Id` filter applies. A collection
|
|
93
|
+
`Count` is the loud exception, rejected with HTTP 400 - `Comments.Count` too.
|
|
94
94
|
- **Bulk endpoint**: writable collections expose
|
|
95
95
|
`POST /api/v1/{collection}/bulk`, taking a JSON array of entity objects -
|
|
96
96
|
an object carrying an `Id` updates that entity, an object without one
|
|
@@ -506,10 +506,10 @@ entity back to TP.
|
|
|
506
506
|
Fields TP computes and returns carry no `ge`/`le` bound. A constraint on a
|
|
507
507
|
server-supplied value fails the **whole entity** rather than the field, so one
|
|
508
508
|
out-of-range roll-up would abort an entire `list()` page with a `ParseError` -
|
|
509
|
-
and TP documents no bounds on effort, progress or flow metrics to assert.
|
|
510
|
-
`RoleEffort` and `Time`
|
|
511
|
-
|
|
512
|
-
|
|
509
|
+
and TP documents no bounds on effort, progress or flow metrics to assert. The
|
|
510
|
+
`RoleEffort` and `Time` join models carry none either; `times.upsert` validates
|
|
511
|
+
on the write side, where the value originates and a range error is actionable.
|
|
512
|
+
The attached-content byte-size fields still carry `ge=0`.
|
|
513
513
|
|
|
514
514
|
`custom_fields` (`CustomFields`) sits on the `Entity` base, so custom-field
|
|
515
515
|
values are reachable on every entity type: fetched with
|
|
@@ -688,7 +688,7 @@ at send time, and outside the set; `prettify` stays deliberately absent (see
|
|
|
688
688
|
above).
|
|
689
689
|
|
|
690
690
|
**Filter paths.** `BaseResource.ignored_filter_paths` maps the leading segment
|
|
691
|
-
of a `where=` path TP
|
|
691
|
+
of a `where=` path TP will not filter on for a collection to the reason and the
|
|
692
692
|
route to use instead. The known set is declared once, as
|
|
693
693
|
`ASSIGNABLE_IGNORED_FILTER_PATHS` in `resources/base.py`, and referenced by the
|
|
694
694
|
six assignable managers (`UserStory`, `Bug`, `Task`, `Feature`, `Epic`,
|
|
@@ -696,7 +696,10 @@ six assignable managers (`UserStory`, `Bug`, `Task`, `Feature`, `Epic`,
|
|
|
696
696
|
`order_by` or `include` - matching a path's leading segment in any casing
|
|
697
697
|
outside quoted values, and refuses with a `ValueError` naming the collection
|
|
698
698
|
and the route. `entities` mirrors the refusal for every spelling of those six
|
|
699
|
-
collections and
|
|
699
|
+
collections and of the untyped Assignable-derived collections confirmed so far -
|
|
700
|
+
`Assignable`, `PortfolioEpic`, `TestPlanRun`, `InboundAssignable` and
|
|
701
|
+
`OutboundAssignable`, in `_UNTYPED_ASSIGNABLE_COLLECTIONS`. That is what has
|
|
702
|
+
been checked, not every candidate; the TestPlan family is unexamined.
|
|
700
703
|
|
|
701
704
|
| Ignored path | Route instead |
|
|
702
705
|
| --- | --- |
|
|
@@ -899,7 +902,7 @@ result = await client.times.upsert(
|
|
|
899
902
|
|
|
900
903
|
## Observability
|
|
901
904
|
|
|
902
|
-
Runtime observability lives in `
|
|
905
|
+
Runtime observability lives in `targetprocess_py/_observability.py` and is
|
|
903
906
|
scoped to what a *library* should own. The application that embeds the
|
|
904
907
|
library owns the rest (metrics, alerting, error tracking, deployment
|
|
905
908
|
observability, product analytics) - it has the deployment context a
|
|
@@ -907,17 +910,17 @@ library cannot assume.
|
|
|
907
910
|
|
|
908
911
|
### Implemented signals
|
|
909
912
|
|
|
910
|
-
- **Structured logging.** A dedicated `logging.getLogger("
|
|
913
|
+
- **Structured logging.** A dedicated `logging.getLogger("targetprocess_py")`
|
|
911
914
|
with a `NullHandler` by default (silent unless the application attaches a
|
|
912
915
|
handler). `StructuredJsonFormatter` emits one JSON line per record
|
|
913
916
|
(`ts`, `level`, `logger`, `msg`, `request_id`, plus caller extras).
|
|
914
|
-
`get_logger("name")` returns a child under the `
|
|
917
|
+
`get_logger("name")` returns a child under the `targetprocess_py` namespace.
|
|
915
918
|
`RequestHandler._request` emits structured `request.start` /
|
|
916
919
|
`request.complete` / `request.retry` / `request.error` /
|
|
917
920
|
`request.transport_error` records.
|
|
918
921
|
- **Log scrubbing.** `ScrubbingFilter` redacts the `access_token` query
|
|
919
922
|
param and `Authorization: Basic|Bearer` header values from the records
|
|
920
|
-
this library emits. It is attached to the `
|
|
923
|
+
this library emits. It is attached to the `targetprocess_py` logger and to
|
|
921
924
|
every child `get_logger()` returns - both, because a filter on a logger
|
|
922
925
|
runs only for records logged *through* that logger, not for records
|
|
923
926
|
propagated up from a child. It pre-formats and redacts the message, the
|
|
@@ -935,7 +938,7 @@ library cannot assume.
|
|
|
935
938
|
for httpx request-URL logging, *in this library's own records*. The filter
|
|
936
939
|
cannot reach records emitted by other libraries - `httpx` and `httpcore`
|
|
937
940
|
log their own request URLs - nor a logger obtained by calling
|
|
938
|
-
`logging.getLogger("
|
|
941
|
+
`logging.getLogger("targetprocess_py.x")` directly instead of via
|
|
939
942
|
`get_logger()`. An application that wants blanket redaction should attach
|
|
940
943
|
a `ScrubbingFilter()` instance to its own handler, which every propagated
|
|
941
944
|
record passes through whatever logger produced it.
|
|
@@ -32,7 +32,7 @@ default, so every client declares its safety posture up front.
|
|
|
32
32
|
```python
|
|
33
33
|
import asyncio
|
|
34
34
|
|
|
35
|
-
from
|
|
35
|
+
from targetprocess_py import ClientMode, TargetProcessClient
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
async def main() -> None:
|
|
@@ -188,7 +188,7 @@ Because the re-read is narrowed, that model carries its `id` and
|
|
|
188
188
|
`get` the entity again when you need the rest.
|
|
189
189
|
|
|
190
190
|
```python
|
|
191
|
-
from
|
|
191
|
+
from targetprocess_py import VerificationError
|
|
192
192
|
|
|
193
193
|
try:
|
|
194
194
|
story = await client.user_stories.update(123, Effort=5, EntityState={"Id": 82}, verify=True)
|
|
@@ -584,7 +584,7 @@ custom activity goes through the ordinary `create` and `list`. Send
|
|
|
584
584
|
the key rather than sending it as `None`:
|
|
585
585
|
|
|
586
586
|
```python
|
|
587
|
-
from
|
|
587
|
+
from targetprocess_py.models import format_tp_date
|
|
588
588
|
|
|
589
589
|
entry = await client.times.create(
|
|
590
590
|
CustomActivity={"Id": 42},
|
|
@@ -811,7 +811,7 @@ catch a specific failure or the base class. HTTP status codes map to types:
|
|
|
811
811
|
```python
|
|
812
812
|
import logging
|
|
813
813
|
|
|
814
|
-
from
|
|
814
|
+
from targetprocess_py import (
|
|
815
815
|
AuthenticationError,
|
|
816
816
|
NotFoundError,
|
|
817
817
|
RateLimitError,
|
|
@@ -862,7 +862,7 @@ To call the library from otherwise-synchronous code, drive it with
|
|
|
862
862
|
```python
|
|
863
863
|
import asyncio
|
|
864
864
|
|
|
865
|
-
from
|
|
865
|
+
from targetprocess_py import ClientMode, TargetProcessClient
|
|
866
866
|
|
|
867
867
|
|
|
868
868
|
async def fetch_open_bugs() -> list[str]:
|
|
@@ -908,7 +908,7 @@ directly — do not nest `asyncio.run()`.
|
|
|
908
908
|
attribute assignment, not a hard sandbox.)
|
|
909
909
|
|
|
910
910
|
```python
|
|
911
|
-
from
|
|
911
|
+
from targetprocess_py import ClientMode, ReadOnlyViolation, TargetProcessClient
|
|
912
912
|
|
|
913
913
|
reporter = TargetProcessClient(
|
|
914
914
|
domain="example.tpondemand.com", token="…", mode=ClientMode.READONLY
|
|
@@ -41,7 +41,7 @@ import asyncio
|
|
|
41
41
|
import os
|
|
42
42
|
import sys
|
|
43
43
|
|
|
44
|
-
from
|
|
44
|
+
from targetprocess_py import ClientMode, TargetProcessClient, TargetProcessError
|
|
45
45
|
|
|
46
46
|
MARKER = "Bulk-updated by the targetprocess-py bulk_updates example."
|
|
47
47
|
|
|
@@ -25,7 +25,7 @@ import os
|
|
|
25
25
|
import sys
|
|
26
26
|
from collections import Counter
|
|
27
27
|
|
|
28
|
-
from
|
|
28
|
+
from targetprocess_py import ClientMode, TargetProcessClient, TargetProcessError
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
def _env(name: str) -> str:
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "targetprocess-py"
|
|
7
|
-
# Single source of truth is
|
|
7
|
+
# Single source of truth is targetprocess_py.__version__; hatchling reads it at
|
|
8
8
|
# build time (see [tool.hatch.version]), so a release bumps that one string.
|
|
9
9
|
dynamic = ["version"]
|
|
10
10
|
description = "A Python library for the TargetProcess v1 REST API"
|
|
@@ -65,10 +65,10 @@ Changelog = "https://github.com/man8/targetprocess-py/blob/main/CHANGELOG.md"
|
|
|
65
65
|
Issues = "https://github.com/man8/targetprocess-py/issues"
|
|
66
66
|
|
|
67
67
|
[tool.hatch.version]
|
|
68
|
-
path = "src/
|
|
68
|
+
path = "src/targetprocess_py/__init__.py"
|
|
69
69
|
|
|
70
70
|
[tool.hatch.build.targets.wheel]
|
|
71
|
-
packages = ["src/
|
|
71
|
+
packages = ["src/targetprocess_py"]
|
|
72
72
|
|
|
73
73
|
[tool.pytest.ini_options]
|
|
74
74
|
asyncio_mode = "auto"
|
|
@@ -142,7 +142,7 @@ max-complexity = 10
|
|
|
142
142
|
# CustomFields, Name) deliberately mirror the wire format the TP API returns,
|
|
143
143
|
# so N802's lowercase rule does not apply to them. They live on the Entity /
|
|
144
144
|
# NamedEntity bases in _base.py; models.py is the re-export surface.
|
|
145
|
-
"src/
|
|
145
|
+
"src/targetprocess_py/_base.py" = ["N802"]
|
|
146
146
|
|
|
147
147
|
[tool.coverage.run]
|
|
148
148
|
source = ["src"]
|
|
@@ -43,8 +43,8 @@ from typing import TYPE_CHECKING, Any, NamedTuple
|
|
|
43
43
|
|
|
44
44
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "src"))
|
|
45
45
|
|
|
46
|
-
from
|
|
47
|
-
from
|
|
46
|
+
from targetprocess_py import models, resources # noqa: E402
|
|
47
|
+
from targetprocess_py.resources.base import BaseResource # noqa: E402
|
|
48
48
|
|
|
49
49
|
if TYPE_CHECKING: # pragma: no cover - import-time typing only
|
|
50
50
|
from pydantic import BaseModel
|
|
@@ -42,7 +42,7 @@ from pathlib import Path
|
|
|
42
42
|
from typing import Any
|
|
43
43
|
from urllib.parse import urlparse
|
|
44
44
|
|
|
45
|
-
from
|
|
45
|
+
from targetprocess_py import ClientMode, ReadOnlyViolation, TargetProcessClient
|
|
46
46
|
|
|
47
47
|
ENV_FILE = Path.home() / ".config" / "targetprocess" / ".env"
|
|
48
48
|
|
{targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/__init__.py
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""A Python library for the TargetProcess v1 REST API."""
|
|
2
2
|
|
|
3
|
-
from
|
|
3
|
+
from targetprocess_py._observability import (
|
|
4
4
|
REQUEST_ID_HEADER,
|
|
5
5
|
ScrubbingFilter,
|
|
6
6
|
StructuredJsonFormatter,
|
|
@@ -9,8 +9,8 @@ from targetprocess._observability import (
|
|
|
9
9
|
new_request_id,
|
|
10
10
|
request_id_context,
|
|
11
11
|
)
|
|
12
|
-
from
|
|
13
|
-
from
|
|
12
|
+
from targetprocess_py.client import TargetProcessClient
|
|
13
|
+
from targetprocess_py.exceptions import (
|
|
14
14
|
AmbiguousMatchError,
|
|
15
15
|
APIError,
|
|
16
16
|
AuthenticationError,
|
|
@@ -25,7 +25,7 @@ from targetprocess.exceptions import (
|
|
|
25
25
|
TargetProcessError,
|
|
26
26
|
VerificationError,
|
|
27
27
|
)
|
|
28
|
-
from
|
|
28
|
+
from targetprocess_py.models import (
|
|
29
29
|
AssignableEntity,
|
|
30
30
|
Assignment,
|
|
31
31
|
Attachment,
|
|
@@ -71,8 +71,8 @@ from targetprocess.models import (
|
|
|
71
71
|
UserStory,
|
|
72
72
|
Workflow,
|
|
73
73
|
)
|
|
74
|
-
from
|
|
75
|
-
from
|
|
74
|
+
from targetprocess_py.request_handler import RequestHandler
|
|
75
|
+
from targetprocess_py.resources import (
|
|
76
76
|
AssignableResource,
|
|
77
77
|
AssignmentsResource,
|
|
78
78
|
AttachmentsResource,
|
|
@@ -109,10 +109,10 @@ from targetprocess.resources import (
|
|
|
109
109
|
UserStoriesResource,
|
|
110
110
|
WorkflowsResource,
|
|
111
111
|
)
|
|
112
|
-
from
|
|
113
|
-
from
|
|
112
|
+
from targetprocess_py.response_parser import ResponseParser
|
|
113
|
+
from targetprocess_py.types import ClientMode, LevelState, StateLevels, UpsertAction, UpsertResult
|
|
114
114
|
|
|
115
|
-
__version__ = "0.
|
|
115
|
+
__version__ = "0.3.0"
|
|
116
116
|
|
|
117
117
|
__all__ = [
|
|
118
118
|
# Exceptions
|
|
@@ -2,19 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
Everything these share - effort, flow metrics, planning references, workflow
|
|
4
4
|
state, assigned users - is declared once on
|
|
5
|
-
:class:`
|
|
5
|
+
:class:`targetprocess_py._base.AssignableEntity`. Each class below adds only what
|
|
6
6
|
TP's ``/meta`` declares beyond that base for its own type. ``InitialEstimate``
|
|
7
7
|
and ``Build`` recur but are deliberately not on the base: TP gives Task and Bug
|
|
8
8
|
no ``InitialEstimate``, and Task no ``Build``.
|
|
9
9
|
|
|
10
|
-
Re-exported by :mod:`
|
|
10
|
+
Re-exported by :mod:`targetprocess_py.models`, which stays the import surface
|
|
11
11
|
callers use.
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
14
|
from pydantic import Field
|
|
15
15
|
|
|
16
|
-
from
|
|
17
|
-
from
|
|
16
|
+
from targetprocess_py._base import AssignableEntity
|
|
17
|
+
from targetprocess_py._nested import EntityRef, RefWithImportance
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
class UserStory(AssignableEntity):
|
{targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/_base.py
RENAMED
|
@@ -12,7 +12,7 @@ counterpart - they hold the identity fields every payload shares and the
|
|
|
12
12
|
lookup and join types) have a base too.
|
|
13
13
|
|
|
14
14
|
The concrete entity models live in the sibling private modules and are
|
|
15
|
-
re-exported by :mod:`
|
|
15
|
+
re-exported by :mod:`targetprocess_py.models`, which stays the import surface
|
|
16
16
|
callers use.
|
|
17
17
|
"""
|
|
18
18
|
|
|
@@ -20,8 +20,8 @@ from datetime import datetime
|
|
|
20
20
|
|
|
21
21
|
from pydantic import BaseModel, ConfigDict, Field
|
|
22
22
|
|
|
23
|
-
from
|
|
24
|
-
from
|
|
23
|
+
from targetprocess_py._dates import TPDateTime
|
|
24
|
+
from targetprocess_py._nested import (
|
|
25
25
|
AssignedUsers,
|
|
26
26
|
CustomFieldValue,
|
|
27
27
|
EntityRef,
|
{targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/_content.py
RENAMED
|
@@ -4,15 +4,15 @@ A ``Comment`` and an ``Attachment`` both hang off a ``General``; a
|
|
|
4
4
|
``CustomField`` describes a field configured on a process rather than a value
|
|
5
5
|
held by an entity. None sits in TP's ``General`` hierarchy.
|
|
6
6
|
|
|
7
|
-
Re-exported by :mod:`
|
|
7
|
+
Re-exported by :mod:`targetprocess_py.models`, which stays the import surface
|
|
8
8
|
callers use.
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
11
|
from pydantic import BaseModel, ConfigDict, Field
|
|
12
12
|
|
|
13
|
-
from
|
|
14
|
-
from
|
|
15
|
-
from
|
|
13
|
+
from targetprocess_py._base import Entity, NamedEntity
|
|
14
|
+
from targetprocess_py._dates import TPDateTime
|
|
15
|
+
from targetprocess_py._nested import CustomFieldConfig, EntityRef, EntityTypeRef, UserRef
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
class Comment(Entity):
|
{targetprocess_py-0.2.1/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/_dates.py
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""TP ``/Date(ms±HHMM)/`` wire-format date handling.
|
|
2
2
|
|
|
3
3
|
The public names here (``TPDateTime``, ``parse_tp_date``, ``format_tp_date``)
|
|
4
|
-
are re-exported by :mod:`
|
|
4
|
+
are re-exported by :mod:`targetprocess_py.models`, which remains the import
|
|
5
5
|
surface callers use.
|
|
6
6
|
"""
|
|
7
7
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
``Project``, ``Team``, ``Release``, ``Iteration``, ``TeamIteration`` and
|
|
4
4
|
``TestCase`` derive from TP's ``General`` base but not from ``Assignable``, so
|
|
5
|
-
they inherit :class:`
|
|
5
|
+
they inherit :class:`targetprocess_py._base.GeneralEntity` and declare their own
|
|
6
6
|
effort and planning fields rather than the assignable set.
|
|
7
7
|
|
|
8
8
|
Several carry ``Effort``/``EffortCompleted``/``EffortToDo``/``Progress``/
|
|
@@ -13,15 +13,15 @@ to gain or lose one of the five would have to be pulled back out of it. The
|
|
|
13
13
|
repetition is the cost of each class listing exactly what its own ``/meta``
|
|
14
14
|
declares, which is the property ``scripts/check_model_coverage.py`` checks.
|
|
15
15
|
|
|
16
|
-
Re-exported by :mod:`
|
|
16
|
+
Re-exported by :mod:`targetprocess_py.models`, which stays the import surface
|
|
17
17
|
callers use.
|
|
18
18
|
"""
|
|
19
19
|
|
|
20
20
|
from pydantic import Field
|
|
21
21
|
|
|
22
|
-
from
|
|
23
|
-
from
|
|
24
|
-
from
|
|
22
|
+
from targetprocess_py._base import GeneralEntity
|
|
23
|
+
from targetprocess_py._dates import TPDateTime
|
|
24
|
+
from targetprocess_py._nested import AssignedUsers, EntityRef, RefWithImportance
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
class Project(GeneralEntity):
|