Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-yamllint for openSUSE:Factory 
checked in at 2026-02-04 21:06:21
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-yamllint (Old)
 and      /work/SRC/openSUSE:Factory/.python-yamllint.new.1670 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-yamllint"

Wed Feb  4 21:06:21 2026 rev:23 rq:1327663 version:1.38.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-yamllint/python-yamllint.changes  
2025-08-26 14:57:47.244375547 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-yamllint.new.1670/python-yamllint.changes    
    2026-02-04 21:06:25.025403470 +0100
@@ -1,0 +2,14 @@
+Fri Jan 16 06:40:58 UTC 2026 - Johannes Kastl 
<[email protected]>
+
+- update to 1.38.0:
+  * Add support for Python 3.14, drop support for Python 3.9
+  * Require pathspec ≥ 1.0.0
+  * Config: Follow gitignore implementation in yaml-files and ignore
+  * Config: Use "mapping" instead of "dict" for user-facing errors
+  * Rule indentation: Fix error message for check-multi-line-strings
+  * Rule quoted-strings: Add quote-type: consistent
+  * Docs: Update the name of BSD ports
+  * Docs: Enhance wording of recursive directory lint in README
+  * Docs: Add Alpine Linux installation instructions in README
+
+-------------------------------------------------------------------

Old:
----
  yamllint-1.37.1.tar.gz

New:
----
  yamllint-1.38.0.tar.gz

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

Other differences:
------------------
++++++ python-yamllint.spec ++++++
--- /var/tmp/diff_new_pack.Oa0woh/_old  2026-02-04 21:06:27.889523418 +0100
+++ /var/tmp/diff_new_pack.Oa0woh/_new  2026-02-04 21:06:27.917524591 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-yamllint
 #
-# Copyright (c) 2025 SUSE LLC and contributors
+# 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
@@ -23,21 +23,24 @@
 %endif
 %{?sle15_python_module_pythons}
 Name:           python-yamllint
-Version:        1.37.1
+Version:        1.38.0
 Release:        0
 Summary:        A linter for YAML files
 License:        GPL-3.0-only
 Group:          Development/Languages/Python
 URL:            https://github.com/adrienverge/yamllint
 Source:         
https://files.pythonhosted.org/packages/source/y/yamllint/yamllint-%{version}.tar.gz
-BuildRequires:  %{python_module base >= 3.8}
+BuildRequires:  %{python_module base >= 3.10}
 BuildRequires:  %{python_module pip}
 BuildRequires:  %{python_module setuptools}
 BuildRequires:  %{python_module wheel}
+# Runtime dependencies
+BuildRequires:  %{python_module PyYAML}
+BuildRequires:  %{python_module pathspec >= 1.0.0}
 BuildRequires:  fdupes
 BuildRequires:  python-rpm-macros
 Requires:       python-PyYAML
-Requires:       python-pathspec >= 0.5.3
+Requires:       python-pathspec >= 1.0.0
 BuildArch:      noarch
 %if %{with libalternatives}
 BuildRequires:  alts

++++++ yamllint-1.37.1.tar.gz -> yamllint-1.38.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yamllint-1.37.1/CHANGELOG.rst 
new/yamllint-1.38.0/CHANGELOG.rst
--- old/yamllint-1.37.1/CHANGELOG.rst   2025-05-04 10:25:26.000000000 +0200
+++ new/yamllint-1.38.0/CHANGELOG.rst   2026-01-13 08:47:21.000000000 +0100
@@ -1,6 +1,19 @@
 Changelog
 =========
 
+1.38.0 (2026-01-13)
+-------------------
+
+- Add support for Python 3.14, drop support for Python 3.9
+- Require pathspec ≥ 1.0.0
+- Config: Follow gitignore implementation in ``yaml-files`` and ``ignore``
+- Config: Use "mapping" instead of "dict" for user-facing errors
+- Rule ``indentation``: Fix error message for ``check-multi-line-strings``
+- Rule ``quoted-strings``: Add ``quote-type: consistent``
+- Docs: Update the name of BSD ports
+- Docs: Enhance wording of recursive directory lint in README
+- Docs: Add Alpine Linux installation instructions in README
+
 1.37.1 (2025-05-04)
 -------------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yamllint-1.37.1/PKG-INFO new/yamllint-1.38.0/PKG-INFO
--- old/yamllint-1.37.1/PKG-INFO        2025-05-04 10:25:33.245692500 +0200
+++ new/yamllint-1.38.0/PKG-INFO        2026-01-13 08:47:29.694193600 +0100
@@ -1,9 +1,9 @@
 Metadata-Version: 2.4
 Name: yamllint
-Version: 1.37.1
+Version: 1.38.0
 Summary: A linter for YAML files.
 Author: Adrien Vergé
-License: GPL-3.0-or-later
+License-Expression: GPL-3.0-or-later
 Project-URL: homepage, https://github.com/adrienverge/yamllint
 Project-URL: repository, https://github.com/adrienverge/yamllint
 Project-URL: documentation, https://yamllint.readthedocs.io
