Pygerrit2
Pygerrit2 is a Python client library, version 2.0.15, for interacting with Gerrit Code Review's REST API. It is actively maintained and provides a simpler interface compared to its predecessor, `pygerrit`, by focusing solely on the REST API and omitting SSH functionality. The library is released as needed, with the latest stable version from June 2021.
Common errors
-
requests.exceptions.HTTPError: 401 Client Error: Unauthorized for url:...
cause This typically occurs due to incorrect authentication. Common reasons include using the wrong authentication type (e.g., `HTTPDigestAuth` with Gerrit 2.14+), providing incorrect HTTP credentials, or a mismatch between the provided username and the associated HTTP password.fixVerify that you are using `pygerrit2.HTTPBasicAuth` for modern Gerrit versions (2.14+). Double-check the username and the specific HTTP password obtained from your Gerrit user settings (not your SSH password). -
requests.exceptions.ConnectionError: ('Connection aborted.', ConnectionResetError(104, 'Connection reset by peer'))cause This error indicates a network-level issue where the connection to the Gerrit server was unexpectedly closed or could not be established. This can be due to transient network problems, server overload, or an incorrect `GERRIT_URL`.fixCheck your `GERRIT_URL` for correctness and ensure network connectivity to the Gerrit server. For production environments, consider implementing retry logic with a library like `backoff` to handle transient connection issues gracefully. -
requests.exceptions.HTTPError: 400 Client Error: Bad Request for url:...
cause A `400 Bad Request` usually means the server understood your request but couldn't process it due to invalid syntax or parameters in your request body or URL. This is common when making POST/PUT requests with malformed JSON data.fixCarefully review the Gerrit REST API documentation for the specific endpoint you are calling, paying close attention to the required JSON input format and URL parameters. Ensure your Python dictionary is correctly serialized to JSON and sent with the appropriate `Content-Type` header (though `pygerrit2` often handles this).
Warnings
- breaking Gerrit Code Review versions 2.14 and later deprecated HTTP Digest authentication in favor of HTTP Basic authentication. Using `HTTPDigestAuth` with newer Gerrit versions will likely result in authentication failures.
- gotcha The `/a/` prefix for authenticated REST API calls is automatically handled by `pygerrit2` when an authentication object is provided. Manually adding `/a/` to the base URL or API endpoints can lead to `400 Bad Request` or `403 Forbidden` errors.
- gotcha The HTTP password used for Gerrit REST API authentication is not the same as your SSH password. It must be obtained from your Gerrit user settings (usually under 'HTTP Password' or 'Settings > HTTP Credentials').
- gotcha Unlike its predecessor `pygerrit`, `pygerrit2` exclusively supports the Gerrit REST API. It does not provide any SSH interface for interacting with Gerrit.
Install
-
pip install pygerrit2
Imports
- GerritRestAPI
from pygerrit2 import GerritRestAPI
- HTTPBasicAuth
from requests.auth import HTTPDigestAuth
from pygerrit2 import HTTPBasicAuth
- HTTPBasicAuthFromNetrc
from pygerrit2.rest.auth import HTTPDigestAuthFromNetrc
from pygerrit2 import HTTPBasicAuthFromNetrc
Quickstart
import os
from pygerrit2 import GerritRestAPI, HTTPBasicAuth
GERRIT_URL = os.environ.get('GERRIT_URL', 'http://localhost:8080')
GERRIT_USERNAME = os.environ.get('GERRIT_USERNAME', 'admin')
GERRIT_HTTP_PASSWORD = os.environ.get('GERRIT_HTTP_PASSWORD', 'secret') # This is NOT your SSH password
if not all([GERRIT_URL, GERRIT_USERNAME, GERRIT_HTTP_PASSWORD]):
print("Please set GERRIT_URL, GERRIT_USERNAME, and GERRIT_HTTP_PASSWORD environment variables.")
exit(1)
try:
auth = HTTPBasicAuth(GERRIT_USERNAME, GERRIT_HTTP_PASSWORD)
rest = GerritRestAPI(url=GERRIT_URL, auth=auth)
# Get open changes owned by the authenticated user
changes = rest.get("/changes/?q=owner:self+status:open")
print(f"Found {len(changes)} open changes for {GERRIT_USERNAME}:")
for change in changes:
print(f" Change ID: {change['id']}, Subject: {change['subject']}")
# Example of getting a specific project
project_name = "All-Projects"
project_info = rest.get(f"/projects/{project_name}")
print(f"\nProject '{project_name}': {project_info['description']}")
except Exception as e:
print(f"An error occurred: {e}")