Skip to content

Commit

Permalink
Merge pull request #1694 from python-gitlab/jlvillal/const_explicit
Browse files Browse the repository at this point in the history
refactor: explicitly import gitlab.const values into top-level namespace
  • Loading branch information
nejch committed Dec 1, 2021
2 parents 09a973e + b3b0b5f commit e6582a3
Show file tree
Hide file tree
Showing 14 changed files with 140 additions and 73 deletions.
12 changes: 6 additions & 6 deletions docs/gl_objects/access_requests.rst
Expand Up @@ -7,11 +7,11 @@ Users can request access to groups and projects.
When access is granted the user should be given a numerical access level. The
following constants are provided to represent the access levels:

* ``gitlab.GUEST_ACCESS``: ``10``
* ``gitlab.REPORTER_ACCESS``: ``20``
* ``gitlab.DEVELOPER_ACCESS``: ``30``
* ``gitlab.MAINTAINER_ACCESS``: ``40``
* ``gitlab.OWNER_ACCESS``: ``50``
* ``gitlab.const.GUEST_ACCESS``: ``10``
* ``gitlab.const.REPORTER_ACCESS``: ``20``
* ``gitlab.const.DEVELOPER_ACCESS``: ``30``
* ``gitlab.const.MAINTAINER_ACCESS``: ``40``
* ``gitlab.const.OWNER_ACCESS``: ``50``

References
----------
Expand Down Expand Up @@ -43,7 +43,7 @@ Create an access request::
Approve an access request::

ar.approve() # defaults to DEVELOPER level
ar.approve(access_level=gitlab.MAINTAINER_ACCESS) # explicitly set access level
ar.approve(access_level=gitlab.const.MAINTAINER_ACCESS) # explicitly set access level

Deny (delete) an access request::

Expand Down
18 changes: 9 additions & 9 deletions docs/gl_objects/groups.rst
Expand Up @@ -80,7 +80,7 @@ Remove a group::

Share/unshare the group with a group::

group.share(group2.id, gitlab.DEVELOPER_ACCESS)
group.share(group2.id, gitlab.const.DEVELOPER_ACCESS)
group.unshare(group2.id)

Import / Export
Expand Down Expand Up @@ -237,11 +237,11 @@ Group members

The following constants define the supported access levels:

* ``gitlab.GUEST_ACCESS = 10``
* ``gitlab.REPORTER_ACCESS = 20``
* ``gitlab.DEVELOPER_ACCESS = 30``
* ``gitlab.MAINTAINER_ACCESS = 40``
* ``gitlab.OWNER_ACCESS = 50``
* ``gitlab.const.GUEST_ACCESS = 10``
* ``gitlab.const.REPORTER_ACCESS = 20``
* ``gitlab.const.DEVELOPER_ACCESS = 30``
* ``gitlab.const.MAINTAINER_ACCESS = 40``
* ``gitlab.const.OWNER_ACCESS = 50``

Reference
---------
Expand Down Expand Up @@ -284,11 +284,11 @@ Get a member of a group, including members inherited through ancestor groups::
Add a member to the group::

member = group.members.create({'user_id': user_id,
'access_level': gitlab.GUEST_ACCESS})
'access_level': gitlab.const.GUEST_ACCESS})

Update a member (change the access level)::

member.access_level = gitlab.DEVELOPER_ACCESS
member.access_level = gitlab.const.DEVELOPER_ACCESS
member.save()

Remove a member from the group::
Expand Down Expand Up @@ -316,7 +316,7 @@ LDAP group links

Add an LDAP group link to an existing GitLab group::

group.add_ldap_group_link(ldap_group_cn, gitlab.DEVELOPER_ACCESS, 'ldapmain')
group.add_ldap_group_link(ldap_group_cn, gitlab.const.DEVELOPER_ACCESS, 'ldapmain')

Remove a link::

Expand Down
16 changes: 8 additions & 8 deletions docs/gl_objects/notifications.rst
Expand Up @@ -5,12 +5,12 @@ Notification settings
You can define notification settings globally, for groups and for projects.
Valid levels are defined as constants:

* ``gitlab.NOTIFICATION_LEVEL_DISABLED``
* ``gitlab.NOTIFICATION_LEVEL_PARTICIPATING``
* ``gitlab.NOTIFICATION_LEVEL_WATCH``
* ``gitlab.NOTIFICATION_LEVEL_GLOBAL``
* ``gitlab.NOTIFICATION_LEVEL_MENTION``
* ``gitlab.NOTIFICATION_LEVEL_CUSTOM``
* ``gitlab.const.NOTIFICATION_LEVEL_DISABLED``
* ``gitlab.const.NOTIFICATION_LEVEL_PARTICIPATING``
* ``gitlab.const.NOTIFICATION_LEVEL_WATCH``
* ``gitlab.const.NOTIFICATION_LEVEL_GLOBAL``
* ``gitlab.const.NOTIFICATION_LEVEL_MENTION``
* ``gitlab.const.NOTIFICATION_LEVEL_CUSTOM``

