From 4bb201b92ef0dcc14a7a9c83e5600ba5b118fc33 Mon Sep 17 00:00:00 2001 From: Nejc Habjan Date: Sun, 31 Jan 2021 11:10:41 +0100 Subject: [PATCH 1/3] feat(api,cli): make user agent configurable --- gitlab/__init__.py | 19 +++++++++++-------- gitlab/__version__.py | 6 ++++++ gitlab/config.py | 12 ++++++++++++ gitlab/const.py | 5 +++++ setup.py | 2 +- 5 files changed, 35 insertions(+), 9 deletions(-) create mode 100644 gitlab/__version__.py diff --git a/gitlab/__init__.py b/gitlab/__init__.py index 98c41443e..5cdcef278 100644 --- a/gitlab/__init__.py +++ b/gitlab/__init__.py @@ -24,19 +24,20 @@ import requests.utils import gitlab.config +from gitlab.__version__ import ( + __author__, + __copyright__, + __email__, + __license__, + __title__, + __version__, +) from gitlab.const import * # noqa from gitlab.exceptions import * # noqa from gitlab import utils # noqa from requests_toolbelt.multipart.encoder import MultipartEncoder -__title__ = "python-gitlab" -__version__ = "2.6.0" -__author__ = "Gauvain Pocentek" -__email__ = "gauvainpocentek@gmail.com" -__license__ = "LGPL3" -__copyright__ = "Copyright 2013-2019 Gauvain Pocentek" - warnings.filterwarnings("default", category=DeprecationWarning, module="^gitlab") REDIRECT_MSG = ( @@ -81,6 +82,7 @@ def __init__( per_page=None, pagination=None, order_by=None, + user_agent=USER_AGENT, ): self._api_version = str(api_version) @@ -90,7 +92,7 @@ def __init__( #: Timeout to use for requests to gitlab server self.timeout = timeout #: Headers that will be used in request to GitLab - self.headers = {"User-Agent": "%s/%s" % (__title__, __version__)} + self.headers = {"User-Agent": user_agent} #: Whether SSL certificates should be validated self.ssl_verify = ssl_verify @@ -204,6 +206,7 @@ def from_config(cls, gitlab_id=None, config_files=None): per_page=config.per_page, pagination=config.pagination, order_by=config.order_by, + user_agent=config.user_agent, ) def auth(self): diff --git a/gitlab/__version__.py b/gitlab/__version__.py new file mode 100644 index 000000000..17082336d --- /dev/null +++ b/gitlab/__version__.py @@ -0,0 +1,6 @@ +__author__ = "Gauvain Pocentek, python-gitlab team" +__copyright__ = "Copyright 2013-2019 Gauvain Pocentek, 2019-2021 python-gitlab team" +__email__ = "gauvainpocentek@gmail.com" +__license__ = "LGPL3" +__title__ = "python-gitlab" +__version__ = "2.6.0" diff --git a/gitlab/config.py b/gitlab/config.py index c8ba89619..4647d615a 100644 --- a/gitlab/config.py +++ b/gitlab/config.py @@ -18,6 +18,8 @@ import os import configparser +from gitlab.const import USER_AGENT + def _env_config(): if "PYTHON_GITLAB_CFG" in os.environ: @@ -177,3 +179,13 @@ def __init__(self, gitlab_id=None, config_files=None): self.order_by = self._config.get(self.gitlab_id, "order_by") except Exception: pass + + self.user_agent = USER_AGENT + try: + self.user_agent = self._config.get("global", "user_agent") + except Exception: + pass + try: + self.user_agent = self._config.get(self.gitlab_id, "user_agent") + except Exception: + pass diff --git a/gitlab/const.py b/gitlab/const.py index bdd3d7387..36e3c1a76 100644 --- a/gitlab/const.py +++ b/gitlab/const.py @@ -15,6 +15,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . +from gitlab.__version__ import __title__, __version__ + + NO_ACCESS = 0 MINIMAL_ACCESS = 5 GUEST_ACCESS = 10 @@ -51,3 +54,5 @@ # specific project scope SEARCH_SCOPE_PROJECT_NOTES = "notes" + +USER_AGENT = "{}/{}".format(__title__, __version__) diff --git a/setup.py b/setup.py index 816d36354..95390a6ca 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ def get_version(): - with open("gitlab/__init__.py") as f: + with open("gitlab/__version__.py") as f: for line in f: if line.startswith("__version__"): return eval(line.split("=")[-1]) From c5a37e7e37a62372c250dfc8c0799e847eecbc30 Mon Sep 17 00:00:00 2001 From: Nejc Habjan Date: Sun, 31 Jan 2021 17:58:20 +0100 Subject: [PATCH 2/3] test(api,cli): add tests for custom user agent --- gitlab/tests/test_config.py | 33 ++++++++++++++++++++++++++++++++- gitlab/tests/test_gitlab.py | 15 ++++++++++++++- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/gitlab/tests/test_config.py b/gitlab/tests/test_config.py index 7fb03e00d..7a9e23954 100644 --- a/gitlab/tests/test_config.py +++ b/gitlab/tests/test_config.py @@ -21,10 +21,12 @@ import mock import io -from gitlab import config +from gitlab import config, USER_AGENT import pytest +custom_user_agent = "my-package/1.0.0" + valid_config = u"""[global] default = one ssl_verify = true @@ -51,6 +53,17 @@ oauth_token = STUV """ +custom_user_agent_config = """[global] +default = one +user_agent = {} + +[one] +url = http://one.url +private_token = ABCDEF +""".format( + custom_user_agent +) + no_default_config = u"""[global] [there] url = http://there.url @@ -178,3 +191,21 @@ def test_valid_data(m_open, path_exists): assert "STUV" == cp.oauth_token assert 2 == cp.timeout assert True == cp.ssl_verify + + +@mock.patch("os.path.exists") +@mock.patch("builtins.open") +@pytest.mark.parametrize( + "config_string,expected_agent", + [ + (valid_config, USER_AGENT), + (custom_user_agent_config, custom_user_agent), + ], +) +def test_config_user_agent(m_open, path_exists, config_string, expected_agent): + fd = io.StringIO(config_string) + fd.close = mock.Mock(return_value=None) + m_open.return_value = fd + + cp = config.GitlabConfigParser() + assert cp.user_agent == expected_agent diff --git a/gitlab/tests/test_gitlab.py b/gitlab/tests/test_gitlab.py index 553afb3a4..4a8220725 100644 --- a/gitlab/tests/test_gitlab.py +++ b/gitlab/tests/test_gitlab.py @@ -18,9 +18,10 @@ import pickle +import pytest from httmock import HTTMock, response, urlmatch, with_httmock # noqa -from gitlab import Gitlab, GitlabList +from gitlab import Gitlab, GitlabList, USER_AGENT from gitlab.v4.objects import CurrentUser @@ -139,3 +140,15 @@ class MyGitlab(Gitlab): config_path = default_config gl = MyGitlab.from_config("one", [config_path]) assert isinstance(gl, MyGitlab) + + +@pytest.mark.parametrize( + "kwargs,expected_agent", + [ + ({}, USER_AGENT), + ({"user_agent": "my-package/1.0.0"}, "my-package/1.0.0"), + ], +) +def test_gitlab_user_agent(kwargs, expected_agent): + gl = Gitlab("http://localhost", **kwargs) + assert gl.headers["User-Agent"] == expected_agent From a69a214ef7f460cef7a7f44351c4861503f9902e Mon Sep 17 00:00:00 2001 From: Nejc Habjan Date: Sun, 31 Jan 2021 18:16:05 +0100 Subject: [PATCH 3/3] docs: add docs and examples for custom user agent --- docs/api-usage.rst | 3 +++ docs/cli-usage.rst | 3 +++ gitlab/__init__.py | 1 + 3 files changed, 7 insertions(+) diff --git a/docs/api-usage.rst b/docs/api-usage.rst index 764f29467..2a40cfa19 100644 --- a/docs/api-usage.rst +++ b/docs/api-usage.rst @@ -26,6 +26,9 @@ To connect to a GitLab server, create a ``gitlab.Gitlab`` object: # anonymous gitlab instance, read-only for public resources gl = gitlab.Gitlab('http://10.0.0.1') + # Define your own custom user agent for requests + gl = gitlab.Gitlab('http://10.0.0.1', user_agent='my-package/1.0.0') + # make an API request to create the gl.user object. This is mandatory if you # use the username/password authentication. gl.auth() diff --git a/docs/cli-usage.rst b/docs/cli-usage.rst index 21a4baf69..1c24824c8 100644 --- a/docs/cli-usage.rst +++ b/docs/cli-usage.rst @@ -78,6 +78,9 @@ parameters. You can override the values in each GitLab server section. - Integer between 1 and 100 - The number of items to return in listing queries. GitLab limits the value at 100. + * - ``user_agent`` + - ``str`` + - A string defining a custom user agent to use when ``gitlab`` makes requests. You must define the ``url`` in each GitLab server section. diff --git a/gitlab/__init__.py b/gitlab/__init__.py index 5cdcef278..a9cbf8901 100644 --- a/gitlab/__init__.py +++ b/gitlab/__init__.py @@ -65,6 +65,7 @@ class Gitlab(object): api_version (str): Gitlab API version to use (support for 4 only) pagination (str): Can be set to 'keyset' to use keyset pagination order_by (str): Set order_by globally + user_agent (str): A custom user agent to use for making HTTP requests. """ def __init__(