@@ -11,22 +11,22 @@
 Classifier: Development Status :: 5 - Production/Stable
 Classifier: Environment :: Console
 Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
 Classifier: Programming Language :: Python
 Classifier: Topic :: Software Development
 Classifier: Topic :: Software Development :: Debuggers
 Classifier: Topic :: Software Development :: Quality Assurance
 Classifier: Topic :: Software Development :: Testing
-Requires-Python: >=3.9
+Requires-Python: >=3.10
 Description-Content-Type: text/x-rst
 License-File: LICENSE
-Requires-Dist: pathspec>=0.5.3
+Requires-Dist: pathspec>=1.0.0
 Requires-Dist: pyyaml
 Provides-Extra: dev
 Requires-Dist: doc8; extra == "dev"
 Requires-Dist: flake8; extra == "dev"
 Requires-Dist: flake8-import-order; extra == "dev"
 Requires-Dist: rstcheck[sphinx]; extra == "dev"
+Requires-Dist: ruff; extra == "dev"
 Requires-Dist: sphinx; extra == "dev"
 Dynamic: license-file
 
@@ -51,7 +51,7 @@
    :target: https://yamllint.readthedocs.io/en/latest/?badge=latest
    :alt: Documentation status
 
-Written in Python (compatible with Python 3 only).
+Written in Python.
 
 Documentation
 -------------
@@ -90,7 +90,7 @@
 
 .. code:: bash
 
- # Lint all YAML files in a directory
+ # Recursively lint all YAML files in a directory
  yamllint .
 
 .. code:: bash
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yamllint-1.37.1/README.rst 
new/yamllint-1.38.0/README.rst
--- old/yamllint-1.37.1/README.rst      2025-05-04 10:25:26.000000000 +0200
+++ new/yamllint-1.38.0/README.rst      2026-01-13 08:47:21.000000000 +0100
@@ -19,7 +19,7 @@
    :target: https://yamllint.readthedocs.io/en/latest/?badge=latest
    :alt: Documentation status
 
-Written in Python (compatible with Python 3 only).
+Written in Python.
 
 Documentation
 -------------
@@ -58,7 +58,7 @@
 
 .. code:: bash
 
- # Lint all YAML files in a directory
+ # Recursively lint all YAML files in a directory
  yamllint .
 
 .. code:: bash
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yamllint-1.37.1/docs/conf.py 
new/yamllint-1.38.0/docs/conf.py
--- old/yamllint-1.37.1/docs/conf.py    2025-05-04 10:25:26.000000000 +0200
+++ new/yamllint-1.38.0/docs/conf.py    2026-01-13 08:47:21.000000000 +0100
@@ -6,7 +6,7 @@
 from unittest.mock import MagicMock
 
 sys.path.insert(0, os.path.abspath('..'))
-from yamllint import __copyright__, APP_NAME, APP_VERSION  # noqa: E402
+from yamllint import APP_NAME, APP_VERSION, __copyright__  # noqa: E402
 
 # -- General configuration ------------------------------------------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yamllint-1.37.1/docs/quickstart.rst 
new/yamllint-1.38.0/docs/quickstart.rst
--- old/yamllint-1.37.1/docs/quickstart.rst     2025-05-04 10:25:26.000000000 
+0200
+++ new/yamllint-1.38.0/docs/quickstart.rst     2026-01-13 08:47:21.000000000 
+0100
@@ -27,13 +27,19 @@
 
 .. code:: sh
 
-  pkg install py36-yamllint
+  pkg install py-yamllint
 
 On OpenBSD:
 
 .. code:: sh
 
-  doas pkg_add py3-yamllint
+  doas pkg_add py-yamllint
+
+On Alpine Linux:
+
+.. code:: bash
+
+  pkg add yamllint
 
 Alternatively using pip, the Python package manager:
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yamllint-1.37.1/pyproject.toml 
new/yamllint-1.38.0/pyproject.toml
--- old/yamllint-1.37.1/pyproject.toml  2025-05-04 10:25:26.000000000 +0200
+++ new/yamllint-1.38.0/pyproject.toml  2026-01-13 08:47:21.000000000 +0100
@@ -2,15 +2,14 @@
 name = "yamllint"
 description = "A linter for YAML files."
 readme = {file = "README.rst", content-type = "text/x-rst"}
-requires-python = ">=3.9"
-license = {text = "GPL-3.0-or-later"}
+requires-python = ">=3.10"
+license = "GPL-3.0-or-later"
 authors = [{name = "Adrien Vergé"}]
 keywords = ["yaml", "lint", "linter", "syntax", "checker"]
 classifiers = [
     "Development Status :: 5 - Production/Stable",
     "Environment :: Console",
     "Intended Audience :: Developers",
-    "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
     "Programming Language :: Python",
     "Topic :: Software Development",
     "Topic :: Software Development :: Debuggers",
@@ -18,7 +17,7 @@
     "Topic :: Software Development :: Testing",
 ]
 dependencies = [
-    "pathspec >= 0.5.3",
+    "pathspec >= 1.0.0",
     "pyyaml",
 ]
 dynamic = ["version"]
@@ -29,6 +28,7 @@
     "flake8",
     "flake8-import-order",
     "rstcheck[sphinx]",
+    "ruff",
     "sphinx",
 ]
 
@@ -42,7 +42,7 @@
 
 [build-system]
 build-backend = "setuptools.build_meta"
