Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-podman for openSUSE:Factory 
checked in at 2024-11-26 20:57:07
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-podman (Old)
 and      /work/SRC/openSUSE:Factory/.python-podman.new.28523 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-podman"

Tue Nov 26 20:57:07 2024 rev:19 rq:1226538 version:5.3.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-podman/python-podman.changes      
2024-08-03 20:04:50.675809032 +0200
+++ /work/SRC/openSUSE:Factory/.python-podman.new.28523/python-podman.changes   
2024-11-26 20:58:55.461975198 +0100
@@ -1,0 +2,52 @@
+Tue Nov 26 13:55:44 UTC 2024 - Johannes Kastl 
<opensuse_buildserv...@ojkastl.de>
+
+- update to 5.3.0:
+  * [skip-ci] Packit: downstream_package_name for each package key
+    by @lsm5 in #416
+  * Make "images.push" method support "format" parameter by
+    @milanbalazs in #415
+  * Add test of container create with DNS option by @Honny1 in #417
+  * Fix podman search flake + update CI VM images by @cevich in
+    #418
+  * Update dependency containers/automation_images to v20240529 by
+    @renovate in #389
+  * Remove wait condition in run() by @inknos in #428
+  * Update dependency containers/automation_images to v20240821 by
+    @renovate in #423
+  * domain/networks_manager.py: use specified driver in IPAMConfig
+    by @jtluka in #429
+  * Fix/Disable Pylint R0917 by @inknos in #432
+  * Extend the parameters of 'images.load' and 'login' methods by
+    @milanbalazs in #434
+  * Don't use root as default user for exec_run by @aparcar in #431
+  * Renovate: Update default assignment by @cevich in #437
+  * Packit: enable c9s downstream update by @lsm5 in #440
+  * Audit and Update OWNERS file by @baude in #441
+  * Update dependency ubuntu to v24 by @renovate in #436
+  * Remove the container in case of detach mode by @milanbalazs in
+    #435
+  * Update CI VM images by @inknos in #430
+  * Fix cyclic-import by @Honny1 in #450
+  * Packit: constrain koji and bodhi jobs to fedora package by
+    @lsm5 in #442
+  * Fix default stderr value of container.logs() to match
+    documentation. by @MattBelle in #452
+  * [skip-ci] RPM: remove conditionals from changelog by @lsm5 in
+    #453
+  * Added stream support to Container.exec_run(). by @MattBelle in
+    #454
+  * Accept integer ports in containers_create.create by @krrhodes
+    in #447
+  * Container.labels now returns an empty dict instead of None. by
+    @MattBelle in #462
+  * Fix typos by @kianmeng in #464
+  * fix[docs]: Unindented example code on the index page by
+    @Mr-Sunglasses in #467
+  * Added support for mounting directories through the volume
+    keyword. by @MattBelle in #460
+  * docs: Add Installation and docs in README.md by @Mr-Sunglasses
+    in #471
+  * fix: name filter in images.list() by @Mr-Sunglasses in #468
+  * Bump release to 5.3.0 and drop python<3.8 by @inknos in #469
+
+-------------------------------------------------------------------

Old:
----
  podman-5.2.0.tar.gz

New:
----
  podman-5.3.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-podman.spec ++++++
--- /var/tmp/diff_new_pack.He0usu/_old  2024-11-26 20:58:55.997997544 +0100
+++ /var/tmp/diff_new_pack.He0usu/_new  2024-11-26 20:58:55.997997544 +0100
@@ -26,7 +26,7 @@
 %bcond_with test
 %endif
 Name:           python-podman%{psuffix}
-Version:        5.2.0
+Version:        5.3.0
 Release:        0
 Summary:        A library to interact with a Podman server
 License:        Apache-2.0

++++++ podman-5.2.0.tar.gz -> podman-5.3.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/.cirrus.yml 
new/podman-py-5.3.0/.cirrus.yml
--- old/podman-py-5.2.0/.cirrus.yml     2024-08-02 15:18:25.000000000 +0200
+++ new/podman-py-5.3.0/.cirrus.yml     2024-11-25 16:27:04.000000000 +0100
@@ -15,7 +15,7 @@
     #### Cache-image names to test with (double-quotes around names are 
critical)
     ####
     # Google-cloud VM Images
-    IMAGE_SUFFIX: "c20240320t153921z-f39f38d13"
+    IMAGE_SUFFIX: "c20241015t085508z-f40f39d13"
     FEDORA_CACHE_IMAGE_NAME: "fedora-podman-py-${IMAGE_SUFFIX}"
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/.github/renovate.json5 
new/podman-py-5.3.0/.github/renovate.json5
--- old/podman-py-5.2.0/.github/renovate.json5  2024-08-02 15:18:25.000000000 
+0200
+++ new/podman-py-5.3.0/.github/renovate.json5  2024-11-25 16:27:04.000000000 
+0100
@@ -51,5 +51,5 @@
    *************************************************/
 
   // Don't leave dep. update. PRs "hanging", assign them to people.
-  "assignees": ["umohnani8", "cevich"],
+  "assignees": ["inknos"],
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/.github/workflows/pr.yml 
new/podman-py-5.3.0/.github/workflows/pr.yml
--- old/podman-py-5.2.0/.github/workflows/pr.yml        2024-08-02 
15:18:25.000000000 +0200
+++ new/podman-py-5.3.0/.github/workflows/pr.yml        2024-11-25 
16:27:04.000000000 +0100
@@ -4,7 +4,7 @@
 
 jobs:
   commit:
-    runs-on: ubuntu-22.04
+    runs-on: ubuntu-24.04
     # Only check commits on pull requests.
     if: github.event_name == 'pull_request'
     steps:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/.packit.yaml 
new/podman-py-5.3.0/.packit.yaml
--- old/podman-py-5.2.0/.packit.yaml    2024-08-02 15:18:25.000000000 +0200
+++ new/podman-py-5.3.0/.packit.yaml    2024-11-25 16:27:04.000000000 +0100
@@ -2,15 +2,16 @@
 # See the documentation for more information:
 # https://packit.dev/docs/configuration/
 
-downstream_package_name: python-podman
 upstream_tag_template: v{version}
 
 packages:
   python-podman-fedora:
     pkg_tool: fedpkg
+    downstream_package_name: python-podman
     specfile_path: rpm/python-podman.spec
   python-podman-centos:
     pkg_tool: centpkg
+    downstream_package_name: python-podman
     specfile_path: rpm/python-podman.spec
   python-podman-rhel:
     specfile_path: rpm/python-podman.spec
@@ -63,13 +64,16 @@
     packages: [python-podman-centos]
     dist_git_branches:
       - c10s
+      - c9s
 
   - job: koji_build
     trigger: commit
+    packages: [python-podman-fedora]
     dist_git_branches:
       - fedora-all
 
   - job: bodhi_update
     trigger: commit
+    packages: [python-podman-fedora]
     dist_git_branches:
       - fedora-branched # rawhide updates are created automatically
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/Makefile new/podman-py-5.3.0/Makefile
--- old/podman-py-5.2.0/Makefile        2024-08-02 15:18:25.000000000 +0200
+++ new/podman-py-5.3.0/Makefile        2024-11-25 16:27:04.000000000 +0100
@@ -8,7 +8,7 @@
 EPOCH_TEST_COMMIT ?= $(shell git merge-base $${DEST_BRANCH:-main} HEAD)
 HEAD ?= HEAD
 
-export PODMAN_VERSION ?= "5.2.0"
+export PODMAN_VERSION ?= "5.3.0"
 
 .PHONY: podman
 podman:
@@ -24,7 +24,7 @@
 .PHONY: tests
 tests: tox
        # see tox.ini for environment variable settings
-       $(PYTHON) -m tox -e pylint,coverage,py36,py38,py39,py310,py311
+       $(PYTHON) -m tox -e coverage,py39,py310,py311,py312,py313
 
 .PHONY: unittest
 unittest:
@@ -39,9 +39,9 @@
 .PHONY: tox
 tox:
 ifeq (, $(shell which dnf))
