Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
3698338
pyproject.toml: add mypy types-pytz types-requests
cdleonard Jul 8, 2025
b2b7128
pyproject.toml: add tool.mypy
cdleonard Jul 8, 2025
fa3e32d
.github/workflows: run mypy as part of "lint"
cdleonard Jul 8, 2025
dbab0f5
typing: handle circular imports using `if TYPE_CHECKING`
cdleonard Jul 8, 2025
5a2c3e8
build: use walrus operator to fix typing error in call to get_job
cdleonard Jul 8, 2025
170ba5e
credential: move field annotation to class level to fix typing errors
cdleonard Jul 8, 2025
299d05e
jenkinsbase: annotate JenkinsBase._data as dict
cdleonard Jul 8, 2025
7402633
view: Fix View.keys return annotation - should be Iterable[str]
cdleonard Jul 8, 2025
eb64f3e
credentials: Fix Credentials.iteritems annotation - it is an iterator…
cdleonard Jul 8, 2025
d5ae4a1
jobs: Fix Jobs.iteritems annotation - it is an iterator of tuples
cdleonard Jul 8, 2025
762a7d0
plugin: Fix iterable return annotations
cdleonard Jul 8, 2025
f0ce021
simple_post_logger: remove legacy python2 imports because they cause …
cdleonard Jul 8, 2025
56d1c1a
jenkinsapi_tests: remove legacy import unittest2
cdleonard Jul 8, 2025
3375331
jenkinsapi_tests: from unittest import mock
cdleonard Jul 8, 2025
6aeb2e3
pyproject.toml: remove external mock package
cdleonard Jul 8, 2025
a10f90d
node: Annotate launcher variable inside Node.get_node_attributes
cdleonard Jul 8, 2025
a5a7c32
queue: Fix Queue.get_queue_item_url annotation of item argument - sho…
cdleonard Jul 8, 2025
9b4f93b
node: Annotate Node._element_tree field
cdleonard Jul 8, 2025
d74b324
queue: introduce _get_queue_item helper for creating QueueItem objects
cdleonard Jul 8, 2025
13fdc3b
systests: add test for Node.get_architecture
cdleonard Jul 8, 2025
539a050
node: annotate Node.upload_config to accept config_xml as bytes
cdleonard Jul 8, 2025
d87a401
test_plugins: remove obsolete StringIO/BytesIO compat
cdleonard Jul 8, 2025
cf31d9c
node: fix get_monitor result type and cast explicitly
cdleonard Jul 8, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ jobs:
run: |
uv run ruff check jenkinsapi/ --output-format full

- name: Lint with mypy
run: |
uv run mypy || true

build:
runs-on: ubuntu-latest
strategy:
Expand Down
6 changes: 5 additions & 1 deletion jenkinsapi/artifact.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,17 @@
import os
import logging
import hashlib
from typing import Any, Literal
from typing import Any, Literal, TYPE_CHECKING

from jenkinsapi.fingerprint import Fingerprint
from jenkinsapi.custom_exceptions import ArtifactBroken

log = logging.getLogger(__name__)

if TYPE_CHECKING:
from jenkinsapi.build import Build
from jenkinsapi.jenkins import Jenkins


class Artifact(object):
"""
Expand Down
14 changes: 9 additions & 5 deletions jenkinsapi/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import datetime

from time import sleep
from typing import Iterator, List, Dict, Any
from typing import TYPE_CHECKING, Iterator, List, Dict, Any

import pytz
from jenkinsapi import config
Expand All @@ -35,6 +35,10 @@

log = logging.getLogger(__name__)

if TYPE_CHECKING:
from jenkinsapi.jenkins import Jenkins
from jenkinsapi.job import Job


class Build(JenkinsBase):
"""
Expand Down Expand Up @@ -238,8 +242,8 @@ def get_upstream_job(self) -> Job | None:
Get the upstream job object if it exist, None otherwise
:return: Job or None
"""
if self.get_upstream_job_name():
return self.get_jenkins_obj().get_job(self.get_upstream_job_name())
if name := self.get_upstream_job_name():
return self.get_jenkins_obj().get_job(name)
return None

def get_upstream_build_number(self) -> int | None:
Expand Down Expand Up @@ -278,8 +282,8 @@ def get_master_job(self) -> Job | None:
Get the master job object if it exist, None otherwise
:return: Job or None
"""
if self.get_master_job_name():
return self.get_jenkins_obj().get_job(self.get_master_job_name())
if name := self.get_master_job_name():
return self.get_jenkins_obj().get_job(name)

return None

