python-semantic-release 8.0.6__tar.gz → 8.0.8__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 (109) hide show
  1. {python-semantic-release-8.0.6/python_semantic_release.egg-info → python-semantic-release-8.0.8}/PKG-INFO +1 -1
  2. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/pyproject.toml +3 -2
  3. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8/python_semantic_release.egg-info}/PKG-INFO +1 -1
  4. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/python_semantic_release.egg-info/requires.txt +2 -1
  5. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/__init__.py +1 -1
  6. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/cli/config.py +1 -1
  7. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/helpers.py +1 -1
  8. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/hvcs/github.py +15 -3
  9. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/changelog/test_template.py +4 -4
  10. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/hvcs/test_gitea.py +0 -12
  11. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/hvcs/test_github.py +79 -26
  12. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/AUTHORS.rst +0 -0
  13. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/LICENSE +0 -0
  14. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/MANIFEST.in +0 -0
  15. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/README.rst +0 -0
  16. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/python_semantic_release.egg-info/SOURCES.txt +0 -0
  17. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/python_semantic_release.egg-info/dependency_links.txt +0 -0
  18. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/python_semantic_release.egg-info/entry_points.txt +0 -0
  19. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/python_semantic_release.egg-info/top_level.txt +0 -0
  20. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/__main__.py +0 -0
  21. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/changelog/__init__.py +0 -0
  22. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/changelog/context.py +0 -0
  23. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/changelog/release_history.py +0 -0
  24. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/changelog/template.py +0 -0
  25. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/cli/__init__.py +0 -0
  26. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/cli/commands/__init__.py +0 -0
  27. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/cli/commands/changelog.py +0 -0
  28. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/cli/commands/generate_config.py +0 -0
  29. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/cli/commands/main.py +0 -0
  30. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/cli/commands/publish.py +0 -0
  31. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/cli/commands/version.py +0 -0
  32. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/cli/common.py +0 -0
  33. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/cli/const.py +0 -0
  34. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/cli/github_actions_output.py +0 -0
  35. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/cli/masking_filter.py +0 -0
  36. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/cli/util.py +0 -0
  37. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/commit_parser/__init__.py +0 -0
  38. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/commit_parser/_base.py +0 -0
  39. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/commit_parser/angular.py +0 -0
  40. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/commit_parser/emoji.py +0 -0
  41. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/commit_parser/scipy.py +0 -0
  42. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/commit_parser/tag.py +0 -0
  43. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/commit_parser/token.py +0 -0
  44. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/commit_parser/util.py +0 -0
  45. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/const.py +0 -0
  46. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/data/templates/CHANGELOG.md.j2 +0 -0
  47. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/data/templates/release_notes.md.j2 +0 -0
  48. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/enums.py +0 -0
  49. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/errors.py +0 -0
  50. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/hvcs/__init__.py +0 -0
  51. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/hvcs/_base.py +0 -0
  52. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/hvcs/gitea.py +0 -0
  53. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/hvcs/gitlab.py +0 -0
  54. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/hvcs/token_auth.py +0 -0
  55. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/hvcs/util.py +0 -0
  56. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/version/__init__.py +0 -0
  57. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/version/algorithm.py +0 -0
  58. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/version/declaration.py +0 -0
  59. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/version/translator.py +0 -0
  60. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/semantic_release/version/version.py +0 -0
  61. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/setup.cfg +0 -0
  62. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/setup.py +0 -0
  63. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/command_line/__init__.py +0 -0
  64. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/command_line/conftest.py +0 -0
  65. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/command_line/test_changelog.py +0 -0
  66. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/command_line/test_generate_config.py +0 -0
  67. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/command_line/test_help.py +0 -0
  68. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/command_line/test_main.py +0 -0
  69. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/command_line/test_publish.py +0 -0
  70. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/command_line/test_version.py +0 -0
  71. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/fixtures/__init__.py +0 -0
  72. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/fixtures/commit_parsers.py +0 -0
  73. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/fixtures/example_project.py +0 -0
  74. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/fixtures/git_repo.py +0 -0
  75. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/fixtures/scipy.py +0 -0
  76. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/scenario/__init__.py +0 -0
  77. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/scenario/test_next_version.py +0 -0
  78. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/scenario/test_release_history.py +0 -0
  79. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/scenario/test_template_render.py +0 -0
  80. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/__init__.py +0 -0
  81. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/__init__.py +0 -0
  82. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/changelog/__init__.py +0 -0
  83. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/changelog/test_changelog_context.py +0 -0
  84. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/changelog/test_default_changelog.py +0 -0
  85. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/changelog/test_release_notes.py +0 -0
  86. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/cli/__init__.py +0 -0
  87. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/cli/test_config.py +0 -0
  88. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/cli/test_github_actions_output.py +0 -0
  89. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/cli/test_masking_filter.py +0 -0
  90. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/cli/test_util.py +0 -0
  91. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/cli/test_version.py +0 -0
  92. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/commit_parser/__init__.py +0 -0
  93. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/commit_parser/helper.py +0 -0
  94. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/commit_parser/test_angular.py +0 -0
  95. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/commit_parser/test_emoji.py +0 -0
  96. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/commit_parser/test_scipy.py +0 -0
  97. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/commit_parser/test_tag.py +0 -0
  98. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/commit_parser/test_token.py +0 -0
  99. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/commit_parser/test_util.py +0 -0
  100. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/hvcs/__init__.py +0 -0
  101. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/hvcs/test__base.py +0 -0
  102. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/hvcs/test_gitlab.py +0 -0
  103. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/hvcs/test_token_auth.py +0 -0
  104. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/hvcs/test_util.py +0 -0
  105. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/version/__init__.py +0 -0
  106. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/version/test_algorithm.py +0 -0
  107. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/version/test_declaration.py +0 -0
  108. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/version/test_translator.py +0 -0
  109. {python-semantic-release-8.0.6 → python-semantic-release-8.0.8}/tests/unit/semantic_release/version/test_version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-semantic-release
