targetprocess-py 0.2.0__tar.gz → 0.2.1__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.
Files changed (224) hide show
  1. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/CHANGELOG.md +15 -1
  2. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/PKG-INFO +1 -1
  3. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/SPEC.md +5 -4
  4. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/docs/USAGE.md +3 -1
  5. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/__init__.py +1 -1
  6. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/_verify.py +15 -8
  7. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/base.py +4 -2
  8. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_custom_field_writes.py +9 -3
  9. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_verified_writes.py +30 -0
  10. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/.coderabbit.yaml +0 -0
  11. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/.commitlintrc.json +0 -0
  12. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/.env.example +0 -0
  13. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  14. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  15. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  16. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/.github/dependabot.yml +0 -0
  17. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/.github/labels.yml +0 -0
  18. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/.github/pull_request_template.md +0 -0
  19. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/.github/workflows/ci.yml +0 -0
  20. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/.github/workflows/commit-message.yml +0 -0
  21. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/.github/workflows/release.yml +0 -0
  22. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/.gitignore +0 -0
  23. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/.jscpd.json +0 -0
  24. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/.pre-commit-config.yaml +0 -0
  25. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/.python-version +0 -0
  26. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/.tool-versions +0 -0
  27. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/CODEOWNERS +0 -0
  28. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/CODE_OF_CONDUCT.md +0 -0
  29. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/CONTRIBUTING.md +0 -0
  30. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/LICENSE +0 -0
  31. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/README.md +0 -0
  32. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/SECURITY.md +0 -0
  33. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/docs/testing.md +0 -0
  34. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/examples/README.md +0 -0
  35. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/examples/bulk_updates.py +0 -0
  36. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/examples/create_bug.py +0 -0
  37. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/examples/list_user_stories.py +0 -0
  38. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/examples/readonly_reporting.py +0 -0
  39. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/pyproject.toml +0 -0
  40. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/scripts/apply_labels.sh +0 -0
  41. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/scripts/check_commit_message.py +0 -0
  42. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/scripts/check_internal_refs.py +0 -0
  43. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/scripts/check_large_files.py +0 -0
  44. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/scripts/check_model_coverage.py +0 -0
  45. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/scripts/check_todos.py +0 -0
  46. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/scripts/live_smoke.py +0 -0
  47. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/_assignables.py +0 -0
  48. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/_base.py +0 -0
  49. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/_content.py +0 -0
  50. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/_dates.py +0 -0
  51. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/_entity_types.py +0 -0
  52. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/_generals.py +0 -0
  53. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/_joins.py +0 -0
  54. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/_lookups.py +0 -0
  55. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/_nested.py +0 -0
  56. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/_observability.py +0 -0
  57. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/client.py +0 -0
  58. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/exceptions.py +0 -0
  59. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/models.py +0 -0
  60. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/py.typed +0 -0
  61. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/request_handler.py +0 -0
  62. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/__init__.py +0 -0
  63. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/assignables.py +0 -0
  64. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/assignments.py +0 -0
  65. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/attachments.py +0 -0
  66. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/bugs.py +0 -0
  67. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/comments.py +0 -0
  68. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/custom_activities.py +0 -0
  69. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/custom_fields.py +0 -0
  70. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/custom_rules.py +0 -0
  71. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/entities.py +0 -0
  72. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/entity_states.py +0 -0
  73. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/entity_types.py +0 -0
  74. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/epics.py +0 -0
  75. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/features.py +0 -0
  76. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/iterations.py +0 -0
  77. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/priorities.py +0 -0
  78. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/processes.py +0 -0
  79. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/projects.py +0 -0
  80. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/relation_types.py +0 -0
  81. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/relations.py +0 -0
  82. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/releases.py +0 -0
  83. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/requests.py +0 -0
  84. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/role_efforts.py +0 -0
  85. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/roles.py +0 -0
  86. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/severities.py +0 -0
  87. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/tasks.py +0 -0
  88. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/team_assignments.py +0 -0
  89. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/team_iterations.py +0 -0
  90. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/teams.py +0 -0
  91. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/terms.py +0 -0
  92. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/test_cases.py +0 -0
  93. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/times.py +0 -0
  94. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/user_stories.py +0 -0
  95. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/users.py +0 -0
  96. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/resources/workflows.py +0 -0
  97. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/response_parser.py +0 -0
  98. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/transport.py +0 -0
  99. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/src/targetprocess/types.py +0 -0
  100. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/__init__.py +0 -0
  101. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/_support/__init__.py +0 -0
  102. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/_support/request_handler.py +0 -0
  103. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/conftest.py +0 -0
  104. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/integration/__init__.py +0 -0
  105. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/integration/cassettes/test_live_readonly/test_entity_states_scoped_to_a_workflow.yaml +0 -0
  106. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/integration/cassettes/test_live_readonly/test_entity_types_catalogue_parses.yaml +0 -0
  107. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/integration/cassettes/test_live_readonly/test_find_for_day_matches_a_real_entry.yaml +0 -0
  108. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/integration/cassettes/test_live_readonly/test_generic_entities_comment.yaml +0 -0
  109. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/integration/cassettes/test_live_readonly/test_get_single_with_include.yaml +0 -0
  110. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/integration/cassettes/test_live_readonly/test_list_user_stories_parses.yaml +0 -0
  111. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/integration/cassettes/test_live_readonly/test_logged_user_resolves_the_acting_user.yaml +0 -0
  112. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/integration/cassettes/test_live_readonly/test_pagination_crosses_page_boundary.yaml +0 -0
  113. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/integration/cassettes/test_live_readonly/test_priorities_scoped_to_an_entity_type.yaml +0 -0
  114. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/integration/cassettes/test_live_readonly/test_severities_rank_the_bug_set.yaml +0 -0
  115. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/integration/cassettes/test_live_readwrite/test_bulk_create_and_update_tasks_under_a_story.yaml +0 -0
  116. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/integration/cassettes/test_live_readwrite/test_custom_field_set_and_clear_round_trip.yaml +0 -0
  117. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/integration/cassettes/test_live_readwrite/test_request_create_update_delete_round_trip.yaml +0 -0
  118. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/integration/cassettes/test_live_readwrite/test_user_story_create_update_delete_round_trip.yaml +0 -0
  119. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/integration/cassettes/test_live_readwrite/test_verified_update_returns_the_re_read.yaml +0 -0
  120. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/integration/cassettes/test_live_readwrite_surfaces/test_assignment_create_and_delete.yaml +0 -0
  121. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/integration/cassettes/test_live_readwrite_surfaces/test_attachment_upload_list_download_and_delete.yaml +0 -0
  122. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/integration/cassettes/test_live_readwrite_surfaces/test_comment_create_update_delete_round_trip.yaml +0 -0
  123. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/integration/cassettes/test_live_readwrite_surfaces/test_relation_create_and_delete.yaml +0 -0
  124. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/integration/cassettes/test_live_readwrite_surfaces/test_relation_inbound_outbound_create_and_filter.yaml +0 -0
  125. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/integration/cassettes/test_live_readwrite_surfaces/test_role_effort_create_update_delete_round_trip.yaml +0 -0
  126. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/integration/cassettes/test_live_readwrite_surfaces/test_team_assignment_create_and_delete.yaml +0 -0
  127. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/integration/cassettes/test_live_readwrite_surfaces/test_two_level_advance_moves_both_levels.yaml +0 -0
  128. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/integration/conftest.py +0 -0
  129. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/integration/test_live_readonly.py +0 -0
  130. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/integration/test_live_readwrite.py +0 -0
  131. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/integration/test_live_readwrite_surfaces.py +0 -0
  132. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/live_payloads.py +0 -0
  133. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_assignment.py +0 -0
  134. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_attachment.py +0 -0
  135. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_bug.py +0 -0
  136. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_cassette_guard.py +0 -0
  137. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_cassette_sanitiser.py +0 -0
  138. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_client.py +0 -0
  139. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_comment.py +0 -0
  140. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_commit_message.py +0 -0
  141. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_custom_activity.py +0 -0
  142. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_custom_field.py +0 -0
  143. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_custom_field_value.py +0 -0
  144. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_custom_rule.py +0 -0
  145. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_entity_extras.py +0 -0
  146. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_entity_ref.py +0 -0
  147. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_entity_state.py +0 -0
  148. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_entity_type.py +0 -0
  149. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_epic.py +0 -0
  150. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_exceptions.py +0 -0
  151. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_feature.py +0 -0
  152. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_integration_request_response.py +0 -0
  153. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_internal_refs.py +0 -0
  154. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_iteration.py +0 -0
  155. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_model_field_coverage.py +0 -0
  156. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_models.py +0 -0
  157. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_observability.py +0 -0
  158. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_priority.py +0 -0
  159. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_process.py +0 -0
  160. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_project.py +0 -0
  161. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_query_parameters.py +0 -0
  162. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_relation.py +0 -0
  163. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_relation_type.py +0 -0
  164. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_release.py +0 -0
  165. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_request.py +0 -0
  166. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_request_handler.py +0 -0
  167. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_request_handler_bulk.py +0 -0
  168. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_request_handler_logged_user.py +0 -0
  169. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_assignable_state.py +0 -0
  170. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_assignments.py +0 -0
  171. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_attachments.py +0 -0
  172. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_base_resource.py +0 -0
  173. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_bugs.py +0 -0
  174. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_comments.py +0 -0
  175. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_custom_activities.py +0 -0
  176. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_custom_fields.py +0 -0
  177. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_custom_rules.py +0 -0
  178. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_entities.py +0 -0
  179. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_entity_states.py +0 -0
  180. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_entity_types.py +0 -0
  181. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_epics.py +0 -0
  182. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_features.py +0 -0
  183. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_ignored_filter_paths.py +0 -0
  184. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_iterations.py +0 -0
  185. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_lookup_resolvers.py +0 -0
  186. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_priorities.py +0 -0
  187. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_processes.py +0 -0
  188. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_projects.py +0 -0
  189. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_relation_types.py +0 -0
  190. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_relations.py +0 -0
  191. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_releases.py +0 -0
  192. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_requests.py +0 -0
  193. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_role_efforts.py +0 -0
  194. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_roles.py +0 -0
  195. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_server_capability.py +0 -0
  196. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_severities.py +0 -0
  197. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_tasks.py +0 -0
  198. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_team_assignments.py +0 -0
  199. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_team_iterations.py +0 -0
  200. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_teams.py +0 -0
  201. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_terms.py +0 -0
  202. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_test_cases.py +0 -0
  203. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_times.py +0 -0
  204. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_user_stories.py +0 -0
  205. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_users.py +0 -0
  206. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_resources/test_workflows.py +0 -0
  207. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_response_parser.py +0 -0
  208. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_role.py +0 -0
  209. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_role_effort.py +0 -0
  210. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_severity.py +0 -0
  211. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_task.py +0 -0
  212. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_team.py +0 -0
  213. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_team_assignment.py +0 -0
  214. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_team_iteration.py +0 -0
  215. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_term.py +0 -0
  216. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_test_case.py +0 -0
  217. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_time.py +0 -0
  218. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_transport.py +0 -0
  219. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_types.py +0 -0
  220. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_uploaded_attachment.py +0 -0
  221. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_user.py +0 -0
  222. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_user_story.py +0 -0
  223. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/tests/test_workflow.py +0 -0
  224. {targetprocess_py-0.2.0 → targetprocess_py-0.2.1}/uv.lock +0 -0