-requires = ["setuptools >= 61"]
+requires = ["setuptools >= 77.0.3"]
 
 [tool.setuptools]
 packages = ["yamllint", "yamllint.conf", "yamllint.rules"]
@@ -52,3 +52,49 @@
 
 [tool.setuptools.dynamic]
 version = {attr = "yamllint.__version__"}
+
+[tool.ruff]
+line-length = 79
+
+[tool.ruff.lint]
+extend-select = [
+    "B",
+    "C4",
+    "EXE",
+    "FA",
+    "ISC",
+    "LOG",
+    "G",
+    "PIE",
+    "PYI",
+    "SIM",
+    "FLY",
+    "I",
+    "PERF",
+    "W",
+    "PGH",
+    "PLC",
+    "PLE",
+    "UP",
+    "FURB",
+    "RUF",
+]
+ignore = [
+    "B028",     # No explicit `stacklevel` keyword argument found
+    "SIM102",   # Use a single `if` statement instead of nested `if` statements
+    "SIM103",   # Return the negated condition directly
+    "SIM105",   # Use `contextlib.suppress(KeyError)` instead of 
`try`-`except`-`pass`
+    "SIM108",   # Use ternary operator instead of `if`-`else`-block
+    "SIM114",   # Combine `if` branches using logical `or` operator
+    "SIM117",   # Use a single `with` statement with multiple contexts
+    "FURB105",  # Unnecessary empty string passed to `print`
+    "RUF001",   # String contains ambiguous Unicode characters
+    "RUF002",   # Docstring contains ambiguous Unicode characters
+    "RUF003",   # Comment contains ambiguous Unicode characters
+    "RUF005",   # Consider unpacking instead of concatenation
+    "RUF100",   # Unused `noqa` directive
+]
+
+[tool.ruff.lint.isort]
+force-sort-within-sections = true
+known-third-party = ["tests"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yamllint-1.37.1/setup.py new/yamllint-1.38.0/setup.py
--- old/yamllint-1.37.1/setup.py        2025-05-04 10:25:26.000000000 +0200
+++ new/yamllint-1.38.0/setup.py        1970-01-01 01:00:00.000000000 +0100
@@ -1,20 +0,0 @@
-# Copyright (C) 2016 Adrien Vergé
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-from setuptools import setup
-
-# This is only kept for backward-compatibility with older versions that don't
-# support new packaging standards (e.g. PEP 517 or PEP 660):
-setup()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yamllint-1.37.1/tests/__init__.py 
new/yamllint-1.38.0/tests/__init__.py
--- old/yamllint-1.37.1/tests/__init__.py       2025-05-04 10:25:26.000000000 
+0200
+++ new/yamllint-1.38.0/tests/__init__.py       2026-01-13 08:47:21.000000000 
+0100
@@ -34,5 +34,5 @@
 for name in env_vars_that_could_interfere_with_tests:
     try:
         del os.environ[name]
-    except KeyError:
+    except KeyError:  # noqa: PERF203
         pass
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yamllint-1.37.1/tests/common.py 
new/yamllint-1.38.0/tests/common.py
--- old/yamllint-1.37.1/tests/common.py 2025-05-04 10:25:26.000000000 +0200
+++ new/yamllint-1.38.0/tests/common.py 2026-01-13 08:47:21.000000000 +0100
@@ -15,6 +15,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 import codecs
+from codecs import CodecInfo
 import contextlib
 from io import StringIO
 import os
@@ -22,15 +23,12 @@
 import sys
 import tempfile
 import unittest
-import warnings
-from codecs import CodecInfo
 
 import yaml
 
 from yamllint import linter
 from yamllint.config import YamlLintConfig
 
-
 # Encoding related stuff:
 UTF_CODECS = (
     'utf_32_be',
@@ -91,17 +89,11 @@
 
 
 def unregister_test_codecs():
-    if sys.version_info >= (3, 10, 0):
-        codecs.unregister(test_codec_infos.get)
-    else:
-        warnings.warn(
-            "This version of Python doesn’t allow us to unregister codecs.",
-            stacklevel=1
-        )
+    codecs.unregister(test_codec_infos.get)
 
 
 def is_test_codec(codec):
-    return codec in test_codec_infos.keys()
+    return codec in test_codec_infos
 
 
 def built_in_equivalent_of_test_codec(test_codec):
@@ -112,10 +104,7 @@
 
 
 def uses_bom(codec):
-    for suffix in ('_32', '_16', '_sig'):
-        if codec.endswith(suffix):
-            return True
-    return False
+    return any(codec.endswith(suffix) for suffix in ('_32', '_16', '_sig'))
 
 
 def encoding_detectable(string, codec):
@@ -193,17 +182,17 @@
 
     def check(self, source, conf, **kwargs):
         expected_problems = []
-        for key in kwargs:
+        for key, value in kwargs.items():
             assert key.startswith('problem')
-            if len(kwargs[key]) > 2:
-                if kwargs[key][2] == 'syntax':
+            if len(value) > 2:
+                if value[2] == 'syntax':
                     rule_id = None
                 else:
-                    rule_id = kwargs[key][2]
+                    rule_id = value[2]
             else:
                 rule_id = self.rule_id
             expected_problems.append(linter.LintProblem(
-                kwargs[key][0], kwargs[key][1], rule=rule_id))
+                value[0], value[1], rule=rule_id))
         expected_problems.sort()
 
         real_problems = list(linter.run(source, self.build_fake_config(conf)))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yamllint-1.37.1/tests/rules/test_line_length.py 