3
- Version: 8.0.6
3
+ Version: 8.0.8
4
4
  Summary: Automatic Semantic Versioning for Python projects
5
5
  Author-email: Rolf Erik Lekang <me@rolflekang.com>
6
6
  License: MIT
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
7
7
 
8
8
  [project]
9
9
  name = "python-semantic-release"
10
- version = "8.0.6"
10
+ version = "8.0.8"
11
11
  description = "Automatic Semantic Versioning for Python projects"
12
12
  requires-python = ">=3.7"
13
13
  license = { text = "MIT" }
@@ -58,11 +58,12 @@ test = [
58
58
  "pytest-mock>=3,<4",
59
59
  "pytest-lazy-fixture~=0.6.3",
60
60
  "pytest-cov>=4,<5",
61
+ "pytest-pretty>=1.2.0,<2",
61
62
  "responses==0.23.3",
62
63
  "requests-mock>=1.10.0,<2",
63
64
  "types-pytest-lazy-fixture>=0.6.3.3",
64
65
  ]
65
- dev = ["pre-commit", "tox", "black", "ruff>=0.0.282"]
66
+ dev = ["pre-commit", "tox", "black", "ruff==0.0.286"]
66
67
  mypy = ["mypy", "types-requests"]
67
68
 
68
69
  [tool.pytest.ini_options]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-semantic-release
3
- Version: 8.0.6
3
+ Version: 8.0.8
4
4
  Summary: Automatic Semantic Versioning for Python projects
5
5
  Author-email: Rolf Erik Lekang <me@rolflekang.com>
6
6
  License: MIT
@@ -14,7 +14,7 @@ shellingham>=1.5.0.post1
14
14
  pre-commit
15
15
  tox
16
16
  black
17
- ruff>=0.0.282
17
+ ruff==0.0.286
18
18
 
19
19
  [docs]
20
20
  Sphinx<=6.0.0
@@ -33,6 +33,7 @@ pytest-xdist<4,>=2
33
33
  pytest-mock<4,>=3
34
34
  pytest-lazy-fixture~=0.6.3
35
35
  pytest-cov<5,>=4
36
+ pytest-pretty<2,>=1.2.0
36
37
  responses==0.23.3
37
38
  requests-mock<2,>=1.10.0
38
39
  types-pytest-lazy-fixture>=0.6.3.3
@@ -23,7 +23,7 @@ from semantic_release.version import (
23
23
  tags_and_versions,
24
24
  )
25
25
 
26
- __version__ = "8.0.6"
26
+ __version__ = "8.0.8"
27
27
 
28
28
 
29
29
  def setup_hook(argv: list[str]) -> None:
@@ -84,7 +84,7 @@ class ChangelogConfig(BaseModel):
84
84
 