-       brew install python@3.8 python@3.9 python@3.10 python@3.11
+       brew install python@3.9 python@3.10 python@3.11 python@3.12 python@3.13
 else
-       -dnf install -y python3 python3.6 python3.8 python3.9
+       -dnf install -y python3 python3.9 python3.10 python3.11 python3.12 
python3.13
 endif
        # ensure tox is available. It will take care of other testing 
requirements
        $(PYTHON) -m pip install --user tox
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/OWNERS new/podman-py-5.3.0/OWNERS
--- old/podman-py-5.2.0/OWNERS  2024-08-02 15:18:25.000000000 +0200
+++ new/podman-py-5.3.0/OWNERS  2024-11-25 16:27:04.000000000 +0100
@@ -1,5 +1,4 @@
 approvers:
-  - baude
   - edsantiago
   - giuseppe
   - jwhonce
@@ -7,23 +6,11 @@
   - Luap99
   - mheon
   - mwhahaha
-  - rhatdan
-  - TomSweeneyRedHat
   - umohnani8
   - vrothberg
+  - inknos
 reviewers:
   - ashley-cui
   - baude
-  - cdoern
-  - edsantiago
-  - giuseppe
-  - jwhonce
-  - lsm5
-  - Luap99
-  - mheon
-  - mwhahaha
   - rhatdan
   - TomSweeneyRedHat
-  - umohnani8
-  - vrothberg
-  - inknos
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/README.md 
new/podman-py-5.3.0/README.md
--- old/podman-py-5.2.0/README.md       2024-08-02 15:18:25.000000000 +0200
+++ new/podman-py-5.3.0/README.md       2024-11-25 16:27:04.000000000 +0100
@@ -4,6 +4,23 @@
 This python package is a library of bindings to use the RESTful API of 
[Podman](https://github.com/containers/podman).
 It is currently under development and contributors are welcome!
 
+## Installation
+
+<div class="termy">
+
+```console
+pip install podman
+```
+
+</div>
+
+---
+
+**Documentation**: <a href="https://podman-py.readthedocs.io/en/latest/"; 
target="_blank">https://podman-py.readthedocs.io/en/latest/</a>
+
+**Source Code**: <a href="https://github.com/containers/podman-py"; 
target="_blank">https://github.com/containers/podman-py</a>
+
+---
 
 ## Dependencies
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/docs/source/index.rst 
new/podman-py-5.3.0/docs/source/index.rst
--- old/podman-py-5.2.0/docs/source/index.rst   2024-08-02 15:18:25.000000000 
+0200
+++ new/podman-py-5.3.0/docs/source/index.rst   2024-11-25 16:27:04.000000000 
+0100
@@ -34,13 +34,14 @@
 .. code-block:: python
    :linenos:
 
-    import podman
+   import podman
+
+   with podman.PodmanClient() as client:
+       if client.ping():
+           images = client.images.list()
+           for image in images:
+               print(image.id)
 
-    with podman.PodmanClient() as client:
-        if client.ping():
-            images = client.images.list()
-            for image in images:
-                print(image.id)
 
 .. toctree::
    :caption: Podman Client
@@ -73,4 +74,4 @@
 
 * :ref:`genindex`
 * :ref:`modindex`
-* :ref:`search`
+* :ref:`search`
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/podman/api/__init__.py 
new/podman-py-5.3.0/podman/api/__init__.py
--- old/podman-py-5.2.0/podman/api/__init__.py  2024-08-02 15:18:25.000000000 
+0200
+++ new/podman-py-5.3.0/podman/api/__init__.py  2024-11-25 16:27:04.000000000 
+0100
@@ -1,9 +1,8 @@
 """Tools for connecting to a Podman service."""
 
-import re
-
 from podman.api.cached_property import cached_property
 from podman.api.client import APIClient
+from podman.api.api_versions import VERSION, COMPATIBLE_VERSION
 from podman.api.http_utils import prepare_body, prepare_filters
 from podman.api.parse_utils import (
     decode_header,
@@ -15,24 +14,9 @@
     stream_helper,
 )
 from podman.api.tar_utils import create_tar, prepare_containerfile, 
prepare_containerignore
-from .. import version
 
 DEFAULT_CHUNK_SIZE = 2 * 1024 * 1024
 
-
-def _api_version(release: str, significant: int = 3) -> str:
-    """Return API version removing any additional identifiers from the release 
version.
-
-    This is a simple lexicographical parsing, no semantics are applied, e.g. 
semver checking.
-    """
-    items = re.split(r"\.|-|\+", release)
-    parts = items[0:significant]
-    return ".".join(parts)
-
-
-VERSION: str = _api_version(version.__version__)
-COMPATIBLE_VERSION: str = _api_version(version.__compatible_version__, 2)
-
 try:
     from typing import Literal
 except (ImportError, ModuleNotFoundError):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/podman/api/api_versions.py 
new/podman-py-5.3.0/podman/api/api_versions.py
--- old/podman-py-5.2.0/podman/api/api_versions.py      1970-01-01 
01:00:00.000000000 +0100
+++ new/podman-py-5.3.0/podman/api/api_versions.py      2024-11-25 
16:27:04.000000000 +0100
@@ -0,0 +1,18 @@
+"""Constants API versions"""
+
+import re
+from .. import version
+
+
+def _api_version(release: str, significant: int = 3) -> str:
+    """Return API version removing any additional identifiers from the release 
version.
+
+    This is a simple lexicographical parsing, no semantics are applied, e.g. 
semver checking.
+    """
+    items = re.split(r"\.|-|\+", release)
+    parts = items[0:significant]
+    return ".".join(parts)
+
+
+VERSION: str = _api_version(version.__version__)
+COMPATIBLE_VERSION: str = _api_version(version.__compatible_version__, 2)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/podman/api/client.py 
new/podman-py-5.3.0/podman/api/client.py
--- old/podman-py-5.2.0/podman/api/client.py    2024-08-02 15:18:25.000000000 
+0200
+++ new/podman-py-5.3.0/podman/api/client.py    2024-11-25 16:27:04.000000000 
+0100
@@ -8,7 +8,7 @@
 import requests
 from requests.adapters import HTTPAdapter
 
-from podman import api  # pylint: disable=cyclic-import
+from podman.api.api_versions import VERSION, COMPATIBLE_VERSION
 from podman.api.ssh import SSHAdapter
 from podman.api.uds import UDSAdapter
 from podman.errors import APIError, NotFound
@@ -102,7 +102,7 @@
         use_ssh_client=True,
         max_pool_size=None,
         **kwargs,
-    ):  # pylint: disable=unused-argument
+    ):  # pylint: disable=unused-argument,too-many-positional-arguments
         """Instantiate APIClient object.
 
         Args:
@@ -158,9 +158,9 @@
         else:
             assert False, "APIClient.supported_schemes changed without adding 
a branch here."
 
-        self.version = version or api.VERSION
+        self.version = version or VERSION
         self.path_prefix = f"/v{self.version}/libpod/"
-        self.compatible_version = kwargs.get("compatible_version", 
api.COMPATIBLE_VERSION)
+        self.compatible_version = kwargs.get("compatible_version", 
COMPATIBLE_VERSION)
         self.compatible_prefix = f"/v{self.compatible_version}/"
 
         self.timeout = timeout
@@ -199,6 +199,7 @@
     def delete(
         self,
         path: Union[str, bytes],
+        *,
         params: Union[None, bytes, Mapping[str, str]] = None,
         headers: Optional[Mapping[str, str]] = None,
         timeout: _Timeout = None,
@@ -233,6 +234,7 @@
     def get(
         self,
         path: Union[str, bytes],
+        *,
         params: Union[None, bytes, Mapping[str, List[str]]] = None,
         headers: Optional[Mapping[str, str]] = None,
         timeout: _Timeout = None,
@@ -267,6 +269,7 @@
     def head(
         self,
         path: Union[str, bytes],
+        *,
         params: Union[None, bytes, Mapping[str, str]] = None,
         headers: Optional[Mapping[str, str]] = None,
         timeout: _Timeout = None,
@@ -301,6 +304,7 @@
     def post(
         self,
         path: Union[str, bytes],
+        *,
         params: Union[None, bytes, Mapping[str, str]] = None,
         data: _Data = None,
         headers: Optional[Mapping[str, str]] = None,
@@ -320,6 +324,7 @@
 
         Keyword Args:
             compatible: Will override the default path prefix with compatible 
prefix
+            verify: Whether to verify TLS certificates.
 
         Raises:
             APIError: when service returns an error
@@ -338,6 +343,7 @@
     def put(
         self,
         path: Union[str, bytes],
+        *,
         params: Union[None, bytes, Mapping[str, str]] = None,
         data: _Data = None,
         headers: Optional[Mapping[str, str]] = None,
@@ -376,6 +382,7 @@
         self,
         method: str,
         path: Union[str, bytes],
+        *,
         data: _Data = None,
         params: Union[None, bytes, Mapping[str, str]] = None,
         headers: Optional[Mapping[str, str]] = None,
@@ -394,6 +401,7 @@
 
         Keyword Args:
             compatible: Will override the default path prefix with compatible 
prefix
+            verify: Whether to verify TLS certificates.
 
         Raises:
             APIError: when service returns an error
@@ -409,10 +417,10 @@
 
         path = path.lstrip("/")  # leading / makes urljoin crazy...
 
-        # TODO should we have an option for HTTPS support?
+        scheme = "https" if kwargs.get("verify", None) else "http"
         # Build URL for operation from base_url
         uri = urllib.parse.ParseResult(
-            "http",
+            scheme,
             self.base_url.netloc,
             urllib.parse.urljoin(path_prefix, path),
             self.base_url.params,
@@ -429,6 +437,7 @@
                     data=data,
                     headers=(headers or {}),
                     stream=stream,
+                    verify=kwargs.get("verify", None),
                     **timeout_kw,
                 )
             )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/podman/api/output_utils.py 
new/podman-py-5.3.0/podman/api/output_utils.py
--- old/podman-py-5.2.0/podman/api/output_utils.py      2024-08-02 
15:18:25.000000000 +0200
+++ new/podman-py-5.3.0/podman/api/output_utils.py      2024-11-25 
16:27:04.000000000 +0100
@@ -46,4 +46,4 @@
         # Update data for next frame
         data_bytes = data_bytes[payload_size:]
 
-    return stdout, stderr
+    return stdout or None, stderr or None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/podman/api/parse_utils.py 
new/podman-py-5.3.0/podman/api/parse_utils.py
--- old/podman-py-5.2.0/podman/api/parse_utils.py       2024-08-02 
15:18:25.000000000 +0200
+++ new/podman-py-5.3.0/podman/api/parse_utils.py       2024-11-25 
16:27:04.000000000 +0100
@@ -8,6 +8,7 @@
 from typing import Any, Dict, Iterator, Optional, Tuple, Union
 
 from requests import Response
+from .output_utils import demux_output
 
 
 def parse_repository(name: str) -> Tuple[str, Optional[str]]:
@@ -79,11 +80,13 @@
         yield response.content[frame_begin:frame_end]
 
 
-def stream_frames(response: Response) -> Iterator[bytes]:
+def stream_frames(
+    response: Response, demux: bool = False
+) -> Iterator[Union[bytes, Tuple[bytes, bytes]]]:
     """Returns each frame from multiplexed streamed payload.
 
