diff --git a/gitlab/mixins.py b/gitlab/mixins.py index 9c00c324d..c2ba6d096 100644 --- a/gitlab/mixins.py +++ b/gitlab/mixins.py @@ -382,9 +382,12 @@ def save(self, **kwargs): # call the manager obj_id = self.get_id() + if isinstance(obj_id, (str)): + obj_id = obj_id.replace('/', '%2F') server_data = self.manager.update(obj_id, updated_data, **kwargs) if server_data is not None: self._update_attrs(server_data) + return server_data class ObjectDeleteMixin(object): diff --git a/gitlab/v4/objects.py b/gitlab/v4/objects.py index f6c09d9f2..b658b43c2 100644 --- a/gitlab/v4/objects.py +++ b/gitlab/v4/objects.py @@ -4937,7 +4937,53 @@ def upload(self, filename, filedata=None, filepath=None, **kwargs): data = self.manager.gitlab.http_post(url, files=file_info) return {"alt": data["alt"], "url": data["url"], "markdown": data["markdown"]} + + # see #56 - add file attachment features + @cli.register_custom_action("Project", ("filename", "filepath")) + @exc.on_http_error(exc.GitlabUploadError) + def wikiattachment(self, filename, filedata=None, filepath=None, **kwargs): + """Upload the specified file into the project Wiki. + https://docs.gitlab.com/ee/api/wikis.html#upload-an-attachment-to-the-wiki-repository + + .. note:: + + Either ``filedata`` or ``filepath`` *MUST* be specified. + + Args: + filename (str): The name of the file being uploaded + filedata (bytes): The raw data of the file being uploaded + filepath (str): The path to a local file to upload (optional) + + Raises: + GitlabConnectionError: If the server cannot be reached + GitlabUploadError: If the file upload fails + GitlabUploadError: If ``filedata`` and ``filepath`` are not + specified + GitlabUploadError: If both ``filedata`` and ``filepath`` are + specified + + Returns: + dict: A ``dict`` with the keys: + * ``alt`` - The alternate text for the upload + * ``url`` - The direct url to the uploaded file + * ``markdown`` - Markdown for the uploaded file + """ + if filepath is None and filedata is None: + raise GitlabUploadError("No file contents or path specified") + + if filedata is not None and filepath is not None: + raise GitlabUploadError("File contents and file path specified") + + if filepath is not None: + with open(filepath, "rb") as f: + filedata = f.read() + + url = "/projects/%(id)s/wikis/attachments" % {"id": self.id} + file_info = {"file": (filename, filedata)} + data = self.manager.gitlab.http_post(url, files=file_info) + return data + @cli.register_custom_action("Project", optional=("wiki",)) @exc.on_http_error(exc.GitlabGetError) def snapshot(