85
85
  class BranchConfig(BaseModel):
86
86
  match: str = "(main|master)"
87
- prerelease_token = "rc" # noqa: S105
87
+ prerelease_token: str = "rc" # noqa: S105
88
88
  prerelease: bool = False
89
89
 
90
90
 
@@ -67,7 +67,7 @@ def dynamic_import(import_path: str) -> Any:
67
67
  string
68
68
  """
69
69
  log.debug("Trying to import %s", import_path)
70
- module_name, _, attr = import_path.split(":", maxsplit=1)
70
+ module_name, attr = import_path.split(":", maxsplit=1)
71
71
  module = importlib.import_module(module_name)
72
72
  return getattr(module, attr)
73
73
 
@@ -36,6 +36,7 @@ class Github(HvcsBase):
36
36
 
37
37
  DEFAULT_DOMAIN = "github.com"
38
38
  DEFAULT_API_DOMAIN = "api.github.com"
39
+ DEFAULT_UPLOAD_DOMAIN = "uploads.github.com"
39
40
 
40
41
  def __init__(
41
42
  self,
@@ -59,6 +60,7 @@ class Github(HvcsBase):
59
60
  ).replace("https://", "")
60
61
 
61
62
  self.api_url = f"https://{self.hvcs_api_domain}"
63
+ self.upload_url = f"https://{self.DEFAULT_UPLOAD_DOMAIN}"
62
64
 
63
65
  self.token = token
64
66
  auth = None if not self.token else TokenAuth(self.token)
@@ -179,15 +181,19 @@ class Github(HvcsBase):
179
181
  return self.edit_release_notes(release_id, release_notes)
180
182
 
181
183
  @logged_function(log)
182
- def asset_upload_url(self, release_id: str) -> str:
184
+ @suppress_not_found
185
+ def asset_upload_url(self, release_id: str) -> str | None:
183
186
  """
184
187
  Get the correct upload url for a release
185
188
  https://docs.github.com/en/enterprise-server@3.5/rest/releases/releases#get-a-release
186
189
  :param release_id: ID of the release to upload to
187
- :return: URL found to upload for a release
190
+ :return: URL to upload for a release if found, else None
188
191
  """
189
192
  # https://docs.github.com/en/enterprise-server@3.5/rest/releases/assets#upload-a-release-asset
190
- return f"{self.api_url}/repos/{self.owner}/{self.repo_name}/releases/{release_id}/assets" # noqa: E501
193
+ response = self.session.get(
194
+ f"{self.api_url}/repos/{self.owner}/{self.repo_name}/releases/{release_id}",
195
+ )
196
+ return response.json().get("upload_url").replace("{?name,label}", "")
191
197
 
192
198
  @logged_function(log)
193
199
  def upload_asset(
@@ -202,6 +208,12 @@ class Github(HvcsBase):
202
208
  :return: The status of the request
203
209
  """
204
210
  url = self.asset_upload_url(release_id)
211
+ if url is None:
212
+ raise HTTPError(
213
+ "There is no associated url for uploading asset for release "
214
+ f"{release_id}. Release url: "
215
+ f"{self.api_url}/repos/{self.owner}/{self.repo_name}/releases/{release_id}"
216
+ )
205
217
  content_type = (
206
218
  mimetypes.guess_type(file, strict=False)[0] or "application/octet-stream"
207
219
  )
