Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-django-avatar for 
openSUSE:Factory checked in at 2026-01-22 15:18:30
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-django-avatar (Old)
 and      /work/SRC/openSUSE:Factory/.python-django-avatar.new.1928 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-django-avatar"

Thu Jan 22 15:18:30 2026 rev:16 rq:1328643 version:9.0.0

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-django-avatar/python-django-avatar.changes    
    2025-02-06 22:10:11.365895699 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-django-avatar.new.1928/python-django-avatar.changes
      2026-01-22 15:19:50.984407227 +0100
@@ -1,0 +2,9 @@
+Thu Jan 22 08:38:48 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 9.0.0:
+  * Fix files not closed in create_thumbnail
+  * Add Django 5.2 and 6.0 support
+  * Add Python 3.13, 3.14 support
+  * Drop Python 3.8, 3.9 support
+
+-------------------------------------------------------------------

Old:
----
  django-avatar-8.0.1.tar.gz

New:
----
  django-avatar-9.0.0.tar.gz

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

Other differences:
------------------
++++++ python-django-avatar.spec ++++++
--- /var/tmp/diff_new_pack.WuezNn/_old  2026-01-22 15:19:51.648434848 +0100
+++ /var/tmp/diff_new_pack.WuezNn/_new  2026-01-22 15:19:51.652435015 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-django-avatar
 #
-# Copyright (c) 2025 SUSE LLC
+# Copyright (c) 2026 SUSE LLC and contributors
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,7 +18,7 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-django-avatar
-Version:        8.0.1
+Version:        9.0.0
 Release:        0
 Summary:        Django-avatar package
 License:        BSD-3-Clause

++++++ django-avatar-8.0.1.tar.gz -> django-avatar-9.0.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-avatar-8.0.1/.github/workflows/release.yml 
new/django-avatar-9.0.0/.github/workflows/release.yml
--- old/django-avatar-8.0.1/.github/workflows/release.yml       2024-09-05 
04:07:29.000000000 +0200
+++ new/django-avatar-9.0.0/.github/workflows/release.yml       2026-01-07 
22:07:17.000000000 +0100
@@ -11,12 +11,12 @@
     runs-on: ubuntu-latest
 
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v6
         with:
           fetch-depth: 0
 
       - name: Set up Python
-        uses: actions/setup-python@v2
+        uses: actions/setup-python@v6
         with:
           python-version: 3.11
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-avatar-8.0.1/.github/workflows/test.yml 
new/django-avatar-9.0.0/.github/workflows/test.yml
--- old/django-avatar-8.0.1/.github/workflows/test.yml  2024-09-05 
04:07:29.000000000 +0200
+++ new/django-avatar-9.0.0/.github/workflows/test.yml  2026-01-07 
22:07:17.000000000 +0100
@@ -5,32 +5,26 @@
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
-        django-version: ['3.2', '4.1', '4.2', '5.0', '5.1.*']
+        python-version: ['3.10', '3.11', '3.12', '3.13', '3.14']
+        django-version: ['4.2', '5.2', '6.0.*']
         exclude:
-          - python-version: 3.11
-            django-version: 3.2
-
-          - python-version: 3.12
-            django-version: 3.2
+          - python-version: 3.13
+            django-version: 4.2
 
-          - python-version: 3.8
-            django-version: 5.0
+          - python-version: 3.14
+            django-version: 4.2
 
-          - python-version: 3.9
-            django-version: 5.0
+          - python-version: 3.10
+            django-version: 6.0.*
 
-          - python-version: 3.8
-            django-version: 5.1.*
-
-          - python-version: 3.9
-            django-version: 5.1.*
+          - python-version: 3.11
+            django-version: 6.0.*
       fail-fast: false
 
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v6
       - name: 'Set up Python ${{ matrix.python-version }}'
-        uses: actions/setup-python@v3
+        uses: actions/setup-python@v6
         with:
           python-version: '${{ matrix.python-version }}'
           cache: 'pip'
@@ -48,4 +42,4 @@
           coverage report
           coverage xml
       - name: Upload coverage reports to Codecov with GitHub Action