new/yamllint-1.38.0/tests/rules/test_line_length.py
--- old/yamllint-1.37.1/tests/rules/test_line_length.py 2025-05-04 
10:25:26.000000000 +0200
+++ new/yamllint-1.38.0/tests/rules/test_line_length.py 2026-01-13 
08:47:21.000000000 +0100
@@ -143,8 +143,8 @@
                    conf, problem=(2, 21))
 
     def test_non_breakable_inline_mappings(self):
-        conf = 'line-length: {max: 20, ' \
-               'allow-non-breakable-inline-mappings: true}'
+        conf = ('line-length: {max: 20, '
+                'allow-non-breakable-inline-mappings: true}')
         self.check('---\n'
                    'long_line: http://localhost/very/very/long/url\n'
                    'long line: http://localhost/very/very/long/url\n', conf)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yamllint-1.37.1/tests/rules/test_quoted_strings.py 
new/yamllint-1.38.0/tests/rules/test_quoted_strings.py
--- old/yamllint-1.37.1/tests/rules/test_quoted_strings.py      2025-05-04 
10:25:26.000000000 +0200
+++ new/yamllint-1.38.0/tests/rules/test_quoted_strings.py      2026-01-13 
08:47:21.000000000 +0100
@@ -186,6 +186,47 @@
                    '   word 2"\n',
                    conf, problem1=(9, 3))
 
+    def test_quote_type_consistent(self):
+        conf = 'quoted-strings: {quote-type: consistent}'
+        self.check('---\n'
+                   'string1: "foo"\n'
+                   'string2: "bar"\n'
+                   'string3: \'baz\'\n'              # fails
+                   'string4: "quux"\n',
+                   conf, problem1=(4, 10))
+
+        conf = ('quoted-strings:\n'
+                '  quote-type: consistent\n'
+                '  check-keys: true\n')
+        self.check('---\n'
+                   '"string1": "foo"\n'
+                   'string2: "bar"\n'                # fails
+                   '\'string3\': "baz"\n'            # fails
+                   '"string4": {"key": "val"}\n'
+                   '"string5": {\'key\': "val"}\n',  # fails
+                   conf, problem1=(3, 1), problem2=(4, 1), problem3=(6, 13))
+
+        conf = ('quoted-strings:\n'
+                '  quote-type: consistent\n'
+                '  check-keys: true\n'
+                '  required: false\n')
+        self.check('---\n'
+                   'string1: \'foo\'\n'
+                   'string2: "bar"\n'               # fails
+                   'string3: \'baz\'\n'
+                   'string4: {\'key\': "val"}\n'    # fails
+                   'string5: {"key": \'val\'}\n'    # fails
+                   'string6:\n'
+                   '  \'key\': "val"\n'             # fails
+                   'string7:\n'
+                   '  "key": \'val\'\n'             # fails
+                   'string8:\n'
+                   '  "string"\n'                   # fails
+                   'string9: >\n'
+                   '  "string"\n',
+                   conf, problem1=(3, 10), problem2=(5, 18), problem3=(6, 11),
+                   problem4=(8, 10), problem5=(10, 3), problem6=(12, 3))
+
     def test_any_quotes_not_required(self):
         conf = 'quoted-strings: {quote-type: any, required: false}\n'
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yamllint-1.37.1/tests/test_cli.py 
new/yamllint-1.38.0/tests/test_cli.py
--- old/yamllint-1.37.1/tests/test_cli.py       2025-05-04 10:25:26.000000000 
+0200
+++ new/yamllint-1.38.0/tests/test_cli.py       2026-01-13 08:47:21.000000000 
+0100
@@ -29,7 +29,7 @@
     register_test_codecs,
     temp_workspace,
     temp_workspace_with_files_in_many_codecs,
-    unregister_test_codecs
+    unregister_test_codecs,
 )
 
 from yamllint import cli, config
@@ -270,7 +270,7 @@
             cli.run(('-d', '', 'file'))
         self.assertEqual(ctx.returncode, -1)
         self.assertEqual(ctx.stdout, '')
-        self.assertRegex(ctx.stderr, r'^invalid config: not a dict')
+        self.assertRegex(ctx.stderr, r'^invalid config: not a mapping')
 
     def test_run_with_implicit_extends_config(self):
         path = os.path.join(self.wd, 'warn.yaml')
@@ -624,7 +624,7 @@
                 file.write(
                     'I am a string\n'
                     'therefore: I am an error\n')
-            with open(stdin_file_path, mode='r', encoding='utf-8') as file:
+            with open(stdin_file_path, encoding='utf-8') as file:
                 # prepares stdin with an invalid yaml string so that we can
                 # check for its specific error, and be assured that stdin was
                 # read
@@ -844,7 +844,7 @@
             # We purposely choose the wrong text encoding here because the text
             # encoding shouldn’t matter. yamllint should completely ignore the
             # text encoding of stdin.