You get access to fine-grained settings if you use the
``NOTIFICATION_LEVEL_CUSTOM`` level.
Expand Down Expand Up @@ -47,10 +47,10 @@ Get the notifications settings::
Update the notifications settings::

# use a predefined level
settings.level = gitlab.NOTIFICATION_LEVEL_WATCH
settings.level = gitlab.const.NOTIFICATION_LEVEL_WATCH

# create a custom setup
settings.level = gitlab.NOTIFICATION_LEVEL_CUSTOM
settings.level = gitlab.const.NOTIFICATION_LEVEL_CUSTOM
settings.save() # will create additional attributes, but not mandatory

settings.new_merge_request = True
Expand Down
14 changes: 7 additions & 7 deletions docs/gl_objects/projects.rst
Expand Up @@ -439,9 +439,9 @@ Project snippets

The snippet visibility can be defined using the following constants:

* ``gitlab.VISIBILITY_PRIVATE``
* ``gitlab.VISIBILITY_INTERNAL``
* ``gitlab.VISIBILITY_PUBLIC``
* ``gitlab.const.VISIBILITY_PRIVATE``
* ``gitlab.const.VISIBILITY_INTERNAL``
* ``gitlab.const.VISIBILITY_PUBLIC``

Reference
---------
Expand Down Expand Up @@ -480,7 +480,7 @@ Create a snippet::
'file_name': 'foo.py',
'code': 'import gitlab',
'visibility_level':
gitlab.VISIBILITY_PRIVATE})
gitlab.const.VISIBILITY_PRIVATE})

Update a snippet::

Expand Down Expand Up @@ -546,11 +546,11 @@ Get a member of a project, including members inherited through ancestor groups::
Add a project member::

member = project.members.create({'user_id': user.id, 'access_level':
gitlab.DEVELOPER_ACCESS})
gitlab.const.DEVELOPER_ACCESS})

Modify a project member (change the access level)::

member.access_level = gitlab.MAINTAINER_ACCESS
member.access_level = gitlab.const.MAINTAINER_ACCESS
member.save()

Remove a member from the project team::
Expand All @@ -561,7 +561,7 @@ Remove a member from the project team::

Share/unshare the project with a group::

project.share(group.id, gitlab.DEVELOPER_ACCESS)
project.share(group.id, gitlab.const.DEVELOPER_ACCESS)
project.unshare(group.id)

Project hooks
Expand Down
6 changes: 3 additions & 3 deletions docs/gl_objects/protected_branches.rst
Expand Up @@ -31,8 +31,8 @@ Create a protected branch::

p_branch = project.protectedbranches.create({
'name': '*-stable',
'merge_access_level': gitlab.DEVELOPER_ACCESS,
'push_access_level': gitlab.MAINTAINER_ACCESS
'merge_access_level': gitlab.const.DEVELOPER_ACCESS,
'push_access_level': gitlab.const.MAINTAINER_ACCESS
})

Create a protected branch with more granular access control::
Expand All @@ -41,7 +41,7 @@ Create a protected branch with more granular access control::
'name': '*-stable',
'allowed_to_push': [{"user_id": 99}, {"user_id": 98}],
'allowed_to_merge': [{"group_id": 653}],
'allowed_to_unprotect': [{"access_level": gitlab.MAINTAINER_ACCESS}]
'allowed_to_unprotect': [{"access_level": gitlab.const.MAINTAINER_ACCESS}]
})

Delete a protected branch::
Expand Down
32 changes: 16 additions & 16 deletions docs/gl_objects/search.rst
Expand Up @@ -9,24 +9,24 @@ string. The following constants are provided to represent the possible scopes:

* Shared scopes (global, group and project):