-        uses: codecov/codecov-action@v3
+        uses: codecov/codecov-action@v5
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-avatar-8.0.1/.pre-commit-config.yaml 
new/django-avatar-9.0.0/.pre-commit-config.yaml
--- old/django-avatar-8.0.1/.pre-commit-config.yaml     2024-09-05 
04:07:29.000000000 +0200
+++ new/django-avatar-9.0.0/.pre-commit-config.yaml     2026-01-07 
22:07:17.000000000 +0100
@@ -1,24 +1,24 @@
 repos:
   - repo: https://github.com/pre-commit/pre-commit-hooks
-    rev: v4.6.0
+    rev: v6.0.0
     hooks:
       - id: end-of-file-fixer
       - id: trailing-whitespace
 
   - repo: https://github.com/pycqa/isort
-    rev: "5.13.2"
+    rev: "7.0.0"
     hooks:
         - id: isort
           args: ["--profile", "black"]
 
   - repo: https://github.com/psf/black
-    rev: 24.8.0
+    rev: 25.12.0
     hooks:
       - id: black
         args: [--target-version=py310]
 
   - repo: https://github.com/pycqa/flake8
-    rev: '7.1.1'
+    rev: '7.3.0'
     hooks:
       - id: flake8
         additional_dependencies:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-avatar-8.0.1/CHANGELOG.rst 
new/django-avatar-9.0.0/CHANGELOG.rst
--- old/django-avatar-8.0.1/CHANGELOG.rst       2024-09-05 04:07:29.000000000 
+0200
+++ new/django-avatar-9.0.0/CHANGELOG.rst       2026-01-07 22:07:17.000000000 
+0100
@@ -1,5 +1,11 @@
 Changelog
 =========
+* 9.0.0
+    * Fix files not closed in `create_thumbnail`
+    * Add Django 5.2 and 6.0 support
+    * Add Python 3.13, 3.14 support
+    * Drop Python 3.8, 3.9 support
+
 * 8.0.1
     * Fix Django 5.1 compatibility
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-avatar-8.0.1/avatar/__init__.py 
new/django-avatar-9.0.0/avatar/__init__.py
--- old/django-avatar-8.0.1/avatar/__init__.py  2024-09-05 04:07:29.000000000 
+0200
+++ new/django-avatar-9.0.0/avatar/__init__.py  2026-01-07 22:07:17.000000000 
+0100
@@ -1 +1 @@
-__version__ = "8.0.1"
+__version__ = "9.0.0"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-avatar-8.0.1/avatar/models.py 
new/django-avatar-9.0.0/avatar/models.py
--- old/django-avatar-8.0.1/avatar/models.py    2024-09-05 04:07:29.000000000 
+0200
+++ new/django-avatar-9.0.0/avatar/models.py    2026-01-07 22:07:17.000000000 
+0100
@@ -1,6 +1,7 @@
 import binascii
 import hashlib
 import os
+from contextlib import closing
 from io import BytesIO
 
 from django.core.files import File
@@ -142,38 +143,38 @@
             orig = self.avatar.storage.open(self.avatar.name, "rb")
         except IOError:
             return  # What should we do here?  Render a "sorry, didn't work" 
img?
-        try:
-            image = Image.open(orig)
-            image = self.transpose_image(image)
-            quality = quality or settings.AVATAR_THUMB_QUALITY
-            w, h = image.size
-            if w != width or h != height:
-                ratioReal = 1.0 * w / h
-                ratioWant = 1.0 * width / height
-                if ratioReal > ratioWant:
-                    diff = int((w - (h * ratioWant)) / 2)
-                    image = image.crop((diff, 0, w - diff, h))
-                elif ratioReal < ratioWant:
-                    diff = int((h - (w / ratioWant)) / 2)
-                    image = image.crop((0, diff, w, h - diff))
-                if settings.AVATAR_THUMB_FORMAT == "JPEG" and image.mode == 
"RGBA":
-                    image = image.convert("RGB")
-                elif image.mode not in (settings.AVATAR_THUMB_MODES):
-                    image = image.convert(settings.AVATAR_THUMB_MODES[0])
-                image = image.resize((width, height), 
settings.AVATAR_RESIZE_METHOD)
-                thumb = BytesIO()
-                image.save(thumb, settings.AVATAR_THUMB_FORMAT, 
quality=quality)
-                thumb_file = ContentFile(thumb.getvalue())
-            else:
+
+        with closing(orig):
+            try:
+                image = Image.open(orig)
+            except IOError:
                 thumb_file = File(orig)
