python-gitea 0.12.0__tar.gz → 0.12.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 (424) hide show
  1. {python_gitea-0.12.0 → python_gitea-0.12.1}/PKG-INFO +1 -1
  2. {python_gitea-0.12.0 → python_gitea-0.12.1}/docs/user-guide/cli.md +7 -2
  3. {python_gitea-0.12.0 → python_gitea-0.12.1}/pyproject.toml +1 -1
  4. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/issue/label/common.py +67 -17
  5. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/label/async_label.py +57 -0
  6. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/label/base.py +39 -0
  7. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/label/label.py +57 -0
  8. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/issue/label/test_cli_issue_label.py +121 -15
  9. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/test_cli_main.py +37 -3
  10. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/label/test_label_async_label.py +13 -0
  11. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/label/test_label_base.py +12 -0
  12. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/label/test_label_label.py +12 -0
  13. {python_gitea-0.12.0 → python_gitea-0.12.1}/uv.lock +1 -1
  14. {python_gitea-0.12.0 → python_gitea-0.12.1}/.coderabbit.yaml +0 -0
  15. {python_gitea-0.12.0 → python_gitea-0.12.1}/.github/ISSUE_TEMPLATE/bug-report.md +0 -0
  16. {python_gitea-0.12.0 → python_gitea-0.12.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  17. {python_gitea-0.12.0 → python_gitea-0.12.1}/.github/ISSUE_TEMPLATE/feature-request.md +0 -0
  18. {python_gitea-0.12.0 → python_gitea-0.12.1}/.github/pull_request_template.md +0 -0
  19. {python_gitea-0.12.0 → python_gitea-0.12.1}/.github/workflows/ci.yml +0 -0
  20. {python_gitea-0.12.0 → python_gitea-0.12.1}/.github/workflows/codeql.yml +0 -0
  21. {python_gitea-0.12.0 → python_gitea-0.12.1}/.github/workflows/documentation.yml +0 -0
  22. {python_gitea-0.12.0 → python_gitea-0.12.1}/.github/workflows/draft_release.yml +0 -0
  23. {python_gitea-0.12.0 → python_gitea-0.12.1}/.github/workflows/publish.yml +0 -0
  24. {python_gitea-0.12.0 → python_gitea-0.12.1}/.github/workflows/publish_testpypi.yml +0 -0
  25. {python_gitea-0.12.0 → python_gitea-0.12.1}/.github/workflows/release.yml +0 -0
  26. {python_gitea-0.12.0 → python_gitea-0.12.1}/.github/workflows/scheduled_release.yml +0 -0
  27. {python_gitea-0.12.0 → python_gitea-0.12.1}/.github/workflows/semantic_pull_request.yml +0 -0
  28. {python_gitea-0.12.0 → python_gitea-0.12.1}/.github/workflows/support_floor_update.yml +0 -0
  29. {python_gitea-0.12.0 → python_gitea-0.12.1}/.gitignore +0 -0
  30. {python_gitea-0.12.0 → python_gitea-0.12.1}/.markdownlint.yaml +0 -0
  31. {python_gitea-0.12.0 → python_gitea-0.12.1}/.pre-commit-config.yaml +0 -0
  32. {python_gitea-0.12.0 → python_gitea-0.12.1}/.prettierrc +0 -0
  33. {python_gitea-0.12.0 → python_gitea-0.12.1}/.pypirc +0 -0
  34. {python_gitea-0.12.0 → python_gitea-0.12.1}/.typos.toml +0 -0
  35. {python_gitea-0.12.0 → python_gitea-0.12.1}/CITATION.cff +0 -0
  36. {python_gitea-0.12.0 → python_gitea-0.12.1}/CODE_OF_CONDUCT.md +0 -0
  37. {python_gitea-0.12.0 → python_gitea-0.12.1}/CONTRIBUTING.md +0 -0
  38. {python_gitea-0.12.0 → python_gitea-0.12.1}/LICENSE +0 -0
  39. {python_gitea-0.12.0 → python_gitea-0.12.1}/README.md +0 -0
  40. {python_gitea-0.12.0 → python_gitea-0.12.1}/SECURITY.md +0 -0
  41. {python_gitea-0.12.0 → python_gitea-0.12.1}/SUPPORT.md +0 -0
  42. {python_gitea-0.12.0 → python_gitea-0.12.1}/cliff.toml +0 -0
  43. {python_gitea-0.12.0 → python_gitea-0.12.1}/docs/contributing.md +0 -0
  44. {python_gitea-0.12.0 → python_gitea-0.12.1}/docs/dev/architecture.md +0 -0
  45. {python_gitea-0.12.0 → python_gitea-0.12.1}/docs/dev/troubleshooting.md +0 -0
  46. {python_gitea-0.12.0 → python_gitea-0.12.1}/docs/gen_ref_pages.py +0 -0
  47. {python_gitea-0.12.0 → python_gitea-0.12.1}/docs/index.md +0 -0
  48. {python_gitea-0.12.0 → python_gitea-0.12.1}/docs/javascripts/mathjax.js +0 -0
  49. {python_gitea-0.12.0 → python_gitea-0.12.1}/docs/security.md +0 -0
  50. {python_gitea-0.12.0 → python_gitea-0.12.1}/docs/style/api.css +0 -0
  51. {python_gitea-0.12.0 → python_gitea-0.12.1}/docs/user-guide/configuration.md +0 -0
  52. {python_gitea-0.12.0 → python_gitea-0.12.1}/docs/user-guide/installation.md +0 -0
  53. {python_gitea-0.12.0 → python_gitea-0.12.1}/docs/user-guide/python-api.md +0 -0
  54. {python_gitea-0.12.0 → python_gitea-0.12.1}/docs/user-guide/quickstart.md +0 -0
  55. {python_gitea-0.12.0 → python_gitea-0.12.1}/mkdocs.yml +0 -0
  56. {python_gitea-0.12.0 → python_gitea-0.12.1}/renovate.json +0 -0
  57. {python_gitea-0.12.0 → python_gitea-0.12.1}/scripts/release_version.py +0 -0
  58. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/__init__.py +0 -0
  59. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/__main__.py +0 -0
  60. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/_lazy.py +0 -0
  61. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/actions/__init__.py +0 -0
  62. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/actions/actions.py +0 -0
  63. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/actions/artifact.py +0 -0
  64. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/actions/async_actions.py +0 -0
  65. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/actions/async_artifact.py +0 -0
  66. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/actions/async_run_management.py +0 -0
  67. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/actions/async_runner.py +0 -0
  68. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/actions/async_secret.py +0 -0
  69. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/actions/async_variable.py +0 -0
  70. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/actions/base.py +0 -0
  71. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/actions/run_management.py +0 -0
  72. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/actions/runner.py +0 -0
  73. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/actions/scope.py +0 -0
  74. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/actions/secret.py +0 -0
  75. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/actions/variable.py +0 -0
  76. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/__init__.py +0 -0
  77. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/__init__.py +0 -0
  78. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/artifact/__init__.py +0 -0
  79. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/artifact/delete.py +0 -0
  80. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/artifact/download.py +0 -0
  81. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/artifact/get.py +0 -0
  82. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/artifact/list.py +0 -0
  83. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/job/__init__.py +0 -0
  84. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/job/get.py +0 -0
  85. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/job/list.py +0 -0
  86. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/job/logs.py +0 -0
  87. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/job/rerun.py +0 -0
  88. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/main.py +0 -0
  89. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/run/__init__.py +0 -0
  90. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/run/approve.py +0 -0
  91. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/run/cancel.py +0 -0
  92. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/run/delete.py +0 -0
  93. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/run/force_cancel.py +0 -0
  94. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/run/get.py +0 -0
  95. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/run/jobs.py +0 -0
  96. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/run/list.py +0 -0
  97. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/run/rerun.py +0 -0
  98. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/runner/__init__.py +0 -0
  99. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/runner/delete.py +0 -0
  100. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/runner/get.py +0 -0
  101. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/runner/list.py +0 -0
  102. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/runner/registration_token.py +0 -0
  103. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/runner/state.py +0 -0
  104. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/runner/update.py +0 -0
  105. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/secret/__init__.py +0 -0
  106. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/secret/delete.py +0 -0
  107. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/secret/list.py +0 -0
  108. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/secret/set.py +0 -0
  109. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/variable/__init__.py +0 -0
  110. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/variable/create.py +0 -0
  111. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/variable/delete.py +0 -0
  112. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/variable/get.py +0 -0
  113. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/variable/list.py +0 -0
  114. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/variable/update.py +0 -0
  115. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/workflow/__init__.py +0 -0
  116. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/workflow/dispatch.py +0 -0
  117. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/workflow/get.py +0 -0
  118. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/actions/workflow/list.py +0 -0
  119. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/comment/__init__.py +0 -0
  120. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/comment/add.py +0 -0
  121. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/comment/delete.py +0 -0
  122. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/comment/edit.py +0 -0
  123. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/comment/list.py +0 -0
  124. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/comment/main.py +0 -0
  125. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/config/__init__.py +0 -0
  126. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/config/add.py +0 -0
  127. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/config/delete.py +0 -0
  128. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/config/list.py +0 -0
  129. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/config/main.py +0 -0
  130. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/config/update.py +0 -0
  131. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/issue/__init__.py +0 -0
  132. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/issue/close.py +0 -0
  133. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/issue/create.py +0 -0
  134. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/issue/dependency/__init__.py +0 -0
  135. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/issue/dependency/add.py +0 -0
  136. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/issue/dependency/list.py +0 -0
  137. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/issue/dependency/main.py +0 -0
  138. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/issue/dependency/remove.py +0 -0
  139. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/issue/edit.py +0 -0
  140. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/issue/get.py +0 -0
  141. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/issue/label/__init__.py +0 -0
  142. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/issue/label/add.py +0 -0
  143. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/issue/label/clear.py +0 -0
  144. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/issue/label/list.py +0 -0
  145. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/issue/label/main.py +0 -0
  146. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/issue/label/remove.py +0 -0
  147. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/issue/label/set.py +0 -0
  148. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/issue/list.py +0 -0
  149. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/issue/main.py +0 -0
  150. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/label/__init__.py +0 -0
  151. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/label/create.py +0 -0
  152. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/label/delete.py +0 -0
  153. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/label/list.py +0 -0
  154. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/label/main.py +0 -0
  155. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/label/update.py +0 -0
  156. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/main.py +0 -0
  157. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/milestone/__init__.py +0 -0
  158. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/milestone/create.py +0 -0
  159. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/milestone/list.py +0 -0
  160. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/milestone/main.py +0 -0
  161. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/notification/__init__.py +0 -0
  162. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/notification/list.py +0 -0
  163. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/notification/main.py +0 -0
  164. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/notification/read.py +0 -0
  165. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/organization/__init__.py +0 -0
  166. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/organization/list.py +0 -0
  167. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/organization/main.py +0 -0
  168. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/output.py +0 -0
  169. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/project/__init__.py +0 -0
  170. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/project/column/__init__.py +0 -0
  171. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/project/column/create.py +0 -0
  172. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/project/column/issues.py +0 -0
  173. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/project/column/list.py +0 -0
  174. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/project/create.py +0 -0
  175. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/project/delete.py +0 -0
  176. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/project/edit.py +0 -0
  177. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/project/get.py +0 -0
  178. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/project/issue/__init__.py +0 -0
  179. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/project/issue/add.py +0 -0
  180. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/project/issue/move.py +0 -0
  181. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/project/issue/remove.py +0 -0
  182. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/project/issues.py +0 -0
  183. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/project/list.py +0 -0
  184. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/project/main.py +0 -0
  185. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/project/show.py +0 -0
  186. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/pull_request/__init__.py +0 -0
  187. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/pull_request/list.py +0 -0
  188. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/pull_request/main.py +0 -0
  189. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/repository/__init__.py +0 -0
  190. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/repository/list.py +0 -0
  191. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/repository/main.py +0 -0
  192. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/user/__init__.py +0 -0
  193. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/user/get.py +0 -0
  194. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/user/main.py +0 -0
  195. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/user/update_settings.py +0 -0
  196. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/utils/__init__.py +0 -0
  197. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/utils/api.py +0 -0
  198. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/utils/auth.py +0 -0
  199. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/utils/convert.py +0 -0
  200. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/utils/errors.py +0 -0
  201. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/utils/issue.py +0 -0
  202. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/utils/options.py +0 -0
  203. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/watch/__init__.py +0 -0
  204. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/watch/advance.py +0 -0
  205. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/watch/list.py +0 -0
  206. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/watch/main.py +0 -0
  207. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/cli/watch/scopes.py +0 -0
  208. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/client/__init__.py +0 -0
  209. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/client/async_gitea.py +0 -0
  210. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/client/base.py +0 -0
  211. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/client/gitea.py +0 -0
  212. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/comment/__init__.py +0 -0
  213. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/comment/async_comment.py +0 -0
  214. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/comment/base.py +0 -0
  215. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/comment/comment.py +0 -0
  216. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/config/__init__.py +0 -0
  217. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/config/manager.py +0 -0
  218. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/config/model.py +0 -0
  219. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/issue/__init__.py +0 -0
  220. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/issue/async_issue.py +0 -0
  221. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/issue/base.py +0 -0
  222. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/issue/issue.py +0 -0
  223. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/issue/project_column.py +0 -0
  224. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/label/__init__.py +0 -0
  225. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/milestone/__init__.py +0 -0
  226. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/milestone/async_milestone.py +0 -0
  227. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/milestone/base.py +0 -0
  228. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/milestone/milestone.py +0 -0
  229. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/notification/__init__.py +0 -0
  230. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/notification/async_notification.py +0 -0
  231. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/notification/base.py +0 -0
  232. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/notification/notification.py +0 -0
  233. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/organization/__init__.py +0 -0
  234. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/organization/async_organization.py +0 -0
  235. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/organization/base.py +0 -0
  236. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/organization/organization.py +0 -0
  237. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/project/__init__.py +0 -0
  238. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/project/async_project.py +0 -0
  239. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/project/base.py +0 -0
  240. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/project/project.py +0 -0
  241. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/pull_request/__init__.py +0 -0
  242. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/pull_request/async_pull_request.py +0 -0
  243. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/pull_request/base.py +0 -0
  244. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/pull_request/pull_request.py +0 -0
  245. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/repository/__init__.py +0 -0
  246. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/repository/async_repository.py +0 -0
  247. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/repository/base.py +0 -0
  248. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/repository/repository.py +0 -0
  249. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/resource/__init__.py +0 -0
  250. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/resource/async_resource.py +0 -0
  251. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/resource/protocol.py +0 -0
  252. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/resource/resource.py +0 -0
  253. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/user/__init__.py +0 -0
  254. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/user/async_user.py +0 -0
  255. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/user/base.py +0 -0
  256. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/user/user.py +0 -0
  257. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/utils/__init__.py +0 -0
  258. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/utils/fields.py +0 -0
  259. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/utils/log.py +0 -0
  260. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/utils/pagination.py +0 -0
  261. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/utils/response.py +0 -0
  262. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/version.py +0 -0
  263. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/watch/__init__.py +0 -0
  264. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/watch/changes.py +0 -0
  265. {python_gitea-0.12.0 → python_gitea-0.12.1}/src/gitea/watch/state.py +0 -0
  266. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/__init__.py +0 -0
  267. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/actions/__init__.py +0 -0
  268. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/actions/test_actions_base.py +0 -0
  269. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/actions/test_actions_imports.py +0 -0
  270. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/actions/test_actions_requests.py +0 -0
  271. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/actions/test_actions_scope.py +0 -0
  272. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/board.py +0 -0
  273. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/__init__.py +0 -0
  274. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/actions/__init__.py +0 -0
  275. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/actions/invoking.py +0 -0
  276. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/actions/test_cli_actions_artifact.py +0 -0
  277. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/actions/test_cli_actions_job_get.py +0 -0
  278. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/actions/test_cli_actions_job_list.py +0 -0
  279. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/actions/test_cli_actions_job_logs.py +0 -0
  280. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/actions/test_cli_actions_main.py +0 -0
  281. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/actions/test_cli_actions_run_get.py +0 -0
  282. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/actions/test_cli_actions_run_jobs.py +0 -0
  283. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/actions/test_cli_actions_run_list.py +0 -0
  284. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/actions/test_cli_actions_run_management.py +0 -0
  285. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/actions/test_cli_actions_runner.py +0 -0
  286. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/actions/test_cli_actions_secret.py +0 -0
  287. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/actions/test_cli_actions_variable.py +0 -0
  288. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/actions/test_cli_actions_workflow_dispatch.py +0 -0
  289. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/actions/test_cli_actions_workflow_get.py +0 -0
  290. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/actions/test_cli_actions_workflow_list.py +0 -0
  291. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/comment/__init__.py +0 -0
  292. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/comment/test_cli_comment_add.py +0 -0
  293. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/comment/test_cli_comment_delete.py +0 -0
  294. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/comment/test_cli_comment_edit.py +0 -0
  295. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/comment/test_cli_comment_list.py +0 -0
  296. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/comment/test_cli_comment_main.py +0 -0
  297. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/config/__init__.py +0 -0
  298. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/config/test_cli_config_add.py +0 -0
  299. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/config/test_cli_config_delete.py +0 -0
  300. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/config/test_cli_config_list.py +0 -0
  301. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/config/test_cli_config_main.py +0 -0
  302. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/config/test_cli_config_update.py +0 -0
  303. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/envelope.py +0 -0
  304. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/issue/__init__.py +0 -0
  305. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/issue/dependency/__init__.py +0 -0
  306. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/issue/dependency/test_cli_issue_dependency.py +0 -0
  307. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/issue/label/__init__.py +0 -0
  308. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/issue/test_cli_issue_close.py +0 -0
  309. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/issue/test_cli_issue_comment.py +0 -0
  310. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/issue/test_cli_issue_create.py +0 -0
  311. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/issue/test_cli_issue_edit.py +0 -0
  312. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/issue/test_cli_issue_get.py +0 -0
  313. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/issue/test_cli_issue_list.py +0 -0
  314. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/issue/test_cli_issue_main.py +0 -0
  315. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/label/__init__.py +0 -0
  316. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/label/test_cli_label_create.py +0 -0
  317. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/label/test_cli_label_delete.py +0 -0
  318. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/label/test_cli_label_list.py +0 -0
  319. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/label/test_cli_label_main.py +0 -0
  320. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/label/test_cli_label_update.py +0 -0
  321. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/milestone/__init__.py +0 -0
  322. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/milestone/test_cli_milestone_create.py +0 -0
  323. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/milestone/test_cli_milestone_list.py +0 -0
  324. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/milestone/test_cli_milestone_main.py +0 -0
  325. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/notification/__init__.py +0 -0
  326. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/notification/test_cli_notification.py +0 -0
  327. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/organization/__init__.py +0 -0
  328. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/organization/test_cli_organization_list.py +0 -0
  329. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/organization/test_cli_organization_main.py +0 -0
  330. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/project/__init__.py +0 -0
  331. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/project/test_cli_project.py +0 -0
  332. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/project/test_cli_project_column_issues.py +0 -0
  333. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/project/test_cli_project_show.py +0 -0
  334. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/pull_request/__init__.py +0 -0
  335. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/pull_request/test_cli_pull_request_list.py +0 -0
  336. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/pull_request/test_cli_pull_request_main.py +0 -0
  337. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/rendering.py +0 -0
  338. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/repository/__init__.py +0 -0
  339. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/repository/test_cli_repository_list.py +0 -0
  340. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/repository/test_cli_repository_main.py +0 -0
  341. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/test_cli_contract.py +0 -0
  342. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/test_cli_output.py +0 -0
  343. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/tree.py +0 -0
  344. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/user/__init__.py +0 -0
  345. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/user/test_cli_user_get.py +0 -0
  346. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/user/test_cli_user_update_settings.py +0 -0
  347. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/utils/__init__.py +0 -0
  348. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/utils/test_cli_utils_api.py +0 -0
  349. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/utils/test_cli_utils_auth.py +0 -0
  350. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/utils/test_cli_utils_convert.py +0 -0
  351. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/utils/test_cli_utils_errors.py +0 -0
  352. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/utils/test_cli_utils_issue.py +0 -0
  353. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/utils/test_cli_utils_options.py +0 -0
  354. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/watch/__init__.py +0 -0
  355. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/watch/support.py +0 -0
  356. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/watch/test_cli_watch_advance.py +0 -0
  357. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/watch/test_cli_watch_list.py +0 -0
  358. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/cli/watch/test_cli_watch_scopes.py +0 -0
  359. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/client/__init__.py +0 -0
  360. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/client/test_client_async_gitea.py +0 -0
  361. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/client/test_client_base.py +0 -0
  362. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/client/test_client_gitea.py +0 -0
  363. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/comment/__init__.py +0 -0
  364. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/comment/test_comment_async_comment.py +0 -0
  365. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/comment/test_comment_base.py +0 -0
  366. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/comment/test_comment_comment.py +0 -0
  367. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/config/__init__.py +0 -0
  368. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/config/test_config_manager.py +0 -0
  369. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/config/test_config_model.py +0 -0
  370. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/conftest.py +0 -0
  371. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/issue/__init__.py +0 -0
  372. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/issue/test_issue_async_issue.py +0 -0
  373. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/issue/test_issue_async_project_column.py +0 -0
  374. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/issue/test_issue_base.py +0 -0
  375. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/issue/test_issue_dependencies.py +0 -0
  376. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/issue/test_issue_issue.py +0 -0
  377. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/issue/test_issue_labels.py +0 -0
  378. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/issue/test_issue_project_column.py +0 -0
  379. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/label/__init__.py +0 -0
  380. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/milestone/__init__.py +0 -0
  381. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/milestone/test_milestone_async_milestone.py +0 -0
  382. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/milestone/test_milestone_base.py +0 -0
  383. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/milestone/test_milestone_milestone.py +0 -0
  384. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/notification/__init__.py +0 -0
  385. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/notification/test_notification_base.py +0 -0
  386. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/notification/test_notification_notification.py +0 -0
  387. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/organization/__init__.py +0 -0
  388. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/organization/test_organization_async_organization.py +0 -0
  389. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/organization/test_organization_base.py +0 -0
  390. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/organization/test_organization_organization.py +0 -0
  391. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/project/__init__.py +0 -0
  392. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/project/test_project_base.py +0 -0
  393. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/project/test_project_project.py +0 -0
  394. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/project/test_project_requests.py +0 -0
  395. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/pull_request/__init__.py +0 -0
  396. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/pull_request/test_pull_request_async_pull_request.py +0 -0
  397. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/pull_request/test_pull_request_base.py +0 -0
  398. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/pull_request/test_pull_request_pull_request.py +0 -0
  399. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/repository/__init__.py +0 -0
  400. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/repository/test_repository_async_repository.py +0 -0
  401. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/repository/test_repository_base.py +0 -0
  402. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/repository/test_repository_repository.py +0 -0
  403. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/resource/__init__.py +0 -0
  404. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/resource/test_resource_async_resource.py +0 -0
  405. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/resource/test_resource_resource.py +0 -0
  406. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/smoke_test.py +0 -0
  407. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/test_import.py +0 -0
  408. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/test_lazy_reexports.py +0 -0
  409. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/test_main.py +0 -0
  410. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/test_release_version.py +0 -0
  411. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/test_version.py +0 -0
  412. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/transport.py +0 -0
  413. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/user/__init__.py +0 -0
  414. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/user/test_user_async_user.py +0 -0
  415. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/user/test_user_base.py +0 -0
  416. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/user/test_user_user.py +0 -0
  417. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/utils/__init__.py +0 -0
  418. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/utils/test_utils_fields.py +0 -0
  419. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/utils/test_utils_log.py +0 -0
  420. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/utils/test_utils_pagination.py +0 -0
  421. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/utils/test_utils_response.py +0 -0
  422. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/watch/__init__.py +0 -0
  423. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/watch/test_watch_changes.py +0 -0
  424. {python_gitea-0.12.0 → python_gitea-0.12.1}/tests/watch/test_watch_state.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: python-gitea
3
- Version: 0.12.0
3
+ Version: 0.12.1
4
4
  Summary: A Python package for interacting with the Gitea API, offering a simple interface to access repositories, users, organizations, issues, and more for automation and data management.
5
5
  Project-URL: Documentation, https://isaac-cf-wong.github.io/python-gitea
6
6
  Project-URL: Source, https://github.com/isaac-cf-wong/python-gitea
@@ -499,8 +499,13 @@ defines. In all of them:
499
499
  anything is written, so it works on a Gitea that only accepts IDs. Names are
500
500
  matched exactly, case included. A name that matches no label, or more than
501
501
  one, fails the command and no issue is changed. A value made only of digits is
502
- taken as an ID and sent as it is, which is how a label defined on the
503
- organization rather than the repository is named.
502
+ taken as an ID, which is how a label defined on the organization rather than
503
+ the repository is named. An ID is checked as well: one that is neither a label
504
+ of the repository nor of the organization owning it fails the command in the
505
+ same way, before anything is written. Label IDs belong to the repository or
506
+ organization that defines them, so an ID read from another repository names a
507
+ different label, or none; prefer the name, which means the same label wherever
508
+ it is defined.
504
509
  - `--issue-id` can be repeated to act on several issues in one run. With one
505
510
  issue, `data` is the list of labels the issue is left with. With several,
506
511
  `data` holds one entry per issue, in the order given:
@@ -38,7 +38,7 @@ dev = [
38
38
  "prek>=0.5.3",
39
39
  "pytest-github-actions-annotate-failures>=0.4.2",
40
40
  "pytest-cov>=7.1.0",
41
- "pytest-mock>=3.15.1",
41
+ "pytest-mock>=3.16.0",
42
42
  "pytest>=9.1.1",
43
43
  "pytest-asyncio>=1.4.0",
44
44
  ]
@@ -7,9 +7,13 @@ and one that does not rejects the whole request. Resolving first also means an
7
7
  unknown name is an error before anything is written, rather than a label silently
8
8
  not applied, and before the first of several issues has been changed.
9
9
 
10
- A value made only of ASCII digits is taken to be an ID and is sent as it is,
11
- without being looked up. That is what lets a label defined on the organization,
12
- which the repository's listing does not include, be applied at all.
10
+ A value made only of ASCII digits is taken to be an ID. An ID is checked too,
11
+ against the repository's labels and then, for one not among them, against the
12
+ labels of the organization owning the repository, which the repository's listing
13
+ does not include. An ID found in neither is an error before anything is written:
14
+ Gitea drops an ID it cannot apply without saying so, so an ID copied from another
15
+ repository would otherwise be a silent no-op for `add`, and for `set` would leave
16
+ the issue with no labels at all.
13
17
 
14
18
  Every command takes one `--issue-id` or several. With one, `data` is that issue's
15
19
  labels, as `gitea-cli issue label list` emits them. With several, `data` holds one
@@ -25,6 +29,8 @@ import re
25
29
  from collections.abc import Callable
26
30
  from typing import TYPE_CHECKING, Any
27
31
 
32
+ from requests import HTTPError
33
+
28
34
  from gitea.cli.utils.errors import CommandError
29
35
  from gitea.utils.pagination import PAGE_SIZE, collect_all_pages
30
36
 
@@ -37,6 +43,7 @@ ISSUE_IDS_HELP = "Issue number shown in the web UI. Repeat the option to act on
37
43
  LABEL_HELP = "Label name or numeric ID. Repeat the option for several labels."
38
44
 
39
45
  _NUMERIC_ID = re.compile(r"[0-9]+")
46
+ _NOT_FOUND = 404
40
47
 
41
48
 
42
49
  def require_issue_ids(issue_ids: list[int] | None, *, command: str) -> list[int]:
@@ -79,14 +86,41 @@ def require_labels(labels: list[str] | None, *, command: str, hint: str = "") ->
79
86
  return labels
80
87
 
81
88
 
89
+ def _organization_label_ids(client: Gitea, owner: str) -> set[int]:
90
+ """Read the IDs of the labels defined on the organization owning a repository.
91
+
92
+ Args:
93
+ client: The client to list the labels with.
94
+ owner: The owner of the repository.
95
+
96
+ Returns:
97
+ The IDs, or none when the owner is a user rather than an organization,
98
+ which Gitea answers with a 404.
99
+
100
+ Raises:
101
+ HTTPError: If the listing failed for any other reason.
102
+
103
+ """
104
+ try:
105
+ defined, _ = collect_all_pages(
106
+ lambda page: client.label.list_organization_labels(organization=owner, page=page, limit=PAGE_SIZE)
107
+ )
108
+ except HTTPError as e:
109
+ response = getattr(e, "response", None)
110
+ if response is None or response.status_code != _NOT_FOUND:
111
+ raise
112
+ return set()
113
+ return {label["id"] for label in defined}
114
+
115
+
82
116
  def resolve_label_ids(client: Gitea, owner: str, repository: str, labels: list[str], *, command: str) -> list[int]:
83
- """Resolve the labels given on the command line to their IDs.
117
+ """Resolve the labels given on the command line to their IDs, and check that each exists.
84
118
 
85
- The repository's labels are listed only when a name has to be resolved, and
86
- then only once for all of them.
119
+ The repository's labels are listed once for all of them. The organization's
120
+ are listed only when an ID is not among the repository's.
87
121
 
88
122
  Args:
89
- client: The client to list the repository's labels with.
123
+ client: The client to list the labels with.
90
124
  owner: The owner of the repository.
91
125
  repository: The name of the repository.
92
126
  labels: The labels, each a name or a numeric ID.
@@ -96,18 +130,19 @@ def resolve_label_ids(client: Gitea, owner: str, repository: str, labels: list[s
96
130
  The label IDs, in the order given, each once.
97
131
 
98
132
  Raises:
99
- CommandError: If a name matches no label of the repository, or more than one.
133
+ CommandError: If a name matches no label of the repository, or more than
134
+ one, or an ID is neither a label of the repository nor of the
135
+ organization owning it.
100
136
 
101
137
  """
102
- names = [label for label in labels if not _NUMERIC_ID.fullmatch(label)]
138
+ defined, _ = collect_all_pages(
139
+ lambda page: client.label.list_labels(owner=owner, repository=repository, page=page, limit=PAGE_SIZE)
140
+ )
103
141
  by_name: dict[str, list[int]] = {}
104
- if names:
105
- defined, _ = collect_all_pages(
106
- lambda page: client.label.list_labels(owner=owner, repository=repository, page=page, limit=PAGE_SIZE)
107
- )
108
- for label in defined:
109
- by_name.setdefault(label["name"], []).append(label["id"])
142
+ for label in defined:
143
+ by_name.setdefault(label["name"], []).append(label["id"])
110
144
 
145
+ names = [label for label in labels if not _NUMERIC_ID.fullmatch(label)]
111
146
  unknown = [name for name in names if name not in by_name]
112
147
  if unknown:
113
148
  raise CommandError(
@@ -122,8 +157,23 @@ def resolve_label_ids(client: Gitea, owner: str, repository: str, labels: list[s
122
157
  f"in {owner}/{repository}. Pass the numeric ID of the one you mean."
123
158
  )
124
159
 
125
- ids = [int(label) if _NUMERIC_ID.fullmatch(label) else by_name[label][0] for label in labels]
126
- return list(dict.fromkeys(ids))
160
+ repository_ids = {label["id"] for label in defined}
161
+ ids = [int(label) for label in labels if _NUMERIC_ID.fullmatch(label)]
162
+ elsewhere = [label_id for label_id in dict.fromkeys(ids) if label_id not in repository_ids]
163
+ if elsewhere:
164
+ organization_ids = _organization_label_ids(client, owner)
165
+ missing = [label_id for label_id in elsewhere if label_id not in organization_ids]
166
+ if missing:
167
+ raise CommandError(
168
+ f"'{command}': no label with ID {', '.join(str(label_id) for label_id in missing)} "
169
+ f"in {owner}/{repository} or on its owner {owner}. "
170
+ f"A label's ID belongs to the repository or organization defining it, so an ID read from "
171
+ f"another repository names a different label there, or none; nothing was changed. "
172
+ f"Pass the label's name instead; 'gitea-cli label list' shows the repository's labels."
173
+ )
174
+
175
+ resolved = [int(label) if _NUMERIC_ID.fullmatch(label) else by_name[label][0] for label in labels]
176
+ return list(dict.fromkeys(resolved))
127
177
 
128
178
 
129
179
  def for_each_issue(
@@ -74,6 +74,63 @@ class AsyncLabel(BaseLabel, AsyncResource):
74
74
  data, status_code = await process_async_response(response, default=[])
75
75
  return cast(list[dict[str, Any]], data), {"status_code": status_code}
76
76
 
77
+ async def _list_organization_labels(
78
+ self,
79
+ organization: str,
80
+ page: int | None = None,
81
+ limit: int | None = None,
82
+ **kwargs: Any,
83
+ ) -> ClientResponse:
84
+ """List the labels defined on an organization.
85
+
86
+ Args:
87
+ organization: The name of the organization.
88
+ page: The page number for pagination.
89
+ limit: The number of labels per page.
90
+ **kwargs: Additional arguments for the request.
91
+
92
+ Returns:
93
+ The HTTP response object.
94
+
95
+ """
96
+ endpoint, params = self._list_organization_labels_helper(
97
+ organization=organization,
98
+ page=page,
99
+ limit=limit,
100
+ )
101
+ return await self._get(endpoint=endpoint, params=params, **kwargs)
102
+
103
+ async def list_organization_labels(
104
+ self,
105
+ organization: str,
106
+ page: int | None = None,
107
+ limit: int | None = None,
108
+ **kwargs: Any,
109
+ ) -> tuple[list[dict[str, Any]], dict[str, Any]]:
110
+ """List the labels defined on an organization.
111
+
112
+ These are the labels every repository of the organization can use, and
113
+ which the listing of a repository's own labels does not include.
114
+
115
+ Args:
116
+ organization: The name of the organization.
117
+ page: The page number for pagination.
118
+ limit: The number of labels per page.
119
+ **kwargs: Additional arguments for the request.
120
+
121
+ Returns:
122
+ A tuple containing a list of labels as dictionaries and a dictionary with metadata.
123
+
124
+ """
125
+ response = await self._list_organization_labels(
126
+ organization=organization,
127
+ page=page,
128
+ limit=limit,
129
+ **kwargs,
130
+ )
131
+ data, status_code = await process_async_response(response, default=[])
132
+ return cast(list[dict[str, Any]], data), {"status_code": status_code}
133
+
77
134
  async def _create_label(
78
135
  self,
79
136
  owner: str,
@@ -50,6 +50,45 @@ class BaseLabel:
50
50
 
51
51
  return endpoint, params
52
52
 
53
+ def _list_organization_labels_endpoint(self, organization: str) -> str:
54
+ """Construct the endpoint URL for listing the labels defined on an organization.
55
+
56
+ Args:
57
+ organization: The name of the organization.
58
+
59
+ Returns:
60
+ The endpoint URL for listing the organization's labels.
61
+
62
+ """
63
+ return f"/orgs/{organization}/labels"
64
+
65
+ def _list_organization_labels_helper(
66
+ self,
67
+ organization: str,
68
+ page: int | None = None,
69
+ limit: int | None = None,
70
+ ) -> tuple[str, dict[str, Any]]:
71
+ """Get the endpoint and parameters for listing the labels defined on an organization.
72
+
73
+ Args:
74
+ organization: The name of the organization.
75
+ page: The page number for pagination.
76
+ limit: The number of labels per page.
77
+
78
+ Returns:
79
+ A tuple containing the endpoint and the request arguments.
80
+
81
+ """
82
+ endpoint = self._list_organization_labels_endpoint(organization=organization)
83
+
84
+ params = {}
85
+ if page is not None:
86
+ params["page"] = page
87
+ if limit is not None:
88
+ params["limit"] = limit
89
+
90
+ return endpoint, params
91
+
53
92
  def _create_label_endpoint(self, owner: str, repository: str) -> str:
54
93
  """Construct the endpoint URL for creating a label in a repository.
55
94
 
@@ -74,6 +74,63 @@ class Label(BaseLabel, Resource):
74
74
  data, status_code = process_response(response, default=[])
75
75
  return cast(list[dict[str, Any]], data), {"status_code": status_code}
76
76
 
77
+ def _list_organization_labels(
78
+ self,
79
+ organization: str,
80
+ page: int | None = None,
81
+ limit: int | None = None,
82
+ **kwargs: Any,
83
+ ) -> Response:
84
+ """List the labels defined on an organization.
85
+
86
+ Args:
87
+ organization: The name of the organization.
88
+ page: The page number for pagination.
89
+ limit: The number of labels per page.
90
+ **kwargs: Additional arguments for the request.
91
+
92
+ Returns:
93
+ The HTTP response object.
94
+
95
+ """
96
+ endpoint, params = self._list_organization_labels_helper(
97
+ organization=organization,
98
+ page=page,
99
+ limit=limit,
100
+ )
101
+ return self._get(endpoint=endpoint, params=params, **kwargs)
102
+
103
+ def list_organization_labels(
104
+ self,
105
+ organization: str,
106
+ page: int | None = None,
107
+ limit: int | None = None,
108
+ **kwargs: Any,
109
+ ) -> tuple[list[dict[str, Any]], dict[str, Any]]:
110
+ """List the labels defined on an organization.
111
+
112
+ These are the labels every repository of the organization can use, and
113
+ which the listing of a repository's own labels does not include.
114
+
115
+ Args:
116
+ organization: The name of the organization.
117
+ page: The page number for pagination.
118
+ limit: The number of labels per page.
119
+ **kwargs: Additional arguments for the request.
120
+
121
+ Returns:
122
+ A tuple containing a list of labels as dictionaries and a dictionary with metadata.
123
+
124
+ """
125
+ response = self._list_organization_labels(
126
+ organization=organization,
127
+ page=page,
128
+ limit=limit,
129
+ **kwargs,
130
+ )
131
+ data, status_code = process_response(response, default=[])
132
+ return cast(list[dict[str, Any]], data), {"status_code": status_code}
133
+
77
134
  def _create_label(
78
135
  self,
79
136
  owner: str,
@@ -2,7 +2,9 @@
2
2
 
3
3
  The commands are run against a stand-in for the instance that keeps each issue's
4
4
  labels as Gitea does: a POST to an issue's labels appends, a PUT replaces them, a
5
- DELETE of the list clears it and a DELETE of one label removes that one. A command
5
+ DELETE of the list clears it and a DELETE of one label removes that one. As Gitea
6
+ does, a POST or PUT drops without a word any ID that is not a label of the
7
+ repository or of the organization owning it. A command
6
8
  that sent the wrong method would therefore leave the issue with the wrong labels,
7
9
  which is what these tests look at, rather than only at which method was sent.
8
10
  """
@@ -11,6 +13,7 @@ from __future__ import annotations
11
13
 
12
14
  import json
13
15
  import re
16
+ from http import HTTPStatus
14
17
  from pathlib import Path
15
18
  from typing import Any
16
19
  from unittest.mock import patch
@@ -32,22 +35,33 @@ BUG = {"id": 3, "name": "bug", "color": "ff0000"}
32
35
  DOCS = {"id": 5, "name": "docs", "color": "00ff00"}
33
36
  URGENT = {"id": 8, "name": "priority: urgent", "color": "0000ff"}
34
37
  DEFINED = [BUG, DOCS, URGENT]
38
+ ORG_WIDE = {"id": 900, "name": "org-wide", "color": "cccccc"}
39
+ # An ID no label of the repository or its organization has, as one copied from another repository would be.
40
+ FOREIGN = 266
35
41
 
36
42
 
37
43
  class FailedResponse:
38
44
  """The answer of an endpoint refusing a request, as far as the client reads it."""
39
45
 
40
- status_code = 404
41
46
  content = b""
42
47
 
48
+ def __init__(self, status_code: int = 404) -> None:
49
+ """Answer with the given status.
50
+
51
+ Args:
52
+ status_code: The status of the refusal.
53
+
54
+ """
55
+ self.status_code = status_code
56
+
43
57
  def raise_for_status(self) -> None:
44
- """Raise as a refused request does.
58
+ """Raise as a refused request does, carrying the response as requests does.
45
59
 
46
60
  Raises:
47
61
  requests.HTTPError: Always.
48
62
 
49
63
  """
50
- raise requests.HTTPError("404 Client Error: Not Found")
64
+ raise requests.HTTPError(f"{self.status_code} Client Error", response=self)
51
65
 
52
66
  def close(self) -> None:
53
67
  """Release the response, as the client does on a failure."""
@@ -61,6 +75,8 @@ class LabelServer(RecordingSession):
61
75
  carried: dict[int, list[int]],
62
76
  defined: list[dict[str, Any]] | None = None,
63
77
  failing: frozenset[int] = frozenset(),
78
+ organization: list[dict[str, Any]] | None = None,
79
+ organization_status: int = 200,
64
80
  ) -> None:
65
81
  """Start the instance with the labels each issue carries.
66
82
 
@@ -68,20 +84,27 @@ class LabelServer(RecordingSession):
68
84
  carried: The IDs of the labels each issue carries, by issue number.
69
85
  defined: The labels the repository defines.
70
86
  failing: Issues whose label endpoints refuse every request.
87
+ organization: The labels the organization owning the repository defines.
88
+ organization_status: The status the organization's label listing answers
89
+ with: 404 is what Gitea answers when the owner is a user.
71
90
 
72
91
  """
73
92
  super().__init__()
74
93
  self.defined = DEFINED if defined is None else defined
94
+ self.organization = [] if organization is None else organization
95
+ self.organization_status = organization_status
75
96
  self.carried = {issue: list(ids) for issue, ids in carried.items()}
76
97
  self.failing = failing
77
98
 
78
99
  def _labels_of(self, issue: int) -> list[dict[str, Any]]:
79
- by_id = {label["id"]: label for label in self.defined}
100
+ by_id = {label["id"]: label for label in [*self.defined, *self.organization]}
80
101
  return [by_id[label_id] for label_id in self.carried[issue]]
81
102
 
82
103
  def _ids(self, values: list[int | str]) -> list[int]:
83
104
  by_name = {label["name"]: label["id"] for label in self.defined}
84
- return [value if isinstance(value, int) else by_name[value] for value in values]
105
+ applicable = {label["id"] for label in [*self.defined, *self.organization]}
106
+ ids = [value if isinstance(value, int) else by_name[value] for value in values]
107
+ return [label_id for label_id in ids if label_id in applicable]
85
108
 
86
109
  def request(self, method: str, url: str, **kwargs: Any) -> Any:
87
110
  """Record a request and answer it as the instance would.
@@ -101,10 +124,17 @@ class LabelServer(RecordingSession):
101
124
  self._record(method, url, **kwargs)
102
125
  path = url.removeprefix(API_ROOT)
103
126
 
104
- if path == "/repos/o/r/labels" and method == "GET":
127
+ listings = {
128
+ "/repos/o/r/labels": (self.defined, 200),
129
+ "/orgs/o/labels": (self.organization, self.organization_status),
130
+ }
131
+ if path in listings and method == "GET":
132
+ listed, status = listings[path]
133
+ if status != HTTPStatus.OK:
134
+ return FailedResponse(status)
105
135
  params = kwargs.get("params") or {}
106
- page, limit = params.get("page", 1), params.get("limit", len(self.defined))
107
- return RecordedResponse(self.defined[(page - 1) * limit : page * limit])
136
+ page, limit = params.get("page", 1), params.get("limit", len(listed))
137
+ return RecordedResponse(listed[(page - 1) * limit : page * limit])
108
138
 
109
139
  match = re.fullmatch(r"/repos/o/r/issues/(\d+)/labels(?:/(\d+))?", path)
110
140
  assert match, f"unexpected request: {method} {url}"
@@ -263,14 +293,90 @@ def test_add_resolves_a_name_on_a_later_page_of_the_listing(config_path):
263
293
  assert server.bodies[-1] == {"labels": [159]}
264
294
 
265
295
 
266
- def test_a_numeric_label_is_sent_as_an_id_without_listing_the_labels(config_path):
267
- """A numeric value is an ID, which needs no lookup and may name an organization label."""
268
- server = LabelServer({34: []}, defined=[{"id": 900, "name": "org-wide", "color": "cccccc"}])
296
+ def test_an_id_of_the_repository_is_sent_without_listing_the_organization(config_path):
297
+ """An ID among the repository's labels needs no further lookup."""
298
+ server = LabelServer({34: []})
299
+
300
+ data_of(run(server, config_path, "add", "--issue-id", "34", "--label", "5"))
301
+
302
+ assert [url for _, url in server.requests if "/orgs/" in url] == []
303
+ assert server.bodies[-1] == {"labels": [5]}
304
+
305
+
306
+ def test_an_id_of_an_organization_label_is_applied(config_path):
307
+ """An ID the repository's listing lacks but its organization defines is a label the issue can carry."""
308
+ server = LabelServer({34: [3]}, organization=[ORG_WIDE])
309
+
310
+ data = data_of(run(server, config_path, "add", "--issue-id", "34", "--label", "900"))
311
+
312
+ assert server.bodies[-1] == {"labels": [900]}
313
+ assert server.carried[34] == [3, 900]
314
+ assert data == [BUG, ORG_WIDE]
315
+
316
+
317
+ @pytest.mark.parametrize("command", ["add", "set", "remove"])
318
+ @pytest.mark.parametrize("organization_status", [200, 404], ids=["organization", "user"])
319
+ def test_an_unknown_id_is_an_error_and_nothing_is_written(config_path, command, organization_status):
320
+ """An ID of no label here should fail before any issue is changed, whether the owner is an organization or not."""
321
+ server = LabelServer({34: [3, 5], 35: [8]}, organization=[ORG_WIDE], organization_status=organization_status)
322
+
323
+ error = run_failing(server, config_path, command, "--issue-id", "34", "--issue-id", "35", "--label", str(FOREIGN))
324
+
325
+ assert f"no label with ID {FOREIGN} in o/r or on its owner o" in error
326
+ assert "Pass the label's name instead" in error
327
+ assert server.writes == []
328
+ assert server.carried == {34: [3, 5], 35: [8]}
329
+
330
+
331
+ def test_set_with_known_and_unknown_ids_changes_nothing(config_path):
332
+ """One unknown ID among known ones should stop `set` before it replaces anything, and be the one named."""
333
+ server = LabelServer({34: [3, 5]}, organization=[ORG_WIDE])
334
+
335
+ error = run_failing(
336
+ server, config_path, "set", "--issue-id", "34", "--label", "8", "--label", str(FOREIGN), "--label", "900"
337
+ )
338
+
339
+ assert f"no label with ID {FOREIGN} in" in error
340
+ assert "8," not in error
341
+ assert "900" not in error
342
+ assert server.writes == []
343
+ assert server.carried[34] == [3, 5]
344
+
269
345
 
270
- data_of(run(server, config_path, "add", "--issue-id", "34", "--label", "900"))
346
+ def test_every_unknown_id_is_named(config_path):
347
+ """Several unknown IDs should all be named, each once, so one run shows everything to fix."""
348
+ server = LabelServer({34: [3]})
271
349
 
272
- assert server.requests[0] == ("POST", f"{API_ROOT}/repos/o/r/issues/34/labels")
273
- assert server.bodies[0] == {"labels": [900]}
350
+ error = run_failing(
351
+ server,
352
+ config_path,
353
+ "add",
354
+ "--issue-id",
355
+ "34",
356
+ "--label",
357
+ "266",
358
+ "--label",
359
+ "3",
360
+ "--label",
361
+ "270",
362
+ "--label",
363
+ "266",
364
+ )
365
+
366
+ assert "no label with ID 266, 270 in o/r" in error
367
+ assert server.writes == []
368
+
369
+
370
+ def test_a_failing_organization_listing_fails_the_command_before_writing(config_path):
371
+ """A refusal other than the 404 of a user owner cannot be read as 'no such label', and should stop the command."""
372
+ server = LabelServer({34: [3]}, organization_status=500)
373
+
374
+ with patch("gitea.cli.utils.api.logger"):
375
+ result = run(server, config_path, "set", "--issue-id", "34", "--label", "900")
376
+
377
+ assert result.exit_code == 1
378
+ assert server.writes == []
379
+ assert server.carried[34] == [3]
274
380
 
275
381
 
276
382
  @pytest.mark.parametrize("command", ["add", "set", "remove"])
@@ -55,9 +55,8 @@ _SCOPE_OPTIONS = frozenset({"--owner", "--repository", "--issue-id", "--dependen
55
55
 
56
56
  # Options a command declares repeatable, and so optional to the parser, but rejects
57
57
  # at run time when none is given, with the value a no-op invocation passes. A
58
- # `--label` is given as an ID so that it is sent as it is: a name would be looked
59
- # up among the stub's labels, find none, and fail for a reason unrelated to the
60
- # command under test.
58
+ # `--label` is checked against the repository's labels, so it is given as the ID
59
+ # of the one label the stub lists.
61
60
  _RUNTIME_REQUIRED_OPTIONS = {"--label": "1"}
62
61
 
63
62
  # The helpers a command routes its result and its failures through. A command
@@ -215,6 +214,24 @@ class _StubGitea:
215
214
  """
216
215
  return {"id": 1}, {"status_code": 200}
217
216
 
217
+ def list_labels(self, *args: Any, **kwargs: Any) -> tuple[list[dict[str, Any]], dict[str, Any]]:
218
+ """Return the single label of the repository the walk's `--label` names.
219
+
220
+ Declared for the same reason as `get_issue`: the `issue label` commands
221
+ check every `--label` against the repository's labels, and a repository
222
+ with none would fail them for a reason that has nothing to do with the
223
+ command under test.
224
+
225
+ Args:
226
+ *args: Ignored.
227
+ **kwargs: Ignored.
228
+
229
+ Returns:
230
+ One label and its metadata.
231
+
232
+ """
233
+ return [{"id": 1, "name": "stub"}], {"status_code": 200}
234
+
218
235
  def list_project_columns(self, *args: Any, **kwargs: Any) -> tuple[list[dict[str, Any]], dict[str, Any]]:
219
236
  """Return the single column of the board the walk's project has.
220
237
 
@@ -397,6 +414,23 @@ class _UnreachableGitea(_StubGitea):
397
414
  """
398
415
  return self(*args, **kwargs)
399
416
 
417
+ def list_labels(self, *args: Any, **kwargs: Any) -> tuple[list[dict[str, Any]], dict[str, Any]]:
418
+ """Fail as every other endpoint of an unreachable instance does.
419
+
420
+ Overridden for the same reason as `get_issue`: the base stub lists a
421
+ label, which would let `label list` succeed on an instance that cannot
422
+ be reached.
423
+
424
+ Args:
425
+ *args: Ignored.
426
+ **kwargs: Ignored.
427
+
428
+ Returns:
429
+ Never; the call always raises.
430
+
431
+ """
432
+ return self(*args, **kwargs)
433
+
400
434
 
401
435
  class TestLoggingLevel:
402
436
  """Test cases for LoggingLevel enum."""
@@ -38,6 +38,19 @@ class TestAsyncLabel:
38
38
  )
39
39
  assert result == ([{"id": 1, "name": "bug"}], {"status_code": 200})
40
40
 
41
+ @pytest.mark.asyncio
42
+ async def test_list_organization_labels(self, async_label, mock_client):
43
+ """Test list_organization_labels."""
44
+ with patch("gitea.label.async_label.process_async_response") as mock_process:
45
+ mock_process.return_value = ([{"id": 900, "name": "org-wide"}], 200)
46
+ result = await async_label.list_organization_labels(organization="test_org", page=1, limit=50)
47
+ mock_client._request.assert_called_once_with(
48
+ method="GET",
49
+ endpoint="/orgs/test_org/labels",
50
+ params={"page": 1, "limit": 50},
51
+ )
52
+ assert result == ([{"id": 900, "name": "org-wide"}], {"status_code": 200})
53
+
41
54
  @pytest.mark.asyncio
42
55
  async def test_create_label(self, async_label, mock_client):
43
56
  """Test create_label."""
@@ -18,6 +18,18 @@ class TestBaseLabel:
18
18
  assert endpoint == "/repos/owner/repo/labels"
19
19
  assert params == {"page": 1, "limit": 20}
20
20
 
21
+ def test_list_organization_labels_helper(self):
22
+ """Test _list_organization_labels_helper builds the endpoint and params."""
23
+ base = BaseLabel()
24
+ endpoint, params = base._list_organization_labels_helper("org", page=2, limit=50)
25
+ assert endpoint == "/orgs/org/labels"
26
+ assert params == {"page": 2, "limit": 50}
27
+
28
+ def test_list_organization_labels_helper_without_paging(self):
29
+ """Test _list_organization_labels_helper omits the paging params when absent."""
30
+ base = BaseLabel()
31
+ assert base._list_organization_labels_helper("org") == ("/orgs/org/labels", {})
32
+
21
33
  def test_create_label_helper(self):
22
34
  """Test _create_label_helper builds the payload."""
23
35
  base = BaseLabel()