Python wrapper for the GitLab API

Overview
https://readthedocs.org/projects/python-gitlab/badge/?version=latest https://codecov.io/github/python-gitlab/python-gitlab/coverage.svg?branch=master

Python GitLab

python-gitlab is a Python package providing access to the GitLab server API.

It supports the v4 API of GitLab, and provides a CLI tool (gitlab).

Installation

Requirements

python-gitlab depends on:

Install with pip

pip install python-gitlab

Using the python-gitlab docker image

How to build

docker build -t python-gitlab:TAG .

How to use

docker run -it --rm -e GITLAB_PRIVATE_TOKEN=<your token> -v /path/to/python-gitlab.cfg:/python-gitlab.cfg python-gitlab <command> ...

or run it directly from the upstream image:

docker run -it --rm -e GITLAB_PRIVATE_TOKEN=<your token> -v /path/to/python-gitlab.cfg:/python-gitlab.cfg registry.gitlab.com/python-gitlab/python-gitlab:latest <command> ...

To change the GitLab URL, use -e GITLAB_URL=<your url>

Bring your own config file: docker run -it --rm -v /path/to/python-gitlab.cfg:/python-gitlab.cfg -e GITLAB_CFG=/python-gitlab.cfg python-gitlab <command> ...

Bug reports

Please report bugs and feature requests at https://github.com/python-gitlab/python-gitlab/issues.

Documentation

The full documentation for CLI and API is available on readthedocs.

Build the docs

You can build the documentation using sphinx:

pip install sphinx
python setup.py build_sphinx

Contributing

You can contribute to the project in multiple ways:

  • Write documentation
  • Implement features
  • Fix bugs
  • Add unit and functional tests
  • Everything else you can think of

Development workflow

Before contributing, please make sure you have pre-commit installed and configured. This will help automate adhering to code style and commit message guidelines described below:

cd python-gitlab/
pip3 install --user pre-commit
pre-commit install -t pre-commit -t commit-msg --install-hooks

Please provide your patches as GitHub pull requests. Thanks!

Commit message guidelines

We enforce commit messages to be formatted using the conventional-changelog. This leads to more readable messages that are easy to follow when looking through the project history.

Code-Style

We use black as code formatter, so you'll need to format your changes using the black code formatter. Pre-commit hooks will validate/format your code when committing. You can then stage any changes black added if the commit failed.

To format your code according to our guidelines before committing, run:

cd python-gitlab/
pip3 install --user black
black .

Running unit tests

Before submitting a pull request make sure that the tests still succeed with your change. Unit tests and functional tests run using the travis service and passing tests are mandatory to get merge requests accepted.

We're currently in a restructing phase for the unit tests. If you're changing existing tests, feel free to keep the current format. Otherwise please write new tests with pytest and using responses. An example for new tests can be found in tests/objects/test_runner.py

You need to install tox to run unit tests and documentation builds locally:

# run the unit tests for all supported python3 versions, and the pep8 tests:
tox

# run tests in one environment only:
tox -epy38

# build the documentation, the result will be generated in
# build/sphinx/html/
tox -edocs

Running integration tests

Integration tests run against a running gitlab instance, using a docker container. You need to have docker installed on the test machine, and your user must have the correct permissions to talk to the docker daemon.

To run these tests:

# run the CLI tests:
tox -e cli_func_v4

# run the python API tests:
tox -e py_func_v4

By default, the tests run against the latest version of the gitlab/gitlab-ce image. You can override both the image and tag by providing either the GITLAB_IMAGE or GITLAB_TAG environment variables.

This way you can run tests against different versions, such as nightly for features in an upcoming release, or an older release (e.g. 12.8.0-ce.0). The tag must match an exact tag on Docker Hub:

# run tests against `nightly` or specific tag
GITLAB_TAG=nightly tox -e py_func_v4
GITLAB_TAG=12.8.0-ce.0 tox -e py_func_v4

# run tests against the latest gitlab EE image
GITLAB_IMAGE=gitlab/gitlab-ee tox -e py_func_v4

A freshly configured gitlab container will be available at http://localhost:8080 (login root / password 5iveL!fe). A configuration for python-gitlab will be written in /tmp/python-gitlab.cfg.

To cleanup the environment delete the container:

docker rm -f gitlab-test
docker rm -f gitlab-runner-test
Comments
  • api authentication is not working

    api authentication is not working

    api call is not working.

    File "auth.py", line 3, in import gitlab File "D:\DevOps\gitlab\gitlab.py", line 17, in g1() File "D:\DevOps\gitlab\gitlab.py", line 10, in g1 gl = gitlab.Gitlab('http://gitlab.com', oauth_token='rUAuB2dWFxccvbbd') AttributeError: module 'gitlab' has no attribute 'Gitlab'

    In page: api-usage.rst

    opened by jaydip189 28
  • feat: add support for mutually exclusive attributes, consolidate attribute validation, fix boards.py _create_attr

    feat: add support for mutually exclusive attributes, consolidate attribute validation, fix boards.py _create_attr

    feat: add support for mutually exclusive attributes, consolidate attribute validation, fix boards.py _create_attr

    • add exclusive tuple to RequiredOptional data class to add support for mutually exclusive attributes
    • consolidate _check_missing_create_attrs and _check_missing_update_attrs from mixins.py into _validate_attrs in utils.py
    • change _create_attrs in board list manager classes from required=('label_ld',) to exclusive=('label_id','asignee_id','milestone_id')

    closes #1897

    opened by walterrowe 26
  • gl.projects.get() fails when provided

    gl.projects.get() fails when provided "namespace/project_name"

    Description of the problem, including code/CLI snippet

    In project-status.py ...

        for this_project in options.project:
            this_project = my_gitlab.projects.get(this_project)
            print("Adding project:", this_project.path_with_namespace)
            projects = projects + [this_project]
    
    • when this_project provided in "namespace/project_name" format, projects.get() fails with 404 error.
    • when this_project specified in project_id format, projects.get() succeeds.
    • same API access token for both forms of request.
    • access token is a project level token with full rights.

    Expected Behavior

    this_project = my_gitlab.projects.get("namespace/project_name") succeeds

    Actual Behavior

    this_project = my_gitlab.projects.get("namespace/project_name") fails with 404 error

    % ./project-status.py --config ~/.python-gitlab.cfg --section gitlab-https --project https-phase2/ha-proxy-migration
    Traceback (most recent call last):
      File "/usr/local/lib/python3.10/site-packages/gitlab/exceptions.py", line 330, in wrapped_f
        return f(*args, **kwargs)
      File "/usr/local/lib/python3.10/site-packages/gitlab/mixins.py", line 139, in get
        server_data = self.gitlab.http_get(path, **kwargs)
      File "/usr/local/lib/python3.10/site-packages/gitlab/client.py", line 790, in http_get
        result = self.http_request(
      File "/usr/local/lib/python3.10/site-packages/gitlab/client.py", line 756, in http_request
        raise gitlab.exceptions.GitlabHttpError(
    gitlab.exceptions.GitlabHttpError: 404: 404 Not Found
    
    The above exception was the direct cause of the following exception:
    
    Traceback (most recent call last):
      File "/Users/wrowe/git-repos/python-gitlab/./project-status.py", line 139, in <module>
        this_project = my_gitlab.projects.get(this_project)
      File "/usr/local/lib/python3.10/site-packages/gitlab/v4/objects/projects.py", line 775, in get
        return cast(Project, super().get(id=id, lazy=lazy, **kwargs))
      File "/usr/local/lib/python3.10/site-packages/gitlab/exceptions.py", line 332, in wrapped_f
        raise error(e.error_message, e.response_code, e.response_body) from e
    gitlab.exceptions.GitlabGetError: 404: 404 Not Found
    
    % ./project-status.py --config ~/.python-gitlab.cfg --section gitlab-https --project 3894 
    Adding project: https-phase2/ha-proxy-migration
    Scanning issues for ha-proxy-migration ...
    Building report for ha-proxy-migration ...
    Writing report file ...
    

    Specifications

    • python-gitlab version: 3.6.0
    • API version you are using (v3/v4): v4
    • Gitlab server version (or gitlab.com): 14.0.12 Community Edition
    opened by walterrowe 24
  • feat: allow global retry_transient_errors

    feat: allow global retry_transient_errors

    Value set on the Gitlab object will be used as a default in case every subsequent API call does not provide a retry_transient_errors parameter.

    This allows code to be succinct and the retry policy to be set for all calls to the Gitlab instance.

    opened by javatarz 20
  • Support for GitLab API v4

    Support for GitLab API v4

    https://about.gitlab.com/2017/02/22/gitlab-8-17-released/

    This blog post announces the fourth version of the API to be introduced as of March 22nd, GitLab 9.0 and the v3 to be removed with 9.3 (that's about three months).

    enhancement 
    opened by GhostLyrics 20
  • Create a issue board list by milestone_id still depends on label_id

    Create a issue board list by milestone_id still depends on label_id

    Description of the problem, including code/CLI snippet

    I followed the API documentation which says that the usage of label_id, milestone_id and assignee_id is mutually exclusive. So I wanted to create a board which would relate on milestones to have a timeline. The function goes like:

    
    def create_board(repository):
      milestones = repository.milestones.list()
      for milestone in milestones:
        print(f'ID: {milestone.id}')
        timeline_board.lists.create({
          'milestone_id': milestone.id
        })
    

    Expected Behavior

    Normally the board should be created according to the documentation.

    Actual Behavior

    AttributeError: Missing attributes: label_id
    

    Specifications

    • python-gitlab==3.1.1
    • Gitlab server version (or gitlab.com): 14.2.4-ee
    bug good first issue 
    opened by kurisukun 18
  • fix: honor parameter value passed

    fix: honor parameter value passed

    Gitlab allows setting the defaults for MR to delete the source. Also the inline help of the CLI suggest that a boolean is expected, but no matter what value you set, it will always delete.

    To mimic the existing behavior as good as possible, we check for not false instead of true. This way the impact on the cli will be minimal.

    opened by ghost 17
  • Maintainer wanted

    Maintainer wanted

    Hi,

    I'm currently the only maintainer of python-gitlab, and don't have a lot of time to work on this project. I'm looking for co-maintainers for starters, with the goal of retiring entirely from the project at some point.

    Please comment on this bug if you're interested in participating in this project development, or send me a mail if you prefer.

    Thanks!

    opened by gpocentek 17
  • feat: Add play command to project pipeline schedules

    feat: Add play command to project pipeline schedules

    I have added a custom play command to the project pipeline schedules.

    I made a previous pull request #1068 but the commits were incorrect. I also fixed the lint errors.

    Please let me know if I am missing anything else.

    opened by twonds 16
  • `AttributeError` on projects within groups

    `AttributeError` on projects within groups

    I'm testing the creation of files through the API and when the files has a path directory that needs to be created, the API returns an AttributeError.

    Note that using the GitLab POST (https://docs.gitlab.com/ee/api/repository_files.html#create-new-file-in-repository) successfully creates the file and the needed path.

    bug 
    opened by adinriv 16
  • Failed to save issue

    Failed to save issue

    Trying a simple:

    $ python
    Python 3.6.3 (default, Oct 24 2017, 14:48:20)                                                                                                                                             
    [GCC 7.2.0] on linux                                                                                                                                                                      
    Type "help", "copyright", "credits" or "license" for more information.                                                                                                                    
    >>> import gitlab
    >>> gl = gitlab.Gitlab('http://gitlab.com', 'XXXXXXXXXXXXX', api_version=4)
    >>> i = gl.projects.get(XXXXXX).issues.get(XXXX)
    >>> i.save()
    Traceback (most recent call last):
      File "/home/stratos/.virtualenvs/gliss-django/lib/python3.6/site-packages/gitlab/exceptions.py", line 239, in wrapped_f
        return f(*args, **kwargs)
      File "/home/stratos/.virtualenvs/gliss-django/lib/python3.6/site-packages/gitlab/mixins.py", line 222, in update
        return self.gitlab.http_put(path, post_data=data, **kwargs)
      File "/home/stratos/.virtualenvs/gliss-django/lib/python3.6/site-packages/gitlab/__init__.py", line 834, in http_put
        post_data=post_data, **kwargs)
      File "/home/stratos/.virtualenvs/gliss-django/lib/python3.6/site-packages/gitlab/__init__.py", line 713, in http_request
        response_body=result.content)
    gitlab.exceptions.GitlabHttpError: 400: b'{"error":"title, description, assignee_ids, assignee_id, milestone_id, labels, created_at, due_date, confidential, state_event, weight, discussion_locked are missing, at least one parameter must be provided"}'
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/home/stratos/.virtualenvs/gliss-django/lib/python3.6/site-packages/gitlab/mixins.py", line 281, in save
        server_data = self.manager.update(obj_id, updated_data, **kwargs)
      File "/home/stratos/.virtualenvs/gliss-django/lib/python3.6/site-packages/gitlab/exceptions.py", line 241, in wrapped_f
        raise error(e.error_message, e.response_code, e.response_body)
    gitlab.exceptions.GitlabUpdateError: 400: b'{"error":"title, description, assignee_ids, assignee_id, milestone_id, labels, created_at, due_date, confidential, state_event, weight, discussion_locked are missing, at least one parameter must be provided"}'
    >>> i.title
    'Sample issue'
    >>> i.description
    'Sample description'
    

    fails on the current 10.1.3-ee version of gitlab.com.

    docs 
    opened by stratosgear 15
  • feat: PEP 544 – Protocols: Structural subtyping (static duck typing)

    feat: PEP 544 – Protocols: Structural subtyping (static duck typing)

    The purpose of this change is to track api changes. For example: package versioning and breaking change announcement in case of protocol change. This is MVP implementation to be used by #2435 Haven't figured out yet how to implement unit tests for a protocol and its value.

    opened by lmilbaum 1
  • netrc auth overrides OAuth bearer token header

    netrc auth overrides OAuth bearer token header

    Description of the problem, including code/CLI snippet

    When using the OAuth integration while having a .netrc file on the filesystem, the .netrc authentication overrides the OAuth bearer token.

    Use the following code to trigger an error:

    user_token = "long oauth token here"
    client = gitlab.Gitlab(url=settings.GITLAB_BASE_URL, oauth_token=user_token)
    
    # Trigger an HTTP 401 response (GitlabAuthenticationError):
    client.auth()
    

    (Any call using the Client's http_xxx() method should fail; auth() is the easiest to use, though)

    Expected Behavior

    Every request to the GitLab API via the Gitlab object should authenticate using the OAuth token provided by the user when initializing the client. It should use the Authorization header containing the OAuth token as a bearer.

    Actual Behavior

    Instead of using the bearer token from the passed headers kwarg, requests falls back to basic authentication using credentials from the netrc file.

    Troubleshooting

    So far, I've found out the following:

    • The header override occurs in requests.sessions.prepare_request()
    • At line 481, since request.auth is empty, auth is filled using get_netrc_auth()
      • At line 494, the auth containing netrc values is passed to the prepared request
    • At line 490, the python-gitlab authorization header get overridden by requests' basic auth one

    See also this relevant quote from Requests netrc documentation:

    If no authentication method is given with the auth argument, Requests will attempt to get the authentication credentials for the URL’s hostname from the user’s netrc file. The netrc file overrides raw HTTP authentication headers set with headers=.

    If credentials for the hostname are found, the request is sent with HTTP Basic Auth.

    This might be fixed by explicitly passing an auth kwarg when using requests to make requests.

    Specifications

    • python-gitlab version: 3.12.0
    • requests version: 2.28.1
    • API version you are using (v3/v4): v4
    • Gitlab server version (or gitlab.com): 15.6.2-ee
    enhancement docs 
    opened by MHLut 3
  • feat(client): replace basic auth with OAuth ROPC flow

    feat(client): replace basic auth with OAuth ROPC flow

    Small step towards https://github.com/python-gitlab/python-gitlab/issues/1195, and also to get rid of the old username/password auth.

    Also gets rid of the requests-specific HTTPBasicAuth.

    opened by nejch 2
  • Allow update of protected branches

    Allow update of protected branches

    In gitlab 15.6 gitlab finally added api support to update protected branch settings, so ProjectProtectedBranch should be updated accordingly

    https://gitlab.com/gitlab-org/gitlab/-/issues/20229/

    feature EE help wanted 
    opened by hoerup 2
Releases(v3.12.0)
asyncio client for Deta Cloud

aiodeta Unofficial client for Deta Clound Install pip install aiodeta Supported functionality Deta Base Deta Drive Decorator for cron tasks Examples i

Andrii Leitsius 19 Feb 14, 2022
Source code for "Efficient Training of BERT by Progressively Stacking"

Introduction This repository is the code to reproduce the result of Efficient Training of BERT by Progressively Stacking. The code is based on Fairseq

Gong Linyuan 101 Dec 02, 2022
Nautobot-custom-jobs - Custom jobs for Nautobot

nautobot-custom-jobs This repo contains custom jobs for Nautobot. Installation P

Dan Peachey 9 Oct 27, 2022
A tool to build scripts to toggle between minimal & default services in Windows based on user defined lists.

A tool to build scripts to toggle between minimal & default services in Windows based on user defined lists.

AMIT 29 Jan 01, 2023
A simple bot that lives in your Telegram group, logging messages to a Postgresql database and serving statistical tables and plots to users as Telegram messages.

telegram-stats-bot Telegram-stats-bot is a simple bot that lives in your Telegram group, logging messages to a Postgresql database and serving statist

22 Dec 26, 2022
Univerity-student oriented (lithuanian) discord bot

Univerity-student oriented (lithuanian) discord bot

3 Nov 30, 2021
Python API wrapper around Trello's API

A wrapper around the Trello API written in Python. Each Trello object is represented by a corresponding Python object. The attributes of these objects

Richard Kolkovich 904 Jan 02, 2023
Yes, it's true :yellow_heart: This repository has 326 stars.

Yes, it's true! Inspired by a similar repository from @RealPeha, but implemented using a webhook on AWS Lambda and API Gateway, so it's serverless! If

510 Dec 28, 2022
A component of BuzzUtilityBot that allows for inter-server communication

A component of BuzzUtilityBot that allows for inter-server communication! Separated due to privacy and ease of inspection concerns

OHaiiBuzzle 2 Oct 11, 2022
eBay Scraper Homework 3 With Python

eBay Scraper Homework 3 Description of Code My ebay-dl.py file is programmed with python to download 6 key pieces of information - name, if there are

1 Nov 10, 2021
Kevin L. 3 Jul 14, 2022
Using GNU Radio and HackRF One to Receive, Analyze and Send ASK/OOK signals

play_with_ask NIS-8016 Lab A code: Recv.grc/py: Receive signals and match with ASK button using HackRF and GNU radio. I use AM demod block(can also in

Chen Anxue 1 Jul 04, 2022
Proxy-Bot - Python proxy bot for telegram

Proxy-Bot 🤖 Proxy bot between the main chat and a newcomer, allows all particip

Anton Shumakov 3 Apr 01, 2022
This repo contains a small project i've done using PILLOW module in python

This repo contains a small project i've done using PILLOW module in python. I wrote an automated script which generates more than 5k+ unique nfts with 0 hassle in less time.

SasiVatsal 11 Nov 05, 2022
Pybt: a BaoTa panel python sdk

About Pybt is a BaoTa panel python sdk. Pybt 是一个宝塔面板API的Python版本sdk封装库。 公司很多服务器都装了宝塔面板,通过宝塔来部署、安装、维护一些服务,服务器的数量上以后,导致了维护的不方便,这个时候就想使用宝塔提供的API来开发一个运维平台

Adam Zhang 9 Dec 05, 2022
Instagram GiftShop Scam Killer

Instagram GiftShop Scam Killer A basic tool for Windows which kills acess to any giftshop scam from Instagram. Protect your Instagram account from the

1 Mar 31, 2022
Telegram bot made with Python to get notified when visa slots are available

Visa slot bot I created this bot to getnotified when screenshots are available in the Telegram channel for dropbox appointments. How do I use this? Ch

Jimil 7 Jan 03, 2023
⚡ PoC: Hide a c&c botnet in the discord client. (Proof Of Concept)

👨‍💻 Discord Self Bot 👨‍💻 A Discord Self-Bot in Python by natrix Installation Run: selfbot.bat Python: version : 3.8 Modules

0хVιcнy#1337 37 Oct 21, 2022
Yes, it's true :two_hearts: This repository has 316 stars.

Yes, it's true! Inspired by a similar repository from @RealPeha, but implemented using a webhook on AWS Lambda and API Gateway, so it's serverless! If

510 Dec 28, 2022
Bot per controllare la disponibilità di appuntamenti per la vaccinazione Covid-19 in Veneto

VaxBot9000 Prerequisites Python 3.9 Poetry latest version of geckodriver Firefox Setup poetry install Copy config.sample.toml to config.toml and edit

Augusto Zanellato 5 Jun 13, 2021