+            else:
+                image = self.transpose_image(image)
+                quality = quality or settings.AVATAR_THUMB_QUALITY
+                w, h = image.size
+                if w != width or h != height:
+                    ratioReal = 1.0 * w / h
+                    ratioWant = 1.0 * width / height
+                    if ratioReal > ratioWant:
+                        diff = int((w - (h * ratioWant)) / 2)
+                        image = image.crop((diff, 0, w - diff, h))
+                    elif ratioReal < ratioWant:
+                        diff = int((h - (w / ratioWant)) / 2)
+                        image = image.crop((0, diff, w, h - diff))
+                    if settings.AVATAR_THUMB_FORMAT == "JPEG" and image.mode 
== "RGBA":
+                        image = image.convert("RGB")
+                    elif image.mode not in (settings.AVATAR_THUMB_MODES):
+                        image = image.convert(settings.AVATAR_THUMB_MODES[0])
+                    image = image.resize((width, height), 
settings.AVATAR_RESIZE_METHOD)
+                    thumb = BytesIO()
+                    image.save(thumb, settings.AVATAR_THUMB_FORMAT, 
quality=quality)
+                    thumb_file = ContentFile(thumb.getvalue())
+                else:
+                    thumb_file = File(orig)
             thumb_name = self.avatar_name(width, height)
             thumb = self.avatar.storage.save(thumb_name, thumb_file)
-        except IOError:
-            thumb_file = File(orig)
-            thumb = self.avatar.storage.save(
-                self.avatar_name(width, height), thumb_file
-            )
-        invalidate_cache(self.user, width, height)
+            invalidate_cache(self.user, width, height)
 
     def avatar_url(self, width, height=None):
         return self.avatar.storage.url(self.avatar_name(width, height))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-avatar-8.0.1/avatar/providers.py 
new/django-avatar-9.0.0/avatar/providers.py
--- old/django-avatar-8.0.1/avatar/providers.py 2024-09-05 04:07:29.000000000 
+0200
+++ new/django-avatar-9.0.0/avatar/providers.py 2026-01-07 22:07:17.000000000 
+0100
@@ -68,7 +68,7 @@
 
 class LibRAvatarProvider:
     """
-    Returns the url of an avatar by the Ravatar service.
+    Returns the url of an avatar by the LibRavatar service.
     """
 
     @classmethod
@@ -87,8 +87,17 @@
                 baseurl = "http://"; + hostname + ":" + port + "/avatar/"
         except Exception:
             baseurl = "https://seccdn.libravatar.org/avatar/";
-        hash = hashlib.md5(email.strip().lower()).hexdigest()
-        return baseurl + hash
+
+        params = {"s": str(width)}
+        if settings.AVATAR_GRAVATAR_DEFAULT:
+            params["d"] = settings.AVATAR_GRAVATAR_DEFAULT
+        if settings.AVATAR_GRAVATAR_FORCEDEFAULT:
+            params["f"] = "y"
+        path = "%s/?%s" % (
+            hashlib.md5(force_bytes(email.strip().lower())).hexdigest(),
+            urlencode(params),
+        )
+        return urljoin(baseurl, path)
 
 
 class FacebookAvatarProvider(object):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/django-avatar-8.0.1/avatar/templates/avatar/confirm_delete.html 
new/django-avatar-9.0.0/avatar/templates/avatar/confirm_delete.html
--- old/django-avatar-8.0.1/avatar/templates/avatar/confirm_delete.html 
2024-09-05 04:07:29.000000000 +0200
+++ new/django-avatar-9.0.0/avatar/templates/avatar/confirm_delete.html 
2026-01-07 22:07:17.000000000 +0100
@@ -3,7 +3,7 @@
 
 {% block content %}
     {% if not avatars %}