+ ``gitlab.SEARCH_SCOPE_PROJECTS``: ``projects``
+ ``gitlab.SEARCH_SCOPE_ISSUES``: ``issues``
+ ``gitlab.SEARCH_SCOPE_MERGE_REQUESTS``: ``merge_requests``
+ ``gitlab.SEARCH_SCOPE_MILESTONES``: ``milestones``
+ ``gitlab.SEARCH_SCOPE_WIKI_BLOBS``: ``wiki_blobs``
+ ``gitlab.SEARCH_SCOPE_COMMITS``: ``commits``
+ ``gitlab.SEARCH_SCOPE_BLOBS``: ``blobs``
+ ``gitlab.SEARCH_SCOPE_USERS``: ``users``
+ ``gitlab.const.SEARCH_SCOPE_PROJECTS``: ``projects``
+ ``gitlab.const.SEARCH_SCOPE_ISSUES``: ``issues``
+ ``gitlab.const.SEARCH_SCOPE_MERGE_REQUESTS``: ``merge_requests``
+ ``gitlab.const.SEARCH_SCOPE_MILESTONES``: ``milestones``
+ ``gitlab.const.SEARCH_SCOPE_WIKI_BLOBS``: ``wiki_blobs``
+ ``gitlab.const.SEARCH_SCOPE_COMMITS``: ``commits``
+ ``gitlab.const.SEARCH_SCOPE_BLOBS``: ``blobs``
+ ``gitlab.const.SEARCH_SCOPE_USERS``: ``users``


* specific global scope:

+ ``gitlab.SEARCH_SCOPE_GLOBAL_SNIPPET_TITLES``: ``snippet_titles``
+ ``gitlab.const.SEARCH_SCOPE_GLOBAL_SNIPPET_TITLES``: ``snippet_titles``


* specific project scope:

+ ``gitlab.SEARCH_SCOPE_PROJECT_NOTES``: ``notes``
+ ``gitlab.const.SEARCH_SCOPE_PROJECT_NOTES``: ``notes``


Reference
Expand All @@ -46,30 +46,30 @@ Examples
Search for issues matching a specific string::

# global search
gl.search(gitlab.SEARCH_SCOPE_ISSUES, 'regression')
gl.search(gitlab.const.SEARCH_SCOPE_ISSUES, 'regression')

# group search
group = gl.groups.get('mygroup')
group.search(gitlab.SEARCH_SCOPE_ISSUES, 'regression')
group.search(gitlab.const.SEARCH_SCOPE_ISSUES, 'regression')

# project search
project = gl.projects.get('myproject')
project.search(gitlab.SEARCH_SCOPE_ISSUES, 'regression')
project.search(gitlab.const.SEARCH_SCOPE_ISSUES, 'regression')

The ``search()`` methods implement the pagination support::

# get lists of 10 items, and start at page 2
gl.search(gitlab.SEARCH_SCOPE_ISSUES, search_str, page=2, per_page=10)
gl.search(gitlab.const.SEARCH_SCOPE_ISSUES, search_str, page=2, per_page=10)

# get a generator that will automatically make required API calls for
# pagination
for item in gl.search(gitlab.SEARCH_SCOPE_ISSUES, search_str, as_list=False):
for item in gl.search(gitlab.const.SEARCH_SCOPE_ISSUES, search_str, as_list=False):
do_something(item)

The search API doesn't return objects, but dicts. If you need to act on
objects, you need to create them explicitly::

for item in gl.search(gitlab.SEARCH_SCOPE_ISSUES, search_str, as_list=False):
for item in gl.search(gitlab.const.SEARCH_SCOPE_ISSUES, search_str, as_list=False):
issue_project = gl.projects.get(item['project_id'], lazy=True)
issue = issue_project.issues.get(item['iid'])
issue.state = 'closed'
Expand Down
2 changes: 1 addition & 1 deletion docs/gl_objects/snippets.rst
Expand Up @@ -44,7 +44,7 @@ Create a snippet::

Update the snippet attributes::

snippet.visibility_level = gitlab.VISIBILITY_PUBLIC
snippet.visibility_level = gitlab.const.VISIBILITY_PUBLIC
snippet.save()

To update a snippet code you need to create a ``ProjectSnippet`` object::
Expand Down
18 changes: 17 additions & 1 deletion gitlab/__init__.py
Expand Up @@ -17,6 +17,7 @@
"""Wrapper for the GitLab API."""

import warnings
from typing import Any

import gitlab.config # noqa: F401
from gitlab.__version__ import ( # noqa: F401
Expand All @@ -28,7 +29,22 @@
__version__,
)
from gitlab.client import Gitlab, GitlabList # noqa: F401
from gitlab.const import * # noqa: F401,F403
from gitlab.exceptions import * # noqa: F401,F403

warnings.filterwarnings("default", category=DeprecationWarning, module="^gitlab")


