# Advanced usage

## Using a custom session

python-gitlab relies on `requests.Session` objects to perform all the HTTP requests to the GitLab servers.

You can provide a custom session to create `gitlab.Gitlab` objects:

    import gitlab
    import requests

    session = requests.Session()
    gl = gitlab.Gitlab(session=session)

    # or when instantiating from configuration files
    gl = gitlab.Gitlab.from_config('somewhere', ['/tmp/gl.cfg'], session=session)

Reference: https://requests.readthedocs.io/en/latest/user/advanced/#session-objects

## Context manager

You can use `Gitlab` objects as context managers. This makes sure that the `requests.Session` object associated with a `Gitlab` instance is always properly closed when you exit a `with` block:

    with gitlab.Gitlab(host, token) as gl:
        gl.statistics.get()

Warning

The context manager will also close the custom `Session` object you might have used to build the `Gitlab` instance.

## netrc authentication

python-gitlab reads credentials from `.netrc` files via the `requests` backend only if you do not provide any other type of authentication yourself.

If you’d like to disable reading netrc files altogether, you can follow Using a custom session and explicitly set `trust_env=False` as described in the `requests` documentation.

    import gitlab
    import requests

    session = requests.Session(trust_env=False)
    gl = gitlab.Gitlab(session=session)

Reference: https://requests.readthedocs.io/en/latest/user/authentication/#netrc-authentication

## Proxy configuration

python-gitlab accepts the standard `http_proxy`, `https_proxy` and `no_proxy` environment variables via the `requests` backend. Uppercase variables are also supported.

For more granular control, you can also explicitly set proxies by Using a custom session as described in the `requests` documentation.

Reference: https://requests.readthedocs.io/en/latest/user/advanced/#proxies

## SSL certificate verification

python-gitlab relies on the CA certificate bundle in the `certifi` package that comes with the requests library.

If you need python-gitlab to use your system CA store instead, you can provide the path to the CA bundle in the `REQUESTS_CA_BUNDLE` environment variable.

Reference: https://requests.readthedocs.io/en/latest/user/advanced/#ssl-cert-verification

## Client side certificate

The following sample illustrates how to use a client-side certificate:

    import gitlab
    import requests

    session = requests.Session()
    session.cert = ('/path/to/client.cert', '/path/to/client.key')
    gl = gitlab.Gitlab(url, token, api_version=4, session=session)

Reference: https://requests.readthedocs.io/en/latest/user/advanced/#client-side-certificates

## Rate limits

python-gitlab obeys the rate limit of the GitLab server by default. On receiving a 429 response (Too Many Requests), python-gitlab sleeps for the amount of time in the Retry-After header that GitLab sends back. If GitLab does not return a response with the Retry-After header, python-gitlab will perform an exponential backoff.

If you don’t want to wait, you can disable the rate-limiting feature, by supplying the `obey_rate_limit` argument.

    import gitlab
    import requests

    gl = gitlab.Gitlab(url, token, api_version=4)
    gl.projects.list(get_all=True, obey_rate_limit=False)

If you do not disable the rate-limiting feature, you can supply a custom value for `max_retries`; by default, this is set to 10. To retry without bound when throttled, you can set this parameter to -1. This parameter is ignored if `obey_rate_limit` is set to `False`.

    import gitlab
    import requests

    gl = gitlab.Gitlab(url, token, api_version=4)
    gl.projects.list(get_all=True, max_retries=12)

Warning

You will get an Exception, if you then go over the rate limit of your GitLab instance.

## Transient errors

GitLab server can sometimes return a transient HTTP error. python-gitlab can automatically retry in such case, when `retry_transient_errors` argument is set to `True`. When enabled, HTTP error codes 500 (Internal Server Error), 502 (502 Bad Gateway), 503 (Service Unavailable), 504 (Gateway Timeout), and Cloudflare errors (520-530) are retried.

Additionally, HTTP error code 409 (Conflict) is retried if the reason is a Resource lock.

It will retry until reaching the `max_retries` value. By default, `retry_transient_errors` is set to `False` and an exception is raised for these errors.

    import gitlab
    import requests

    gl = gitlab.Gitlab(url, token, api_version=4)
    gl.projects.list(get_all=True, retry_transient_errors=True)

The default `retry_transient_errors` can also be set on the `Gitlab` object and overridden by individual API calls.

    import gitlab
    import requests
    gl = gitlab.Gitlab(url, token, api_version=4, retry_transient_errors=True)
    gl.projects.list(get_all=True)                               # retries due to default value
    gl.projects.list(get_all=True, retry_transient_errors=False) # does not retry

## Timeout

python-gitlab will by default use the `timeout` option from its configuration for all requests. This is passed downwards to the `requests` module at the time of making the HTTP request. However if you would like to override the global timeout parameter for a particular call, you can provide the `timeout` parameter to that API invocation:

    import gitlab

    gl = gitlab.Gitlab(url, token, api_version=4)
    gl.projects.import_github(ACCESS_TOKEN, 123456, "root", timeout=120.0)

## Typing

Generally, `python-gitlab` is a fully typed package. However, currently you may still need to do some type narrowing on your own, such as for nested API responses and `Union` return types. For example:

    from typing import TYPE_CHECKING

    import gitlab

    gl = gitlab.Gitlab(url, token, api_version=4)
    license = gl.get_license()

    if TYPE_CHECKING:
       assert isinstance(license["plan"], str)

## Per request HTTP headers override

The `extra_headers` keyword argument can be used to add and override the HTTP headers for a specific request. For example, it can be used do add `Range` header to download a part of artifacts archive:

    import gitlab

    gl = gitlab.Gitlab(url, token)
    project = gl.projects.get(1)
    job = project.jobs.get(123)

    artifacts = job.artifacts(extra_headers={"Range": "bytes=0-9"})