/ github / GitRelease.py
GitRelease.py
  1  ############################ Copyrights and license ############################
  2  #                                                                              #
  3  # Copyright 2015 Ed Holland <eholland@alertlogic.com>                          #
  4  # Copyright 2016 Benjamin Whitney <benjamin.whitney@ironnetcybersecurity.com>  #
  5  # Copyright 2016 Jannis Gebauer <ja.geb@me.com>                                #
  6  # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com>          #
  7  # Copyright 2017 Chris McBride <thehighlander@users.noreply.github.com>        #
  8  # Copyright 2017 Simon <spam@esemi.ru>                                         #
  9  # Copyright 2018 Daniel Kesler <kesler.daniel@gmail.com>                       #
 10  # Copyright 2018 Kuba <jakub.glapa@adspired.com>                               #
 11  # Copyright 2018 Maarten Fonville <mfonville@users.noreply.github.com>         #
 12  # Copyright 2018 Shinichi TAMURA <shnch.tmr@gmail.com>                         #
 13  # Copyright 2018 Wan Liuyang <tsfdye@gmail.com>                                #
 14  # Copyright 2018 edquist <edquist@users.noreply.github.com>                    #
 15  # Copyright 2018 nurupo <nurupo.contributions@gmail.com>                       #
 16  # Copyright 2018 sfdye <tsfdye@gmail.com>                                      #
 17  #                                                                              #
 18  # This file is part of PyGithub.                                               #
 19  # http://pygithub.readthedocs.io/                                              #
 20  #                                                                              #
 21  # PyGithub is free software: you can redistribute it and/or modify it under    #
 22  # the terms of the GNU Lesser General Public License as published by the Free  #
 23  # Software Foundation, either version 3 of the License, or (at your option)    #
 24  # any later version.                                                           #
 25  #                                                                              #
 26  # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY  #
 27  # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS    #
 28  # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
 29  # details.                                                                     #
 30  #                                                                              #
 31  # You should have received a copy of the GNU Lesser General Public License     #
 32  # along with PyGithub. If not, see <http://www.gnu.org/licenses/>.             #
 33  #                                                                              #
 34  ################################################################################
 35  from __future__ import annotations
 36  
 37  from datetime import datetime
 38  from os.path import basename
 39  from typing import Any, BinaryIO
 40  
 41  import github.GitReleaseAsset
 42  import github.NamedUser
 43  from github.GithubObject import Attribute, CompletableGithubObject, NotSet, Opt
 44  from github.PaginatedList import PaginatedList
 45  
 46  from . import Consts
 47  
 48  
 49  class GitRelease(CompletableGithubObject):
 50      """
 51      This class represents GitReleases. The reference can be found here https://docs.github.com/en/rest/reference/repos#releases
 52      """
 53  
 54      def _initAttributes(self) -> None:
 55          self._id: Attribute[int] = NotSet
 56          self._body: Attribute[str] = NotSet
 57          self._title: Attribute[str] = NotSet
 58          self._tag_name: Attribute[str] = NotSet
 59          self._target_commitish: Attribute[str] = NotSet
 60          self._draft: Attribute[bool] = NotSet
 61          self._prerelease: Attribute[bool] = NotSet
 62          self._generate_release_notes: Attribute[bool] = NotSet
 63          self._author: Attribute[github.NamedUser.NamedUser] = NotSet
 64          self._url: Attribute[str] = NotSet
 65          self._upload_url: Attribute[str] = NotSet
 66          self._html_url: Attribute[str] = NotSet
 67          self._created_at: Attribute[datetime] = NotSet
 68          self._published_at: Attribute[datetime] = NotSet
 69          self._tarball_url: Attribute[str] = NotSet
 70          self._zipball_url: Attribute[str] = NotSet
 71          self._assets: Attribute[list[github.GitReleaseAsset.GitReleaseAsset]] = NotSet
 72  
 73      def __repr__(self) -> str:
 74          return self.get__repr__({"title": self._title.value})
 75  
 76      @property
 77      def id(self) -> int:
 78          self._completeIfNotSet(self._id)
 79          return self._id.value
 80  
 81      @property
 82      def body(self) -> str:
 83          self._completeIfNotSet(self._body)
 84          return self._body.value
 85  
 86      @property
 87      def title(self) -> str:
 88          self._completeIfNotSet(self._title)
 89          return self._title.value
 90  
 91      @property
 92      def tag_name(self) -> str:
 93          self._completeIfNotSet(self._tag_name)
 94          return self._tag_name.value
 95  
 96      @property
 97      def target_commitish(self) -> str:
 98          self._completeIfNotSet(self._target_commitish)
 99          return self._target_commitish.value
