1414import gitlab .config
1515import gitlab .const
1616import gitlab .exceptions
17- from gitlab import http_backends ,utils
17+ from gitlab import http_backends ,oauth , utils
1818
1919REDIRECT_MSG = (
2020"python-gitlab detected a {status_code} ({reason!r}) redirection. You must update "
@@ -43,8 +43,8 @@ class Gitlab:
4343 the value is a string, it is the path to a CA file used for
4444 certificate validation.
4545 timeout: Timeout to use for requests to the GitLab server.
46- http_username: Username forHTTP authentication
47- http_password: Password forHTTP authentication
46+ http_username: Username forOAuth ROPC flow (deprecated, use oauth_credentials)
47+ http_password: Password forOAuth ROPC flow (deprecated, use oauth_credentials)
4848 api_version: Gitlab API version to use (support for 4 only)
4949 pagination: Can be set to 'keyset' to use keyset pagination
5050 order_by: Set order_by globally
@@ -53,6 +53,7 @@ class Gitlab:
5353 or 52x responses. Defaults to False.
5454 keep_base_url: keep user-provided base URL for pagination if it
5555 differs from response headers
56+ oauth_credentials: Password credentials for authenticating via OAuth ROPC flow
5657
5758 Keyward Args:
5859 requests.Session session: Http Requests Session
@@ -76,6 +77,8 @@ def __init__(
7677user_agent :str = gitlab .const .USER_AGENT ,
7778retry_transient_errors :bool = False ,
7879keep_base_url :bool = False ,
80+ * ,
81+ oauth_credentials :Optional [oauth .PasswordCredentials ]= None ,
7982** kwargs :Any ,
8083 )-> None :
8184self ._api_version = str (api_version )
@@ -98,13 +101,15 @@ def __init__(
98101self .http_password = http_password
99102self .oauth_token = oauth_token
100103self .job_token = job_token
101- self ._set_auth_info ()
104+ self .oauth_credentials = oauth_credentials
102105
103106#: Create a session object for requests
104107http_backend :Type [http_backends .DefaultBackend ]= kwargs .pop (
105108"http_backend" ,http_backends .DefaultBackend
106109 )
107110self .http_backend = http_backend (** kwargs )
111+
112+ self ._set_auth_info ()
108113self .session = self .http_backend .client
109114
110115self .per_page = per_page
@@ -514,28 +519,53 @@ def _set_auth_info(self) -> None:
514519"Only one of oauth authentication or http "
515520"authentication should be defined"
516521 )
517-
518522self ._http_auth = None
519523if self .private_token :
520524self .headers .pop ("Authorization" ,None )
521525self .headers ["PRIVATE-TOKEN" ]= self .private_token
522526self .headers .pop ("JOB-TOKEN" ,None )
527+ return
528+
529+ if not self .oauth_credentials and (self .http_username and self .http_password ):
530+ utils .warn (
531+ "Passing http_username and http_password is deprecated and will be "
532+ "removed in a future version.\n Please use the OAuth ROPC flow with"
533+ "(gitlab.oauth.PasswordCredentials) if you need password-based"
534+ "authentication. See https://docs.gitlab.com/ee/api/oauth2.html"
535+ "#resource-owner-password-credentials-flow for more details." ,
536+ category = DeprecationWarning ,
537+ )
538+ self .oauth_credentials = oauth .PasswordCredentials (
539+ self .http_username ,self .http_password
540+ )
541+
542+ if self .oauth_credentials :
543+ post_data = {
544+ "grant_type" :self .oauth_credentials .grant_type ,
545+ "scope" :self .oauth_credentials .scope ,
546+ "username" :self .oauth_credentials .username ,
547+ "password" :self .oauth_credentials .password ,
548+ }
549+ response = self .http_post (
550+ f"{ self ._base_url } /oauth/token" ,post_data = post_data
551+ )
552+ if isinstance (response ,dict ):
553+ self .oauth_token = response ["access_token" ]
554+ else :
555+ self .oauth_token = response .json ()["access_token" ]
556+ self ._http_auth = self .oauth_credentials .basic_auth
523557
524558if self .oauth_token :
525559self .headers ["Authorization" ]= f"Bearer{ self .oauth_token } "
526560self .headers .pop ("PRIVATE-TOKEN" ,None )
527561self .headers .pop ("JOB-TOKEN" ,None )
562+ return
528563
529564if self .job_token :
530565self .headers .pop ("Authorization" ,None )
531566self .headers .pop ("PRIVATE-TOKEN" ,None )
532567self .headers ["JOB-TOKEN" ]= self .job_token
533568
534- if self .http_username :
535- self ._http_auth = requests .auth .HTTPBasicAuth (
536- self .http_username ,self .http_password
537- )
538-
539569@staticmethod
540570def enable_debug ()-> None :
541571import logging