targetprocess-py 0.1.0__tar.gz → 0.2.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.1.0 → targetprocess_py-0.2.0}/.coderabbit.yaml +8 -5
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/.env.example +4 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/.github/dependabot.yml +10 -2
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/.github/workflows/ci.yml +4 -4
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/.github/workflows/commit-message.yml +1 -1
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/.github/workflows/release.yml +1 -1
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/.pre-commit-config.yaml +1 -1
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/CHANGELOG.md +67 -1
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/CONTRIBUTING.md +108 -16
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/PKG-INFO +30 -12
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/README.md +28 -10
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/SECURITY.md +2 -1
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/SPEC.md +134 -90
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/docs/USAGE.md +338 -4
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/docs/testing.md +16 -5
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/examples/README.md +11 -10
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/examples/bulk_updates.py +25 -15
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/examples/create_bug.py +25 -16
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/pyproject.toml +1 -1
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/scripts/check_internal_refs.py +8 -32
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/scripts/live_smoke.py +1 -1
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/__init__.py +10 -2
- targetprocess_py-0.2.0/src/targetprocess/exceptions.py +272 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/request_handler.py +92 -6
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/__init__.py +2 -0
- targetprocess_py-0.2.0/src/targetprocess/resources/_verify.py +209 -0
- targetprocess_py-0.2.0/src/targetprocess/resources/assignables.py +351 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/base.py +378 -10
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/bugs.py +6 -2
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/entities.py +42 -2
- targetprocess_py-0.2.0/src/targetprocess/resources/entity_states.py +129 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/epics.py +6 -2
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/features.py +6 -2
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/relation_types.py +1 -1
- targetprocess_py-0.2.0/src/targetprocess/resources/relations.py +36 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/requests.py +6 -2
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/tasks.py +6 -2
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/user_stories.py +6 -2
- targetprocess_py-0.2.0/src/targetprocess/resources/users.py +81 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/types.py +37 -0
- targetprocess_py-0.2.0/tests/integration/cassettes/test_live_readonly/test_entity_states_scoped_to_a_workflow.yaml +373 -0
- targetprocess_py-0.2.0/tests/integration/cassettes/test_live_readonly/test_logged_user_resolves_the_acting_user.yaml +89 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/integration/cassettes/test_live_readwrite/test_bulk_create_and_update_tasks_under_a_story.yaml +3 -3
- targetprocess_py-0.2.0/tests/integration/cassettes/test_live_readwrite/test_custom_field_set_and_clear_round_trip.yaml +641 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/integration/cassettes/test_live_readwrite/test_request_create_update_delete_round_trip.yaml +2 -2
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/integration/cassettes/test_live_readwrite/test_user_story_create_update_delete_round_trip.yaml +2 -2
- targetprocess_py-0.2.0/tests/integration/cassettes/test_live_readwrite/test_verified_update_returns_the_re_read.yaml +533 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/integration/cassettes/test_live_readwrite_surfaces/test_assignment_create_and_delete.yaml +1 -1
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/integration/cassettes/test_live_readwrite_surfaces/test_attachment_upload_list_download_and_delete.yaml +3 -3
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/integration/cassettes/test_live_readwrite_surfaces/test_comment_create_update_delete_round_trip.yaml +3 -3
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/integration/cassettes/test_live_readwrite_surfaces/test_relation_create_and_delete.yaml +2 -2
- targetprocess_py-0.2.0/tests/integration/cassettes/test_live_readwrite_surfaces/test_relation_inbound_outbound_create_and_filter.yaml +895 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/integration/cassettes/test_live_readwrite_surfaces/test_role_effort_create_update_delete_round_trip.yaml +1 -1
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/integration/cassettes/test_live_readwrite_surfaces/test_team_assignment_create_and_delete.yaml +1 -1
- targetprocess_py-0.2.0/tests/integration/cassettes/test_live_readwrite_surfaces/test_two_level_advance_moves_both_levels.yaml +2060 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/integration/conftest.py +87 -11
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/integration/test_live_readonly.py +47 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/integration/test_live_readwrite.py +126 -9
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/integration/test_live_readwrite_surfaces.py +170 -8
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_cassette_guard.py +56 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_cassette_sanitiser.py +222 -1
- targetprocess_py-0.2.0/tests/test_exceptions.py +297 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_internal_refs.py +13 -11
- targetprocess_py-0.2.0/tests/test_query_parameters.py +120 -0
- targetprocess_py-0.2.0/tests/test_request_handler_logged_user.py +59 -0
- targetprocess_py-0.2.0/tests/test_resources/test_assignable_state.py +468 -0
- targetprocess_py-0.2.0/tests/test_resources/test_custom_field_writes.py +152 -0
- targetprocess_py-0.2.0/tests/test_resources/test_entity_states.py +201 -0
- targetprocess_py-0.2.0/tests/test_resources/test_ignored_filter_paths.py +257 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_relations.py +32 -0
- targetprocess_py-0.2.0/tests/test_resources/test_users.py +165 -0
- targetprocess_py-0.2.0/tests/test_resources/test_verified_writes.py +606 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/uv.lock +21 -21
- targetprocess_py-0.1.0/src/targetprocess/exceptions.py +0 -147
- targetprocess_py-0.1.0/src/targetprocess/resources/entity_states.py +0 -20
- targetprocess_py-0.1.0/src/targetprocess/resources/relations.py +0 -34
- targetprocess_py-0.1.0/src/targetprocess/resources/users.py +0 -20
- targetprocess_py-0.1.0/tests/test_exceptions.py +0 -124
- targetprocess_py-0.1.0/tests/test_resources/test_entity_states.py +0 -39
- targetprocess_py-0.1.0/tests/test_resources/test_users.py +0 -39
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/.commitlintrc.json +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/.github/labels.yml +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/.github/pull_request_template.md +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/.gitignore +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/.jscpd.json +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/.python-version +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/.tool-versions +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/CODEOWNERS +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/CODE_OF_CONDUCT.md +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/LICENSE +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/examples/list_user_stories.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/examples/readonly_reporting.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/scripts/apply_labels.sh +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/scripts/check_commit_message.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/scripts/check_large_files.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/scripts/check_model_coverage.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/scripts/check_todos.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/_assignables.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/_base.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/_content.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/_dates.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/_entity_types.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/_generals.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/_joins.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/_lookups.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/_nested.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/_observability.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/client.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/models.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/py.typed +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/assignments.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/attachments.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/comments.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/custom_activities.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/custom_fields.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/custom_rules.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/entity_types.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/iterations.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/priorities.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/processes.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/projects.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/releases.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/role_efforts.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/roles.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/severities.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/team_assignments.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/team_iterations.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/teams.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/terms.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/test_cases.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/times.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/resources/workflows.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/response_parser.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/src/targetprocess/transport.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/__init__.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/_support/__init__.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/_support/request_handler.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/conftest.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/integration/__init__.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/integration/cassettes/test_live_readonly/test_entity_types_catalogue_parses.yaml +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/integration/cassettes/test_live_readonly/test_find_for_day_matches_a_real_entry.yaml +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/integration/cassettes/test_live_readonly/test_generic_entities_comment.yaml +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/integration/cassettes/test_live_readonly/test_get_single_with_include.yaml +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/integration/cassettes/test_live_readonly/test_list_user_stories_parses.yaml +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/integration/cassettes/test_live_readonly/test_pagination_crosses_page_boundary.yaml +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/integration/cassettes/test_live_readonly/test_priorities_scoped_to_an_entity_type.yaml +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/integration/cassettes/test_live_readonly/test_severities_rank_the_bug_set.yaml +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/live_payloads.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_assignment.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_attachment.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_bug.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_client.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_comment.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_commit_message.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_custom_activity.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_custom_field.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_custom_field_value.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_custom_rule.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_entity_extras.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_entity_ref.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_entity_state.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_entity_type.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_epic.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_feature.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_integration_request_response.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_iteration.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_model_field_coverage.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_models.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_observability.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_priority.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_process.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_project.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_relation.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_relation_type.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_release.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_request.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_request_handler.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_request_handler_bulk.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_assignments.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_attachments.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_base_resource.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_bugs.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_comments.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_custom_activities.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_custom_fields.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_custom_rules.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_entities.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_entity_types.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_epics.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_features.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_iterations.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_lookup_resolvers.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_priorities.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_processes.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_projects.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_relation_types.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_releases.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_requests.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_role_efforts.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_roles.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_server_capability.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_severities.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_tasks.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_team_assignments.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_team_iterations.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_teams.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_terms.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_test_cases.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_times.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_user_stories.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_resources/test_workflows.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_response_parser.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_role.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_role_effort.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_severity.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_task.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_team.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_team_assignment.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_team_iteration.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_term.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_test_case.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_time.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_transport.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_types.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_uploaded_attachment.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_user.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_user_story.py +0 -0
- {targetprocess_py-0.1.0 → targetprocess_py-0.2.0}/tests/test_workflow.py +0 -0
|
@@ -124,11 +124,14 @@ reviews:
|
|
|
124
124
|
Items/Next/Prev envelope — are kept as recorded so a cassette still
|
|
125
125
|
exercises real parsing, pagination and filter behaviour
|
|
126
126
|
(docs/testing.md). On a write-path cassette the REQUEST body is
|
|
127
|
-
recorded as sent and is deliberately not field-scrubbed
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
127
|
+
recorded as sent and is deliberately not field-scrubbed, save the Name
|
|
128
|
+
of each CustomFields entry (in one entity, or every item of a bulk
|
|
129
|
+
array), which is the tenant's configuration and is scrubbed to the
|
|
130
|
+
"Sanitised Name" placeholder as every Name in a response body is: its
|
|
131
|
+
other Name/Description values are synthetic strings the test invented,
|
|
132
|
+
carrying the module's recording prefix, and must NOT be flagged. Do
|
|
133
|
+
flag a request body carrying text that reads as having come off the
|
|
134
|
+
live instance rather than being invented.
|
|
132
135
|
- path: ".github/workflows/**"
|
|
133
136
|
instructions: |
|
|
134
137
|
GitHub Actions CI — high blast radius. Validation jobs run on pull
|
|
@@ -11,6 +11,10 @@ TP_DOMAIN=example.tpondemand.com
|
|
|
11
11
|
# Fetch it from your TP instance's account settings; never share or commit it.
|
|
12
12
|
TP_TOKEN=your-api-token
|
|
13
13
|
|
|
14
|
+
# The project the write examples target when --project-id is not given. Set it
|
|
15
|
+
# to a throwaway/sandbox project on your own instance; never production.
|
|
16
|
+
TP_SANDBOX_PROJECT_ID=
|
|
17
|
+
|
|
14
18
|
# Comma-separated allow-list of project ids the write examples may modify.
|
|
15
19
|
# Only set this for a throwaway/sandbox project; never production.
|
|
16
20
|
# Required by examples/create_bug.py and examples/bulk_updates.py.
|
|
@@ -17,6 +17,14 @@
|
|
|
17
17
|
# mypy --strict, pytest with --cov-fail-under=90, the pre-commit hook suite,
|
|
18
18
|
# duplication detection, CodeQL, CodeRabbit review) decide whether a bump is safe
|
|
19
19
|
# before it reaches main.
|
|
20
|
+
#
|
|
21
|
+
# Every commit-message prefix below (prefix and prefix-development alike) must
|
|
22
|
+
# be a type the commit-msg hooks accept — the type-enum in .commitlintrc.json,
|
|
23
|
+
# enforced by conventional-pre-commit — because CI lints each pull request's
|
|
24
|
+
# title as a commit message and squash merge makes that title the commit on
|
|
25
|
+
# main, so a prefix outside that set leaves every update from that ecosystem
|
|
26
|
+
# unmergeable. The uv ecosystem uses build; pre-commit and github-actions both
|
|
27
|
+
# use ci.
|
|
20
28
|
version: 2
|
|
21
29
|
|
|
22
30
|
updates:
|
|
@@ -42,8 +50,8 @@ updates:
|
|
|
42
50
|
labels:
|
|
43
51
|
- "dependencies"
|
|
44
52
|
commit-message:
|
|
45
|
-
prefix: "
|
|
46
|
-
prefix-development: "
|
|
53
|
+
prefix: "build"
|
|
54
|
+
prefix-development: "build"
|
|
47
55
|
include: "scope"
|
|
48
56
|
groups:
|
|
49
57
|
# Test/lint/type tooling moves together: a mypy or ruff bump is judged by
|
|
@@ -22,7 +22,7 @@ jobs:
|
|
|
22
22
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
23
23
|
with:
|
|
24
24
|
persist-credentials: false
|
|
25
|
-
- uses: astral-sh/setup-uv@
|
|
25
|
+
- uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
|
|
26
26
|
with:
|
|
27
27
|
python-version: ${{ matrix.python-version }}
|
|
28
28
|
- run: uv sync --all-extras
|
|
@@ -45,7 +45,7 @@ jobs:
|
|
|
45
45
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
46
46
|
with:
|
|
47
47
|
persist-credentials: false
|
|
48
|
-
- uses: astral-sh/setup-uv@
|
|
48
|
+
- uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
|
|
49
49
|
- run: uv sync --all-extras
|
|
50
50
|
- run: uv run pre-commit run --all-files --hook-stage pre-commit --show-diff-on-failure
|
|
51
51
|
- run: uv run pre-commit run --all-files --hook-stage pre-push --show-diff-on-failure
|
|
@@ -80,7 +80,7 @@ jobs:
|
|
|
80
80
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
81
81
|
with:
|
|
82
82
|
persist-credentials: false
|
|
83
|
-
- uses: astral-sh/setup-uv@
|
|
83
|
+
- uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
|
|
84
84
|
- run: uv export --all-extras --no-emit-project --format requirements-txt --quiet -o requirements-audit.txt
|
|
85
85
|
- run: uvx pip-audit --strict --no-deps --disable-pip --progress-spinner off -r requirements-audit.txt
|
|
86
86
|
|
|
@@ -95,7 +95,7 @@ jobs:
|
|
|
95
95
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
96
96
|
with:
|
|
97
97
|
persist-credentials: false
|
|
98
|
-
- uses: astral-sh/setup-uv@
|
|
98
|
+
- uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
|
|
99
99
|
- run: uv build
|
|
100
100
|
- run: uvx twine==7.0.0 check --strict dist/*
|
|
101
101
|
- name: Smoke-test the built wheel in a clean environment
|
|
@@ -22,7 +22,7 @@ jobs:
|
|
|
22
22
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
23
23
|
with:
|
|
24
24
|
persist-credentials: false
|
|
25
|
-
- uses: astral-sh/setup-uv@
|
|
25
|
+
- uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
|
|
26
26
|
- run: uv sync --all-extras
|
|
27
27
|
- name: Check the pull request title as a commit message
|
|
28
28
|
run: |
|
|
@@ -42,7 +42,7 @@ jobs:
|
|
|
42
42
|
# before building it.
|
|
43
43
|
- name: Assert the tagged commit is on main
|
|
44
44
|
run: git merge-base --is-ancestor "$GITHUB_SHA" origin/main
|
|
45
|
-
- uses: astral-sh/setup-uv@
|
|
45
|
+
- uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
|
|
46
46
|
- run: uv build
|
|
47
47
|
- run: uvx twine==7.0.0 check --strict dist/*
|
|
48
48
|
# The version is read from the package, not the tag (see
|
|
@@ -82,7 +82,7 @@ repos:
|
|
|
82
82
|
# line above sets up; CI runs the same two over a pull request's title,
|
|
83
83
|
# since squash merge makes the title the commit on main.
|
|
84
84
|
- repo: https://github.com/compilerla/conventional-pre-commit
|
|
85
|
-
rev: v4.
|
|
85
|
+
rev: v4.4.0
|
|
86
86
|
hooks:
|
|
87
87
|
- id: conventional-pre-commit
|
|
88
88
|
name: commit message follows Conventional Commits
|
|
@@ -7,6 +7,71 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.2.0] - 2026-09-17
|
|
11
|
+
|
|
12
|
+
The first beta release.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- `users.logged_user()`: resolves the user the client's credential
|
|
17
|
+
authenticates as with one `GET /api/v1/Users/LoggedUser`, returning the
|
|
18
|
+
`User` model, cached per client instance. `RequestHandler.logged_user()` is
|
|
19
|
+
the fixed-path read beneath it.
|
|
20
|
+
- `update()` and `update_many()` take an opt-in, keyword-only `verify=True`:
|
|
21
|
+
after the write each entity is re-read with one independent GET narrowed to
|
|
22
|
+
the requested keys, the re-read model is returned instead of TargetProcess's
|
|
23
|
+
own echo, and a requested field that is not observed raises the new
|
|
24
|
+
`VerificationError`, which carries every mismatch and survives a pickle
|
|
25
|
+
round trip. A verified write refuses, before sending, a `CustomFields` entry
|
|
26
|
+
that is not a mapping with a string `Name`. The default path is unchanged.
|
|
27
|
+
- `set_custom_field(id, name, value)` on every typed manager sets a
|
|
28
|
+
custom-field value by name, or clears it when `value` is `None`, sending
|
|
29
|
+
`{"CustomFields": [{"Name": ..., "Value": ...}]}`. It re-reads the entity by
|
|
30
|
+
default and raises `VerificationError` when the value, or the clear, did not
|
|
31
|
+
land, or no field of that name came back.
|
|
32
|
+
- `entity_states.for_workflow(workflow_id)`, `entity_states.resolve(name, *,
|
|
33
|
+
workflow_id)` and `entity_states.final_states(workflow_id)`: the states of
|
|
34
|
+
one workflow, a state name resolved within that workflow (raising
|
|
35
|
+
`NotFoundError` or `AmbiguousMatchError` rather than guessing), and the
|
|
36
|
+
workflow's final states.
|
|
37
|
+
- `entity_state_levels(id)` and `advance_state(id, *, to, team_to=None,
|
|
38
|
+
verify=True)` on the six work-item managers, through their new shared base
|
|
39
|
+
`AssignableResource`: a work item's project-workflow and team-workflow
|
|
40
|
+
entity states read together as `StateLevels` (of two `LevelState`s), and
|
|
41
|
+
moved as one transition - each target resolved within its own level's
|
|
42
|
+
workflow, one write where both levels share a workflow, and the new
|
|
43
|
+
`SplitTransitionError`, which survives a pickle round trip, raised before
|
|
44
|
+
any write when a distinct team level would be left behind.
|
|
45
|
+
|
|
46
|
+
### Changed
|
|
47
|
+
|
|
48
|
+
- Development status moves from Alpha to Beta (the
|
|
49
|
+
`Development Status :: 4 - Beta` classifier), and the README states what
|
|
50
|
+
1.0.0 requires.
|
|
51
|
+
- `list()` refuses, before any request is sent, a `where=` filter naming a
|
|
52
|
+
nested collection path TargetProcess accepts and silently ignores -
|
|
53
|
+
currently `Assignments.*` on the assignable collections (`UserStory`,
|
|
54
|
+
`Bug`, `Task`, `Feature`, `Epic`, `Request`, and `Assignable` through
|
|
55
|
+
`entities`), which answer HTTP 200 with the unfiltered rows. The
|
|
56
|
+
`ValueError` names the join-entity route: query `assignments` by
|
|
57
|
+
`GeneralUser.Id`.
|
|
58
|
+
- Every query-parameter name the request handler puts on an entity-API
|
|
59
|
+
request is declared in one allowlist (`QUERY_PARAMETERS`), and a name
|
|
60
|
+
outside it is refused before the request is built rather than sent for
|
|
61
|
+
TargetProcess to ignore. The `access_token` the transport merges in at
|
|
62
|
+
send time is not part of the allowlist.
|
|
63
|
+
- The relation examples in the `relations` and `relation_types` docstrings,
|
|
64
|
+
and the relations read in `scripts/live_smoke.py`, use the current
|
|
65
|
+
`Inbound`/`Outbound` names in place of the deprecated `Master`/`Slave`: the
|
|
66
|
+
create, the `Outbound.Id` filter and the include.
|
|
67
|
+
|
|
68
|
+
### Fixed
|
|
69
|
+
|
|
70
|
+
- `ReadOnlyViolation` raised with an operation and a resource now survives a
|
|
71
|
+
pickle round trip with its message and attributes; it used to come back
|
|
72
|
+
with the generic readonly-mode message. Every library exception now pickles
|
|
73
|
+
through one mechanism on `TargetProcessError`.
|
|
74
|
+
|
|
10
75
|
## [0.1.0] - 2026-09-08
|
|
11
76
|
|
|
12
77
|
The first public release.
|
|
@@ -97,5 +162,6 @@ The first public release.
|
|
|
97
162
|
- Log scrubbing redacts the `access_token` query parameter and `Authorization`
|
|
98
163
|
header values from the library's own log records.
|
|
99
164
|
|
|
100
|
-
[Unreleased]: https://github.com/man8/targetprocess-py/compare/v0.
|
|
165
|
+
[Unreleased]: https://github.com/man8/targetprocess-py/compare/v0.2.0...HEAD
|
|
166
|
+
[0.2.0]: https://github.com/man8/targetprocess-py/compare/v0.1.0...v0.2.0
|
|
101
167
|
[0.1.0]: https://github.com/man8/targetprocess-py/releases/tag/v0.1.0
|
|
@@ -22,15 +22,16 @@ unacceptable behaviour to louis@man8.com.
|
|
|
22
22
|
|
|
23
23
|
## Development setup
|
|
24
24
|
|
|
25
|
-
Requires [uv](https://docs.astral.sh/uv/). `.python-version`
|
|
26
|
-
development interpreter (3.13); the library
|
|
27
|
-
|
|
25
|
+
Requires [uv](https://docs.astral.sh/uv/). `.python-version` and
|
|
26
|
+
`.tool-versions` both pin the development interpreter (3.13); the library
|
|
27
|
+
itself supports 3.12 and 3.13 (`requires-python >=3.12` in `pyproject.toml`),
|
|
28
|
+
and CI runs the test suite on both.
|
|
28
29
|
|
|
29
30
|
```bash
|
|
30
31
|
git clone https://github.com/man8/targetprocess-py.git
|
|
31
32
|
cd targetprocess-py
|
|
32
33
|
uv sync --all-extras
|
|
33
|
-
uv run pre-commit install # installs
|
|
34
|
+
uv run pre-commit install # installs the pre-commit, commit-msg and pre-push hooks
|
|
34
35
|
```
|
|
35
36
|
|
|
36
37
|
## Quality gates
|
|
@@ -52,17 +53,83 @@ package build run in CI.
|
|
|
52
53
|
| Dependency vulnerabilities | `pip-audit` over the locked environment (CI) |
|
|
53
54
|
| Package build | `uv build` and `twine check` (CI) |
|
|
54
55
|
|
|
55
|
-
|
|
56
|
-
(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
56
|
+
Every hook that names no stage — `ruff-check`, `ruff-format`, the three
|
|
57
|
+
repository checks (file size, debt markers, internal references) and the
|
|
58
|
+
upstream `pre-commit-hooks` set (large added files, YAML and TOML validity,
|
|
59
|
+
merge-conflict markers, private keys, end-of-file and trailing whitespace) —
|
|
60
|
+
runs at both the commit and the push stage. `mypy --strict src` is pinned to
|
|
61
|
+
the push stage alone, being too slow to gate every commit and meaningful only
|
|
62
|
+
over the whole package. Ruff and mypy run through `uv run`, so the hook
|
|
63
|
+
versions are exactly the ones pinned in `uv.lock`, with no second pin to
|
|
64
|
+
drift.
|
|
65
|
+
|
|
66
|
+
Also enforced:
|
|
67
|
+
|
|
68
|
+
- A 1000-line / 256 KiB ceiling per tracked file
|
|
69
|
+
(`scripts/check_large_files.py`). `uv.lock` and the integration cassettes
|
|
70
|
+
are exempt, as generated artefacts whose size is not a design decision.
|
|
71
|
+
- An issue reference on every debt marker (`scripts/check_todos.py`): a
|
|
72
|
+
`TODO`, `FIXME`, `HACK` or `XXX` with no reference is debt nobody owns,
|
|
73
|
+
since it never reaches a board. Markdown is not scanned — a marker in
|
|
74
|
+
prose is documentation about markers, not debt in a code path.
|
|
75
|
+
- No internal references in tracked files (`scripts/check_internal_refs.py`)
|
|
76
|
+
or in commit messages (`scripts/check_commit_message.py`).
|
|
77
|
+
- A cyclomatic-complexity ceiling of 10 (ruff `C901`).
|
|
78
|
+
- Copy-paste detection above 3% duplication over Python sources
|
|
79
|
+
(`.jscpd.json`). Node-only tooling, so it runs in CI rather than requiring
|
|
80
|
+
a Node toolchain on every dev machine.
|
|
81
|
+
|
|
82
|
+
The internal-references check matches a generic shape — an upper-case key of
|
|
83
|
+
two to six characters, a dash, and up to six digits — rather than a list of
|
|
84
|
+
keys, since publishing that list would leak the very thing the check exists to
|
|
85
|
+
keep out. Matching is case-sensitive: lower-cased, the same shape also matches
|
|
86
|
+
a locked dependency version and a GUID fragment. `EXCLUDED_PREFIXES` excuses
|
|
87
|
+
the public standards designations that share the shape. Prose is scanned
|
|
88
|
+
here, unlike the debt-marker check above, because the hook runs over every
|
|
89
|
+
tracked text file. `ALLOWED_PATHS` permits a file by path alone — an entry
|
|
90
|
+
exempts references only, so a session URL or trailer is refused there too —
|
|
91
|
+
and it lapses as soon as the file stops carrying a reference, which
|
|
92
|
+
`tests/test_internal_refs.py` asserts. The commit-message hook refuses the
|
|
93
|
+
same shape with the same exclusions.
|
|
61
94
|
|
|
62
95
|
Coverage is branch coverage over `src/`, gated at 90%. A change that drops
|
|
63
96
|
coverage below the gate is not mergeable; add tests with the change rather than
|
|
64
97
|
after it.
|
|
65
98
|
|
|
99
|
+
`.github/workflows/ci.yml` runs five job definitions — six job runs, since
|
|
100
|
+
`test` is a two-value matrix — on every push to `main` and every pull
|
|
101
|
+
request: `test` (`uv sync`, `ruff check`, `ruff format --check`,
|
|
102
|
+
`mypy --strict`, `pytest` with the coverage gate, over a Python 3.12/3.13
|
|
103
|
+
matrix with `UV_PYTHON` overriding the `.python-version` pin per leg);
|
|
104
|
+
`quality` (`pre-commit run --all-files` at both the `pre-commit` and
|
|
105
|
+
`pre-push` stages, which also proves the hook configuration itself still
|
|
106
|
+
works); `duplication` (jscpd); `audit` (`pip-audit` over `uv.lock` exported
|
|
107
|
+
with every extra and its hashes, failing the job on any known
|
|
108
|
+
vulnerability); and `build` (`uv build`, `twine check --strict`, and an
|
|
109
|
+
import of the built wheel from a clean environment).
|
|
110
|
+
|
|
111
|
+
`.github/workflows/release.yml` builds the distributions on a `v*` tag,
|
|
112
|
+
refuses a tag whose commit is not on `main` or whose name disagrees with the
|
|
113
|
+
wheel's version, and publishes to PyPI by trusted publishing (OIDC) under the
|
|
114
|
+
`pypi` GitHub environment. No token is stored; the environment's protection
|
|
115
|
+
rules are the manual gate on a publish.
|
|
116
|
+
|
|
117
|
+
One check runs outside CI, since it needs a live instance and a real token
|
|
118
|
+
that CI has neither of: `scripts/check_model_coverage.py` diffs each model's
|
|
119
|
+
declared aliases against its type's `/api/v1/{collection}/meta` and reports
|
|
120
|
+
coverage per model in both directions — a field TP declares that the model
|
|
121
|
+
does not, and a field the model declares that TP does not. It is GET-only;
|
|
122
|
+
`--fail-under` turns it into a gate for a caller who does have both a live
|
|
123
|
+
instance and a token. Three further conditions fail a run besides a coverage
|
|
124
|
+
shortfall: a declared field absent from `/meta`; a dead `EXCLUDED` or
|
|
125
|
+
`KNOWN_DEVIATIONS` entry — recorded to keep a decision visible, and stale as
|
|
126
|
+
soon as that decision changes; and a `/meta` body reporting no properties at
|
|
127
|
+
all, which is a failed measurement rather than full coverage. `--validate`
|
|
128
|
+
additionally fetches real records and parses them through each model — the
|
|
129
|
+
check `/meta` alone cannot make, since it says which properties exist and
|
|
130
|
+
not what TP puts in them — and a model whose sample cannot be fetched is
|
|
131
|
+
reported as not checked and fails the run.
|
|
132
|
+
|
|
66
133
|
## Tests
|
|
67
134
|
|
|
68
135
|
- Unit tests live in `tests/` (one file per model, resource or component) and
|
|
@@ -104,9 +171,12 @@ after it.
|
|
|
104
171
|
body rather than a fixture teardown a later refactor could move outside the
|
|
105
172
|
cassette.
|
|
106
173
|
- **Everything sent is synthetic.** `_scrub_request` neutralises the host and
|
|
107
|
-
the token but nothing field-level,
|
|
108
|
-
|
|
109
|
-
the
|
|
174
|
+
the token but nothing field-level, save the name of each custom field in a
|
|
175
|
+
JSON request body (one entity, or every item of a bulk array), which is the
|
|
176
|
+
tenant's configuration and is scrubbed to the placeholder as every `Name` in
|
|
177
|
+
a response body is. So a request body is otherwise recorded as sent: a
|
|
178
|
+
write-path test may only send text it invented, never a value copied off the
|
|
179
|
+
live instance.
|
|
110
180
|
- **Org-level state is read, never written.** Where a surface needs an
|
|
111
181
|
existing Role, Team, RelationType or project membership, the test reads it
|
|
112
182
|
live and uses it. Creating one would be a write outside the sandbox.
|
|
@@ -160,9 +230,10 @@ after it.
|
|
|
160
230
|
|
|
161
231
|
- Ruff enforces PEP 8, pep8-naming, Google-convention docstrings on the public
|
|
162
232
|
API, and the complexity ceiling. There are two documented naming exceptions:
|
|
163
|
-
the PascalCase accessors in `
|
|
164
|
-
`pyproject.toml`
|
|
165
|
-
declaration). Add a third only
|
|
233
|
+
the PascalCase accessors in `_base.py` (a per-file ignore in
|
|
234
|
+
`pyproject.toml`; `models.py` is the re-export surface) and the
|
|
235
|
+
`ReadOnlyViolation` name (a `noqa` at its declaration). Add a third only
|
|
236
|
+
with the same kind of justification.
|
|
166
237
|
- Prose (docs, comments, docstrings) uses British English, and identifiers
|
|
167
238
|
follow suit where a spelling choice exists. Field names that mirror the
|
|
168
239
|
TargetProcess wire format keep TP's spelling and casing.
|
|
@@ -222,6 +293,27 @@ feat!: require an explicit mode on the client
|
|
|
222
293
|
session that produced the change, are welcome: they say how the change was
|
|
223
294
|
made.
|
|
224
295
|
|
|
296
|
+
## Releasing
|
|
297
|
+
|
|
298
|
+
A release is a pull request followed by a tag.
|
|
299
|
+
|
|
300
|
+
1. In a pull request, set `__version__` in `src/targetprocess/__init__.py`
|
|
301
|
+
(the only version string; the build reads it). Move the `[Unreleased]`
|
|
302
|
+
entries in `CHANGELOG.md` under a `## [X.Y.Z] - YYYY-MM-DD` heading dated
|
|
303
|
+
the release day, and update the link references at its foot. When the minor
|
|
304
|
+
version changes, update the supported-versions table in `SECURITY.md`. When
|
|
305
|
+
the development status changes, update the classifier in `pyproject.toml`
|
|
306
|
+
and the README's Development Status section.
|
|
307
|
+
2. Once it has merged, a maintainer creates a signed, annotated tag on that
|
|
308
|
+
commit on `main` and pushes it:
|
|
309
|
+
`git tag -s vX.Y.Z -m "targetprocess-py X.Y.Z" <commit>`, then
|
|
310
|
+
`git push origin vX.Y.Z`.
|
|
311
|
+
3. `.github/workflows/release.yml` builds and checks the distributions, then
|
|
312
|
+
waits for a maintainer to approve the `pypi` environment deployment. Once
|
|
313
|
+
approved it publishes to PyPI and creates the GitHub Release from the
|
|
314
|
+
version's CHANGELOG section.
|
|
315
|
+
4. Confirm the new version on PyPI and its GitHub Release.
|
|
316
|
+
|
|
225
317
|
## Reporting a vulnerability
|
|
226
318
|
|
|
227
319
|
See [SECURITY.md](SECURITY.md). Do not open a public issue for a suspected
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: targetprocess-py
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.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
|
|
@@ -11,7 +11,7 @@ Author-email: Louis Mandelstam <louis@man8.com>
|
|
|
11
11
|
License: MIT
|
|
12
12
|
License-File: LICENSE
|
|
13
13
|
Keywords: api,async,asyncio,client,httpx,pydantic,rest,sdk,targetprocess
|
|
14
|
-
Classifier: Development Status ::
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
15
|
Classifier: Framework :: AsyncIO
|
|
16
16
|
Classifier: Framework :: Pydantic :: 2
|
|
17
17
|
Classifier: Intended Audience :: Developers
|
|
@@ -326,16 +326,33 @@ See [SPEC.md](SPEC.md) for the full specification, including detailed architectu
|
|
|
326
326
|
|
|
327
327
|
## Development Status
|
|
328
328
|
|
|
329
|
-
**Current
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
329
|
+
**Current status**: Beta. The core library is complete and tested against a
|
|
330
|
+
real TargetProcess instance. The public surface may still change between 0.x
|
|
331
|
+
minor releases; every change is recorded in [CHANGELOG.md](CHANGELOG.md).
|
|
332
|
+
|
|
333
|
+
### What 1.0.0 requires
|
|
334
|
+
|
|
335
|
+
1.0.0 will be released once all of the following hold:
|
|
336
|
+
|
|
337
|
+
1. At least one comprehensive production integration is built on the library
|
|
338
|
+
and has been stable through the beta period.
|
|
339
|
+
2. No open issue labelled `bug` remains unless explicitly deferred past 1.0.0,
|
|
340
|
+
and every known case where TargetProcess silently ignores all or part of a
|
|
341
|
+
request has been resolved: the library refuses it before sending, verifies it
|
|
342
|
+
after the write, or SPEC.md documents it as a limitation.
|
|
343
|
+
3. The public surface is frozen: SPEC.md's Public API Surface matches
|
|
344
|
+
`targetprocess.__all__`, a Semantic Versioning promise for that surface is
|
|
345
|
+
stated, and a deprecation policy is written.
|
|
346
|
+
4. Documentation and the recorded test cassettes are current: every public
|
|
347
|
+
resource manager is documented in [docs/USAGE.md](docs/USAGE.md), the
|
|
348
|
+
`KNOWN_DEVIATIONS` table in `scripts/check_model_coverage.py` has been
|
|
349
|
+
re-checked against a live instance, and the recorded test cassettes have no
|
|
350
|
+
open hygiene issues.
|
|
351
|
+
5. CI tests every Python version `pyproject.toml` claims.
|
|
352
|
+
6. The last beta release needed no breaking change to the public surface.
|
|
353
|
+
7. The release carries the `Development Status :: 5 - Production/Stable`
|
|
354
|
+
classifier, a CHANGELOG section for 1.0.0, a `v1.0.0` tag on `main`, and is
|
|
355
|
+
published to PyPI through the release workflow.
|
|
339
356
|
|
|
340
357
|
## Requirements
|
|
341
358
|
|
|
@@ -359,6 +376,7 @@ in [`.env.example`](.env.example) (the committed template) and the
|
|
|
359
376
|
| --- | --- |
|
|
360
377
|
| `TP_DOMAIN` | TargetProcess instance domain |
|
|
361
378
|
| `TP_TOKEN` | API token (sent as the `access_token` query parameter) |
|
|
379
|
+
| `TP_SANDBOX_PROJECT_ID` | Default target project for the write examples |
|
|
362
380
|
| `TP_WRITE_ALLOWED_PROJECT_IDS` | Project id allow-list for the write examples |
|
|
363
381
|
|
|
364
382
|
For local development, copy the template to `.env` (which is gitignored) and
|
|
@@ -287,16 +287,33 @@ See [SPEC.md](SPEC.md) for the full specification, including detailed architectu
|
|
|
287
287
|
|
|
288
288
|
## Development Status
|
|
289
289
|
|
|
290
|
-
**Current
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
290
|
+
**Current status**: Beta. The core library is complete and tested against a
|
|
291
|
+
real TargetProcess instance. The public surface may still change between 0.x
|
|
292
|
+
minor releases; every change is recorded in [CHANGELOG.md](CHANGELOG.md).
|
|
293
|
+
|
|
294
|
+
### What 1.0.0 requires
|
|
295
|
+
|
|
296
|
+
1.0.0 will be released once all of the following hold:
|
|
297
|
+
|
|
298
|
+
1. At least one comprehensive production integration is built on the library
|
|
299
|
+
and has been stable through the beta period.
|
|
300
|
+
2. No open issue labelled `bug` remains unless explicitly deferred past 1.0.0,
|
|
301
|
+
and every known case where TargetProcess silently ignores all or part of a
|
|
302
|
+
request has been resolved: the library refuses it before sending, verifies it
|
|
303
|
+
after the write, or SPEC.md documents it as a limitation.
|
|
304
|
+
3. The public surface is frozen: SPEC.md's Public API Surface matches
|
|
305
|
+
`targetprocess.__all__`, a Semantic Versioning promise for that surface is
|
|
306
|
+
stated, and a deprecation policy is written.
|
|
307
|
+
4. Documentation and the recorded test cassettes are current: every public
|
|
308
|
+
resource manager is documented in [docs/USAGE.md](docs/USAGE.md), the
|
|
309
|
+
`KNOWN_DEVIATIONS` table in `scripts/check_model_coverage.py` has been
|
|
310
|
+
re-checked against a live instance, and the recorded test cassettes have no
|
|
311
|
+
open hygiene issues.
|
|
312
|
+
5. CI tests every Python version `pyproject.toml` claims.
|
|
313
|
+
6. The last beta release needed no breaking change to the public surface.
|
|
314
|
+
7. The release carries the `Development Status :: 5 - Production/Stable`
|
|
315
|
+
classifier, a CHANGELOG section for 1.0.0, a `v1.0.0` tag on `main`, and is
|
|
316
|
+
published to PyPI through the release workflow.
|
|
300
317
|
|
|
301
318
|
## Requirements
|
|
302
319
|
|
|
@@ -320,6 +337,7 @@ in [`.env.example`](.env.example) (the committed template) and the
|
|
|
320
337
|
| --- | --- |
|
|
321
338
|
| `TP_DOMAIN` | TargetProcess instance domain |
|
|
322
339
|
| `TP_TOKEN` | API token (sent as the `access_token` query parameter) |
|
|
340
|
+
| `TP_SANDBOX_PROJECT_ID` | Default target project for the write examples |
|
|
323
341
|
| `TP_WRITE_ALLOWED_PROJECT_IDS` | Project id allow-list for the write examples |
|
|
324
342
|
|
|
325
343
|
For local development, copy the template to `.env` (which is gitignored) and
|