ujenkins


Nameujenkins JSON
Version 0.10.2 PyPI version JSON
download
home_pagehttps://github.com/pbelskiy/ujenkins
SummaryUniversal (sync/async) Python client for Jenkins
upload_time2023-09-05 13:55:07
maintainer
docs_urlNone
authorPetr Belskiy
requires_python>=3.7
licenseMIT
keywords jenkins
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            Universal Python client for `Jenkins <http://jenkins.io>`_
==========================================================

|Build status|
|Docs status|
|Coverage status|
|Version status|
|Downloads status|

.. |Build status|
   image:: https://github.com/pbelskiy/ujenkins/workflows/Tests/badge.svg
.. |Docs status|
   image:: https://readthedocs.org/projects/ujenkins/badge/?version=latest
.. |Coverage status|
   image:: https://img.shields.io/coveralls/github/pbelskiy/ujenkins?label=Coverage
.. |Version status|
   image:: https://img.shields.io/pypi/pyversions/ujenkins?label=Python
.. |Downloads status|
   image:: https://img.shields.io/pypi/dm/ujenkins?color=1&label=Downloads

----

Python client for Jenkins which supports both sync and async syntax with same interface.

+--------------------------------------------+
|   Comparison to other packages             |
+-------------------+-------+-------+--------+
| Name              | Sync  | Async | Python |
+===================+=======+=======+========+
| `ujenkins`_       |  YES  |  YES  | 3.6+   |
+-------------------+-------+-------+--------+
| `aiojenkins`_     |  NO   |  YES  | 3.5+   |
+-------------------+-------+-------+--------+
| `python-jenkins`_ |  YES  |  NO   | 3.4+   |
+-------------------+-------+-------+--------+
| `jenkinsapi`_     |  YES  |  NO   | 3.4+   |
+-------------------+-------+-------+--------+

.. _ujenkins: https://github.com/pbelskiy/ujenkins
.. _aiojenkins: https://github.com/pbelskiy/aiojenkins
.. _python-jenkins: https://opendev.org/jjb/python-jenkins
.. _jenkinsapi: https://github.com/pycontribs/jenkinsapi

Installation
------------

Latest release from PyPI

.. code:: shell

    pip3 install ujenkins

Or latest developing version

.. code:: shell

    pip3 install git+https://github.com/pbelskiy/ujenkins

Usage
-----

Get Jenkins version using sync client:

.. code:: python

    from ujenkins import JenkinsClient

    def example():
        client = JenkinsClient('http://server', 'user', 'password')
        version = client.system.get_version()
        print(version)

    example()

With async client (be careful ``AsyncJenkinsClient`` must be called inside async function):

.. code:: python

    import asyncio
    from ujenkins import AsyncJenkinsClient

    async def example():
        client = AsyncJenkinsClient('http://server', 'user', 'password')
        version = await client.system.get_version()
        print(version)
        await client.close()

    asyncio.run(example())

Examples
--------

In all code examples below client instance is created by:

.. code:: python

    from ujenkins import JenkinsClient
    client = JenkinsClient('http://server', 'user', 'password')

Get timestamp of latest build
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. code:: python

    client.builds.get_info('job', 'lastBuild')['timestamp']

Get url of started build
~~~~~~~~~~~~~~~~~~~~~~~~

Be careful, ``JenkinsNotFoundError`` could be raise in case build with same arg already enqueued.

.. code:: python

    item_id = client.builds.start('my_job')
    while True:
        time.sleep(5)
        try:
            info = client.queue.get_info(item_id)
            print(info['executable']['url'])
            break
        except (KeyError, TypeError):
            pass  # wait for build will be started

Get all jobs
~~~~~~~~~~~~

Basically ``client.jobs.get()`` returns jobs from root (depth = 0), in case you
want receive all the jobs, there are few approaches for it.

1) Set needed depth, experimentally 10 is enough.

.. code-block:: python

    jobs = client.jobs.get(depth=10)