-            with open(path, mode="r", encoding="cp037") as file:
+            with open(path, encoding="cp037") as file:
                 sys.stdin = file
                 with RunContext(self) as ctx:
                     cli.run(('-c', config_path, '-'))
@@ -855,7 +855,7 @@
                     self.assertNotEqual(ctx.returncode, 0)
                 else:
                     raise ValueError(
-                        f"root_dir was set to {repr(root_dir)}. It should only"
+                        f"root_dir was set to {root_dir!r}. It should only"
                         "ever be set to 'sorted_correctly' or"
                         "'sorted_incorrectly'."
                     )
@@ -891,7 +891,7 @@
         }
 
         with temp_workspace(workspace):
-            for config_path in config_files.keys():
+            for config_path in config_files:
                 # First, make sure that encoding autodetection works when the
                 # file’s path is given as a command-line argument.
                 with RunContext(self) as ctx:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yamllint-1.37.1/tests/test_config.py 
new/yamllint-1.38.0/tests/test_config.py
--- old/yamllint-1.37.1/tests/test_config.py    2025-05-04 10:25:26.000000000 
+0200
+++ new/yamllint-1.38.0/tests/test_config.py    2026-01-13 08:47:21.000000000 
+0100
@@ -14,18 +14,18 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+from io import StringIO
 import itertools
 import os
 import shutil
 import sys
 import tempfile
 import unittest
-from io import StringIO
 
 from tests.common import (
+    RunContext,
     build_temp_workspace,
     register_test_codecs,
-    RunContext,
     unregister_test_codecs,
 )
 
@@ -199,12 +199,12 @@
     def test_invalid_rule(self):
         with self.assertRaisesRegex(
                 config.YamlLintConfigError,
-                'invalid config: rules should be a dict'):
+                'invalid config: rules should be a mapping'):
             config.YamlLintConfig('rules:\n')
         with self.assertRaisesRegex(
                 config.YamlLintConfigError,
                 'invalid config: rule "colons": should be either '
-                '"enable", "disable" or a dict'):
+                '"enable", "disable" or a mapping'):
             config.YamlLintConfig('rules:\n'
                                   '  colons: invalid\n')
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yamllint-1.37.1/tests/test_decoder.py 
new/yamllint-1.38.0/tests/test_decoder.py
--- old/yamllint-1.37.1/tests/test_decoder.py   2025-05-04 10:25:26.000000000 
+0200
+++ new/yamllint-1.38.0/tests/test_decoder.py   2026-01-13 08:47:21.000000000 
+0100
@@ -448,7 +448,7 @@
                         codec,
                         string
                     )