Expand Down
31 changes: 19 additions & 12 deletions jenkinsapi/credential.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ class UsernamePasswordCredential(Credential):
dict
"""

username: str
password: str

def __init__(self, cred_dict: dict) -> None:
jenkins_class: str = (
"com.cloudbees.plugins.credentials.impl."
Expand All @@ -92,12 +95,11 @@ def __init__(self, cred_dict: dict) -> None:
cred_dict, jenkins_class
)
if "typeName" in cred_dict:
username: str = cred_dict["displayName"].split("/")[0]
self.username = cred_dict["displayName"].split("/")[0]
else:
username: str = cred_dict["userName"]
self.username = cred_dict["userName"]

self.username: str = username
self.password: str = cred_dict.get("password", "")
self.password = cred_dict.get("password", "")

def get_attributes(self):
"""
Expand Down Expand Up @@ -223,26 +225,31 @@ class SSHKeyCredential(Credential):
dict
"""

username: str
passphrase: str
key_type: int
key_value: str

def __init__(self, cred_dict: dict) -> None:
jenkins_class: str = (
"com.cloudbees.jenkins.plugins.sshcredentials.impl."
"BasicSSHUserPrivateKey"
)
super(SSHKeyCredential, self).__init__(cred_dict, jenkins_class)

if "typeName" in cred_dict:
username: str = cred_dict["displayName"].split(" ")[0]
self.username = cred_dict["displayName"].split(" ")[0]
else:
username: str = cred_dict["userName"]
self.username = cred_dict["userName"]

self.username: str = username
self.passphrase: str = cred_dict.get("passphrase", "")
self.passphrase = cred_dict.get("passphrase", "")

if "private_key" not in cred_dict or cred_dict["private_key"] is None:
self.key_type: int = -1
self.key_value: str = ""
self.key_type = -1
self.key_value = ""
elif cred_dict["private_key"].startswith("-"):
self.key_type: int = 0
self.key_value: str = cred_dict["private_key"]
self.key_type = 0
self.key_value = cred_dict["private_key"]
else:
raise ValueError("Invalid private_key value")

Expand Down
7 changes: 5 additions & 2 deletions jenkinsapi/credentials.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from __future__ import annotations

from typing import Iterator
from typing import TYPE_CHECKING, Iterator, Tuple

import logging
from urllib.parse import urlencode
Expand All @@ -20,6 +20,9 @@

log: logging.Logger = logging.getLogger(__name__)

if TYPE_CHECKING:
from jenkinsapi.jenkins import Jenkins


class Credentials(JenkinsBase):
"""
Expand Down Expand Up @@ -65,7 +68,7 @@ def iterkeys(self):
def keys(self):
return list(self.iterkeys())

def iteritems(self) -> Iterator[str, "Credential"]:
def iteritems(self) -> Iterator[Tuple[str, "Credential"]]:
for cred in self.credentials.values():
yield cred.description, cred

Expand Down
4 changes: 4 additions & 0 deletions jenkinsapi/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@
"""

from __future__ import annotations
from typing import TYPE_CHECKING

from jenkinsapi.jenkinsbase import JenkinsBase
import logging

log = logging.getLogger(__name__)

if TYPE_CHECKING:
from jenkinsapi.jenkins import Jenkins


class Executor(JenkinsBase):
"""
Expand Down
7 changes: 5 additions & 2 deletions jenkinsapi/executors.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@
from __future__ import annotations

import logging
from typing import Iterator
from typing import TYPE_CHECKING, Iterator

from jenkinsapi.executor import Executor
from jenkinsapi.jenkinsbase import JenkinsBase

log: logging.Logger = logging.getLogger(__name__)

if TYPE_CHECKING:
from jenkinsapi.jenkins import Jenkins


class Executors(JenkinsBase):
"""
Expand All @@ -27,7 +30,7 @@ def __init__(
self, baseurl: str, nodename: str, jenkins: "Jenkins"
) -> None:
self.nodename: str = nodename
self.jenkins: str = jenkins
self.jenkins: "Jenkins" = jenkins
JenkinsBase.__init__(self, baseurl)
self.count: int = self._data["numExecutors"]

Expand Down
5 changes: 4 additions & 1 deletion jenkinsapi/fingerprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import re
import logging
from typing import Any
from typing import TYPE_CHECKING, Any

import requests

Expand All @@ -15,6 +15,9 @@

log: logging.Logger = logging.getLogger(__name__)

if TYPE_CHECKING:
from jenkinsapi.jenkins import Jenkins


class Fingerprint(JenkinsBase):
"""
Expand Down
2 changes: 2 additions & 0 deletions jenkinsapi/jenkinsbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ class JenkinsBase(object):
inherited from
"""

_data: dict

def __repr__(self):
return """<%s.%s %s>""" % (
self.__class__.__module__,
Expand Down
4 changes: 4 additions & 0 deletions jenkinsapi/job.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import json
import logging
from typing import TYPE_CHECKING
import xml.etree.ElementTree as ET
import urllib.parse as urlparse

Expand Down Expand Up @@ -34,6 +35,9 @@

log = logging.getLogger(__name__)

if TYPE_CHECKING:
from jenkinsapi.jenkins import Jenkins


class Job(JenkinsBase, MutableJenkinsThing):
"""
Expand Down
8 changes: 6 additions & 2 deletions jenkinsapi/jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from __future__ import annotations

from typing import Iterator
from typing import TYPE_CHECKING, Iterator, Tuple
import logging
import time

Expand All @@ -14,6 +14,10 @@

log = logging.getLogger(__name__)

if TYPE_CHECKING:
from jenkinsapi.jenkins import Jenkins
from jenkinsapi.queue import QueueItem


class Jobs(object):
"""
Expand Down Expand Up @@ -94,7 +98,7 @@ def __getitem__(self, job_name: str) -> "Job":
else:
raise UnknownJob(job_name)

def iteritems(self) -> Iterator[str, "Job"]:
def iteritems(self) -> Iterator[Tuple[str, "Job"]]:
"""
Iterate over the names & objects for all jobs
"""
Expand Down
Loading