@cli.register_custom_action('<STR_LIT>', ('<STR_LIT:filename>', '<STR_LIT>'))<EOL><INDENT>@exc.on_http_error(exc.GitlabUploadError)<EOL>def upload(self, filename, filedata=None, filepath=None, **kwargs):<DEDENT>
if filepath is None and filedata is None:<EOL><INDENT>raise GitlabUploadError("<STR_LIT>")<EOL><DEDENT>if filedata is not None and filepath is not None:<EOL><INDENT>raise GitlabUploadError("<STR_LIT>")<EOL><DEDENT>if filepath is not None:<EOL><INDENT>with open(filepath, "<STR_LIT:rb>") as f:<EOL><INDENT>filedata = f.read()<EOL><DEDENT><DEDENT>url = ('<STR_LIT>' % {<EOL>'<STR_LIT:id>': self.id,<EOL>})<EOL>file_info = {<EOL>'<STR_LIT:file>': (filename, filedata),<EOL>}<EOL>data = self.manager.gitlab.http_post(url, files=file_info)<EOL>return {<EOL>"<STR_LIT>": data['<STR_LIT>'],<EOL>"<STR_LIT:url>": data['<STR_LIT:url>'],<EOL>"<STR_LIT>": data['<STR_LIT>']<EOL>}<EOL>
Upload the specified file into the project.

        .. 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