-                except UnicodeDecodeError:
+                except UnicodeDecodeError:  # noqa: PERF203
                     at_least_one_decode_error = True
         self.assertTrue(
             at_least_one_decode_error,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yamllint-1.37.1/yamllint/__init__.py 
new/yamllint-1.38.0/yamllint/__init__.py
--- old/yamllint-1.37.1/yamllint/__init__.py    2025-05-04 10:25:26.000000000 
+0200
+++ new/yamllint-1.38.0/yamllint/__init__.py    2026-01-13 08:47:21.000000000 
+0100
@@ -21,7 +21,7 @@
 
 
 APP_NAME = 'yamllint'
-APP_VERSION = '1.37.1'
+APP_VERSION = '1.38.0'
 APP_DESCRIPTION = __doc__
 
 __author__ = 'Adrien Vergé'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yamllint-1.37.1/yamllint/cli.py 
new/yamllint-1.38.0/yamllint/cli.py
--- old/yamllint-1.37.1/yamllint/cli.py 2025-05-04 10:25:26.000000000 +0200
+++ new/yamllint-1.38.0/yamllint/cli.py 2026-01-13 08:47:21.000000000 +0100
@@ -79,9 +79,9 @@
 
     @staticmethod
     def github(problem, filename):
-        line = f'::{problem.level} file={filename},' \
-               f'line={problem.line},col={problem.column}' \
-               f'::{problem.line}:{problem.column} '
+        line = (f'::{problem.level} file={filename},'
+                f'line={problem.line},col={problem.column}'
+                f'::{problem.line}:{problem.column} ')
         if problem.rule:
             line += f'[{problem.rule}] '
         line += problem.desc
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yamllint-1.37.1/yamllint/config.py 
new/yamllint-1.38.0/yamllint/config.py
--- old/yamllint-1.37.1/yamllint/config.py      2025-05-04 10:25:26.000000000 
+0200
+++ new/yamllint-1.38.0/yamllint/config.py      2026-01-13 08:47:21.000000000 
+0100
@@ -15,11 +15,11 @@
 
 import os.path
 
-import pathspec
+from pathspec import GitIgnoreSpec
 import yaml
 
-import yamllint.rules
 from yamllint import decoder
+import yamllint.rules
 
 
 class YamlLintConfigError(Exception):
@@ -32,8 +32,8 @@
 
         self.ignore = None
 
-        self.yaml_files = pathspec.PathSpec.from_lines(
-            'gitwildmatch', ['*.yaml', '*.yml', '.yamllint'])
+        self.yaml_files = GitIgnoreSpec.from_lines(
+            ['*.yaml', '*.yml', '.yamllint'])
 
         self.locale = None
 
@@ -79,11 +79,12 @@
             raise YamlLintConfigError(f'invalid config: {e}') from e
 
         if not isinstance(conf, dict):
-            raise YamlLintConfigError('invalid config: not a dict')
+            raise YamlLintConfigError('invalid config: not a mapping')
 
         self.rules = conf.get('rules', {})
         if not isinstance(self.rules, dict):
-            raise YamlLintConfigError('invalid config: rules should be a dict')
+            raise YamlLintConfigError('invalid config: rules should be a '
+                                      'mapping')
         for rule in self.rules:
             if self.rules[rule] == 'enable':
                 self.rules[rule] = {}
@@ -111,18 +112,16 @@
                 raise YamlLintConfigError(
                     'invalid config: ignore-from-file should contain '
                     'filename(s), either as a list or string')
-            self.ignore = pathspec.PathSpec.from_lines(
-                'gitwildmatch',
+            self.ignore = GitIgnoreSpec.from_lines(
                 decoder.lines_in_files(conf['ignore-from-file'])
             )
         elif 'ignore' in conf:
             if isinstance(conf['ignore'], str):
-                self.ignore = pathspec.PathSpec.from_lines(
-                    'gitwildmatch', conf['ignore'].splitlines())
+                self.ignore = GitIgnoreSpec.from_lines(
+                    conf['ignore'].splitlines())
             elif (isinstance(conf['ignore'], list) and
                     all(isinstance(line, str) for line in conf['ignore'])):
-                self.ignore = pathspec.PathSpec.from_lines(
-                    'gitwildmatch', conf['ignore'])
+                self.ignore = GitIgnoreSpec.from_lines(conf['ignore'])
             else:
                 raise YamlLintConfigError(
                     'invalid config: ignore should contain file patterns')
@@ -133,8 +132,7 @@
                 raise YamlLintConfigError(
                     'invalid config: yaml-files '
                     'should be a list of file patterns')
-            self.yaml_files = pathspec.PathSpec.from_lines('gitwildmatch',
-                                                           conf['yaml-files'])
+            self.yaml_files = GitIgnoreSpec.from_lines(conf['yaml-files'])
 
         if 'locale' in conf:
             if not isinstance(conf['locale'], str):
@@ -157,8 +155,8 @@
         return False
 
     if isinstance(conf, dict):
-        if ('ignore-from-file' in conf and not isinstance(
-                conf['ignore-from-file'], pathspec.pathspec.PathSpec)):
+        if ('ignore-from-file' in conf and
+                not isinstance(conf['ignore-from-file'], GitIgnoreSpec)):
             if isinstance(conf['ignore-from-file'], str):
                 conf['ignore-from-file'] = [conf['ignore-from-file']]
             if not (isinstance(conf['ignore-from-file'], list)
@@ -167,19 +165,17 @@
                 raise YamlLintConfigError(
                     'invalid config: ignore-from-file should contain '
                     'valid filename(s), either as a list or string')
-            conf['ignore'] = pathspec.PathSpec.from_lines(
-                'gitwildmatch',
+            conf['ignore'] = GitIgnoreSpec.from_lines(
                 decoder.lines_in_files(conf['ignore-from-file'])
             )
-        elif ('ignore' in conf and not isinstance(
-                conf['ignore'], pathspec.pathspec.PathSpec)):
+        elif ('ignore' in conf and
+                not isinstance(conf['ignore'], GitIgnoreSpec)):
             if isinstance(conf['ignore'], str):
-                conf['ignore'] = pathspec.PathSpec.from_lines(
-                    'gitwildmatch', conf['ignore'].splitlines())
+                conf['ignore'] = GitIgnoreSpec.from_lines(
+                    conf['ignore'].splitlines())
             elif (isinstance(conf['ignore'], list) and
                     all(isinstance(line, str) for line in conf['ignore'])):
-                conf['ignore'] = pathspec.PathSpec.from_lines(
-                    'gitwildmatch', conf['ignore'])
+                conf['ignore'] = GitIgnoreSpec.from_lines(conf['ignore'])
             else:
                 raise YamlLintConfigError(
                     'invalid config: ignore should contain file patterns')
@@ -235,7 +231,7 @@
     else:
         raise YamlLintConfigError(
             f'invalid config: rule "{rule.ID}": should be either "enable", '
-            f'"disable" or a dict')
+            f'"disable" or a mapping')
 
     return conf
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yamllint-1.37.1/yamllint/rules/indentation.py 
new/yamllint-1.38.0/yamllint/rules/indentation.py
--- old/yamllint-1.37.1/yamllint/rules/indentation.py   2025-05-04 
10:25:26.000000000 +0200
+++ new/yamllint-1.38.0/yamllint/rules/indentation.py   2026-01-13 
08:47:21.000000000 +0100
@@ -302,7 +302,7 @@
 
         if indent != expected_indent:
             yield LintProblem(line_no, indent + 1,
-                              f'wrong indentation: expected {expected_indent}'
+                              f'wrong indentation: expected {expected_indent} '
                               f'but found {indent}')
 
 
@@ -341,11 +341,11 @@
 
         if found_indentation != expected:
             if expected < 0:
-                message = f'wrong indentation: expected at least ' \
-                          f'{found_indentation + 1}'
+                message = (f'wrong indentation: expected at least '
+                           f'{found_indentation + 1}')
             else:
-                message = f'wrong indentation: expected {expected} but ' \
-                          f'found {found_indentation}'
+                message = (f'wrong indentation: expected {expected} but '
+                           f'found {found_indentation}')
             yield LintProblem(token.start_mark.line + 1,
                               found_indentation + 1, message)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yamllint-1.37.1/yamllint/rules/key_ordering.py 
new/yamllint-1.38.0/yamllint/rules/key_ordering.py
--- old/yamllint-1.37.1/yamllint/rules/key_ordering.py  2025-05-04 
10:25:26.000000000 +0200
+++ new/yamllint-1.38.0/yamllint/rules/key_ordering.py  2026-01-13 
08:47:21.000000000 +0100
@@ -105,8 +105,8 @@
       d:
 """
 
-import re
 from locale import strcoll
+import re
 
 import yaml
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yamllint-1.37.1/yamllint/rules/line_length.py 
new/yamllint-1.38.0/yamllint/rules/line_length.py
--- old/yamllint-1.37.1/yamllint/rules/line_length.py   2025-05-04 
10:25:26.000000000 +0200
+++ new/yamllint-1.38.0/yamllint/rules/line_length.py   2026-01-13 
08:47:21.000000000 +0100
@@ -129,7 +129,9 @@
 
 
 def check(conf, line):
-    if line.end - line.start > conf['max']:
+    max_length = conf['max']
+    length = line.end - line.start
+    if length > max_length:
         conf['allow-non-breakable-words'] |= \
             conf['allow-non-breakable-inline-mappings']
         if conf['allow-non-breakable-words']:
@@ -152,6 +154,6 @@
                         check_inline_mapping(line)):
                     return
 
-        yield LintProblem(line.line_no, conf['max'] + 1,
-                          'line too long (%d > %d characters)' %
-                          (line.end - line.start, conf['max']))
+        yield LintProblem(line.line_no, max_length + 1,
+                          f'line too long'
+                          f' ({length} > {max_length} characters)')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yamllint-1.37.1/yamllint/rules/quoted_strings.py 
new/yamllint-1.38.0/yamllint/rules/quoted_strings.py
--- old/yamllint-1.37.1/yamllint/rules/quoted_strings.py        2025-05-04 
10:25:26.000000000 +0200
+++ new/yamllint-1.38.0/yamllint/rules/quoted_strings.py        2026-01-13 
08:47:21.000000000 +0100
@@ -20,8 +20,8 @@
 
 .. rubric:: Options
 
-* ``quote-type`` defines allowed quotes: ``single``, ``double`` or ``any``
-  (default).
+* ``quote-type`` defines allowed quotes: ``single``, ``double``, ``consistent``
+  or ``any`` (default).
 * ``required`` defines whether using quotes in string values is required
   (``true``, default) or not (``false``), or only allowed when really needed
   (``only-when-needed``).
@@ -139,6 +139,20 @@
 
     foo: 'bar"baz'
 
+#. With ``quoted-strings: {quote-type: consistent}``
+
+   the following code snippet would **PASS**:
+   ::
+
+    foo: 'bar'
+    baz: 'quux'
+
+   the following code snippet would **FAIL**:
+   ::
+
+    foo: 'bar'
+    baz: "quux"
+
 #. With ``quoted-strings: {required: only-when-needed, check-keys: true,
    extra-required: ["[:]"]}``
 
@@ -161,7 +175,7 @@
 
 ID = 'quoted-strings'
 TYPE = 'token'
-CONF = {'quote-type': ('any', 'single', 'double'),
+CONF = {'quote-type': ('any', 'single', 'double', 'consistent'),
         'required': (True, False, 'only-when-needed'),
         'extra-required': [str],
         'extra-allowed': [str],
@@ -198,7 +212,14 @@
     list('-+0123456789'))
 
 
-def _quote_match(quote_type, token_style):
+def _quote_match(quote_type, token_style, context):
+    if quote_type == 'consistent' and token_style is not None:
+        # The canonical token style in a document is assumed to be the first
+        # one found for the purpose of 'consistent'
+        if 'quoted_strings_consistent_token_style' not in context:
+            context['quoted_strings_consistent_token_style'] = token_style
+        return context['quoted_strings_consistent_token_style'] == token_style
+
     return ((quote_type == 'any') or
             (quote_type == 'single' and token_style == "'") or
             (quote_type == 'double' and token_style == '"'))
@@ -294,7 +315,7 @@
 
         # Quotes are mandatory and need to match config
         if (token.style is None or
-            not (_quote_match(quote_type, token.style) or
+            not (_quote_match(quote_type, token.style, context) or
                  (conf['allow-quoted-quotes'] and _has_quoted_quotes(token)))):
             msg = f"string {node} is not quoted with {quote_type} quotes"
 
@@ -302,7 +323,7 @@
 
         # Quotes are not mandatory but when used need to match config
         if (token.style and
-                not _quote_match(quote_type, token.style) and
+                not _quote_match(quote_type, token.style, context) and
                 not (conf['allow-quoted-quotes'] and
                      _has_quoted_quotes(token))):
             msg = f"string {node} is not quoted with {quote_type} quotes"
@@ -323,12 +344,12 @@
             is_extra_allowed = any(re.search(r, token.value)
                                    for r in conf['extra-allowed'])
             if not (is_extra_required or is_extra_allowed):
-                msg = f"string {node} is redundantly quoted with " \
-                      f"{quote_type} quotes"
+                msg = (f"string {node} is redundantly quoted with "
+                       f"{quote_type} quotes")
 
         # But when used need to match config
         elif (token.style and
-              not _quote_match(quote_type, token.style) and
+              not _quote_match(quote_type, token.style, context) and
               not (conf['allow-quoted-quotes'] and _has_quoted_quotes(token))):
             msg = f"string {node} is not quoted with {quote_type} quotes"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yamllint-1.37.1/yamllint/rules/trailing_spaces.py 
new/yamllint-1.38.0/yamllint/rules/trailing_spaces.py
--- old/yamllint-1.37.1/yamllint/rules/trailing_spaces.py       2025-05-04 
10:25:26.000000000 +0200
+++ new/yamllint-1.38.0/yamllint/rules/trailing_spaces.py       2026-01-13 
08:47:21.000000000 +0100
@@ -33,7 +33,7 @@
     this document contains     """ """
     trailing spaces
     on lines 1 and 3         """ """
-"""
+"""  # noqa: ISC001
 
 
 import string
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yamllint-1.37.1/yamllint.egg-info/PKG-INFO 
new/yamllint-1.38.0/yamllint.egg-info/PKG-INFO
--- old/yamllint-1.37.1/yamllint.egg-info/PKG-INFO      2025-05-04 
10:25:33.000000000 +0200
+++ new/yamllint-1.38.0/yamllint.egg-info/PKG-INFO      2026-01-13 
08:47:29.000000000 +0100
@@ -1,9 +1,9 @@
 Metadata-Version: 2.4
 Name: yamllint
-Version: 1.37.1
+Version: 1.38.0
 Summary: A linter for YAML files.
 Author: Adrien Vergé
-License: GPL-3.0-or-later
+License-Expression: GPL-3.0-or-later
 Project-URL: homepage, https://github.com/adrienverge/yamllint
 Project-URL: repository, https://github.com/adrienverge/yamllint
 Project-URL: documentation, https://yamllint.readthedocs.io
@@ -11,22 +11,22 @@
 Classifier: Development Status :: 5 - Production/Stable
 Classifier: Environment :: Console
 Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
 Classifier: Programming Language :: Python
 Classifier: Topic :: Software Development
 Classifier: Topic :: Software Development :: Debuggers
 Classifier: Topic :: Software Development :: Quality Assurance
 Classifier: Topic :: Software Development :: Testing
-Requires-Python: >=3.9
+Requires-Python: >=3.10
 Description-Content-Type: text/x-rst
 License-File: LICENSE
-Requires-Dist: pathspec>=0.5.3
+Requires-Dist: pathspec>=1.0.0
 Requires-Dist: pyyaml
 Provides-Extra: dev
 Requires-Dist: doc8; extra == "dev"
 Requires-Dist: flake8; extra == "dev"
 Requires-Dist: flake8-import-order; extra == "dev"
 Requires-Dist: rstcheck[sphinx]; extra == "dev"
+Requires-Dist: ruff; extra == "dev"
 Requires-Dist: sphinx; extra == "dev"
 Dynamic: license-file
 
@@ -51,7 +51,7 @@
    :target: https://yamllint.readthedocs.io/en/latest/?badge=latest
    :alt: Documentation status
 
-Written in Python (compatible with Python 3 only).
+Written in Python.
 
 Documentation
 -------------
@@ -90,7 +90,7 @@
 
 .. code:: bash
 
- # Lint all YAML files in a directory
+ # Recursively lint all YAML files in a directory
  yamllint .
 
 .. code:: bash
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yamllint-1.37.1/yamllint.egg-info/SOURCES.txt 
new/yamllint-1.38.0/yamllint.egg-info/SOURCES.txt
--- old/yamllint-1.37.1/yamllint.egg-info/SOURCES.txt   2025-05-04 
10:25:33.000000000 +0200
+++ new/yamllint-1.38.0/yamllint.egg-info/SOURCES.txt   2026-01-13 
08:47:29.000000000 +0100
@@ -4,7 +4,6 @@
 MANIFEST.in
 README.rst
 pyproject.toml
-setup.py
 docs/Makefile
 docs/character_encoding.rst
 docs/conf.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yamllint-1.37.1/yamllint.egg-info/requires.txt 
new/yamllint-1.38.0/yamllint.egg-info/requires.txt
--- old/yamllint-1.37.1/yamllint.egg-info/requires.txt  2025-05-04 
10:25:33.000000000 +0200
+++ new/yamllint-1.38.0/yamllint.egg-info/requires.txt  2026-01-13 
08:47:29.000000000 +0100
@@ -1,4 +1,4 @@
-pathspec>=0.5.3
+pathspec>=1.0.0
 pyyaml
 
 [dev]
@@ -6,4 +6,5 @@
 flake8
 flake8-import-order
 rstcheck[sphinx]
+ruff
 sphinx

Reply via email to