-    Notes:
-        The stdout and stderr frames are undifferentiated as they are returned.
+    If ``demux`` then output will be tuples where the first position is 
``STDOUT`` and the second
+    is ``STDERR``.
     """
     while True:
         header = response.raw.read(8)
@@ -95,6 +98,10 @@
             continue
 
         data = response.raw.read(frame_length)
+
+        if demux:
+            data = demux_output(header + data)
+
         if not data:
             return
         yield data
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/podman/api/ssh.py 
new/podman-py-5.3.0/podman/api/ssh.py
--- old/podman-py-5.2.0/podman/api/ssh.py       2024-08-02 15:18:25.000000000 
+0200
+++ new/podman-py-5.3.0/podman/api/ssh.py       2024-11-25 16:27:04.000000000 
+0100
@@ -250,7 +250,7 @@
         max_retries: int = DEFAULT_RETRIES,
         pool_block: int = DEFAULT_POOLBLOCK,
         **kwargs,
-    ):
+    ):  # pylint: disable=too-many-positional-arguments
         """Initialize SSHAdapter.
 
         Args:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/podman/api/typing_extensions.py 
new/podman-py-5.3.0/podman/api/typing_extensions.py
--- old/podman-py-5.2.0/podman/api/typing_extensions.py 2024-08-02 
15:18:25.000000000 +0200
+++ new/podman-py-5.3.0/podman/api/typing_extensions.py 2024-11-25 
16:27:04.000000000 +0100
@@ -22,7 +22,7 @@
 
 # After PEP 560, internal typing API was substantially reworked.
 # This is especially important for Protocol class which uses internal APIs
-# quite extensivelly.
+# quite extensively.
 PEP_560 = sys.version_info[:3] >= (3, 7, 0)
 
 if PEP_560:
@@ -2097,7 +2097,7 @@
         return len(name) > 4 and name.startswith('__') and name.endswith('__')
 
     # Prior to Python 3.7 types did not have `copy_with`. A lot of the equality
-    # checks, argument expansion etc. are done on the _subs_tre. As a result we
+    # checks, argument expansion etc. are done on the _subs_tree. As a result 
we
     # can't provide a get_type_hints function that strips out annotations.
 
     class AnnotatedMeta(typing.GenericMeta):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/podman/api/uds.py 
new/podman-py-5.3.0/podman/api/uds.py
--- old/podman-py-5.2.0/podman/api/uds.py       2024-08-02 15:18:25.000000000 
+0200
+++ new/podman-py-5.3.0/podman/api/uds.py       2024-11-25 16:27:04.000000000 
+0100
@@ -137,7 +137,7 @@
         max_retries=DEFAULT_RETRIES,
         pool_block=DEFAULT_POOLBLOCK,
         **kwargs,
