diff options
Diffstat (limited to 'gitlab')
| -rw-r--r-- | gitlab/base.py | 2 | ||||
| -rw-r--r-- | gitlab/cli.py | 14 | ||||
| -rw-r--r-- | gitlab/const.py | 17 | ||||
| -rw-r--r-- | gitlab/tests/objects/test_bridges.py | 111 | ||||
| -rw-r--r-- | gitlab/tests/test_base.py | 7 | ||||
| -rw-r--r-- | gitlab/v4/cli.py | 8 | ||||
| -rw-r--r-- | gitlab/v4/objects/__init__.py | 36 |
7 files changed, 182 insertions, 13 deletions
diff --git a/gitlab/base.py b/gitlab/base.py index 40bc06c..ad35339 100644 --- a/gitlab/base.py +++ b/gitlab/base.py @@ -131,7 +131,7 @@ class RESTObject(object): def _update_attrs(self, new_attrs): self.__dict__["_updated_attrs"] = {} - self.__dict__["_attrs"].update(new_attrs) + self.__dict__["_attrs"] = new_attrs def get_id(self): """Returns the id of the resource.""" diff --git a/gitlab/cli.py b/gitlab/cli.py index d356d16..ff98a4f 100644 --- a/gitlab/cli.py +++ b/gitlab/cli.py @@ -149,6 +149,20 @@ def _parse_value(v): return v +def docs(): + """ + Provide a statically generated parser for sphinx only, so we don't need + to provide dummy gitlab config for readthedocs. + """ + if "sphinx" not in sys.modules: + sys.exit("Docs parser is only intended for build_sphinx") + + parser = _get_base_parser(add_help=False) + cli_module = importlib.import_module("gitlab.v4.cli") + + return _get_parser(cli_module) + + def main(): if "--version" in sys.argv: print(gitlab.__version__) diff --git a/gitlab/const.py b/gitlab/const.py index 7791a39..0d2f421 100644 --- a/gitlab/const.py +++ b/gitlab/const.py @@ -33,3 +33,20 @@ NOTIFICATION_LEVEL_WATCH = "watch" NOTIFICATION_LEVEL_GLOBAL = "global" NOTIFICATION_LEVEL_MENTION = "mention" NOTIFICATION_LEVEL_CUSTOM = "custom" + +# Search scopes +# all scopes (global, group and project) +SEARCH_SCOPE_PROJECTS = "projects" +SEARCH_SCOPE_ISSUES = "issues" +SEARCH_SCOPE_MERGE_REQUESTS = "merge_requests" +SEARCH_SCOPE_MILESTONES = "milestones" +SEARCH_SCOPE_WIKI_BLOBS = "wiki_blobs" +SEARCH_SCOPE_COMMITS = "commits" +SEARCH_SCOPE_BLOBS = "blobs" +SEARCH_SCOPE_USERS = "users" + +# specific global scope +SEARCH_SCOPE_GLOBAL_SNIPPET_TITLES = "snippet_titles" + +# specific project scope +SEARCH_SCOPE_PROJECT_NOTES = "notes" diff --git a/gitlab/tests/objects/test_bridges.py b/gitlab/tests/objects/test_bridges.py new file mode 100644 index 0000000..ea8c634 --- /dev/null +++ b/gitlab/tests/objects/test_bridges.py @@ -0,0 +1,111 @@ +""" +GitLab API: https://docs.gitlab.com/ee/api/jobs.html#list-pipeline-bridges +""" +import re + +import pytest +import responses + +from gitlab.v4.objects import Project, ProjectPipelineBridge + + +@pytest.fixture +def resp_list_bridges(): + export_bridges_content = { + "commit": { + "author_email": "admin@example.com", + "author_name": "Administrator", + "created_at": "2015-12-24T16:51:14.000+01:00", + "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", + "message": "Test the CI integration.", + "short_id": "0ff3ae19", + "title": "Test the CI integration.", + }, + "allow_failure": False, + "created_at": "2015-12-24T15:51:21.802Z", + "started_at": "2015-12-24T17:54:27.722Z", + "finished_at": "2015-12-24T17:58:27.895Z", + "duration": 240, + "id": 7, + "name": "teaspoon", + "pipeline": { + "id": 6, + "ref": "master", + "sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", + "status": "pending", + "created_at": "2015-12-24T15:50:16.123Z", + "updated_at": "2015-12-24T18:00:44.432Z", + "web_url": "https://example.com/foo/bar/pipelines/6", + }, + "ref": "master", + "stage": "test", + "status": "pending", + "tag": False, + "web_url": "https://example.com/foo/bar/-/jobs/7", + "user": { + "id": 1, + "name": "Administrator", + "username": "root", + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "web_url": "http://gitlab.dev/root", + "created_at": "2015-12-21T13:14:24.077Z", + "public_email": "", + "skype": "", + "linkedin": "", + "twitter": "", + "website_url": "", + "organization": "", + }, + "downstream_pipeline": { + "id": 5, + "sha": "f62a4b2fb89754372a346f24659212eb8da13601", + "ref": "master", + "status": "pending", + "created_at": "2015-12-24T17:54:27.722Z", + "updated_at": "2015-12-24T17:58:27.896Z", + "web_url": "https://example.com/diaspora/diaspora-client/pipelines/5", + }, + } + + export_pipelines_content = [ + { + "id": 6, + "status": "pending", + "ref": "new-pipeline", + "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", + "web_url": "https://example.com/foo/bar/pipelines/47", + "created_at": "2016-08-11T11:28:34.085Z", + "updated_at": "2016-08-11T11:32:35.169Z", + }, + ] + + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/projects/1/pipelines/6/bridges", + json=[export_bridges_content], + content_type="application/json", + status=200, + ) + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/projects/1/pipelines", + json=export_pipelines_content, + content_type="application/json", + status=200, + ) + yield rsps + + +def test_list_projects_pipelines_bridges(project, resp_list_bridges): + pipeline = project.pipelines.list()[0] + bridges = pipeline.bridges.list() + + assert isinstance(bridges, list) + assert isinstance(bridges[0], ProjectPipelineBridge) + assert bridges[0].downstream_pipeline["id"] == 5 + assert ( + bridges[0].downstream_pipeline["sha"] + == "f62a4b2fb89754372a346f24659212eb8da13601" + ) diff --git a/gitlab/tests/test_base.py b/gitlab/tests/test_base.py index 58c0d47..a0adcb0 100644 --- a/gitlab/tests/test_base.py +++ b/gitlab/tests/test_base.py @@ -128,6 +128,13 @@ class TestRESTObject: assert {"foo": "foo", "bar": "bar"} == obj._attrs assert {} == obj._updated_attrs + def test_update_attrs_deleted(self, fake_manager): + obj = FakeObject(fake_manager, {"foo": "foo", "bar": "bar"}) + obj.bar = "baz" + obj._update_attrs({"foo": "foo"}) + assert {"foo": "foo"} == obj._attrs + assert {} == obj._updated_attrs + def test_create_managers(self, fake_gitlab, fake_manager): class ObjectWithManager(FakeObject): _managers = (("fakes", "FakeManager"),) diff --git a/gitlab/v4/cli.py b/gitlab/v4/cli.py index 51416f1..6172f93 100644 --- a/gitlab/v4/cli.py +++ b/gitlab/v4/cli.py @@ -85,11 +85,7 @@ class GitlabCLI(object): try: project = self.gl.projects.get(int(self.args["project_id"]), lazy=True) data = project.exports.get().download() - if hasattr(sys.stdout, "buffer"): - # python3 - sys.stdout.buffer.write(data) - else: - sys.stdout.write(data) + sys.stdout.buffer.write(data) except Exception as e: cli.die("Impossible to download the export", e) @@ -440,5 +436,7 @@ def run(gl, what, action, args, verbose, output, fields): printer.display(get_dict(data, fields), verbose=verbose, obj=data) elif isinstance(data, str): print(data) + elif isinstance(data, bytes): + sys.stdout.buffer.write(data) elif hasattr(data, "decode"): print(data.decode()) diff --git a/gitlab/v4/objects/__init__.py b/gitlab/v4/objects/__init__.py index 80b3c21..edeff04 100644 --- a/gitlab/v4/objects/__init__.py +++ b/gitlab/v4/objects/__init__.py @@ -3859,6 +3859,17 @@ class ProjectPipelineJobManager(ListMixin, RESTManager): _list_filters = ("scope",) +class ProjectPipelineBridge(RESTObject): + pass + + +class ProjectPipelineBridgeManager(ListMixin, RESTManager): + _path = "/projects/%(project_id)s/pipelines/%(pipeline_id)s/bridges" + _obj_cls = ProjectPipelineBridge + _from_parent_attrs = {"project_id": "project_id", "pipeline_id": "id"} + _list_filters = ("scope",) + + class ProjectPipelineVariable(RESTObject): _id_attr = "key" @@ -3872,6 +3883,7 @@ class ProjectPipelineVariableManager(ListMixin, RESTManager): class ProjectPipeline(RESTObject, RefreshMixin, ObjectDeleteMixin): _managers = ( ("jobs", "ProjectPipelineJobManager"), + ("bridges", "ProjectPipelineBridgeManager"), ("variables", "ProjectPipelineVariableManager"), ) @@ -5422,19 +5434,29 @@ class ProjectManager(CRUDMixin, RESTManager): ) _types = {"avatar": types.ImageAttribute} _list_filters = ( - "search", - "owned", - "starred", "archived", - "visibility", + "id_after", + "id_before", + "last_activity_after", + "last_activity_before", + "membership", + "min_access_level", "order_by", - "sort", + "owned", + "repository_checksum_failed", + "repository_storage", + "search_namespaces", + "search", "simple", - "membership", + "sort", + "starred", "statistics", + "visibility", + "wiki_checksum_failed", + "with_custom_attributes", "with_issues_enabled", "with_merge_requests_enabled", - "with_custom_attributes", + "with_programming_language", ) def import_project( |
