Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-aiodns for openSUSE:Factory 
checked in at 2025-12-10 15:32:38
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-aiodns (Old)
 and      /work/SRC/openSUSE:Factory/.python-aiodns.new.1939 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-aiodns"

Wed Dec 10 15:32:38 2025 rev:12 rq:1321786 version:3.6.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-aiodns/python-aiodns.changes      
2025-07-18 15:58:15.285780502 +0200
+++ /work/SRC/openSUSE:Factory/.python-aiodns.new.1939/python-aiodns.changes    
2025-12-10 15:33:03.892664113 +0100
@@ -1,0 +2,23 @@
+Tue Dec  9 11:19:10 UTC 2025 - John Paul Adrian Glaubitz 
<[email protected]>
+
+- Update to 3.6.0
+  * Fix resolver garbage collection during pending queries (#211)
+    * Prevents resolver from being garbage collected while queries are in 
progress
+  * Socket callback optimizations (#172)
+    * Improved performance for socket state handling
+  * Fixed RTD links (#176)
+  * Added Python 3.14 to the CI (#212)
+  * Updated dependencies
+    * Bumped pycares from 4.9.0 to 4.11.0 (#186, #194)
+    * Bumped pytest-asyncio from 1.0.0 to 1.2.0 (#181, #196)
+    * Bumped pytest-cov from 6.2.1 to 7.0.0 (#193)
+    * Bumped pytest from 8.4.0 to 8.4.2 (#171, #190)
+    * Bumped mypy from 1.16.0 to 1.19.0 (#170, #179, #185, #195, #197, #207)
+    * Bumped uvloop from 0.21.0 to 0.22.1 (#202)
+    * Bumped winloop from 0.1.8 to 0.3.1 (#182, #183, #184, #187, #200, #201, 
#203)
+    * Bumped actions/setup-python from 5 to 6 (#199)
+    * Bumped actions/checkout from 4 to 6 (#188, #208)
+    * Bumped actions/upload-artifact from 4 to 5 (#204)
+    * Bumped actions/download-artifact from 4.3.0 to 6.0.0 (#205)
+
+-------------------------------------------------------------------

Old:
----
  aiodns-3.5.0.tar.gz

New:
----
  aiodns-3.6.0.tar.gz

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

Other differences:
------------------
++++++ python-aiodns.spec ++++++
--- /var/tmp/diff_new_pack.wLOBHA/_old  2025-12-10 15:33:04.900706614 +0100
+++ /var/tmp/diff_new_pack.wLOBHA/_new  2025-12-10 15:33:04.900706614 +0100
@@ -20,7 +20,7 @@
 %bcond_with tests
 %{?sle15_python_module_pythons}
 Name:           python-aiodns
-Version:        3.5.0
+Version:        3.6.0
 Release:        0
 Summary:        Simple DNS resolver for asyncio
 License:        MIT

++++++ aiodns-3.5.0.tar.gz -> aiodns-3.6.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aiodns-3.5.0/.github/workflows/ci.yml 
new/aiodns-3.6.0/.github/workflows/ci.yml
--- old/aiodns-3.5.0/.github/workflows/ci.yml   2025-06-13 18:19:58.000000000 
+0200
+++ new/aiodns-3.6.0/.github/workflows/ci.yml   2025-12-05 18:44:54.000000000 
+0100
@@ -15,9 +15,9 @@
     timeout-minutes: 5
     steps:
     - name: Checkout
-      uses: actions/checkout@v4
+      uses: actions/checkout@v6
     - name: Setup Python
-      uses: actions/setup-python@v5
+      uses: actions/setup-python@v6
       with:
         python-version: 3.11
     - name: Run pre-commit
@@ -29,9 +29,9 @@
     timeout-minutes: 5
     steps:
     - name: Checkout
-      uses: actions/checkout@v4
+      uses: actions/checkout@v6
     - name: Setup Python
-      uses: actions/setup-python@v5
+      uses: actions/setup-python@v6
       with:
         python-version: 3.11
         cache: 'pip'
@@ -59,7 +59,7 @@
     strategy:
       matrix:
         os: [ubuntu-latest, windows-latest, macos-latest]
-        python-version: [ '3.9', '3.10', '3.11', '3.12', '3.13' ]
+        python-version: [ '3.9', '3.10', '3.11', '3.12', '3.13', '3.14' ]
         exclude:
           - os: macos-latest
             python-version: 3.9
@@ -69,9 +69,9 @@
     timeout-minutes: 15
     steps:
     - name: Checkout
-      uses: actions/checkout@v4
+      uses: actions/checkout@v6
     - name: Setup Python
-      uses: actions/setup-python@v5
+      uses: actions/setup-python@v6
       with:
         python-version: ${{ matrix.python-version }}
         cache: 'pip'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aiodns-3.5.0/.github/workflows/release-wheels.yml 
new/aiodns-3.6.0/.github/workflows/release-wheels.yml
--- old/aiodns-3.5.0/.github/workflows/release-wheels.yml       2025-06-13 
18:19:58.000000000 +0200
+++ new/aiodns-3.6.0/.github/workflows/release-wheels.yml       2025-12-05 
18:44:54.000000000 +0100
@@ -11,15 +11,15 @@
     runs-on: ubuntu-latest
 
     steps:
-      - uses: actions/checkout@v4
-      - uses: actions/setup-python@v5
+      - uses: actions/checkout@v6
+      - uses: actions/setup-python@v6
         name: Install Python
         with:
           python-version: '3.13'
       - run: pip install setuptools wheel
       - name: Build wheels
         run: python setup.py bdist_wheel
-      - uses: actions/upload-artifact@v4
+      - uses: actions/upload-artifact@v5
         with:
           path: dist/*.whl
           name: artifact-wheels
@@ -28,15 +28,15 @@
     name: Build source distribution
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v4
-      - uses: actions/setup-python@v5
+      - uses: actions/checkout@v6
+      - uses: actions/setup-python@v6
         name: Install Python
         with:
           python-version: '3.13'
       - run: pip install setuptools
       - name: Build sdist
         run: python setup.py sdist
-      - uses: actions/upload-artifact@v4
+      - uses: actions/upload-artifact@v5
         with:
           path: dist/*.tar.gz
           name: artifact-sdist
@@ -54,7 +54,7 @@
     # upload to PyPI when a GitHub Release is created
     if: github.event_name == 'release' && github.event.action == 'published'
     steps:
-      - uses: actions/[email protected]
+      - uses: actions/[email protected]
         with:
           pattern: artifact-*
           path: dist
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aiodns-3.5.0/ChangeLog new/aiodns-3.6.0/ChangeLog
--- old/aiodns-3.5.0/ChangeLog  2025-06-13 18:19:58.000000000 +0200
+++ new/aiodns-3.6.0/ChangeLog  2025-12-05 18:44:54.000000000 +0100
@@ -1,3 +1,24 @@
+3.6.0
+=====
+- Fix resolver garbage collection during pending queries (#211)
+  - Prevents resolver from being garbage collected while queries are in 
progress
+- Socket callback optimizations (#172)
+  - Improved performance for socket state handling
+- Fixed RTD links (#176)
+- Added Python 3.14 to the CI (#212)
+- Updated dependencies
+  - Bumped pycares from 4.9.0 to 4.11.0 (#186, #194)
+  - Bumped pytest-asyncio from 1.0.0 to 1.2.0 (#181, #196)
+  - Bumped pytest-cov from 6.2.1 to 7.0.0 (#193)
+  - Bumped pytest from 8.4.0 to 8.4.2 (#171, #190)
+  - Bumped mypy from 1.16.0 to 1.19.0 (#170, #179, #185, #195, #197, #207)
+  - Bumped uvloop from 0.21.0 to 0.22.1 (#202)
+  - Bumped winloop from 0.1.8 to 0.3.1 (#182, #183, #184, #187, #200, #201, 
#203)
+  - Bumped actions/setup-python from 5 to 6 (#199)
+  - Bumped actions/checkout from 4 to 6 (#188, #208)
+  - Bumped actions/upload-artifact from 4 to 5 (#204)
+  - Bumped actions/download-artifact from 4.3.0 to 6.0.0 (#205)
+
 3.5.0
 =====
 - Added explicit close method (#166)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aiodns-3.5.0/README.rst new/aiodns-3.6.0/README.rst
--- old/aiodns-3.5.0/README.rst 2025-06-13 18:19:58.000000000 +0200
+++ new/aiodns-3.6.0/README.rst 2025-12-05 18:44:54.000000000 +0100
@@ -41,14 +41,14 @@
   instance of ``asyncio.Future``. The actual result of the DNS query is taken 
directly from pycares.
   As of version 1.0.0 of aiodns (and pycares, for that matter) results are 
always namedtuple-like
   objects with different attributes. Please check the `documentation
-  
<http://pycares.readthedocs.org/en/latest/channel.html#pycares.Channel.query>`_
+  <http://pycares.readthedocs.org/latest/channel.html#pycares.Channel.query>`_
   for the result fields.
 * ``gethostbyname(host, socket_family)``: Do a DNS resolution for the given
   hostname and the desired type of address family (i.e. ``socket.AF_INET``).
   While ``query()`` always performs a request to a DNS server,
   ``gethostbyname()`` first looks into ``/etc/hosts`` and thus can resolve
   local hostnames (such as ``localhost``).  Please check `the documentation
-  
<http://pycares.readthedocs.io/en/latest/channel.html#pycares.Channel.gethostbyname>`_
+  
<http://pycares.readthedocs.io/latest/channel.html#pycares.Channel.gethostbyname>`_
   for the result fields. The actual result of the call is a ``asyncio.Future``.
 * ``gethostbyaddr(name)``: Make a reverse lookup for an address.
 * ``cancel()``: Cancel all pending DNS queries. All futures will get 
``DNSError`` exception set, with
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aiodns-3.5.0/aiodns/__init__.py 
new/aiodns-3.6.0/aiodns/__init__.py
--- old/aiodns-3.5.0/aiodns/__init__.py 2025-06-13 18:19:58.000000000 +0200
+++ new/aiodns-3.6.0/aiodns/__init__.py 2025-12-05 18:44:54.000000000 +0100
@@ -20,7 +20,7 @@
 
 from . import error
 
-__version__ = '3.5.0'
+__version__ = '3.6.0'
 
 __all__ = ('DNSResolver', 'error')
 
@@ -33,9 +33,6 @@
 
 _LOGGER = logging.getLogger(__name__)
 
-READ = 1
-WRITE = 2
-
 query_type_map = {
     'A': pycares.QUERY_TYPE_A,
     'AAAA': pycares.QUERY_TYPE_AAAA,
@@ -131,9 +128,8 @@
     def nameservers(self, value: Iterable[Union[str, bytes]]) -> None:
         self._channel.servers = value
 
-    @staticmethod
     def _callback(
-        fut: asyncio.Future[_T], result: _T, errorno: Optional[int]
+        self, fut: asyncio.Future[_T], result: _T, errorno: Optional[int]
     ) -> None:
         if fut.cancelled():
             return
@@ -271,10 +267,14 @@
     def _sock_state_cb(self, fd: int, readable: bool, writable: bool) -> None:
         if readable or writable:
             if readable:
-                self.loop.add_reader(fd, self._handle_event, fd, READ)
+                self.loop.add_reader(
+                    fd, self._channel.process_fd, fd, pycares.ARES_SOCKET_BAD
+                )
                 self._read_fds.add(fd)
             if writable:
-                self.loop.add_writer(fd, self._handle_event, fd, WRITE)
+                self.loop.add_writer(
+                    fd, self._channel.process_fd, pycares.ARES_SOCKET_BAD, fd
+                )
                 self._write_fds.add(fd)
             if self._timer is None:
                 self._start_timer()
@@ -296,15 +296,6 @@
                 self._timer.cancel()
                 self._timer = None
 
-    def _handle_event(self, fd: int, event: int) -> None:
-        read_fd = pycares.ARES_SOCKET_BAD
-        write_fd = pycares.ARES_SOCKET_BAD
-        if event == READ:
-            read_fd = fd
-        elif event == WRITE:
-            write_fd = fd
-        self._channel.process_fd(read_fd, write_fd)
-
     def _timer_cb(self) -> None:
         if self._read_fds or self._write_fds:
             self._channel.process_fd(
@@ -335,9 +326,9 @@
             self._timer = None
 
         # Remove all file descriptors
-        for fd in list(self._read_fds):
+        for fd in self._read_fds:
             self.loop.remove_reader(fd)
-        for fd in list(self._write_fds):
+        for fd in self._write_fds:
             self.loop.remove_writer(fd)
 
         self._read_fds.clear()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aiodns-3.5.0/requirements-dev.txt 
new/aiodns-3.6.0/requirements-dev.txt
--- old/aiodns-3.5.0/requirements-dev.txt       2025-06-13 18:19:58.000000000 
+0200
+++ new/aiodns-3.6.0/requirements-dev.txt       2025-12-05 18:44:54.000000000 
+0100
@@ -1,3 +1,3 @@
 -r requirements.txt
 
-mypy==1.16.0
+mypy==1.19.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aiodns-3.5.0/requirements.txt 
new/aiodns-3.6.0/requirements.txt
--- old/aiodns-3.5.0/requirements.txt   2025-06-13 18:19:58.000000000 +0200
+++ new/aiodns-3.6.0/requirements.txt   2025-12-05 18:44:54.000000000 +0100
@@ -1,7 +1,7 @@
 -e .
-pycares==4.9.0
-pytest==8.4.0
-pytest-asyncio==1.0.0
-pytest-cov==6.2.1
-uvloop==0.21.0; platform_system != "Windows" and implementation_name == 
"cpython"
-winloop==0.1.8; platform_system == "Windows"
+pycares==4.11.0
+pytest==8.4.2
+pytest-asyncio==1.2.0
+pytest-cov==7.0.0
+uvloop==0.22.1; platform_system != "Windows" and implementation_name == 
"cpython"
+winloop==0.3.1; platform_system == "Windows"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aiodns-3.5.0/tests/test_aiodns.py 
new/aiodns-3.6.0/tests/test_aiodns.py
--- old/aiodns-3.5.0/tests/test_aiodns.py       2025-06-13 18:19:58.000000000 
+0200
+++ new/aiodns-3.6.0/tests/test_aiodns.py       2025-12-05 18:44:54.000000000 
+0100
@@ -28,14 +28,24 @@
 except ModuleNotFoundError:
     skip_uvloop = True
 
+# Skip uvloop tests on Python 3.14+ due to EventLoopPolicy deprecation
+if sys.version_info >= (3, 14):
+    skip_uvloop = True
+
 
 class DNSTest(unittest.TestCase):
     def setUp(self) -> None:
         if sys.platform == 'win32':
-            asyncio.set_event_loop_policy(
-                asyncio.WindowsSelectorEventLoopPolicy()
-            )
-        self.loop = asyncio.new_event_loop()
+            if sys.version_info >= (3, 14):
+                # Policy deprecated in 3.14, create SelectorEventLoop directly
+                self.loop = asyncio.SelectorEventLoop()
+            else:
+                asyncio.set_event_loop_policy(
+                    asyncio.WindowsSelectorEventLoopPolicy()
+                )
+                self.loop = asyncio.new_event_loop()
+        else:
+            self.loop = asyncio.new_event_loop()
         self.addCleanup(self.loop.close)
         self.resolver = aiodns.DNSResolver(loop=self.loop, timeout=5.0)
         self.resolver.nameservers = ['8.8.8.8']
@@ -217,10 +227,15 @@
 
     def setUp(self) -> None:
         if sys.platform == 'win32':
-            asyncio.set_event_loop_policy(
-                asyncio.WindowsSelectorEventLoopPolicy()
-            )
-        self.loop = asyncio.new_event_loop()
+            if sys.version_info >= (3, 14):
+                self.loop = asyncio.SelectorEventLoop()
+            else:
+                asyncio.set_event_loop_policy(
+                    asyncio.WindowsSelectorEventLoopPolicy()
+                )
+                self.loop = asyncio.new_event_loop()
+        else:
+            self.loop = asyncio.new_event_loop()
         self.addCleanup(self.loop.close)
         self.resolver = aiodns.DNSResolver(loop=self.loop)
         self.resolver.nameservers = ['1.1.1.1']
@@ -236,10 +251,15 @@
 
     def setUp(self) -> None:
         if sys.platform == 'win32':
-            asyncio.set_event_loop_policy(
-                asyncio.WindowsSelectorEventLoopPolicy()
-            )
-        self.loop = asyncio.new_event_loop()
+            if sys.version_info >= (3, 14):
+                self.loop = asyncio.SelectorEventLoop()
+            else:
+                asyncio.set_event_loop_policy(
+                    asyncio.WindowsSelectorEventLoopPolicy()
+                )
+                self.loop = asyncio.new_event_loop()
+        else:
+            self.loop = asyncio.new_event_loop()
         self.addCleanup(self.loop.close)
         self.resolver = aiodns.DNSResolver(
             timeout=0.1, tries=1, loop=self.loop
@@ -262,7 +282,7 @@
         self.assertLess(time.monotonic() - started, 1)
 
 
[email protected](skip_uvloop, "We don't have a uvloop or winloop module")
[email protected](skip_uvloop, 'uvloop/winloop unavailable or Python 3.14+')
 class TestUV_DNS(DNSTest):
     def setUp(self) -> None:
         asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
@@ -282,7 +302,7 @@
             super().setUp()
 
 
[email protected](skip_uvloop, "We don't have a uvloop or winloop module")
[email protected](skip_uvloop, 'uvloop/winloop unavailable or Python 3.14+')
 class TestUV_QueryTxtChaos(TestQueryTxtChaos):
     """Test DNS queries with CHAOS class using uvloop."""
 
@@ -294,7 +314,7 @@
         self.resolver.nameservers = ['1.1.1.1']
 
 
[email protected](skip_uvloop, "We don't have a uvloop or winloop module")
[email protected](skip_uvloop, 'uvloop/winloop unavailable or Python 3.14+')
 class TestUV_QueryTimeout(TestQueryTimeout):
     """Test DNS queries with timeout configuration using uvloop."""
 
@@ -571,7 +591,9 @@
 @pytest.mark.asyncio
 async def test_close_resolver() -> None:
     """Test that DNSResolver.close() properly shuts down the resolver."""
+    # Use a non-routable IP to ensure the query doesn't complete before close
     resolver = aiodns.DNSResolver()
+    resolver.nameservers = ['192.0.2.1']  # TEST-NET-1, non-routable
 
     # Create a query to ensure resolver is active
     query_future = resolver.query('google.com', 'A')
@@ -801,5 +823,31 @@
     assert close_count == 2
 
 
[email protected]
+async def test_temporary_resolver_not_garbage_collected() -> None:
+    """Test temporary resolver is not garbage collected before query completes.
+
+    Regression test for https://github.com/aio-libs/aiodns/issues/209
+
+    When calling query() on a temporary resolver (not stored in a variable),
+    the resolver should not be garbage collected before the query completes.
+    Previously, the callback was a @staticmethod which didn't hold a reference
+    to self, causing the resolver to be garbage collected and the query
+    cancelled.
+    """
+    # Force garbage collection to ensure any weak references are cleared
+    gc.collect()
+
+    # This pattern previously failed with DNSError(24, 'DNS query cancelled')
+    # because the resolver was garbage collected before the query completed
+    result = await aiodns.DNSResolver(nameservers=['8.8.8.8']).query(
+        'google.com', 'A'
+    )
+
+    # Query should succeed
+    assert result
+    assert len(result) > 0
+
+
 if __name__ == '__main__':  # pragma: no cover
     unittest.main(verbosity=2)

Reply via email to