-        {% url 'avatar_change' as avatar_change_url %}
+        {% url 'avatar:change' as avatar_change_url %}
         <p>{% blocktrans %}You have no avatars to delete. Please <a href="{{ 
avatar_change_url }}">upload one</a> now.{% endblocktrans %}</p>
     {% else %}
         <p>{% trans "Please select the avatars that you would like to delete." 
%}</p>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-avatar-8.0.1/pyproject.toml 
new/django-avatar-9.0.0/pyproject.toml
--- old/django-avatar-8.0.1/pyproject.toml      2024-09-05 04:07:29.000000000 
+0200
+++ new/django-avatar-9.0.0/pyproject.toml      2026-01-07 22:07:17.000000000 
+0100
@@ -13,20 +13,20 @@
 classifiers=[
         "Development Status :: 5 - Production/Stable",
         "Environment :: Web Environment",
-        "Framework :: Django",
         "Intended Audience :: Developers",
         "Framework :: Django",
-        "Framework :: Django :: 3.2",
-        "Framework :: Django :: 4.1",
         "Framework :: Django :: 4.2",
+        "Framework :: Django :: 5.0",
+        "Framework :: Django :: 5.2",
+        "Framework :: Django :: 6.0",
         "License :: OSI Approved :: BSD License",
         "Operating System :: OS Independent",
         "Programming Language :: Python",
-        "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",
+        "Programming Language :: Python :: 3.14",
     ]
 dynamic = ["version", "dependencies"]
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django-avatar-8.0.1/tests/tests.py 
new/django-avatar-9.0.0/tests/tests.py
--- old/django-avatar-8.0.1/tests/tests.py      2024-09-05 04:07:29.000000000 
+0200
+++ new/django-avatar-9.0.0/tests/tests.py      2026-01-07 22:07:17.000000000 
+0100
@@ -1,7 +1,9 @@
 import math
 import os.path
+import sys
 from pathlib import Path
 from shutil import rmtree
+from unittest import skipIf
 
 from django.contrib.admin.sites import AdminSite
 from django.core import management
@@ -118,6 +120,7 @@
         self.assertTrue(avatar.primary)
 
     # We allow the .tiff file extension but not the mime type
+    @skipIf(sys.platform == "win32", "Skipping test on Windows platform")
     @override_settings(AVATAR_ALLOWED_FILE_EXTS=(".png", ".gif", ".jpg", 
".tiff"))
     @override_settings(
         AVATAR_ALLOWED_MIMETYPES=("image/png", "image/gif", "image/jpeg")
@@ -130,6 +133,7 @@
         self.assertNotEqual(response.context["upload_avatar_form"].errors, {})
 
     # We allow the .tiff file extension and the mime type
+    @skipIf(sys.platform == "win32", "Skipping test on Windows platform")
     @override_settings(AVATAR_ALLOWED_FILE_EXTS=(".png", ".gif", ".jpg", 
".tiff"))
     @override_settings(
         AVATAR_ALLOWED_MIMETYPES=("image/png", "image/gif", "image/jpeg", 
"image/tiff")
@@ -141,6 +145,7 @@
         self.assertEqual(len(response.redirect_chain), 1)  # Redirect only if 
it worked
         self.assertEqual(response.context["upload_avatar_form"].errors, {})
 
+    @skipIf(sys.platform == "win32", "Skipping test on Windows platform")
     @override_settings(AVATAR_ALLOWED_FILE_EXTS=(".jpg", ".png"))
     def test_image_without_wrong_extension(self):
         response = upload_helper(self, "imagefilewithoutext")
@@ -148,6 +153,7 @@
         self.assertEqual(len(response.redirect_chain), 0)  # Redirect only if 
it worked
         self.assertNotEqual(response.context["upload_avatar_form"].errors, {})
 
+    @skipIf(sys.platform == "win32", "Skipping test on Windows platform")
     @override_settings(AVATAR_ALLOWED_FILE_EXTS=(".jpg", ".png"))
     def test_image_with_wrong_extension(self):
         response = upload_helper(self, "imagefilewithwrongext.ogg")

Reply via email to