Output:

.. code-block:: python

    {'folder': {'_class': 'com.cloudbees.hudson.plugins.folder.Folder',
                'jobs': [{'_class': 'hudson.model.FreeStyleProject',
                        'color': 'notbuilt',
                        'name': 'job_in_folder1',
                        'url': 'http://localhost:8080/job/folder/job/job_in_folder1/'},
                        {'_class': 'com.cloudbees.hudson.plugins.folder.Folder',
                        'jobs': [{'_class': 'hudson.model.FreeStyleProject',
                                    'color': 'notbuilt',
                                    'name': 'sub_job_in_subfolder',
                                    'url': 'http://localhost:8080/job/folder/job/subfolder/job/sub_job_in_subfolder/'}],
                        'name': 'subfolder',
                        'url': 'http://localhost:8080/job/folder/job/subfolder/'}],
                'name': 'folder',
                'url': 'http://localhost:8080/job/folder/'},
    'job': {'_class': 'hudson.model.FreeStyleProject',
            'color': 'blue',
            'name': 'job',
            'url': 'http://localhost:8080/job/job/'}}

2) Or just write your code to recursively form it, example is below.

.. code:: python

    def get_all_jobs(url: str = '', parent: str = '') -> Dict[str, dict]:
        jobs = {}

        for name, prop in client.jobs.get(url).items():
            jobs[parent + name] = prop
            if 'Folder' in prop.get('_class', ''):
                jobs.update(get_all_jobs(prop['url'], parent + name + '/'))

        return jobs

    all_jobs = get_all_jobs()

Working with build artifacts
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. code:: python

    # get content of artifact (bytes)
    content = client.builds.get_artifact('my_job', 31, 'photo.jpg')
    with open('/tmp/photo.jpg', 'wb') as f:
        w.write(content)

    # enumerate artifacts
    artifacts = client.builds.get_list_artifacts('my_job', 31)
    for artifact in artifacts:
        # get content and manually save it
        content = client.builds.get_artifact('my_job', 31, artifact['path'])

        # or absolute url could be used for external download
        print(artifact['url'])
        # >> 'http://server/job/my_job/31/artifact/photo.jpg'

Documentation
-------------

`Read the Docs <https://ujenkins.readthedocs.io/en/latest/>`_

Testing
-------

Prerequisites: ``tox``

Then just run tox, all dependencies and checks will run automatically

::

    tox

Contributing
------------