@@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.2.1] - 2026-09-18
11
+
12
+ ### Fixed
13
+
14
+ - A verified clear of a custom field (`update(..., verify=True)` or
15
+ `set_custom_field(id, name, None)`) no longer raises `VerificationError`
16
+ when the field reads back `False` or `0`. The re-read comparison now
17
+ accepts any of TargetProcess's empty-equivalent values - null, `""`,
18
+ `False` or `0` - as showing a requested clear, rather than only null or
19
+ `""`. This fixes clearing a `CheckBox` custom field, which reads back
20
+ `False`, and a numeric one, which reads back `0`; a *set* value of `False`
21
+ or `0` is unaffected and still compares exactly as before.
22
+
10
23
  ## [0.2.0] - 2026-09-17
11
24
 
12
25
  The first beta release.
@@ -162,6 +175,7 @@ The first public release.
162
175
  - Log scrubbing redacts the `access_token` query parameter and `Authorization`
163
176
  header values from the library's own log records.
164
177
 
165
- [Unreleased]: https://github.com/man8/targetprocess-py/compare/v0.2.0...HEAD
178
+ [Unreleased]: https://github.com/man8/targetprocess-py/compare/v0.2.1...HEAD
179
+ [0.2.1]: https://github.com/man8/targetprocess-py/compare/v0.2.0...v0.2.1
166
180
  [0.2.0]: https://github.com/man8/targetprocess-py/compare/v0.1.0...v0.2.0