-    ):
+    ):  # pylint: disable=too-many-positional-arguments
         """Initialize UDSAdapter.
 
         Args:
@@ -153,7 +153,7 @@
 
         Examples:
             requests.Session.mount(
-                "http://";, 
UDSAdapater("http+unix:///run/user/1000/podman/podman.sock"))
+                "http://";, 
UDSAdapter("http+unix:///run/user/1000/podman/podman.sock"))
         """
         self.poolmanager: Optional[UDSPoolManager] = None
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/podman/client.py 
new/podman-py-5.3.0/podman/client.py
--- old/podman-py-5.2.0/podman/client.py        2024-08-02 15:18:25.000000000 
+0200
+++ new/podman-py-5.3.0/podman/client.py        2024-11-25 16:27:04.000000000 
+0100
@@ -82,6 +82,7 @@
     @classmethod
     def from_env(
         cls,
+        *,
         version: str = "auto",
         timeout: Optional[int] = None,
         max_pool_size: Optional[int] = None,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/podman/domain/containers.py 
new/podman-py-5.3.0/podman/domain/containers.py
--- old/podman-py-5.2.0/podman/domain/containers.py     2024-08-02 
15:18:25.000000000 +0200
+++ new/podman-py-5.3.0/podman/domain/containers.py     2024-11-25 
16:27:04.000000000 +0100
@@ -42,11 +42,15 @@
     @property
     def labels(self):
         """dict[str, str]: Returns labels associated with container."""
+        labels = None
         with suppress(KeyError):
+            # Container created from ``list()`` operation
             if "Labels" in self.attrs:
-                return self.attrs["Labels"]
-            return self.attrs["Config"]["Labels"]
-        return {}
+                labels = self.attrs["Labels"]
+            # Container created from ``get()`` operation
+            else:
+                labels = self.attrs["Config"].get("Labels", {})
+        return labels or {}
 
     @property
     def status(self):
@@ -126,10 +130,11 @@
         response.raise_for_status()
         return response.json()
 
-    # pylint: disable=too-many-arguments,unused-argument
+    # pylint: disable=too-many-arguments
     def exec_run(
         self,
         cmd: Union[str, List[str]],
+        *,
         stdout: bool = True,
         stderr: bool = True,
         stdin: bool = False,
@@ -138,11 +143,13 @@
         user=None,
         detach: bool = False,
         stream: bool = False,
-        socket: bool = False,
+        socket: bool = False,  # pylint: disable=unused-argument
         environment: Union[Mapping[str, str], List[str]] = None,
         workdir: str = None,
         demux: bool = False,
-    ) -> Tuple[Optional[int], Union[Iterator[bytes], Any, Tuple[bytes, 
bytes]]]:
+    ) -> Tuple[
+        Optional[int], Union[Iterator[Union[bytes, Tuple[bytes, bytes]]], Any, 
Tuple[bytes, bytes]]
+    ]:
         """Run given command inside container and return results.
 
         Args:
@@ -152,10 +159,10 @@
             stdin: Attach to stdin. Default: False
             tty: Allocate a pseudo-TTY. Default: False
             privileged: Run as privileged.
-            user: User to execute command as. Default: root
+            user: User to execute command as.
             detach: If true, detach from the exec command.
                 Default: False
-            stream: Stream response data. Default: False
+            stream: Stream response data. Ignored if ``detach`` is ``True``. 
Default: False
             socket: Return the connection socket to allow custom
                 read/write operations. Default: False
             environment: A dictionary or a List[str] in
@@ -165,17 +172,19 @@
             demux: Return stdout and stderr separately
 
         Returns:
-            First item is the command response code.
-            Second item is the requests response content.
-            If demux is True, the second item is a tuple of
-            (stdout, stderr).
+            A tuple of (``response_code``, ``output``).
+            ``response_code``:
+                The exit code of the provided command. ``None`` if ``stream``.
+            ``output``:
+                If ``stream``, then a generator yielding response chunks.
+                If ``demux``, then a tuple of (``stdout``, ``stderr``).
+                Else the response content.
 
         Raises:
             NotImplementedError: method not implemented.
             APIError: when service reports error
         """
         # pylint: disable-msg=too-many-locals
-        user = user or "root"
         if isinstance(environment, dict):
             environment = [f"{k}={v}" for k, v in environment.items()]
         data = {
@@ -187,18 +196,26 @@
             "Env": environment,
             "Privileged": privileged,
             "Tty": tty,
-            "User": user,
             "WorkingDir": workdir,
         }
+        if user:
+            data["User"] = user
+
+        stream = stream and not detach
+
         # create the exec instance
         response = self.client.post(f"/containers/{self.name}/exec", 
data=json.dumps(data))
         response.raise_for_status()
         exec_id = response.json()['Id']
         # start the exec instance, this will store command output
         start_resp = self.client.post(
-            f"/exec/{exec_id}/start", data=json.dumps({"Detach": detach, 
"Tty": tty})
+            f"/exec/{exec_id}/start", data=json.dumps({"Detach": detach, 
"Tty": tty}), stream=stream
         )
         start_resp.raise_for_status()
+
+        if stream:
+            return None, api.stream_frames(start_resp, demux=demux)
+
         # get and return exec information
         response = self.client.get(f"/exec/{exec_id}/json")
         response.raise_for_status()