# NOTE(jlvillal): We are deprecating access to the gitlab.const values which
# were previously imported into this namespace by the
# 'from gitlab.const import *' statement.
def __getattr__(name: str) -> Any:
# Deprecate direct access to constants without namespace
if name in gitlab.const._DEPRECATED:
warnings.warn(
f"\nDirect access to 'gitlab.{name}' is deprecated and will be "
f"removed in a future major python-gitlab release. Please "
f"use 'gitlab.const.{name}' instead.",
DeprecationWarning,
)
return getattr(gitlab.const, name)
raise AttributeError(f"module {__name__} has no attribute {name}")
35 changes: 35 additions & 0 deletions gitlab/const.py
Expand Up @@ -17,6 +17,41 @@

from gitlab.__version__ import __title__, __version__

# NOTE(jlvillal): '_DEPRECATED' only affects users accessing constants via the
# top-level gitlab.* namespace. See 'gitlab/__init__.py:__getattr__()' for the
# consumer of '_DEPRECATED' For example 'x = gitlab.NO_ACCESS'. We want users
# to instead use constants by doing code like: gitlab.const.NO_ACCESS.
_DEPRECATED = [
"DEFAULT_URL",
"DEVELOPER_ACCESS",
"GUEST_ACCESS",
"MAINTAINER_ACCESS",
"MINIMAL_ACCESS",
"NO_ACCESS",
"NOTIFICATION_LEVEL_CUSTOM",
"NOTIFICATION_LEVEL_DISABLED",
"NOTIFICATION_LEVEL_GLOBAL",
"NOTIFICATION_LEVEL_MENTION",
"NOTIFICATION_LEVEL_PARTICIPATING",
"NOTIFICATION_LEVEL_WATCH",
"OWNER_ACCESS",
"REPORTER_ACCESS",
"SEARCH_SCOPE_BLOBS",
"SEARCH_SCOPE_COMMITS",
"SEARCH_SCOPE_GLOBAL_SNIPPET_TITLES",
"SEARCH_SCOPE_ISSUES",
"SEARCH_SCOPE_MERGE_REQUESTS",
"SEARCH_SCOPE_MILESTONES",
"SEARCH_SCOPE_PROJECT_NOTES",
"SEARCH_SCOPE_PROJECTS",
"SEARCH_SCOPE_USERS",
"SEARCH_SCOPE_WIKI_BLOBS",
"USER_AGENT",
"VISIBILITY_INTERNAL",
"VISIBILITY_PRIVATE",
"VISIBILITY_PUBLIC",
]

DEFAULT_URL: str = "https://gitlab.com"

NO_ACCESS: int = 0
Expand Down
2 changes: 1 addition & 1 deletion gitlab/mixins.py
Expand Up @@ -618,7 +618,7 @@ class AccessRequestMixin(_RestObjectBase):
)
@exc.on_http_error(exc.GitlabUpdateError)
def approve(
self, access_level: int = gitlab.DEVELOPER_ACCESS, **kwargs: Any
self, access_level: int = gitlab.const.DEVELOPER_ACCESS, **kwargs: Any
) -> None:
"""Approve an access request.
Expand Down
4 changes: 2 additions & 2 deletions tests/functional/api/test_gitlab.py
Expand Up @@ -118,11 +118,11 @@ def test_namespaces(gl):

def test_notification_settings(gl):
settings = gl.notificationsettings.get()
settings.level = gitlab.NOTIFICATION_LEVEL_WATCH
settings.level = gitlab.const.NOTIFICATION_LEVEL_WATCH
settings.save()

settings = gl.notificationsettings.get()
assert settings.level == gitlab.NOTIFICATION_LEVEL_WATCH
assert settings.level == gitlab.const.NOTIFICATION_LEVEL_WATCH


def test_user_activities(gl):
Expand Down
2 changes: 1 addition & 1 deletion tests/functional/api/test_snippets.py
Expand Up @@ -33,7 +33,7 @@ def test_project_snippets(project):
"title": "snip1",
"file_name": "foo.py",
"content": "initial content",
"visibility": gitlab.VISIBILITY_PRIVATE,
"visibility": gitlab.const.VISIBILITY_PRIVATE,
}
)

Expand Down
5 changes: 3 additions & 2 deletions tests/unit/test_config.py
Expand Up @@ -22,7 +22,8 @@

import pytest

from gitlab import config, USER_AGENT
import gitlab
from gitlab import config

custom_user_agent = "my-package/1.0.0"

Expand Down Expand Up @@ -252,7 +253,7 @@ def test_data_from_helper(m_open, path_exists, tmp_path):
@pytest.mark.parametrize(
"config_string,expected_agent",
[
(valid_config, USER_AGENT),
(valid_config, gitlab.const.USER_AGENT),
(custom_user_agent_config, custom_user_agent),
],
)
Expand Down

0 comments on commit e6582a3

Please sign in to comment.