Any contributions are welcome!

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/pbelskiy/ujenkins",
    "name": "ujenkins",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.7",
    "maintainer_email": "",
    "keywords": "jenkins",
    "author": "Petr Belskiy",
    "author_email": "",
    "download_url": "https://files.pythonhosted.org/packages/33/05/f9d58ce532d45e13a816389cfc2fe146863afadb03cdabf475432a1be1da/ujenkins-0.10.2.tar.gz",
    "platform": null,
    "description": "Universal Python client for `Jenkins <http://jenkins.io>`_\n==========================================================\n\n|Build status|\n|Docs status|\n|Coverage status|\n|Version status|\n|Downloads status|\n\n.. |Build status|\n   image:: https://github.com/pbelskiy/ujenkins/workflows/Tests/badge.svg\n.. |Docs status|\n   image:: https://readthedocs.org/projects/ujenkins/badge/?version=latest\n.. |Coverage status|\n   image:: https://img.shields.io/coveralls/github/pbelskiy/ujenkins?label=Coverage\n.. |Version status|\n   image:: https://img.shields.io/pypi/pyversions/ujenkins?label=Python\n.. |Downloads status|\n   image:: https://img.shields.io/pypi/dm/ujenkins?color=1&label=Downloads\n\n----\n\nPython client for Jenkins which supports both sync and async syntax with same interface.\n\n+--------------------------------------------+\n|   Comparison to other packages             |\n+-------------------+-------+-------+--------+\n| Name              | Sync  | Async | Python |\n+===================+=======+=======+========+\n| `ujenkins`_       |  YES  |  YES  | 3.6+   |\n+-------------------+-------+-------+--------+\n| `aiojenkins`_     |  NO   |  YES  | 3.5+   |\n+-------------------+-------+-------+--------+\n| `python-jenkins`_ |  YES  |  NO   | 3.4+   |\n+-------------------+-------+-------+--------+\n| `jenkinsapi`_     |  YES  |  NO   | 3.4+   |\n+-------------------+-------+-------+--------+\n\n.. _ujenkins: https://github.com/pbelskiy/ujenkins\n.. _aiojenkins: https://github.com/pbelskiy/aiojenkins\n.. _python-jenkins: https://opendev.org/jjb/python-jenkins\n.. _jenkinsapi: https://github.com/pycontribs/jenkinsapi\n\nInstallation\n------------\n\nLatest release from PyPI\n\n.. code:: shell\n\n    pip3 install ujenkins\n\nOr latest developing version\n\n.. code:: shell\n\n    pip3 install git+https://github.com/pbelskiy/ujenkins\n\nUsage\n-----\n\nGet Jenkins version using sync client:\n\n.. code:: python\n\n    from ujenkins import JenkinsClient\n\n    def example():\n        client = JenkinsClient('http://server', 'user', 'password')\n        version = client.system.get_version()\n        print(version)\n\n    example()\n\nWith async client (be careful ``AsyncJenkinsClient`` must be called inside async function):\n\n.. code:: python\n\n    import asyncio\n    from ujenkins import AsyncJenkinsClient\n\n    async def example():\n        client = AsyncJenkinsClient('http://server', 'user', 'password')\n        version = await client.system.get_version()\n        print(version)\n        await client.close()\n\n    asyncio.run(example())\n\nExamples\n--------\n\nIn all code examples below client instance is created by:\n\n.. code:: python\n\n    from ujenkins import JenkinsClient\n    client = JenkinsClient('http://server', 'user', 'password')\n\nGet timestamp of latest build\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n.. code:: python\n\n    client.builds.get_info('job', 'lastBuild')['timestamp']\n\nGet url of started build\n~~~~~~~~~~~~~~~~~~~~~~~~\n\nBe careful, ``JenkinsNotFoundError`` could be raise in case build with same arg already enqueued.\n\n.. code:: python\n\n    item_id = client.builds.start('my_job')\n    while True:\n        time.sleep(5)\n        try:\n            info = client.queue.get_info(item_id)\n            print(info['executable']['url'])\n            break\n        except (KeyError, TypeError):\n            pass  # wait for build will be started\n\nGet all jobs\n~~~~~~~~~~~~\n\nBasically ``client.jobs.get()`` returns jobs from root (depth = 0), in case you\nwant receive all the jobs, there are few approaches for it.\n\n1) Set needed depth, experimentally 10 is enough.\n\n.. code-block:: python\n\n    jobs = client.jobs.get(depth=10)\n\nOutput:\n\n.. code-block:: python\n\n    {'folder': {'_class': 'com.cloudbees.hudson.plugins.folder.Folder',\n                'jobs': [{'_class': 'hudson.model.FreeStyleProject',\n                        'color': 'notbuilt',\n                        'name': 'job_in_folder1',\n                        'url': 'http://localhost:8080/job/folder/job/job_in_folder1/'},\n                        {'_class': 'com.cloudbees.hudson.plugins.folder.Folder',\n                        'jobs': [{'_class': 'hudson.model.FreeStyleProject',\n                                    'color': 'notbuilt',\n                                    'name': 'sub_job_in_subfolder',\n                                    'url': 'http://localhost:8080/job/folder/job/subfolder/job/sub_job_in_subfolder/'}],\n                        'name': 'subfolder',\n                        'url': 'http://localhost:8080/job/folder/job/subfolder/'}],\n                'name': 'folder',\n                'url': 'http://localhost:8080/job/folder/'},\n    'job': {'_class': 'hudson.model.FreeStyleProject',\n            'color': 'blue',\n            'name': 'job',\n            'url': 'http://localhost:8080/job/job/'}}\n\n2) Or just write your code to recursively form it, example is below.\n\n.. code:: python\n\n    def get_all_jobs(url: str = '', parent: str = '') -> Dict[str, dict]:\n        jobs = {}\n\n        for name, prop in client.jobs.get(url).items():\n            jobs[parent + name] = prop\n            if 'Folder' in prop.get('_class', ''):\n                jobs.update(get_all_jobs(prop['url'], parent + name + '/'))\n\n        return jobs\n\n    all_jobs = get_all_jobs()\n\nWorking with build artifacts\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n.. code:: python\n\n    # get content of artifact (bytes)\n    content = client.builds.get_artifact('my_job', 31, 'photo.jpg')\n    with open('/tmp/photo.jpg', 'wb') as f:\n        w.write(content)\n\n    # enumerate artifacts\n    artifacts = client.builds.get_list_artifacts('my_job', 31)\n    for artifact in artifacts:\n        # get content and manually save it\n        content = client.builds.get_artifact('my_job', 31, artifact['path'])\n\n        # or absolute url could be used for external download\n        print(artifact['url'])\n        # >> 'http://server/job/my_job/31/artifact/photo.jpg'\n\nDocumentation\n-------------\n\n`Read the Docs <https://ujenkins.readthedocs.io/en/latest/>`_\n\nTesting\n-------\n\nPrerequisites: ``tox``\n\nThen just run tox, all dependencies and checks will run automatically\n\n::\n\n    tox\n\nContributing\n------------\n\nAny contributions are welcome!\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Universal (sync/async) Python client for Jenkins",
    "version": "0.10.2",
    "project_urls": {
        "Download": "https://pypi.org/project/ujenkins",
        "Homepage": "https://github.com/pbelskiy/ujenkins"
    },
    "split_keywords": [
        "jenkins"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "c9d5c404c7889221c98cc8d9db2598b2197fb1e6ecfae6c6f3ae7b9f1de31f47",
                "md5": "574849b0431ec6eeec7d2ea936860991",
                "sha256": "fb484b18dc80a27497cb8093596c8098179f0d2b3e702ee78a42c4223d6c90d2"
            },
            "downloads": -1,
            "filename": "ujenkins-0.10.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "574849b0431ec6eeec7d2ea936860991",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7",
            "size": 34184,
            "upload_time": "2023-09-05T13:55:06",
            "upload_time_iso_8601": "2023-09-05T13:55:06.140750Z",
            "url": "https://files.pythonhosted.org/packages/c9/d5/c404c7889221c98cc8d9db2598b2197fb1e6ecfae6c6f3ae7b9f1de31f47/ujenkins-0.10.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "3305f9d58ce532d45e13a816389cfc2fe146863afadb03cdabf475432a1be1da",
                "md5": "cb7f9a8c3c2c4bf2068784b409117c36",
                "sha256": "ee5c5066fcd1d43fe9228b2f16c3b6b210c970071bf4bb696b049d5240d48bab"
            },
            "downloads": -1,
            "filename": "ujenkins-0.10.2.tar.gz",
            "has_sig": false,
            "md5_digest": "cb7f9a8c3c2c4bf2068784b409117c36",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7",
            "size": 18004,
            "upload_time": "2023-09-05T13:55:07",
            "upload_time_iso_8601": "2023-09-05T13:55:07.996804Z",
            "url": "https://files.pythonhosted.org/packages/33/05/f9d58ce532d45e13a816389cfc2fe146863afadb03cdabf475432a1be1da/ujenkins-0.10.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-09-05 13:55:07",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "pbelskiy",
    "github_project": "ujenkins",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [],
    "lcname": "ujenkins"
}
        
Elapsed time: 0.10883s