@@ -285,7 +302,7 @@
         params = {
             "follow": kwargs.get("follow", kwargs.get("stream", None)),
             "since": api.prepare_timestamp(kwargs.get("since")),
-            "stderr": kwargs.get("stderr", None),
+            "stderr": kwargs.get("stderr", True),
             "stdout": kwargs.get("stdout", True),
             "tail": kwargs.get("tail"),
             "timestamps": kwargs.get("timestamps"),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/podman/domain/containers_create.py 
new/podman-py-5.3.0/podman/domain/containers_create.py
--- old/podman-py-5.2.0/podman/domain/containers_create.py      2024-08-02 
15:18:25.000000000 +0200
+++ new/podman-py-5.3.0/podman/domain/containers_create.py      2024-11-25 
16:27:04.000000000 +0100
@@ -16,6 +16,8 @@
 
 logger = logging.getLogger("podman.containers")
 
+NAMED_VOLUME_PATTERN = re.compile(r'[a-zA-Z0-9][a-zA-Z0-9_.-]*')
+
 
 class CreateMixin:  # pylint: disable=too-few-public-methods
     """Class providing create method for ContainersManager."""
@@ -174,7 +176,7 @@
             pids_limit (int): Tune a container's pids limit. Set -1 for 
unlimited.
             platform (str): Platform in the format os[/arch[/variant]]. Only 
used if the method
                 needs to pull the requested image.
-            ports (Dict[str, Union[int, Tuple[str, int], List[int], Dict[str, 
Union[int, Tuple[str, int], List[int]]]]]): Ports to bind inside the container.
+            ports (Dict[Union[int, str], Union[int, Tuple[str, int], 
List[int], Dict[str, Union[int, Tuple[str, int], List[int]]]]]): Ports to bind 
inside the container.
 
                 The keys of the dictionary are the ports to bind inside the 
container, either as an
                 integer or a string in the form port/protocol, where the 
protocol is either
@@ -622,6 +624,9 @@
             return result
 
         for container, host in args.pop("ports", {}).items():
+            if isinstance(container, int):
+                container = str(container)
+
             if "/" in container:
                 container_port, protocol = container.split("/")
             else:
@@ -680,8 +685,21 @@
                     raise ValueError("'mode' value should be a str")
                 options.append(mode)
 
-            volume = {"Name": key, "Dest": value["bind"], "Options": options}
-            params["volumes"].append(volume)
+            # The Podman API only supports named volumes through the 
``volume`` parameter. Directory
+            # mounting needs to happen through the ``mounts`` parameter. 
Luckily the translation
+            # isn't too complicated so we can just do it for the user if we 
suspect that the key
+            # isn't a named volume.
+            if NAMED_VOLUME_PATTERN.match(key):
+                volume = {"Name": key, "Dest": value["bind"], "Options": 
options}
+                params["volumes"].append(volume)
+            else:
+                mount_point = {
+                    "destination": value['bind'],
+                    "options": options,
+                    "source": key,
+                    "type": 'bind',
+                }
+                params["mounts"].append(mount_point)
 
         for item in args.pop("secrets", []):
             if isinstance(item, Secret):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/podman/domain/containers_run.py 
new/podman-py-5.3.0/podman/domain/containers_run.py
--- old/podman-py-5.2.0/podman/domain/containers_run.py 2024-08-02 
15:18:25.000000000 +0200
+++ new/podman-py-5.3.0/podman/domain/containers_run.py 2024-11-25 
16:27:04.000000000 +0100
@@ -1,6 +1,7 @@
 """Mixin to provide Container run() method."""
 
 import logging
+import threading
 from contextlib import suppress
 from typing import Generator, Iterator, List, Union
 
@@ -18,6 +19,7 @@
         self,
         image: Union[str, Image],
         command: Union[str, List[str], None] = None,
+        *,
         stdout=True,
         stderr=False,
         remove: bool = False,
@@ -64,10 +66,21 @@
             container = self.create(image=image, command=command, **kwargs)
 
         container.start()
-        container.wait(condition=["running", "exited"])
         container.reload()
 
+        def remove_container(container_object: Container) -> None:
+            """
+            Wait the container to finish and remove it.
+            Args:
+                container_object: Container object
+            """
+            container_object.wait()  # Wait for the container to finish
+            container_object.remove()  # Remove the container
+
         if kwargs.get("detach", False):
+            if remove:
+                # Start a background thread to remove the container after 
finishing
+                threading.Thread(target=remove_container, 
args=(container,)).start()
             return container
 
         with suppress(KeyError):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/podman/domain/images_manager.py 
new/podman-py-5.3.0/podman/domain/images_manager.py
--- old/podman-py-5.2.0/podman/domain/images_manager.py 2024-08-02 
15:18:25.000000000 +0200
+++ new/podman-py-5.3.0/podman/domain/images_manager.py 2024-11-25 
16:27:04.000000000 +0100
@@ -3,8 +3,10 @@
 import io
 import json
 import logging
+import os
 import urllib.parse
-from typing import Any, Dict, Generator, Iterator, List, Mapping, Optional, 
Union
+from typing import Any, Dict, Iterator, List, Mapping, Optional, Union, 
Generator
+from pathlib import Path
 import requests
 
 from podman import api
@@ -14,7 +16,7 @@
 from podman.domain.images_build import BuildMixin
 from podman.domain.manager import Manager
 from podman.domain.registry_data import RegistryData
-from podman.errors import APIError, ImageNotFound
+from podman.errors import APIError, ImageNotFound, PodmanError
 
 try:
     from rich.progress import (
@@ -59,10 +61,13 @@
         Raises:
             APIError: when service returns an error
         """
+        filters = kwargs.get("filters", {}).copy()
+        if name := kwargs.get("name"):
+            filters["reference"] = name
+
         params = {
             "all": kwargs.get("all"),
-            "name": kwargs.get("name"),
-            "filters": api.prepare_filters(kwargs.get("filters")),
+            "filters": api.prepare_filters(filters=filters),
         }
         response = self.client.get("/images/json", params=params)
         if response.status_code == requests.codes.not_found:
@@ -113,26 +118,51 @@
             collection=self,
         )
 
-    def load(self, data: bytes) -> Generator[Image, None, None]:
+    def load(
+        self, data: Optional[bytes] = None, file_path: Optional[os.PathLike] = 
None
+    ) -> Generator[bytes, None, None]:
         """Restore an image previously saved.
 
         Args:
             data: Image to be loaded in tarball format.
+            file_path: Path of the Tarball.
+                       It works with both str and Path-like objects
 
         Raises:
-            APIError: when service returns an error
+            APIError: When service returns an error.
+            PodmanError: When the arguments are not set correctly.
         """
         # TODO fix podman swagger cannot use this header!
         # headers = {"Content-type": "application/x-www-form-urlencoded"}
 
+        # Check that exactly one of the data or file_path is provided
+        if not data and not file_path:
+            raise PodmanError("The 'data' or 'file_path' parameter should be 
set.")
+
+        if data and file_path:
+            raise PodmanError(
+                "Only one parameter should be set from 'data' and 'file_path' 
parameters."
+            )
+
+        post_data = data
+        if file_path:
+            # Convert to Path if file_path is a string
+            file_path_object = Path(file_path)
+            post_data = file_path_object.read_bytes()  # Read the tarball file 
as bytes
+
+        # Make the client request before entering the generator
         response = self.client.post(
-            "/images/load", data=data, headers={"Content-type": 
"application/x-tar"}
+            "/images/load", data=post_data, headers={"Content-type": 
"application/x-tar"}
         )
-        response.raise_for_status()
+        response.raise_for_status()  # Catch any errors before proceeding
+
+        def _generator(body: dict) -> Generator[bytes, None, None]:
+            # Iterate and yield images from response body
+            for item in body["Names"]:
+                yield self.get(item)
 
-        body = response.json()
-        for item in body["Names"]:
-            yield self.get(item)
+        # Pass the response body to the generator
+        return _generator(response.json())
 
     def prune(
         self, filters: Optional[Mapping[str, Any]] = None
@@ -206,6 +236,8 @@
             destination (str): alternate destination for image. (Podman only)
             stream (bool): return output as blocking generator. Default: False.
             tlsVerify (bool): Require TLS verification.
+            format (str): Manifest type (oci, v2s1, or v2s2) to use when 
pushing an image.
+                Default is manifest type of source, with fallbacks.
 
         Raises:
             APIError: when service returns an error
@@ -220,6 +252,7 @@
         params = {
             "destination": kwargs.get("destination"),
             "tlsVerify": kwargs.get("tlsVerify"),
+            "format": kwargs.get("format"),
         }
 
         name = f'{repository}:{tag}' if tag else repository
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/podman/domain/ipam.py 
new/podman-py-5.3.0/podman/domain/ipam.py
--- old/podman-py-5.2.0/podman/domain/ipam.py   2024-08-02 15:18:25.000000000 
+0200
+++ new/podman-py-5.3.0/podman/domain/ipam.py   2024-11-25 16:27:04.000000000 
+0100
@@ -40,7 +40,7 @@
 
     def __init__(
         self,
-        driver: Optional[str] = "default",
+        driver: Optional[str] = "host-local",
         pool_configs: Optional[List[IPAMPool]] = None,
         options: Optional[Mapping[str, Any]] = None,
     ):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/podman/domain/networks_manager.py 
new/podman-py-5.3.0/podman/domain/networks_manager.py
--- old/podman-py-5.2.0/podman/domain/networks_manager.py       2024-08-02 
15:18:25.000000000 +0200
+++ new/podman-py-5.3.0/podman/domain/networks_manager.py       2024-11-25 
16:27:04.000000000 +0100
@@ -76,6 +76,9 @@
         return self.prepare_model(attrs=response.json())
 
     def _prepare_ipam(self, data: Dict[str, Any], ipam: Dict[str, Any]):
+        if "Driver" in ipam:
+            data["ipam_options"] = {"driver": ipam["Driver"]}
+
         if "Config" not in ipam:
             return
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/podman/domain/system.py 
new/podman-py-5.3.0/podman/domain/system.py
--- old/podman-py-5.2.0/podman/domain/system.py 2024-08-02 15:18:25.000000000 
+0200
+++ new/podman-py-5.3.0/podman/domain/system.py 2024-11-25 16:27:04.000000000 
+0100
@@ -1,7 +1,7 @@
 """SystemManager to provide system level information from Podman service."""
 
 import logging
-from typing import Any, Dict, Optional
+from typing import Any, Dict, Optional, Union
 
 from podman.api.client import APIClient
 from podman import api
@@ -36,14 +36,18 @@
         response.raise_for_status()
         return response.json()
 
-    def login(
+    def login(  # pylint: 
disable=too-many-arguments,too-many-positional-arguments,unused-argument
         self,
         username: str,
         password: Optional[str] = None,
         email: Optional[str] = None,
         registry: Optional[str] = None,
-        reauth: Optional[bool] = False,  # pylint: disable=unused-argument
-        dockercfg_path: Optional[str] = None,  # pylint: 
disable=unused-argument
+        reauth: Optional[bool] = False,
+        dockercfg_path: Optional[str] = None,
+        auth: Optional[str] = None,
+        identitytoken: Optional[str] = None,
+        registrytoken: Optional[str] = None,
+        tls_verify: Optional[Union[bool, str]] = None,
     ) -> Dict[str, Any]:
         """Log into Podman service.
 
@@ -55,6 +59,11 @@
             reauth: Ignored: If True, refresh existing authentication. 
Default: False
             dockercfg_path: Ignored: Path to custom configuration file.
                 https://quay.io/v2
+            auth: TODO: Add description based on the source code of Podman.
+            identitytoken: IdentityToken is used to authenticate the user and
+                           get an access token for the registry.
+            registrytoken: RegistryToken is a bearer token to be sent to a 
registry
+            tls_verify: Whether to verify TLS certificates.
         """
 
         payload = {
@@ -62,6 +71,9 @@
             "password": password,
             "email": email,
             "serveraddress": registry,
+            "auth": auth,
+            "identitytoken": identitytoken,
+            "registrytoken": registrytoken,
         }
         payload = api.prepare_body(payload)
         response = self.client.post(
@@ -69,6 +81,7 @@
             headers={"Content-type": "application/json"},
             data=payload,
             compatible=True,
+            verify=tls_verify,  # Pass tls_verify to the client
         )
         response.raise_for_status()
         return response.json()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/podman/errors/exceptions.py 
new/podman-py-5.3.0/podman/errors/exceptions.py
--- old/podman-py-5.2.0/podman/errors/exceptions.py     2024-08-02 
15:18:25.000000000 +0200
+++ new/podman-py-5.3.0/podman/errors/exceptions.py     2024-11-25 
16:27:04.000000000 +0100
@@ -115,7 +115,7 @@
         command: Union[str, List[str]],
         image: str,
         stderr: Optional[Iterable[str]] = None,
-    ):
+    ):  # pylint: disable=too-many-positional-arguments
         """Initialize ContainerError.
 
         Args:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/podman/tests/__init__.py 
new/podman-py-5.3.0/podman/tests/__init__.py
--- old/podman-py-5.2.0/podman/tests/__init__.py        2024-08-02 
15:18:25.000000000 +0200
+++ new/podman-py-5.3.0/podman/tests/__init__.py        2024-11-25 
16:27:04.000000000 +0100
@@ -3,5 +3,5 @@
 # Do not auto-update these from version.py,
 #   as test code should be changed to reflect changes in Podman API versions
 BASE_SOCK = "unix:///run/api.sock"
-LIBPOD_URL = "http://%2Frun%2Fapi.sock/v5.2.0/libpod";
+LIBPOD_URL = "http://%2Frun%2Fapi.sock/v5.3.0/libpod";
 COMPATIBLE_URL = "http://%2Frun%2Fapi.sock/v1.40";
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/podman-py-5.2.0/podman/tests/integration/test_container_create.py 
new/podman-py-5.3.0/podman/tests/integration/test_container_create.py
--- old/podman-py-5.2.0/podman/tests/integration/test_container_create.py       
2024-08-02 15:18:25.000000000 +0200
+++ new/podman-py-5.3.0/podman/tests/integration/test_container_create.py       
2024-11-25 16:27:04.000000000 +0100
@@ -24,7 +24,7 @@
         for container in self.containers:
             container.remove(force=True)
 
-    def test_container_volume_mount(self):
+    def test_container_named_volume_mount(self):
         with self.subTest("Check volume mount"):
             volumes = {
                 'test_bind_1': {'bind': '/mnt/vol1', 'mode': 'rw'},
@@ -52,6 +52,33 @@
                 for o in other_options:
                     self.assertIn(o, mount.get('Options'))
 
+    def test_container_directory_volume_mount(self):
+        """Test that directories can be mounted with the ``volume`` 
parameter."""
+        with self.subTest("Check bind mount"):
+            volumes = {
+                "/etc/hosts": dict(bind="/test_ro", mode='ro'),
+                "/etc/hosts": dict(bind="/test_rw", mode='rw'),
+            }
+            container = self.client.containers.create(
+                self.alpine_image, command=["cat", "/test_ro", "/test_rw"], 
volumes=volumes
+            )
+            container_mounts = container.attrs.get('Mounts', {})
+            self.assertEqual(len(container_mounts), len(volumes))
+
+            self.containers.append(container)
+
+            for directory, mount_spec in volumes.items():
+                self.assertIn(
+                    
f"{directory}:{mount_spec['bind']}:{mount_spec['mode']},rprivate,rbind",
+                    container.attrs.get('HostConfig', {}).get('Binds', list()),
+                )
+
+            # check if container can be started and exits with EC == 0
+            container.start()
+            container.wait()
+
+            self.assertEqual(container.attrs.get('State', 
dict()).get('ExitCode', 256), 0)
+
     def test_container_extra_hosts(self):
         """Test Container Extra hosts"""
         extra_hosts = {"host1 host3": "127.0.0.2", "host2": "127.0.0.3"}
@@ -142,6 +169,16 @@
                     '1223/tcp': [{'HostIp': '', 'HostPort': '1235'}],
                 },
             },
+            {
+                'input': {
+                    2244: 3344,
+                },
+                'expected_output': {
+                    '2244/tcp': [
+                        {'HostIp': '', 'HostPort': '3344'},
+                    ],
+                },
+            },
         ]
 
         for port_test in port_tests:
@@ -157,6 +194,26 @@
                 )
             )
 
+    def test_container_dns_option(self):
+        expected_dns_opt = ['edns0']
+
+        container = self.client.containers.create(
+            self.alpine_image, command=["cat", "/etc/resolv.conf"], 
dns_opt=expected_dns_opt
+        )
+        self.containers.append(container)
+
+        with self.subTest("Check HostConfig"):
+            self.assertEqual(
+                container.attrs.get('HostConfig', {}).get('DnsOptions'), 
expected_dns_opt
+            )
+
+        with self.subTest("Check content of /etc/resolv.conf"):
+            container.start()
+            container.wait()
+            self.assertTrue(
+                all([opt in b"\n".join(container.logs()).decode() for opt in 
expected_dns_opt])
+            )
+
     def test_container_healthchecks(self):
         """Test passing various healthcheck options"""
         parameters = {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/podman-py-5.2.0/podman/tests/integration/test_container_exec.py 
new/podman-py-5.3.0/podman/tests/integration/test_container_exec.py
--- old/podman-py-5.2.0/podman/tests/integration/test_container_exec.py 
2024-08-02 15:18:25.000000000 +0200
+++ new/podman-py-5.3.0/podman/tests/integration/test_container_exec.py 
2024-11-25 16:27:04.000000000 +0100
@@ -49,5 +49,75 @@
         error_code, output = container.exec_run("ls nonexistent", demux=True)
 
         self.assertEqual(error_code, 1)
-        self.assertEqual(output[0], b'')
+        self.assertEqual(output[0], None)
         self.assertEqual(output[1], b"ls: nonexistent: No such file or 
directory\n")
+
+    def test_container_exec_run_stream(self):
+        """Test streaming the output from a long running command."""
+        container = self.client.containers.create(self.alpine_image, 
command=["top"], detach=True)
+        container.start()
+
+        command = [
+            '/bin/sh',
+            '-c',
+            'echo 0 ; sleep .1 ; echo 1 ; sleep .1 ; echo 2 ; sleep .1 ;',
+        ]
+        error_code, output = container.exec_run(command, stream=True)
+
+        self.assertEqual(error_code, None)
+        self.assertEqual(
+            list(output),
+            [
+                b'0\n',
+                b'1\n',
+                b'2\n',
+            ],
+        )
+
+    def test_container_exec_run_stream_demux(self):
+        """Test streaming the output from a long running command with demux 
enabled."""
+        container = self.client.containers.create(self.alpine_image, 
command=["top"], detach=True)
+        container.start()
+
+        command = [
+            '/bin/sh',
+            '-c',
+            'echo 0 ; >&2 echo 1 ; sleep .1 ; '
+            + 'echo 2 ; >&2 echo 3 ; sleep .1 ; '
+            + 'echo 4 ; >&2 echo 5 ; sleep .1 ;',
+        ]
+        error_code, output = container.exec_run(command, stream=True, 
demux=True)
+
+        self.assertEqual(error_code, None)
+        self.assertEqual(
+            list(output),
+            [
+                (b'0\n', None),
+                (None, b'1\n'),
+                (b'2\n', None),
+                (None, b'3\n'),
+                (b'4\n', None),
+                (None, b'5\n'),
+            ],
+        )
+
+    def test_container_exec_run_stream_detach(self):
+        """Test streaming the output from a long running command with detach 
enabled."""
+        container = self.client.containers.create(self.alpine_image, 
command=["top"], detach=True)
+        container.start()
+
+        command = [
+            '/bin/sh',
+            '-c',
+            'echo 0 ; sleep .1 ; echo 1 ; sleep .1 ; echo 2 ; sleep .1 ;',
+        ]
+        error_code, output = container.exec_run(command, stream=True, 
detach=True)
+
+        # Detach should make the ``exec_run`` ignore the ``stream`` flag so we 
will assert against the standard,
+        # non-streaming behavior.
+        self.assertEqual(error_code, 0)
+        # The endpoint should return immediately, before we are able to 
actually get any of the output.
+        self.assertEqual(
+            output,
+            b'\n',
+        )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/podman-py-5.2.0/podman/tests/integration/test_containers.py 
new/podman-py-5.3.0/podman/tests/integration/test_containers.py
--- old/podman-py-5.2.0/podman/tests/integration/test_containers.py     
2024-08-02 15:18:25.000000000 +0200
+++ new/podman-py-5.3.0/podman/tests/integration/test_containers.py     
2024-11-25 16:27:04.000000000 +0100
@@ -43,7 +43,9 @@
 
         with self.subTest("Create from Alpine Image"):
             container = self.client.containers.create(
-                self.alpine_image, command=["echo", random_string], 
ports={'2222/tcp': 3333}
+                self.alpine_image,
+                command=["echo", random_string],
+                ports={'2222/tcp': 3333, 2244: 3344},
             )
             self.assertIsInstance(container, Container)
             self.assertGreater(len(container.attrs), 0)
@@ -63,6 +65,10 @@
             self.assertEqual(
                 "3333", 
container.attrs["NetworkSettings"]["Ports"]["2222/tcp"][0]["HostPort"]
             )
+            self.assertIn("2244/tcp", 
container.attrs["NetworkSettings"]["Ports"])
+            self.assertEqual(
+                "3344", 
container.attrs["NetworkSettings"]["Ports"]["2244/tcp"][0]["HostPort"]
+            )
 
         file_contents = b"This is an integration test for archive."
         file_buffer = io.BytesIO(file_contents)
@@ -189,6 +195,31 @@
             volume_list = self.client.volumes.list()
             self.assertEqual(len(volume_list), len(existing_volumes))
 
+    def test_container_labels(self):
+        labels = {'label1': 'value1', 'label2': 'value2'}
+        labeled_container = self.client.containers.create(self.alpine_image, 
labels=labels)
+        unlabeled_container = self.client.containers.create(
+            self.alpine_image,
+        )
+
+        # inspect and list have 2 different schemas so we need to verify that 
we can
+        # successfully retrieve the labels on both
+        try:
+            # inspect schema
+            self.assertEqual(labeled_container.labels, labels)
+            self.assertEqual(unlabeled_container.labels, {})
+
+            # list schema
+            for container in self.client.containers.list(all=True):
+                if container.id == labeled_container.id:
+                    self.assertEqual(container.labels, labels)
+                elif container.id == unlabeled_container.id:
+                    self.assertEqual(container.labels, {})
+
+        finally:
+            labeled_container.remove(v=True)
+            unlabeled_container.remove(v=True)
+
 
 if __name__ == '__main__':
     unittest.main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/podman-py-5.2.0/podman/tests/integration/test_images.py 
new/podman-py-5.3.0/podman/tests/integration/test_images.py
--- old/podman-py-5.2.0/podman/tests/integration/test_images.py 2024-08-02 
15:18:25.000000000 +0200
+++ new/podman-py-5.3.0/podman/tests/integration/test_images.py 2024-11-25 
16:27:04.000000000 +0100
@@ -44,7 +44,7 @@
         """Test Image CRUD.
 
         Notes:
-            Written to maximize re-use of pulled image.
+            Written to maximize reuse of pulled image.
         """
 
         with self.subTest("Pull Alpine Image"):
@@ -129,12 +129,9 @@
                     self.assertTrue("alpine" in str(repositories_content))
 
     def test_search(self):
-        actual = self.client.images.search("alpine", filters={"is-official": 
True})
-        self.assertEqual(len(actual), 1)
-        self.assertEqual(actual[0]["Official"], "[OK]")
-
-        actual = self.client.images.search("alpine", listTags=True)
-        self.assertIsNotNone(actual[0]["Tag"])
+        # N/B: This is an infrequently used feature, that tends to flake a lot.
+        # Just check that it doesn't throw an exception and move on.
+        self.client.images.search("alpine")
 
     @unittest.skip("Needs Podman 3.1.0")
     def test_corrupt_load(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/podman-py-5.2.0/podman/tests/unit/test_containersmanager.py 
new/podman-py-5.3.0/podman/tests/unit/test_containersmanager.py
--- old/podman-py-5.2.0/podman/tests/unit/test_containersmanager.py     
2024-08-02 15:18:25.000000000 +0200
+++ new/podman-py-5.3.0/podman/tests/unit/test_containersmanager.py     
2024-11-25 16:27:04.000000000 +0100
@@ -1,3 +1,4 @@
+import json
 import unittest
 
 try:
@@ -7,7 +8,7 @@
     # Python < 3.10
     from collections import Iterator
 
-from unittest.mock import DEFAULT, patch
+from unittest.mock import ANY, DEFAULT, patch, MagicMock
 
 import requests_mock
 
@@ -213,6 +214,49 @@
         with self.assertRaises(ImageNotFound):
             self.client.containers.create("fedora", "/usr/bin/ls", 
cpu_count=9999)
 
+    @requests_mock.Mocker()
+    def test_create_parse_host_port(self, mock):
+        mock_response = MagicMock()
+        mock_response.json = lambda: {
+            "Id": 
"87e1325c82424e49a00abdd4de08009eb76c7de8d228426a9b8af9318ced5ecd",
+            "Size": 1024,
+        }
+        self.client.containers.client.post = 
MagicMock(return_value=mock_response)
+        mock.get(
+            tests.LIBPOD_URL
+            + 
"/containers/87e1325c82424e49a00abdd4de08009eb76c7de8d228426a9b8af9318ced5ecd/json",
+            json=FIRST_CONTAINER,
+        )
+
+        port_str = {'2233': 3333}
+        port_str_protocol = {'2244/tcp': 3344}
+        port_int = {2255: 3355}
+        ports = {**port_str, **port_str_protocol, **port_int}
+        self.client.containers.create("fedora", "/usr/bin/ls", ports=ports)
+
+        self.client.containers.client.post.assert_called()
+        expected_ports = [
+            {
+                'container_port': 2233,
+                'host_port': 3333,
+                'protocol': 'tcp',
+            },
+            {
+                'container_port': 2244,
+                'host_port': 3344,
+                'protocol': 'tcp',
+            },
+            {
+                'container_port': 2255,
+                'host_port': 3355,
+                'protocol': 'tcp',
+            },
+        ]
+        actual_ports = 
json.loads(self.client.containers.client.post.call_args[1]['data'])[
+            'portmappings'
+        ]
+        self.assertEqual(expected_ports, actual_ports)
+
     def test_create_unsupported_key(self):
         with self.assertRaises(TypeError) as e:
             self.client.containers.create("fedora", "/usr/bin/ls", 
blkio_weight=100.0)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/podman-py-5.2.0/podman/tests/unit/test_imagesmanager.py 
new/podman-py-5.3.0/podman/tests/unit/test_imagesmanager.py
--- old/podman-py-5.2.0/podman/tests/unit/test_imagesmanager.py 2024-08-02 
15:18:25.000000000 +0200
+++ new/podman-py-5.3.0/podman/tests/unit/test_imagesmanager.py 2024-11-25 
16:27:04.000000000 +0100
@@ -1,5 +1,6 @@
 import types
 import unittest
+from unittest.mock import mock_open, patch
 
 try:
     # Python >= 3.10
@@ -13,7 +14,7 @@
 from podman import PodmanClient, tests
 from podman.domain.images import Image
 from podman.domain.images_manager import ImagesManager
-from podman.errors import APIError, ImageNotFound
+from podman.errors import APIError, ImageNotFound, PodmanError
 
 FIRST_IMAGE = {
     "Id": 
"sha256:326dd9d7add24646a325e8eaa82125294027db2332e49c5828d96312c5d773ab",
@@ -320,6 +321,37 @@
 
     @requests_mock.Mocker()
     def test_load(self, mock):
+        with self.assertRaises(PodmanError):
+            self.client.images.load()
+
+        with self.assertRaises(PodmanError):
+            self.client.images.load(b'data', b'file_path')
+
+        with self.assertRaises(PodmanError):
+            self.client.images.load(data=b'data', file_path=b'file_path')
+
+        # Patch Path.read_bytes to mock the file reading behavior
+        with patch("pathlib.Path.read_bytes", return_value=b"mock tarball 
data"):
+            mock.post(
+                tests.LIBPOD_URL + "/images/load",
+                json={"Names": ["quay.io/fedora:latest"]},
+            )
+            mock.get(
+                tests.LIBPOD_URL + "/images/quay.io%2ffedora%3Alatest/json",
+                json=FIRST_IMAGE,
+            )
+
+            # 3a. Test the case where only 'file_path' is provided
+            gntr = self.client.images.load(file_path="mock_file.tar")
+            self.assertIsInstance(gntr, types.GeneratorType)
+
+            report = list(gntr)
+            self.assertEqual(len(report), 1)
+            self.assertEqual(
+                report[0].id,
+                
"sha256:326dd9d7add24646a325e8eaa82125294027db2332e49c5828d96312c5d773ab",
+            )
+
         mock.post(
             tests.LIBPOD_URL + "/images/load",
             json={"Names": ["quay.io/fedora:latest"]},
@@ -557,6 +589,84 @@
             images[1].id, 
"c4b16966ecd94ffa910eab4e630e24f259bf34a87e924cd4b1434f267b0e354e"
         )
 
+    @requests_mock.Mocker()
+    def test_list_with_name_parameter(self, mock):
+        """Test that name parameter is correctly converted to a reference 
filter"""
+        mock.get(
+            tests.LIBPOD_URL + 
"/images/json?filters=%7B%22reference%22%3A+%5B%22fedora%22%5D%7D",
+            json=[FIRST_IMAGE],
+        )
+
+        images = self.client.images.list(name="fedora")
+
+        self.assertEqual(len(images), 1)
+        self.assertIsInstance(images[0], Image)
+        self.assertEqual(images[0].tags, ["fedora:latest", "fedora:33"])
+
+    @requests_mock.Mocker()
+    def test_list_with_name_and_existing_filters(self, mock):
+        """Test that name parameter works alongside other filters"""
+        mock.get(
+            tests.LIBPOD_URL
+            + 
"/images/json?filters=%7B%22dangling%22%3A+%5B%22True%22%5D%2C+%22reference%22%3A+%5B%22fedora%22%5D%7D",
+            json=[FIRST_IMAGE],
+        )
+
+        images = self.client.images.list(name="fedora", filters={"dangling": 
True})
+
+        self.assertEqual(len(images), 1)
+        self.assertIsInstance(images[0], Image)
+
+    @requests_mock.Mocker()
+    def test_list_with_name_overrides_reference_filter(self, mock):
+        """Test that name parameter takes precedence over existing reference 
filter"""
+        mock.get(
+            tests.LIBPOD_URL + 
"/images/json?filters=%7B%22reference%22%3A+%5B%22fedora%22%5D%7D",
+            json=[FIRST_IMAGE],
+        )
+
+        # The name parameter should override the reference filter
+        images = self.client.images.list(
+            name="fedora", filters={"reference": "ubuntu"}  # This should be 
overridden
+        )
+
+        self.assertEqual(len(images), 1)
+        self.assertIsInstance(images[0], Image)
+
+    @requests_mock.Mocker()
+    def test_list_with_all_and_name(self, mock):
+        """Test that all parameter works alongside name filter"""
+        mock.get(
+            tests.LIBPOD_URL
+            + 
"/images/json?all=true&filters=%7B%22reference%22%3A+%5B%22fedora%22%5D%7D",
+            json=[FIRST_IMAGE],
+        )
+
+        images = self.client.images.list(all=True, name="fedora")
+
+        self.assertEqual(len(images), 1)
+        self.assertIsInstance(images[0], Image)
+
+    @requests_mock.Mocker()
+    def test_list_with_empty_name(self, mock):
+        """Test that empty name parameter doesn't add a reference filter"""
+        mock.get(tests.LIBPOD_URL + "/images/json", json=[FIRST_IMAGE])
+
+        images = self.client.images.list(name="")
+
+        self.assertEqual(len(images), 1)
+        self.assertIsInstance(images[0], Image)
+
+    @requests_mock.Mocker()
+    def test_list_with_none_name(self, mock):
+        """Test that None name parameter doesn't add a reference filter"""
+        mock.get(tests.LIBPOD_URL + "/images/json", json=[FIRST_IMAGE])
+
+        images = self.client.images.list(name=None)
+
+        self.assertEqual(len(images), 1)
+        self.assertIsInstance(images[0], Image)
+
 
 if __name__ == '__main__':
     unittest.main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/podman/version.py 
new/podman-py-5.3.0/podman/version.py
--- old/podman-py-5.2.0/podman/version.py       2024-08-02 15:18:25.000000000 
+0200
+++ new/podman-py-5.3.0/podman/version.py       2024-11-25 16:27:04.000000000 
+0100
@@ -1,4 +1,4 @@
 """Version of PodmanPy."""
 
-__version__ = "5.2.0"
+__version__ = "5.3.0"
 __compatible_version__ = "1.40"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/pyproject.toml 
new/podman-py-5.3.0/pyproject.toml
--- old/podman-py-5.2.0/pyproject.toml  2024-08-02 15:18:25.000000000 +0200
+++ new/podman-py-5.3.0/pyproject.toml  2024-11-25 16:27:04.000000000 +0100
@@ -2,7 +2,7 @@
 line-length = 100
 skip-string-normalization = true
 preview = true
-target-version = ["py36"]
+target-version = ["py39"]
 include = '\.pyi?$'
 exclude = '''
 /(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/rpm/python-podman.spec 
new/podman-py-5.3.0/rpm/python-podman.spec
--- old/podman-py-5.2.0/rpm/python-podman.spec  2024-08-02 15:18:25.000000000 
+0200
+++ new/podman-py-5.3.0/rpm/python-podman.spec  2024-11-25 16:27:04.000000000 
+0100
@@ -100,9 +100,4 @@
 %doc README.md
 
 %changelog
-%if %{defined autochangelog}
 %autochangelog
-%else
-* Mon May 01 2023 RH Container Bot <rhcontainer...@fedoraproject.org>
-- Placeholder changelog for envs that are not autochangelog-ready
-%endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/setup.cfg 
new/podman-py-5.3.0/setup.cfg
--- old/podman-py-5.2.0/setup.cfg       2024-08-02 15:18:25.000000000 +0200
+++ new/podman-py-5.3.0/setup.cfg       2024-11-25 16:27:04.000000000 +0100
@@ -1,6 +1,6 @@
 [metadata]
 name = podman
-version = 5.2.0
+version = 5.3.0
 author = Brent Baude, Jhon Honce, Urvashi Mohnani, Nicola Sella
 author_email = jho...@redhat.com
 description = Bindings for Podman RESTful API
@@ -19,19 +19,17 @@
     License :: OSI Approved :: Apache Software License
     Operating System :: OS Independent
     Programming Language :: Python :: 3 :: Only
-    Programming Language :: Python :: 3.6
-    Programming Language :: Python :: 3.7
-    Programming Language :: Python :: 3.8
     Programming Language :: Python :: 3.9
     Programming Language :: Python :: 3.10
     Programming Language :: Python :: 3.11
     Programming Language :: Python :: 3.12
+    Programming Language :: Python :: 3.13
     Topic :: Software Development :: Libraries :: Python Modules
 keywords = podman, libpod
 
 [options]
 include_package_data = True
-python_requires = >=3.6
+python_requires = >=3.9
 test_suite =
 # Any changes should be copied into pyproject.toml
 install_requires =
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podman-py-5.2.0/tox.ini new/podman-py-5.3.0/tox.ini
--- old/podman-py-5.2.0/tox.ini 2024-08-02 15:18:25.000000000 +0200
+++ new/podman-py-5.3.0/tox.ini 2024-11-25 16:27:04.000000000 +0100
@@ -1,6 +1,6 @@
 [tox]
 minversion = 3.2.0
-envlist = pylint,coverage,py36,py38,py39,py310,py311,py312
+envlist = pylint,coverage,py39,py310,py311,py312,py313
 ignore_basepython_conflict = true
 
 [testenv]

Reply via email to