167
181
  [0.1.0]: https://github.com/man8/targetprocess-py/releases/tag/v0.1.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: targetprocess-py
3
- Version: 0.2.0
3
+ Version: 0.2.1
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
@@ -520,10 +520,11 @@ Every typed manager writes one with
520
520
  `{"CustomFields": [{"Name": name, "Value": value}]}` through `update`; a null
521
521
  `Value` clears. A partial update omitting a custom field keeps its value behind
522
522
  a success status, so `verify` defaults on here (off on `update`): the re-read
523
- matches the entry by name, a clear reading back null or `""`, and raises
524
- `VerificationError` when the value differs or no entry of that name comes back.
525
- A date-typed value reads back in wire form, so it verifies only when sent in
526
- that form (`format_tp_date`) or with `verify=False`.
523
+ matches the entry by name, a clear reading back any of TP's empty-equivalent
524
+ values - null, `""`, `False` or `0`, since a CheckBox reads back `False` and a
525
+ numeric field `0` - and raises `VerificationError` when the value differs or no
526
+ entry of that name comes back. A date-typed value reads back in wire form, so it
527
+ verifies only when sent in that form (`format_tp_date`) or with `verify=False`.
527
528
 
528
529
  Nested references use one of four lightweight shapes, chosen by what the
529
530
  API actually sends:
