|
| 1 | +""" |
| 2 | +GitLab API: |
| 3 | +https://docs.gitlab.com/ee/api/secure_files.html |
| 4 | +""" |
| 5 | +from typing import Any, Callable, cast, Iterator, Optional, TYPE_CHECKING, Union |
| 6 | + |
| 7 | +import requests |
| 8 | + |
| 9 | +from gitlab import cli |
| 10 | +from gitlab import exceptions as exc |
| 11 | +from gitlab import utils |
| 12 | +from gitlab.base import RESTManager, RESTObject |
| 13 | +from gitlab.mixins import NoUpdateMixin, ObjectDeleteMixin |
| 14 | +from gitlab.types import FileAttribute, RequiredOptional |
| 15 | + |
| 16 | +__all__ = ["SecureFile", "SecureFileManager"] |
| 17 | + |
| 18 | + |
| 19 | +class SecureFile(ObjectDeleteMixin, RESTObject): |
| 20 | + @cli.register_custom_action("SecureFile") |
| 21 | + @exc.on_http_error(exc.GitlabGetError) |
| 22 | + def download( |
| 23 | + self, |
| 24 | + streamed: bool = False, |
| 25 | + action: Optional[Callable[[bytes], None]] = None, |
| 26 | + chunk_size: int = 1024, |
| 27 | + *, |
| 28 | + iterator: bool = False, |
| 29 | + **kwargs: Any, |
| 30 | + ) -> Optional[Union[bytes, Iterator[Any]]]: |
| 31 | + """Download the secure file. |
| 32 | +
|
| 33 | + Args: |
| 34 | + streamed: If True the data will be processed by chunks of |
| 35 | + `chunk_size` and each chunk is passed to `action` for |
| 36 | + treatment |
| 37 | + iterator: If True directly return the underlying response |
| 38 | + iterator |
| 39 | + action: Callable responsible of dealing with chunk of |
| 40 | + data |
| 41 | + chunk_size: Size of each chunk |
| 42 | + **kwargs: Extra options to send to the server (e.g. sudo) |
| 43 | +
|
| 44 | + Raises: |
| 45 | + GitlabAuthenticationError: If authentication is not correct |
| 46 | + GitlabGetError: If the artifacts could not be retrieved |
| 47 | +
|
| 48 | + Returns: |
| 49 | + The artifacts if `streamed` is False, None otherwise.""" |
| 50 | + path = f"{self.manager.path}/{self.id}/download" |
| 51 | + result = self.manager.gitlab.http_get( |
| 52 | + path, streamed=streamed, raw=True, **kwargs |
| 53 | + ) |
| 54 | + if TYPE_CHECKING: |
| 55 | + assert isinstance(result, requests.Response) |
| 56 | + return utils.response_content( |
| 57 | + result, streamed, action, chunk_size, iterator=iterator |
| 58 | + ) |
| 59 | + |
| 60 | + |
| 61 | +class SecureFileManager(NoUpdateMixin, RESTManager): |
| 62 | + _path = "/projects/{project_id}/secure_files" |
| 63 | + _obj_cls = SecureFile |
| 64 | + _from_parent_attrs = {"project_id": "id"} |
| 65 | + _create_attrs = RequiredOptional(required=("name", "file")) |
| 66 | + _types = {"file": FileAttribute} |
| 67 | + |
| 68 | + def get(self, id: Union[str, int], lazy: bool = False, **kwargs: Any) -> SecureFile: |
| 69 | + return cast(SecureFile, super().get(id=id, lazy=lazy, **kwargs)) |
0 commit comments