@@ -30,12 +30,12 @@ EXAMPLE_TEMPLATE_FORMAT_STR = """
30
30
  "comment_end_string": "#}",
31
31
  },
32
32
  {
33
- "block_start_string": "{%",
34
- "block_end_string": "%}",
33
+ "block_start_string": "{[",
34
+ "block_end_string": "]}",
35
35
  "variable_start_string": "{{",
36
36
  "variable_end_string": "}}",
37
- "comment_start_string": "{#",
38
- "comment_end_string": "#}",
37
+ "comment_start_string": "/*",
38
+ "comment_end_string": "*/",
39
39
  },
40
40
  ],
41
41
  )
@@ -127,18 +127,6 @@ def test_gitea_get_repository_owner_and_name(default_gitea_client):
127
127
  "git@gitea.com:custom/example.git",
128
128
  "https://aabbcc@gitea.com/custom/example.git",
129
129
  ),
130
- (
131
- False,
132
- "aabbcc",
133
- "git@gitea.com:custom/example.git",
134
- "git@gitea.com:custom/example.git",
135
- ),
136
- (
137
- True,
138
- "aabbcc",
139
- "git@gitea.com:custom/example.git",
140
- "https://aabbcc@gitea.com/custom/example.git",
141
- ),
142
130
  ],
143
131
  )
144
132
  def test_remote_url(
@@ -213,17 +213,6 @@ def test_pull_request_url(default_gh_client, pr_number):
213
213
  )
214
214
 
215
215
 
216
- def test_asset_upload_url(default_gh_client):
217
- assert default_gh_client.asset_upload_url(
218
- release_id=420
219
- ) == "https://{domain}/repos/{owner}/{repo}/releases/{release_id}/assets".format(
220
- domain=default_gh_client.hvcs_api_domain,
221
- owner=default_gh_client.owner,
222
- repo=default_gh_client.repo_name,
223
- release_id=420,
224
- )
225
-
226
-
227
216
  ############
228
217
  # Tests which need http response mocking
229
218
  ############
@@ -231,6 +220,7 @@ def test_asset_upload_url(default_gh_client):
231
220
 
232
221
  github_matcher = re.compile(rf"^https://{Github.DEFAULT_DOMAIN}")
233
222
  github_api_matcher = re.compile(rf"^https://{Github.DEFAULT_API_DOMAIN}")
223
+ github_upload_matcher = re.compile(rf"^https://{Github.DEFAULT_UPLOAD_DOMAIN}")
234
224
 
235
225
 
236
226
  @pytest.mark.parametrize("status_code", (200, 201))
@@ -533,6 +523,43 @@ def test_create_or_update_release_when_create_fails_and_no_release_for_tag(
533
523
  mock_edit_release_notes.assert_not_called()
534
524
 
535
525
 
526
+ def test_asset_upload_url(default_gh_client):
527
+ release_id = 1
528
+ # '{?name,label}' are added by github.com at least, maybe custom too
529
+ # https://docs.github.com/en/rest/releases/releases?apiVersion=2022-11-28#get-a-release
530
+ resp_payload = {
531
+ "upload_url": (
532
+ f"{default_gh_client.upload_url}/repos/"
533
+ f"{default_gh_client.owner}/{default_gh_client.repo_name}/"
534
+ f"releases/{release_id}/"
535
+ "assets{?name,label}"
536
+ ),
537
+ "status": "success",
538
+ }
539
+ with requests_mock.Mocker(session=default_gh_client.session) as m:
540
+ m.register_uri("GET", github_api_matcher, json=resp_payload, status_code=200)
541
+ assert default_gh_client.asset_upload_url(
542
+ release_id
543
+ ) == "https://{domain}/repos/{owner}/{repo}/releases/{release_id}/assets".format(
544
+ domain=default_gh_client.DEFAULT_UPLOAD_DOMAIN,
545
+ owner=default_gh_client.owner,
546
+ repo=default_gh_client.repo_name,
547
+ release_id=release_id,
548
+ )
549
+ assert m.called
550
+ assert len(m.request_history) == 1
551
+ assert m.last_request.method == "GET"
552
+ assert (
553
+ m.last_request.url
554
+ == "{api_url}/repos/{owner}/{repo_name}/releases/{release_id}".format(
555
+ api_url=default_gh_client.api_url,
556
+ owner=default_gh_client.owner,
557
+ repo_name=default_gh_client.repo_name,
558
+ release_id=1,
559
+ )
560
+ )
561
+
562
+
536
563
  @pytest.mark.parametrize("status_code", (200, 201))
537
564
  @pytest.mark.parametrize("mock_release_id", range(3))
538
565
  def test_upload_asset_succeeds(
@@ -540,9 +567,21 @@ def test_upload_asset_succeeds(
540
567
  ):
541
568
  label = "abc123"
542
569
  urlparams = {"name": example_changelog_md.name, "label": label}
570
+ expected_upload_url = (
571
+ f"{default_gh_client.upload_url}/repos/{default_gh_client.owner}/"
572
+ f"{default_gh_client.repo_name}/releases/{mock_release_id}/"
573
+ r"assets{?name,label}"
574
+ )
575
+ json_get_up_url = {"status": "ok", "upload_url": expected_upload_url}
543
576
  with requests_mock.Mocker(session=default_gh_client.session) as m:
544
577
  m.register_uri(
545
- "POST", github_api_matcher, json={"status": "ok"}, status_code=status_code
578
+ "POST",
579
+ github_upload_matcher,
580
+ json={"status": "ok"},
581
+ status_code=status_code,
582
+ )
583
+ m.register_uri(
584
+ "GET", github_api_matcher, json=json_get_up_url, status_code=status_code
546
585
  )
547
586
  assert (
548
587
  default_gh_client.upload_asset(
@@ -553,13 +592,17 @@ def test_upload_asset_succeeds(
553
592
  is True
554
593
  )
555
594
  assert m.called
556
- assert len(m.request_history) == 1
557
- assert m.last_request.method == "POST"
558
- assert m.last_request.url == "{url}?{params}".format(
559
- url=default_gh_client.asset_upload_url(mock_release_id),
595
+ assert len(m.request_history) == 2
596
+ get_req, post_req = m.request_history
597
+ assert isinstance(get_req, requests_mock.request._RequestObjectProxy)
598
+ assert isinstance(post_req, requests_mock.request._RequestObjectProxy)
599
+ assert get_req.method == "GET"
600
+
601
+ assert post_req.method == "POST"
602
+ assert post_req.url == "{url}?{params}".format(
603
+ url=expected_upload_url.replace(r"{?name,label}", ""),
560
604
  params=urlencode(urlparams),
561
605
  )
562
-
563
606
  # Check if content-type header was correctly set according to
564
607
  # mimetypes - not retesting guessing functionality
565
608
  assert {
@@ -567,8 +610,8 @@ def test_upload_asset_succeeds(
567
610
  example_changelog_md.resolve(), strict=False
568
611
  )[0]
569
612
  or "application/octet-stream"
570
- }.items() <= m.last_request.headers.items()
571
- assert m.last_request.body == example_changelog_md.read_bytes()
613
+ }.items() <= post_req.headers.items()
614
+ assert post_req.body == example_changelog_md.read_bytes()
572
615
 
573
616
 
574
617
  @pytest.mark.parametrize("status_code", (400, 404, 429, 500, 503))
@@ -578,14 +621,23 @@ def test_upload_asset_fails(
578
621
  ):
579
622
  label = "abc123"
580
623
  urlparams = {"name": example_changelog_md.name, "label": label}
624
+ json_get_up_url = {
625
+ "status": "ok",
626
+ "upload_url": "{up_url}/repos/{owner}/{repo_name}/releases/{release_id}".format(
627
+ up_url=default_gh_client.upload_url,
628
+ owner=default_gh_client.owner,
629
+ repo_name=default_gh_client.repo_name,
630
+ release_id=mock_release_id,
631
+ ),
632
+ }
581
633
  with requests_mock.Mocker(session=default_gh_client.session) as m:
582
634
  m.register_uri(
583
635
  "POST",
584
- github_api_matcher,
636
+ github_upload_matcher,
585
637
  json={"message": "error"},
586
638
  status_code=status_code,
587
639
  )
588
-
640
+ m.register_uri("GET", github_api_matcher, json=json_get_up_url, status_code=200)
589
641
  with pytest.raises(HTTPError):
590
642
  default_gh_client.upload_asset(
591
643
  release_id=mock_release_id,
@@ -594,9 +646,10 @@ def test_upload_asset_fails(
594
646
  )
595
647
 
596
648
  assert m.called
597
- assert len(m.request_history) == 1
598
- assert m.last_request.method == "POST"
599
- assert m.last_request.url == "{url}?{params}".format(
649
+ assert len(m.request_history) == 2
650
+ post_req = m.last_request.copy()
651
+ assert post_req.method == "POST"
652
+ assert post_req.url == "{url}?{params}".format(
600
653
  url=default_gh_client.asset_upload_url(mock_release_id),
601
654
  params=urlencode(urlparams),
602
655
  )
@@ -608,8 +661,8 @@ def test_upload_asset_fails(
608
661
  example_changelog_md.resolve(), strict=False
609
662
  )[0]
610
663
  or "application/octet-stream"
611
- }.items() <= m.last_request.headers.items()
612
- assert m.last_request.body == example_changelog_md.read_bytes()
664
+ }.items() <= post_req.headers.items()
665
+ assert post_req.body == example_changelog_md.read_bytes()
613
666
 
614
667
 
615
668
  # Note - mocking as the logic for uploading an asset