@@ -245,7 +245,9 @@ story = await client.user_stories.set_custom_field(123, "Release note", None)
245
245
  Leaving a field out of an update is not a clear: TargetProcess keeps the old
246
246
  value and still answers with a success status. So `set_custom_field` verifies
247
247
  by default, re-reading `include=["CustomFields"]` and matching the entry by
248
- name (case-insensitively); a cleared field may read back as `None` or `""`.
248
+ name (case-insensitively); a cleared field may read back as `None`, `""`,
249
+ `False` or `0` - a CheckBox reads back `False`, and any of these empty
250
+ equivalents counts, regardless of the field's own configured type.
249
251
  `VerificationError` here means the value did not land, a clear was discarded,
250
252
  or no field of that name exists on the entity's process - a misspelt name, or
251
253
  one configured on another process. Pass `verify=False` to skip the re-read.
@@ -112,7 +112,7 @@ from targetprocess.resources import (
112
112
  from targetprocess.response_parser import ResponseParser
113
113
  from targetprocess.types import ClientMode, LevelState, StateLevels, UpsertAction, UpsertResult
114
114
 
115
- __version__ = "0.2.0"
115
+ __version__ = "0.2.1"
116
116
 
117
117
  __all__ = [
118
118
  # Exceptions
@@ -7,12 +7,13 @@ matched against the raw re-read, by these rules in order:
7
7
  - A requested ``CustomFields`` sequence (any but a string, bytes or
8
8
  bytearray) is routed entry by entry before any other rule applies, each
9
9
  entry matched by name (case-insensitively). A cleared entry (``Value``
10
- ``None``) matches an observed null or empty string, any other value is
11
- compared by the rules below, and an entry of that name missing from the
12
- re-read is a mismatch keyed ``CustomFields[<name>]``. An entry that is not
13
- a mapping carrying a string ``Name`` cannot be looked up, so it is a
14
- mismatch too, keyed by its zero-based position
15
- (``CustomFields[#<position>]``) and observed as
10
+ ``None``) matches an observed null, ``""``, ``False`` or ``0`` - each is
11
+ TP's empty state for some field type, so accepting the set never masks a
12
+ failed clear. Any other value is compared by the rules below, and an entry
13
+ of that name missing from the re-read is a mismatch keyed
14
+ ``CustomFields[<name>]``. An entry that is not a mapping carrying a string
15
+ ``Name`` cannot be looked up, so it is a mismatch too, keyed by its
16
+ zero-based position (``CustomFields[#<position>]``) and observed as
16
17
  ``VerificationError.ABSENT``.
17
18
  - A requested key the re-read does not carry at all is a mismatch, observed
18
19
  as ``VerificationError.ABSENT`` - unless the request was ``None``, which an
@@ -122,7 +123,9 @@ def custom_field_mismatch(name: str, value: object, observed: object) -> Mismatc
122
123
 
123
124
  Args:
124
125
  name: The custom field's name, matched case-insensitively.
125
- value: The value the write sent; ``None`` is a clear.
126
+ value: The value the write sent; ``None`` is a clear, verified by an
127
+ observed null, ``""``, ``False`` or ``0`` - any of TP's empty
128
+ states, regardless of the field's own ``Type``.
126
129
  observed: The re-read's ``CustomFields`` list (or whatever it carried).
127
130
 
128
131
  Returns:
@@ -137,7 +140,11 @@ def custom_field_mismatch(name: str, value: object, observed: object) -> Mismatc
137
140
  _, entry_name = _get(entry, "Name")
138
141
  if isinstance(entry_name, str) and entry_name.strip().casefold() == wanted:
139
142
  _, seen = _get(entry, "Value")
140
- cleared = value is None and (seen is None or seen == "")
143
+ # Each of null, "", False and 0 is TP's empty state for some field
144
+ # type, so accepting the set on a requested clear cannot mask a
145
+ # failed one: for it to pass wrongly the field would already have
146
+ # to be holding an empty value.
147
+ cleared = value is None and seen in (None, "", False, 0)
141
148
  return None if cleared or values_match(value, seen) else (value, seen)
142
149
  return (value, ABSENT)
143
150
 
@@ -889,8 +889,10 @@ class BaseResource[T: Entity]:
889
889
  discarded custom-field write is otherwise silent. The re-read requests
890
890
  ``include=[CustomFields]``, finds the entry whose name matches
891
891
  ``name`` case-insensitively, and compares its value; a cleared field
892
- reads back as null or an empty string, and either counts. A name that
893
- is misspelt, or belongs to another process's configuration, reads
892
+ reads back as null, an empty string, ``False`` or ``0`` - TP's empty
893
+ state for some field type (a CheckBox reads back ``False``) - and any
894
+ of them counts, regardless of the field's own configured type. A name
895
+ that is misspelt, or belongs to another process's configuration, reads
894
896
  back no entry at all and raises too. Values are compared as sent, with
895
897
  no conversion between forms: a date-typed field reads back as a
896
898
  ``/Date(ms±HHMM)/`` wire string, so it verifies only when the value
@@ -64,9 +64,15 @@ async def test_clear_sends_a_null_value() -> None:
64
64
  assert json.loads(log[0].content) == {"CustomFields": [{"Name": "Deadline", "Value": None}]}
65
65
 
66
66
 
67
- @pytest.mark.parametrize("cleared", [None, ""])
68
- async def test_clear_verifies_against_null_or_empty(cleared: str | None) -> None:
69
- client, log = _client(_with_fields({"Name": "Deadline", "Type": "Text", "Value": cleared}))
67
+ @pytest.mark.parametrize(
68
+ ("cleared", "field_type"),
69
+ [(None, "Text"), ("", "Text"), (False, "CheckBox"), (0, "Number")],
70
+ ids=["null", "empty-string", "checkbox-false", "numeric-zero"],
71
+ )
72
+ async def test_clear_verifies_against_any_empty_equivalent(
73
+ cleared: str | bool | int | None, field_type: str
74
+ ) -> None:
75
+ client, log = _client(_with_fields({"Name": "Deadline", "Type": field_type, "Value": cleared}))
70
76
 
71
77
  story = await client.user_stories.set_custom_field(123, "Deadline", None)
72
78
 
@@ -569,6 +569,36 @@ def test_custom_field_mismatch_accepts_null_or_empty_as_cleared() -> None:
569
569
  assert custom_field_mismatch("Ticket", None, [{"Name": "Ticket", "Value": "x"}]) == (None, "x")
570
570
 
571
571
 
572
+ @pytest.mark.parametrize(
573
+ "observed",
574
+ [None, "", False, 0],
575
+ ids=["null", "empty-string", "checkbox-false", "numeric-zero"],
576
+ )
577
+ def test_custom_field_mismatch_accepts_any_empty_equivalent_as_cleared(observed: object) -> None:
578
+ assert custom_field_mismatch("Done", None, [{"Name": "Done", "Value": observed}]) is None
579
+
580
+
581
+ @pytest.mark.parametrize(
582
+ "observed",
583
+ [True, 3, "x"],
584
+ ids=["checkbox-true", "non-zero-number", "populated-string"],
585
+ )
586
+ def test_custom_field_mismatch_still_raises_a_clear_against_a_non_empty_value(
587
+ observed: object,
588
+ ) -> None:
589
+ assert custom_field_mismatch("Done", None, [{"Name": "Done", "Value": observed}]) == (
590
+ None,
591
+ observed,
592
+ )
593
+
594
+
595
+ def test_custom_field_mismatch_does_not_treat_a_requested_false_as_clearing_against_zero() -> None:
596
+ # R2: the empty-equivalent widening applies only when the *requested* value
597
+ # is None - a requested False is a set value and still compares through
598
+ # values_match, which treats bool and int as different types.
599
+ assert custom_field_mismatch("Done", False, [{"Name": "Done", "Value": 0}]) == (False, 0)
600
+
601
+
572
602
  def test_custom_field_mismatch_reports_an_absent_entry() -> None:
573
603
  assert custom_field_mismatch("Ticket", "x", []) == ("x", _ABSENT)
574
604
  assert custom_field_mismatch("Ticket", "x", None) == ("x", _ABSENT)