100  
101      @property
102      def draft(self) -> bool:
103          self._completeIfNotSet(self._draft)
104          return self._draft.value
105  
106      @property
107      def prerelease(self) -> bool:
108          self._completeIfNotSet(self._prerelease)
109          return self._prerelease.value
110  
111      @property
112      def author(self) -> github.NamedUser.NamedUser:
113          self._completeIfNotSet(self._author)
114          return self._author.value
115  
116      @property
117      def created_at(self) -> datetime:
118          self._completeIfNotSet(self._created_at)
119          return self._created_at.value
120  
121      @property
122      def published_at(self) -> datetime:
123          self._completeIfNotSet(self._published_at)
124          return self._published_at.value
125  
126      @property
127      def url(self) -> str:
128          self._completeIfNotSet(self._url)
129          return self._url.value
130  
131      @property
132      def upload_url(self) -> str:
133          self._completeIfNotSet(self._upload_url)
134          return self._upload_url.value
135  
136      @property
137      def html_url(self) -> str:
138          self._completeIfNotSet(self._html_url)
139          return self._html_url.value
140  
141      @property
142      def tarball_url(self) -> str:
143          self._completeIfNotSet(self._tarball_url)
144          return self._tarball_url.value
145  
146      @property
147      def zipball_url(self) -> str:
148          self._completeIfNotSet(self._zipball_url)
149          return self._zipball_url.value
150  
151      @property
152      def assets(self) -> list[github.GitReleaseAsset.GitReleaseAsset]:
153          self._completeIfNotSet(self._assets)
154          return self._assets.value
155  
156      def delete_release(self) -> None:
157          """
158          :calls: `DELETE /repos/{owner}/{repo}/releases/{release_id} <https://docs.github.com/en/rest/reference/repos#delete-a-release>`_
159          """
160          headers, data = self._requester.requestJsonAndCheck("DELETE", self.url)
161  
162      def update_release(
163          self,
164          name: str,
165          message: str,
166          draft: bool = False,
167          prerelease: bool = False,
168          tag_name: Opt[str] = NotSet,
169          target_commitish: Opt[str] = NotSet,
170      ) -> GitRelease:
171          """
172          :calls: `PATCH /repos/{owner}/{repo}/releases/{release_id} <https://docs.github.com/en/rest/reference/repos#update-a-release>`_
173          """
174          assert tag_name is NotSet or isinstance(tag_name, str), "tag_name must be a str/unicode object"
175          assert target_commitish is NotSet or isinstance(
176              target_commitish, str
177          ), "target_commitish must be a str/unicode object"
178          assert isinstance(name, str), name
179          assert isinstance(message, str), message
180          assert isinstance(draft, bool), draft
181          assert isinstance(prerelease, bool), prerelease
182          if tag_name is NotSet:
183              tag_name = self.tag_name
184          post_parameters = {
185              "tag_name": tag_name,
186              "name": name,
187              "body": message,
188              "draft": draft,
189              "prerelease": prerelease,
190          }
191          # Do not set target_commitish to self.target_commitish when omitted, just don't send it
192          # altogether in that case, in order to match the Github API behaviour. Only send it when set.
193          if target_commitish is not NotSet:
194              post_parameters["target_commitish"] = target_commitish
195          headers, data = self._requester.requestJsonAndCheck("PATCH", self.url, input=post_parameters)
196          return github.GitRelease.GitRelease(self._requester, headers, data, completed=True)
197  
198      def upload_asset(
199          self, path: str, label: str = "", content_type: Opt[str] = NotSet, name: Opt[str] = NotSet
200      ) -> github.GitReleaseAsset.GitReleaseAsset:
201          """
202          :calls: `POST https://<upload_url>/repos/{owner}/{repo}/releases/{release_id}/assets <https://docs.github.com/en/rest/reference/repos#upload-a-release-asset>`_
203          """
204          assert isinstance(path, str), path
205          assert isinstance(label, str), label
206          assert name is NotSet or isinstance(name, str), name
207  
208          post_parameters: dict[str, Any] = {"label": label}
209          if name is NotSet:
210              post_parameters["name"] = basename(path)
211          else:
212              post_parameters["name"] = name
213          headers: dict[str, Any] = {}
214          if content_type is not NotSet:
215              headers["Content-Type"] = content_type
216          resp_headers, data = self._requester.requestBlobAndCheck(
217              "POST",
218              self.upload_url.split("{?")[0],
219              parameters=post_parameters,
220              headers=headers,
221              input=path,
222          )
223          return github.GitReleaseAsset.GitReleaseAsset(self._requester, resp_headers, data, completed=True)
224  
225      def upload_asset_from_memory(
226          self,
227          file_like: BinaryIO,
228          file_size: int,
229          name: str,
230          content_type: Opt[str] = NotSet,
231          label: str = "",
232      ) -> github.GitReleaseAsset.GitReleaseAsset:
233          """Uploads an asset. Unlike ``upload_asset()`` this method allows you to pass in a file-like object to upload.
234          Note that this method is more strict and requires you to specify the ``name``, since there's no file name to infer these from.
235          :calls: `POST https://<upload_url>/repos/{owner}/{repo}/releases/{release_id}/assets <https://docs.github.com/en/rest/reference/repos#upload-a-release-asset>`_
236          :param file_like: binary file-like object, such as those returned by ``open("file_name", "rb")``. At the very minimum, this object must implement ``read()``.
237          :param file_size: int, size in bytes of ``file_like``
238          """
239          assert isinstance(name, str), name
240          assert isinstance(file_size, int), file_size
241          assert isinstance(label, str), label
242  
243          post_parameters = {"label": label, "name": name}
244          content_type = content_type if content_type is not NotSet else Consts.defaultMediaType
245          headers = {"Content-Type": content_type, "Content-Length": str(file_size)}
246  
247          resp_headers, data = self._requester.requestMemoryBlobAndCheck(
248              "POST",
249              self.upload_url.split("{?")[0],
250              parameters=post_parameters,
251              headers=headers,
252              file_like=file_like,
253          )
254          return github.GitReleaseAsset.GitReleaseAsset(self._requester, resp_headers, data, completed=True)
255  
256      def get_assets(self) -> PaginatedList[github.GitReleaseAsset.GitReleaseAsset]:
257          """
258          :calls: `GET /repos/{owner}/{repo}/releases/{release_id}/assets <https://docs.github.com/en/rest/reference/repos#list-release-assets>`_
259          """
260          return github.PaginatedList.PaginatedList(
261              github.GitReleaseAsset.GitReleaseAsset,
262              self._requester,
263              f"{self.url}/assets",
264              None,
265          )
266  
267      def _useAttributes(self, attributes: dict[str, Any]) -> None:
268          if "id" in attributes:
269              self._id = self._makeIntAttribute(attributes["id"])
270          if "body" in attributes:
271              self._body = self._makeStringAttribute(attributes["body"])
272          if "name" in attributes:
273              self._title = self._makeStringAttribute(attributes["name"])
274          if "tag_name" in attributes:
275              self._tag_name = self._makeStringAttribute(attributes["tag_name"])
276          if "target_commitish" in attributes:
277              self._target_commitish = self._makeStringAttribute(attributes["target_commitish"])
278          if "draft" in attributes:
279              self._draft = self._makeBoolAttribute(attributes["draft"])
280          if "prerelease" in attributes:
281              self._prerelease = self._makeBoolAttribute(attributes["prerelease"])
282          if "generate_release_notes" in attributes:
283              self._generate_release_notes = self._makeBoolAttribute(attributes["generate_release_notes"])
284          if "author" in attributes:
285              self._author = self._makeClassAttribute(github.NamedUser.NamedUser, attributes["author"])
286          if "url" in attributes:
287              self._url = self._makeStringAttribute(attributes["url"])
288          if "upload_url" in attributes:
289              self._upload_url = self._makeStringAttribute(attributes["upload_url"])
290          if "html_url" in attributes:
291              self._html_url = self._makeStringAttribute(attributes["html_url"])
292          if "created_at" in attributes:
293              self._created_at = self._makeDatetimeAttribute(attributes["created_at"])
294          if "published_at" in attributes:
295              self._published_at = self._makeDatetimeAttribute(attributes["published_at"])
296          if "tarball_url" in attributes:
297              self._tarball_url = self._makeStringAttribute(attributes["tarball_url"])
298          if "zipball_url" in attributes:
299              self._zipball_url = self._makeStringAttribute(attributes["zipball_url"])
300          if "assets" in attributes:
301              self._assets = self._makeListOfClassesAttribute(
302                  github.GitReleaseAsset.GitReleaseAsset, attributes["assets"]
303              )