targetprocess-py 0.2.0__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.
Files changed (226) hide show
  1. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/.coderabbit.yaml +1 -1
  2. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/.github/workflows/ci.yml +2 -2
  3. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/.github/workflows/release.yml +1 -1
  4. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/CHANGELOG.md +72 -1
  5. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/CODEOWNERS +1 -1
  6. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/CONTRIBUTING.md +2 -2
  7. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/PKG-INFO +4 -4
  8. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/README.md +3 -3
  9. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/SECURITY.md +2 -1
  10. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/SPEC.md +25 -21
  11. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/docs/USAGE.md +9 -7
  12. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/examples/bulk_updates.py +1 -1
  13. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/examples/create_bug.py +1 -1
  14. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/examples/list_user_stories.py +1 -1
  15. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/examples/readonly_reporting.py +1 -1
  16. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/pyproject.toml +4 -4
  17. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/scripts/check_model_coverage.py +2 -2
  18. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/scripts/live_smoke.py +1 -1
  19. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/__init__.py +9 -9
  20. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/_assignables.py +4 -4
  21. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/_base.py +3 -3
  22. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/_content.py +4 -4
  23. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/_dates.py +1 -1
  24. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/_generals.py +5 -5
  25. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/_joins.py +47 -25
  26. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/_lookups.py +7 -7
  27. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/_nested.py +2 -2
  28. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/_observability.py +10 -10
  29. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/client.py +5 -5
  30. targetprocess_py-0.3.0/src/targetprocess_py/models.py +121 -0
  31. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/request_handler.py +5 -5
  32. targetprocess_py-0.3.0/src/targetprocess_py/resources/__init__.py +78 -0
  33. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/_verify.py +17 -10
  34. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/assignables.py +5 -5
  35. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/assignments.py +2 -2
  36. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/attachments.py +4 -4
  37. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/base.py +37 -26
  38. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/bugs.py +2 -2
  39. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/comments.py +2 -2
  40. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/custom_activities.py +2 -2
  41. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/custom_fields.py +2 -2
  42. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/custom_rules.py +2 -2
  43. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/entities.py +57 -22
  44. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/entity_states.py +2 -2
  45. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/entity_types.py +2 -2
  46. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/epics.py +2 -2
  47. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/features.py +2 -2
  48. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/iterations.py +2 -2
  49. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/priorities.py +3 -3
  50. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/processes.py +2 -2
  51. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/projects.py +2 -2
  52. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/relation_types.py +2 -2
  53. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/relations.py +2 -2
  54. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/releases.py +2 -2
  55. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/requests.py +2 -2
  56. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/role_efforts.py +2 -2
  57. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/roles.py +2 -2
  58. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/severities.py +2 -2
  59. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/tasks.py +2 -2
  60. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/team_assignments.py +2 -2
  61. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/team_iterations.py +2 -2
  62. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/teams.py +2 -2
  63. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/terms.py +3 -3
  64. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/test_cases.py +2 -2
  65. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/times.py +9 -7
  66. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/user_stories.py +2 -2
  67. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/users.py +5 -5
  68. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/resources/workflows.py +2 -2
  69. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/response_parser.py +2 -2
  70. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/transport.py +1 -1
  71. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/types.py +1 -1
  72. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/_support/request_handler.py +2 -2
  73. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/conftest.py +1 -1
  74. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/integration/conftest.py +1 -1
  75. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/integration/test_live_readonly.py +1 -1
  76. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/integration/test_live_readwrite.py +2 -2
  77. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/integration/test_live_readwrite_surfaces.py +3 -3
  78. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_assignment.py +1 -1
  79. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_attachment.py +1 -1
  80. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_bug.py +1 -1
  81. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_cassette_guard.py +1 -1
  82. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_client.py +1 -1
  83. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_comment.py +1 -1
  84. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_custom_activity.py +1 -1
  85. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_custom_field.py +1 -1
  86. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_custom_field_value.py +1 -1
  87. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_custom_rule.py +1 -1
  88. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_entity_extras.py +5 -5
  89. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_entity_ref.py +4 -4
  90. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_entity_state.py +1 -1
  91. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_entity_type.py +1 -1
  92. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_epic.py +1 -1
  93. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_exceptions.py +17 -17
  94. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_feature.py +1 -1
  95. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_integration_request_response.py +5 -5
  96. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_iteration.py +1 -1
  97. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_model_field_coverage.py +5 -5
  98. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_models.py +1 -1
  99. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_observability.py +32 -30
  100. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_priority.py +2 -2
  101. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_process.py +1 -1
  102. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_project.py +1 -1
  103. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_query_parameters.py +4 -4
  104. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_relation.py +1 -1
  105. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_relation_type.py +1 -1
  106. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_release.py +1 -1
  107. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_request.py +1 -1
  108. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_request_handler.py +6 -6
  109. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_request_handler_bulk.py +3 -3
  110. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_request_handler_logged_user.py +1 -1
  111. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_assignable_state.py +13 -13
  112. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_assignments.py +4 -4
  113. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_attachments.py +5 -5
  114. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_base_resource.py +6 -6
  115. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_bugs.py +3 -3
  116. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_comments.py +3 -3
  117. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_custom_activities.py +3 -3
  118. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_custom_field_writes.py +12 -6
  119. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_custom_fields.py +3 -3
  120. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_custom_rules.py +3 -3
  121. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_entities.py +13 -13
  122. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_entity_states.py +6 -6
  123. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_entity_types.py +3 -3
  124. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_epics.py +3 -3
  125. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_features.py +3 -3
  126. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_ignored_filter_paths.py +104 -23
  127. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_iterations.py +3 -3
  128. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_lookup_resolvers.py +9 -9
  129. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_priorities.py +6 -6
  130. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_processes.py +3 -3
  131. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_projects.py +3 -3
  132. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_relation_types.py +6 -6
  133. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_relations.py +4 -4
  134. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_releases.py +3 -3
  135. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_requests.py +3 -3
  136. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_role_efforts.py +4 -4
  137. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_roles.py +6 -6
  138. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_server_capability.py +6 -6
  139. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_severities.py +3 -3
  140. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_tasks.py +3 -3
  141. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_team_assignments.py +4 -4
  142. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_team_iterations.py +3 -3
  143. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_teams.py +3 -3
  144. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_terms.py +3 -3
  145. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_test_cases.py +3 -3
  146. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_times.py +6 -6
  147. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_user_stories.py +3 -3
  148. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_users.py +6 -6
  149. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_verified_writes.py +34 -4
  150. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_resources/test_workflows.py +3 -3
  151. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_response_parser.py +3 -3
  152. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_role.py +1 -1
  153. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_role_effort.py +20 -5
  154. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_severity.py +1 -1
  155. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_task.py +1 -1
  156. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_team.py +1 -1
  157. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_team_assignment.py +1 -1
  158. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_team_iteration.py +1 -1
  159. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_term.py +1 -1
  160. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_test_case.py +1 -1
  161. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_time.py +21 -7
  162. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_transport.py +1 -1
  163. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_types.py +3 -3
  164. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_uploaded_attachment.py +1 -1
  165. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_user.py +1 -1
  166. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_user_story.py +1 -1
  167. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_workflow.py +1 -1
  168. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/uv.lock +30 -19
  169. targetprocess_py-0.2.0/src/targetprocess/models.py +0 -121
  170. targetprocess_py-0.2.0/src/targetprocess/resources/__init__.py +0 -78
  171. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/.commitlintrc.json +0 -0
  172. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/.env.example +0 -0
  173. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  174. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  175. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  176. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/.github/dependabot.yml +0 -0
  177. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/.github/labels.yml +0 -0
  178. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/.github/pull_request_template.md +0 -0
  179. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/.github/workflows/commit-message.yml +0 -0
  180. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/.gitignore +0 -0
  181. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/.jscpd.json +0 -0
  182. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/.pre-commit-config.yaml +0 -0
  183. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/.python-version +0 -0
  184. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/.tool-versions +0 -0
  185. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/CODE_OF_CONDUCT.md +0 -0
  186. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/LICENSE +0 -0
  187. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/docs/testing.md +0 -0
  188. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/examples/README.md +0 -0
  189. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/scripts/apply_labels.sh +0 -0
  190. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/scripts/check_commit_message.py +0 -0
  191. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/scripts/check_internal_refs.py +0 -0
  192. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/scripts/check_large_files.py +0 -0
  193. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/scripts/check_todos.py +0 -0
  194. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/_entity_types.py +0 -0
  195. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/exceptions.py +0 -0
  196. {targetprocess_py-0.2.0/src/targetprocess → targetprocess_py-0.3.0/src/targetprocess_py}/py.typed +0 -0
  197. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/__init__.py +0 -0
  198. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/_support/__init__.py +0 -0
  199. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/integration/__init__.py +0 -0
  200. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readonly/test_entity_states_scoped_to_a_workflow.yaml +0 -0
  201. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readonly/test_entity_types_catalogue_parses.yaml +0 -0
  202. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readonly/test_find_for_day_matches_a_real_entry.yaml +0 -0
  203. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readonly/test_generic_entities_comment.yaml +0 -0
  204. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readonly/test_get_single_with_include.yaml +0 -0
  205. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readonly/test_list_user_stories_parses.yaml +0 -0
  206. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readonly/test_logged_user_resolves_the_acting_user.yaml +0 -0
  207. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readonly/test_pagination_crosses_page_boundary.yaml +0 -0
  208. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readonly/test_priorities_scoped_to_an_entity_type.yaml +0 -0
  209. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readonly/test_severities_rank_the_bug_set.yaml +0 -0
  210. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readwrite/test_bulk_create_and_update_tasks_under_a_story.yaml +0 -0
  211. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readwrite/test_custom_field_set_and_clear_round_trip.yaml +0 -0
  212. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readwrite/test_request_create_update_delete_round_trip.yaml +0 -0
  213. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readwrite/test_user_story_create_update_delete_round_trip.yaml +0 -0
  214. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readwrite/test_verified_update_returns_the_re_read.yaml +0 -0
  215. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readwrite_surfaces/test_assignment_create_and_delete.yaml +0 -0
  216. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readwrite_surfaces/test_attachment_upload_list_download_and_delete.yaml +0 -0
  217. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readwrite_surfaces/test_comment_create_update_delete_round_trip.yaml +0 -0
  218. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readwrite_surfaces/test_relation_create_and_delete.yaml +0 -0
  219. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readwrite_surfaces/test_relation_inbound_outbound_create_and_filter.yaml +0 -0
  220. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readwrite_surfaces/test_role_effort_create_update_delete_round_trip.yaml +0 -0
  221. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readwrite_surfaces/test_team_assignment_create_and_delete.yaml +0 -0
  222. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/integration/cassettes/test_live_readwrite_surfaces/test_two_level_advance_moves_both_levels.yaml +0 -0
  223. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/live_payloads.py +0 -0
  224. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_cassette_sanitiser.py +0 -0
  225. {targetprocess_py-0.2.0 → targetprocess_py-0.3.0}/tests/test_commit_message.py +0 -0
  226. {targetprocess_py-0.2.0 → 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/targetprocess/**"
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=targetprocess --cov-report=term --cov-fail-under=90
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 targetprocess; print(targetprocess.__version__)"
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
- # targetprocess.__version__ would publish a release whose files carry a
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,75 @@ 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
+
66
+ ## [0.2.1] - 2026-09-18
67
+
68
+ ### Fixed
69
+
70
+ - A verified clear of a custom field (`update(..., verify=True)` or
71
+ `set_custom_field(id, name, None)`) no longer raises `VerificationError`
72
+ when the field reads back `False` or `0`. The re-read comparison now
73
+ accepts any of TargetProcess's empty-equivalent values - null, `""`,
74
+ `False` or `0` - as showing a requested clear, rather than only null or
75
+ `""`. This fixes clearing a `CheckBox` custom field, which reads back
76
+ `False`, and a numeric one, which reads back `0`; a *set* value of `False`
77
+ or `0` is unaffected and still compares exactly as before.
78
+
10
79
  ## [0.2.0] - 2026-09-17
11
80
 
12
81
  The first beta release.
@@ -162,6 +231,8 @@ The first public release.
162
231
  - Log scrubbing redacts the `access_token` query parameter and `Authorization`
163
232
  header values from the library's own log records.
164
233
 
165
- [Unreleased]: https://github.com/man8/targetprocess-py/compare/v0.2.0...HEAD
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
236
+ [0.2.1]: https://github.com/man8/targetprocess-py/compare/v0.2.0...v0.2.1
166
237
  [0.2.0]: https://github.com/man8/targetprocess-py/compare/v0.1.0...v0.2.0
167
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/targetprocess/ @man8 @someone`, `.github/ @man8`).
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=targetprocess --cov-report=term --cov-fail-under=90` |
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/targetprocess/__init__.py`
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.2.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 targetprocess import ClientMode, TargetProcessClient
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 targetprocess import (
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
- `targetprocess.__all__`, a Semantic Versioning promise for that surface is
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 targetprocess import ClientMode, TargetProcessClient
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 targetprocess import (
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
- `targetprocess.__all__`, a Semantic Versioning promise for that surface is
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
@@ -4,7 +4,8 @@
4
4
 
5
5
  | Version | Supported |
6
6
  | --- | --- |
7
- | 0.2.x | Yes |
7
+ | 0.3.x | Yes |
8
+ | 0.2.x | No |
8
9
  | 0.1.x | No |
9
10
  | Pre-release commits before 0.1.0 | No |
10
11
 
@@ -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
- filter on, with HTTP 200 and the unfiltered, unsorted rows -
90
- indistinguishable from success. The confirmed case is a filter on the
91
- `Assignments` collection of an assignable, which returns the same rows as
92
- the unfiltered request, while the `Assignment` entity's own
93
- `GeneralUser.Id` filter applies.
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` keep the bounds they were published with, and
511
- `times.upsert` validates on the write side, where the value originates and a
512
- range error is actionable.
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
@@ -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:
@@ -687,7 +688,7 @@ at send time, and outside the set; `prettify` stays deliberately absent (see
687
688
  above).
688
689
 
689
690
  **Filter paths.** `BaseResource.ignored_filter_paths` maps the leading segment
690
- of a `where=` path TP silently ignores on a collection to the reason and the
691
+ of a `where=` path TP will not filter on for a collection to the reason and the
691
692
  route to use instead. The known set is declared once, as
692
693
  `ASSIGNABLE_IGNORED_FILTER_PATHS` in `resources/base.py`, and referenced by the
693
694
  six assignable managers (`UserStory`, `Bug`, `Task`, `Feature`, `Epic`,
@@ -695,7 +696,10 @@ six assignable managers (`UserStory`, `Bug`, `Task`, `Feature`, `Epic`,
695
696
  `order_by` or `include` - matching a path's leading segment in any casing
696
697
  outside quoted values, and refuses with a `ValueError` naming the collection
697
698
  and the route. `entities` mirrors the refusal for every spelling of those six
698
- collections and for the polymorphic `Assignable` / `Assignables` collection.
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.
699
703
 
700
704
  | Ignored path | Route instead |
701
705
  | --- | --- |
@@ -898,7 +902,7 @@ result = await client.times.upsert(
898
902
 
899
903
  ## Observability
900
904
 
901
- Runtime observability lives in `targetprocess/_observability.py` and is
905
+ Runtime observability lives in `targetprocess_py/_observability.py` and is
902
906
  scoped to what a *library* should own. The application that embeds the
903
907
  library owns the rest (metrics, alerting, error tracking, deployment
904
908
  observability, product analytics) - it has the deployment context a
@@ -906,17 +910,17 @@ library cannot assume.
906
910
 
907
911
  ### Implemented signals
908
912
 
909
- - **Structured logging.** A dedicated `logging.getLogger("targetprocess")`
913
+ - **Structured logging.** A dedicated `logging.getLogger("targetprocess_py")`
910
914
  with a `NullHandler` by default (silent unless the application attaches a
911
915
  handler). `StructuredJsonFormatter` emits one JSON line per record
912
916
  (`ts`, `level`, `logger`, `msg`, `request_id`, plus caller extras).
913
- `get_logger("name")` returns a child under the `targetprocess` namespace.
917
+ `get_logger("name")` returns a child under the `targetprocess_py` namespace.
914
918
  `RequestHandler._request` emits structured `request.start` /
915
919
  `request.complete` / `request.retry` / `request.error` /
916
920
  `request.transport_error` records.
917
921
  - **Log scrubbing.** `ScrubbingFilter` redacts the `access_token` query
918
922
  param and `Authorization: Basic|Bearer` header values from the records
919
- this library emits. It is attached to the `targetprocess` logger and to
923
+ this library emits. It is attached to the `targetprocess_py` logger and to
920
924
  every child `get_logger()` returns - both, because a filter on a logger
921
925
  runs only for records logged *through* that logger, not for records
922
926
  propagated up from a child. It pre-formats and redacts the message, the
@@ -934,7 +938,7 @@ library cannot assume.
934
938
  for httpx request-URL logging, *in this library's own records*. The filter
935
939
  cannot reach records emitted by other libraries - `httpx` and `httpcore`
936
940
  log their own request URLs - nor a logger obtained by calling
937
- `logging.getLogger("targetprocess.x")` directly instead of via
941
+ `logging.getLogger("targetprocess_py.x")` directly instead of via
938
942
  `get_logger()`. An application that wants blanket redaction should attach
939
943
  a `ScrubbingFilter()` instance to its own handler, which every propagated
940
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 targetprocess import ClientMode, TargetProcessClient
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 targetprocess import VerificationError
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)
@@ -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.
@@ -582,7 +584,7 @@ custom activity goes through the ordinary `create` and `list`. Send
582
584
  the key rather than sending it as `None`:
583
585
 
584
586
  ```python
585
- from targetprocess.models import format_tp_date
587
+ from targetprocess_py.models import format_tp_date
586
588
 
587
589
  entry = await client.times.create(
588
590
  CustomActivity={"Id": 42},
@@ -809,7 +811,7 @@ catch a specific failure or the base class. HTTP status codes map to types:
809
811
  ```python
810
812
  import logging
811
813
 
812
- from targetprocess import (
814
+ from targetprocess_py import (
813
815
  AuthenticationError,
814
816
  NotFoundError,
815
817
  RateLimitError,
@@ -860,7 +862,7 @@ To call the library from otherwise-synchronous code, drive it with
860
862
  ```python
861
863
  import asyncio
862
864
 
863
- from targetprocess import ClientMode, TargetProcessClient
865
+ from targetprocess_py import ClientMode, TargetProcessClient
864
866
 
865
867
 
866
868
  async def fetch_open_bugs() -> list[str]:
@@ -906,7 +908,7 @@ directly — do not nest `asyncio.run()`.
906
908
  attribute assignment, not a hard sandbox.)
907
909
 
908
910
  ```python
909
- from targetprocess import ClientMode, ReadOnlyViolation, TargetProcessClient
911
+ from targetprocess_py import ClientMode, ReadOnlyViolation, TargetProcessClient
910
912
 
911
913
  reporter = TargetProcessClient(
912
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 targetprocess import ClientMode, TargetProcessClient, TargetProcessError
44
+ from targetprocess_py import ClientMode, TargetProcessClient, TargetProcessError
45
45
 
46
46
  MARKER = "Bulk-updated by the targetprocess-py bulk_updates example."
47
47
 
@@ -35,7 +35,7 @@ import asyncio
35
35
  import os
36
36
  import sys
37
37
 
38
- from targetprocess import ClientMode, TargetProcessClient, TargetProcessError
38
+ from targetprocess_py import ClientMode, TargetProcessClient, TargetProcessError
39
39
 
40
40
 
41
41
  def _env(name: str) -> str:
@@ -24,7 +24,7 @@ import asyncio
24
24
  import os
25
25
  import sys
26
26
 
27
- from targetprocess import ClientMode, TargetProcessClient, TargetProcessError
27
+ from targetprocess_py import ClientMode, TargetProcessClient, TargetProcessError
28
28
 
29
29
 
30
30
  def _env(name: str) -> str:
@@ -25,7 +25,7 @@ import os
25
25
  import sys
26
26
  from collections import Counter
27
27
 
28
- from targetprocess import ClientMode, TargetProcessClient, TargetProcessError
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 targetprocess.__version__; hatchling reads it at
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/targetprocess/__init__.py"
68
+ path = "src/targetprocess_py/__init__.py"
69
69
 
70
70
  [tool.hatch.build.targets.wheel]
71
- packages = ["src/targetprocess"]
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/targetprocess/_base.py" = ["N802"]
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 targetprocess import models, resources # noqa: E402
47
- from targetprocess.resources.base import BaseResource # noqa: E402
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 targetprocess import ClientMode, ReadOnlyViolation, TargetProcessClient
45
+ from targetprocess_py import ClientMode, ReadOnlyViolation, TargetProcessClient
46
46
 
47
47
  ENV_FILE = Path.home() / ".config" / "targetprocess" / ".env"
48
48
 
@@ -1,6 +1,6 @@
1
1
  """A Python library for the TargetProcess v1 REST API."""
2
2
 
3
- from targetprocess._observability import (
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 targetprocess.client import TargetProcessClient
13
- from targetprocess.exceptions import (
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 targetprocess.models import (
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 targetprocess.request_handler import RequestHandler
75
- from targetprocess.resources import (
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 targetprocess.response_parser import ResponseParser
113
- from targetprocess.types import ClientMode, LevelState, StateLevels, UpsertAction, UpsertResult
112
+ from targetprocess_py.response_parser import ResponseParser
113
+ from targetprocess_py.types import ClientMode, LevelState, StateLevels, UpsertAction, UpsertResult
114
114
 
115
- __version__ = "0.2.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:`targetprocess._base.AssignableEntity`. Each class below adds only what
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:`targetprocess.models`, which stays the import surface
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 targetprocess._base import AssignableEntity
17
- from targetprocess._nested import EntityRef, RefWithImportance
16
+ from targetprocess_py._base import AssignableEntity
17
+ from targetprocess_py._nested import EntityRef, RefWithImportance
18
18
 
19
19
 
20
20
  class UserStory(AssignableEntity):
@@ -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:`targetprocess.models`, which stays the import surface
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 targetprocess._dates import TPDateTime
24
- from targetprocess._nested import (
23
+ from targetprocess_py._dates import TPDateTime
24
+ from targetprocess_py._nested import (
25
25
  AssignedUsers,
26
26
  CustomFieldValue,
27
27
  EntityRef,
@@ -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:`targetprocess.models`, which stays the import surface
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 targetprocess._base import Entity, NamedEntity
14
- from targetprocess._dates import TPDateTime
15
- from targetprocess._nested import CustomFieldConfig, EntityRef, EntityTypeRef, UserRef
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):
@@ -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:`targetprocess.models`, which remains the import
4
+ are re-exported by :mod:`targetprocess_py.models`, which remains the import
5
5
  surface callers use.
6
6
  """
7
7