Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-bandit for openSUSE:Factory 
checked in at 2025-11-27 15:21:38
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-bandit (Old)
 and      /work/SRC/openSUSE:Factory/.python-bandit.new.14147 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-bandit"

Thu Nov 27 15:21:38 2025 rev:19 rq:1320304 version:1.9.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-bandit/python-bandit.changes      
2025-09-02 17:58:44.007534166 +0200
+++ /work/SRC/openSUSE:Factory/.python-bandit.new.14147/python-bandit.changes   
2025-11-27 15:23:27.433777410 +0100
@@ -1,0 +2,35 @@
+Thu Nov 27 08:17:43 UTC 2025 - John Paul Adrian Glaubitz 
<[email protected]>
+
+- Update to 1.9.2
+  * Argparse Python 3.14 enhancements by @ericwb in (#1331)
+  * Check whether Constant value is str by @ericwb in (#1333)
+- from version 1.9.1
+  * More Python version related fixes by @ericwb in (#1327)
+- from version 1.9.0
+  * Add instructions for Maintainers to create/publish a release
+    by @ericwb in (#1275)
+  * Bump sigstore/cosign-installer from 3.9.1 to 3.9.2
+    by @dependabot[bot] in (#1289)
+  * Bump docker/login-action from 3.4.0 to 3.5.0
+    by @dependabot[bot] in (#1290)
+  * [pre-commit.ci] pre-commit autoupdate
+    by @pre-commit-ci[bot] in (#1291)
+  * Bump actions/checkout from 4 to 5 by @dependabot[bot] in (#1292)
+  * Replace deprecated datetime.datetime.utcnow()
+    by @purplezimmermann in (#1295)
+  * Bump actions/setup-python from 5 to 6
+    by @dependabot[bot] in (#1296)
+  * Bump sigstore/cosign-installer from 3.9.2 to 3.10.0
+    by @dependabot[bot] in (#1298)
+  * [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in (#1303)
+  * Fix typos by @Shortfinga in (#1305)
+  * Bump docker/login-action from 3.5.0 to 3.6.0
+    by @dependabot[bot] in (#1306)
+  * [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in (#1315)
+  * Bump sigstore/cosign-installer from 3.10.0 to 4.0.0
+    by @dependabot[bot] in (#1317)
+  * Support of Python 3.14 by @ericwb in (#1323)
+  * Drop support of end-of-life Python 3.9 by @ericwb in (#1325)
+  * [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in (#1324)
+
+-------------------------------------------------------------------

Old:
----
  bandit-1.8.6.tar.gz

New:
----
  bandit-1.9.2.tar.gz

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

Other differences:
------------------
++++++ python-bandit.spec ++++++
--- /var/tmp/diff_new_pack.r0GGdQ/_old  2025-11-27 15:23:27.953799340 +0100
+++ /var/tmp/diff_new_pack.r0GGdQ/_new  2025-11-27 15:23:27.957799508 +0100
@@ -34,7 +34,7 @@
 %bcond_without  builddocs
 %{?sle15_python_module_pythons}
 Name:           python-bandit
-Version:        1.8.6
+Version:        1.9.2
 Release:        0
 Summary:        Security oriented static analyser for Python code
 License:        Apache-2.0

++++++ bandit-1.8.6.tar.gz -> bandit-1.9.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/.github/ISSUE_TEMPLATE/bug-report.yml 
new/bandit-1.9.2/.github/ISSUE_TEMPLATE/bug-report.yml
--- old/bandit-1.8.6/.github/ISSUE_TEMPLATE/bug-report.yml      2025-07-06 
05:10:12.000000000 +0200
+++ new/bandit-1.9.2/.github/ISSUE_TEMPLATE/bug-report.yml      2025-11-23 
22:35:40.000000000 +0100
@@ -44,7 +44,12 @@
       label: Bandit version
       description: Run "bandit --version" if unsure of version number
       options:
-        - 1.8.3 (Default)
+        - 1.9.1 (Default)
+        - 1.9.0
+        - 1.8.6
+        - 1.8.5
+        - 1.8.4
+        - 1.8.3
         - 1.8.2
         - 1.8.1
         - 1.8.0
@@ -53,12 +58,6 @@
         - 1.7.8
         - 1.7.7
         - 1.7.6
-        - 1.7.5
-        - 1.7.4
-        - 1.7.3
-        - 1.7.2
-        - 1.7.1
-        - 1.7.0
     validations:
       required: true
 
@@ -68,7 +67,8 @@
       label: Python version
       description: Run "bandit --version" if unsure of version number
       options:
-        - "3.13 (Default)"
+        - "3.14 (Default)"
+        - "3.13"
         - "3.12"
         - "3.11"
         - "3.10"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/bandit-1.8.6/.github/workflows/build-publish-image.yml 
new/bandit-1.9.2/.github/workflows/build-publish-image.yml
--- old/bandit-1.8.6/.github/workflows/build-publish-image.yml  2025-07-06 
05:10:12.000000000 +0200
+++ new/bandit-1.9.2/.github/workflows/build-publish-image.yml  2025-11-23 
22:35:40.000000000 +0100
@@ -26,7 +26,7 @@
         echo "RELEASE_TAG=$TAG" >> $GITHUB_ENV
 
     - name: Check out the repo
-      uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
+      uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v4
       with:
         ref: ${{ github.event_name == 'release' && github.ref || 
env.RELEASE_TAG }}
 
@@ -34,14 +34,14 @@
       uses: 
docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3
 
     - name: Log in to GitHub Container Registry
-      uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3
+      uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3
       with:
         registry: ghcr.io
         username: ${{ github.actor }}
         password: ${{ secrets.GITHUB_TOKEN }}
 
     - name: Install Cosign
-      uses: sigstore/cosign-installer@398d4b0eeef1380460a10c8013a76f728fb906ac 
# v3.9.1
+      uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad 
# v4.0.0
       with:
         cosign-release: 'v2.2.2'
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/.github/workflows/dependency-review.yml 
new/bandit-1.9.2/.github/workflows/dependency-review.yml
--- old/bandit-1.8.6/.github/workflows/dependency-review.yml    2025-07-06 
05:10:12.000000000 +0200
+++ new/bandit-1.9.2/.github/workflows/dependency-review.yml    2025-11-23 
22:35:40.000000000 +0100
@@ -9,6 +9,6 @@
     runs-on: ubuntu-latest
     steps:
       - name: Checkout repository
-        uses: actions/checkout@v4
+        uses: actions/checkout@v5
       - name: 'Dependency Review'
         uses: actions/dependency-review-action@v4
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/.github/workflows/publish-to-pypi.yml 
new/bandit-1.9.2/.github/workflows/publish-to-pypi.yml
--- old/bandit-1.8.6/.github/workflows/publish-to-pypi.yml      2025-07-06 
05:10:12.000000000 +0200
+++ new/bandit-1.9.2/.github/workflows/publish-to-pypi.yml      2025-11-23 
22:35:40.000000000 +0100
@@ -10,13 +10,13 @@
       # IMPORTANT: this permission is mandatory for trusted publishing
       id-token: write
     steps:
-    - uses: actions/checkout@v4
+    - uses: actions/checkout@v5
       with:
         fetch-depth: 0
-    - name: Set up Python 3.9
-      uses: actions/setup-python@v5
+    - name: Set up Python 3.10
+      uses: actions/setup-python@v6
       with:
-        python-version: 3.9
+        python-version: "3.10"
 
     - name: Install dependencies
       run: pip install tox wheel
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/bandit-1.8.6/.github/workflows/publish-to-test-pypi.yml 
new/bandit-1.9.2/.github/workflows/publish-to-test-pypi.yml
--- old/bandit-1.8.6/.github/workflows/publish-to-test-pypi.yml 2025-07-06 
05:10:12.000000000 +0200
+++ new/bandit-1.9.2/.github/workflows/publish-to-test-pypi.yml 2025-11-23 
22:35:40.000000000 +0100
@@ -10,13 +10,13 @@
       # IMPORTANT: this permission is mandatory for trusted publishing
       id-token: write
     steps:
-    - uses: actions/checkout@v4
+    - uses: actions/checkout@v5
       with:
         fetch-depth: 0
-    - name: Set up Python 3.9
-      uses: actions/setup-python@v5
+    - name: Set up Python 3.10
+      uses: actions/setup-python@v6
       with:
-        python-version: 3.9
+        python-version: "3.10"
 
     - name: Install dependencies
       run: pip install tox wheel
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/.github/workflows/pythonpackage.yml 
new/bandit-1.9.2/.github/workflows/pythonpackage.yml
--- old/bandit-1.8.6/.github/workflows/pythonpackage.yml        2025-07-06 
05:10:12.000000000 +0200
+++ new/bandit-1.9.2/.github/workflows/pythonpackage.yml        2025-11-23 
22:35:40.000000000 +0100
@@ -7,12 +7,12 @@
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        python-version: [3.9]
+        python-version: ["3.10"]
     steps:
     - name: Checkout repository
-      uses: actions/checkout@v4
+      uses: actions/checkout@v5
     - name: Set up Python ${{ matrix.python-version }}
-      uses: actions/setup-python@v5
+      uses: actions/setup-python@v6
       with:
         python-version: ${{ matrix.python-version }}
     - name: Install dependencies
@@ -26,14 +26,14 @@
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        python-version: [3.9]
+        python-version: ["3.10"]
     steps:
     - name: Checkout repository
-      uses: actions/checkout@v4
+      uses: actions/checkout@v5
       with:
         fetch-depth: 2
     - name: Set up Python ${{ matrix.python-version }}
-      uses: actions/setup-python@v5
+      uses: actions/setup-python@v6
       with:
         python-version: ${{ matrix.python-version }}
     - name: Install dependencies
@@ -47,20 +47,20 @@
     strategy:
       matrix:
         python-version: [
-          ["3.9", "39"],
           ["3.10", "310"],
           ["3.11", "311"],
           ["3.12", "312"],
           ["3.13", "313"],
+          ["3.14", "314"],
         ]
         os: [ubuntu-latest, macos-latest]
     runs-on: ${{ matrix.os }}
     name: ${{ matrix.os }} (${{ matrix.python-version[0] }})
     steps:
     - name: Checkout repository
-      uses: actions/checkout@v4
+      uses: actions/checkout@v5
     - name: Set up Python ${{ matrix.python-version[0] }}
-      uses: actions/setup-python@v5
+      uses: actions/setup-python@v6
       with:
         python-version: ${{ matrix.python-version[0] }}
     - name: Install dependencies
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/.pre-commit-config.yaml 
new/bandit-1.9.2/.pre-commit-config.yaml
--- old/bandit-1.8.6/.pre-commit-config.yaml    2025-07-06 05:10:12.000000000 
+0200
+++ new/bandit-1.9.2/.pre-commit-config.yaml    2025-11-23 22:35:40.000000000 
+0100
@@ -1,24 +1,24 @@
 exclude: ^(examples|tools|doc)
 repos:
 - repo: https://github.com/pre-commit/pre-commit-hooks
-  rev: v5.0.0
+  rev: v6.0.0
   hooks:
   - id: check-yaml
   - id: debug-statements
   - id: end-of-file-fixer
   - id: trailing-whitespace
 - repo: https://github.com/asottile/reorder-python-imports
-  rev: v3.15.0
+  rev: v3.16.0
   hooks:
   - id: reorder-python-imports
     args: [--application-directories, '.:src', --py38-plus]
 - repo: https://github.com/psf/black-pre-commit-mirror
-  rev: 25.1.0
+  rev: 25.11.0
   hooks:
   - id: black
     args: [--line-length=79, --target-version=py38]
 - repo: https://github.com/asottile/pyupgrade
-  rev: v3.20.0
+  rev: v3.21.1
   hooks:
   - id: pyupgrade
     args: [--py38-plus]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/.readthedocs.yaml 
new/bandit-1.9.2/.readthedocs.yaml
--- old/bandit-1.8.6/.readthedocs.yaml  2025-07-06 05:10:12.000000000 +0200
+++ new/bandit-1.9.2/.readthedocs.yaml  2025-11-23 22:35:40.000000000 +0100
@@ -3,7 +3,7 @@
 build:
   os: ubuntu-lts-latest
   tools:
-    python: "3.9"
+    python: "3.10"
 
 sphinx:
   configuration: doc/source/conf.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/AUTHORS new/bandit-1.9.2/AUTHORS
--- old/bandit-1.8.6/AUTHORS    2025-07-06 05:10:35.000000000 +0200
+++ new/bandit-1.9.2/AUTHORS    2025-11-23 22:36:04.000000000 +0100
@@ -99,6 +99,7 @@
 Mathieu Kniewallner <[email protected]>
 Matthew Edmonds <[email protected]>
 Matthew Egan <[email protected]>
+Maximilian <[email protected]>
 Michael McCune <[email protected]>
 Michael Spallino <[email protected]>
 Michael Spallino <[email protected]>
@@ -139,6 +140,7 @@
 Soumitr <[email protected]>
 Stanisław Pitucha <[email protected]>
 Stanisław Pitucha <[email protected]>
+Stefan Zimmermann <[email protected]>
 Takashi Kajinami <[email protected]>
 Taybin Rutkin <[email protected]>
 Thibaut Le Page <[email protected]>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/CONTRIBUTING.md 
new/bandit-1.9.2/CONTRIBUTING.md
--- old/bandit-1.8.6/CONTRIBUTING.md    2025-07-06 05:10:12.000000000 +0200
+++ new/bandit-1.9.2/CONTRIBUTING.md    2025-11-23 22:35:40.000000000 +0100
@@ -56,7 +56,11 @@
 
 Create you own branch to start writing code:
 ```shell script
-git checkout -b mybranch
+git switch -c mybranch
+<create local changes>
+git add <changed files>
+git commit -S
+<create a good commit message>
 git push origin mybranch
 ```
 You can test any changes with tox:
@@ -64,7 +68,8 @@
 ```shell script
 pip install tox
 tox run -e pep8
-tox run -e py37
+tox run -e format
+tox run -e py39
 tox run -e docs
 tox run -e cover
 ```
@@ -245,3 +250,29 @@
             bson = bandit_bson:formatter
         bandit.plugins =
             mako = bandit_mako
+
+## Creating and Publishing a Release (Maintainers)
+
+### Create the GitHub Release
+
+1. Navigate to the [Releases](https://github.com/PyCQA/bandit/releases) page
+2. Click on `Draft a new release`
+3. Under `Choose a tag` enter a new release version (typically increment the 
patch number) and select `Create new tag: <version> on publish`
+4. Click on `Generate release notes`
+5. Click on `Publish release`
+
+### Publish the Release to Test PyPI
+
+1. Go to `Actions` tab
+2. Click on the `Publish to Test PyPI` action
+3. Click on `Run workflow`
+4. Select `Use workflow from`, then `Tags` tab, and select `<version>`
+5. Click on `Run workflow`
+
+### Publish the Release to PyPI
+
+1. Go to `Actions` tab
+2. Click on the `Publish to PyPI` action
+3. Click on `Run workflow`
+4. Select `Use workflow from`, then `Tags` tab, and select `<version>`
+5. Click on `Run workflow`
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/ChangeLog new/bandit-1.9.2/ChangeLog
--- old/bandit-1.8.6/ChangeLog  2025-07-06 05:10:35.000000000 +0200
+++ new/bandit-1.9.2/ChangeLog  2025-11-23 22:36:04.000000000 +0100
@@ -1,6 +1,37 @@
 CHANGES
 =======
 
+1.9.2
+-----
+
+* Check whether Constant value is str (#1333)
+* Argparse Python 3.14 enhancements (#1331)
+
+1.9.1
+-----
+
+* More Python version related fixes (#1327)
+
+1.9.0
+-----
+
+* [pre-commit.ci] pre-commit autoupdate (#1324)
+* Drop support of end-of-life Python 3.9 (#1325)
+* Support of Python 3.14 (#1323)
+* Bump sigstore/cosign-installer from 3.10.0 to 4.0.0 (#1317)
+* [pre-commit.ci] pre-commit autoupdate (#1315)
+* Bump docker/login-action from 3.5.0 to 3.6.0 (#1306)
+* Fix typos (#1305)
+* [pre-commit.ci] pre-commit autoupdate (#1303)
+* Bump sigstore/cosign-installer from 3.9.2 to 3.10.0 (#1298)
+* Bump actions/setup-python from 5 to 6 (#1296)
+* Replace deprecated datetime.datetime.utcnow() (#1295)
+* Bump actions/checkout from 4 to 5 (#1292)
+* [pre-commit.ci] pre-commit autoupdate (#1291)
+* Bump docker/login-action from 3.4.0 to 3.5.0 (#1290)
+* Bump sigstore/cosign-installer from 3.9.1 to 3.9.2 (#1289)
+* Add instructions for Maintainers to create/publish a release (#1275)
+
 1.8.6
 -----
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/PKG-INFO new/bandit-1.9.2/PKG-INFO
--- old/bandit-1.8.6/PKG-INFO   2025-07-06 05:10:36.064527800 +0200
+++ new/bandit-1.9.2/PKG-INFO   2025-11-23 22:36:05.340152700 +0100
@@ -1,6 +1,6 @@
-Metadata-Version: 2.1
+Metadata-Version: 2.4
 Name: bandit
-Version: 1.8.6
+Version: 1.9.2
 Summary: Security oriented static analyser for python code.
 Home-page: https://bandit.readthedocs.io/
 Author: PyCQA
@@ -12,7 +12,6 @@
 Project-URL: Issue Tracker, https://github.com/PyCQA/bandit/issues
 Project-URL: Discord, https://discord.gg/qYxpadCgkx
 Project-URL: Sponsor, 
https://psfmember.org/civicrm/contribute/transact/?reset=1&id=42
-Platform: UNKNOWN
 Classifier: Development Status :: 5 - Production/Stable
 Classifier: Environment :: Console
 Classifier: Intended Audience :: Information Technology
@@ -22,20 +21,48 @@
 Classifier: Operating System :: MacOS :: MacOS X
 Classifier: Programming Language :: Python
 Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.9
 Classifier: Programming Language :: Python :: 3.10
 Classifier: Programming Language :: Python :: 3.11
 Classifier: Programming Language :: Python :: 3.12
 Classifier: Programming Language :: Python :: 3.13
+Classifier: Programming Language :: Python :: 3.14
 Classifier: Programming Language :: Python :: 3 :: Only
 Classifier: Topic :: Security
-Requires-Python: >=3.9
+Requires-Python: >=3.10
+License-File: LICENSE
+Requires-Dist: PyYAML>=5.3.1
+Requires-Dist: stevedore>=1.20.0
+Requires-Dist: rich
+Requires-Dist: colorama>=0.3.9; platform_system == "Windows"
 Provides-Extra: yaml
+Requires-Dist: PyYAML; extra == "yaml"
 Provides-Extra: toml
+Requires-Dist: tomli>=1.1.0; python_version < "3.11" and extra == "toml"
 Provides-Extra: baseline
+Requires-Dist: GitPython>=3.1.30; extra == "baseline"
 Provides-Extra: sarif
+Requires-Dist: sarif-om>=1.0.4; extra == "sarif"
+Requires-Dist: jschema-to-python>=1.2.3; extra == "sarif"
 Provides-Extra: test
-License-File: LICENSE
+Requires-Dist: coverage>=4.5.4; extra == "test"
+Requires-Dist: fixtures>=3.0.0; extra == "test"
+Requires-Dist: flake8>=4.0.0; extra == "test"
+Requires-Dist: stestr>=2.5.0; extra == "test"
+Requires-Dist: testscenarios>=0.5.0; extra == "test"
+Requires-Dist: testtools>=2.3.0; extra == "test"
+Requires-Dist: beautifulsoup4>=4.8.0; extra == "test"
+Requires-Dist: pylint==1.9.4; extra == "test"
+Dynamic: author
+Dynamic: author-email
+Dynamic: description
+Dynamic: home-page
+Dynamic: license
+Dynamic: license-file
+Dynamic: project-url
+Dynamic: provides-extra
+Dynamic: requires-dist
+Dynamic: requires-python
+Dynamic: summary
 
 .. image:: 
https://raw.githubusercontent.com/pycqa/bandit/main/logo/logotype-sm.png
     :alt: Bandit
@@ -183,5 +210,3 @@
 
 If you also ❤️ Bandit, please consider sponsoring.
 
-
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/bandit/cli/baseline.py 
new/bandit-1.9.2/bandit/cli/baseline.py
--- old/bandit-1.8.6/bandit/cli/baseline.py     2025-07-06 05:10:12.000000000 
+0200
+++ new/bandit-1.9.2/bandit/cli/baseline.py     2025-11-23 22:35:40.000000000 
+0100
@@ -168,6 +168,9 @@
         epilog="Additional Bandit arguments such as severity filtering (-ll) "
         "can be added and will be passed to Bandit.",
     )
+    if sys.version_info >= (3, 14):
+        parser.suggest_on_error = True
+        parser.color = False
 
     parser.add_argument(
         "targets",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/bandit/cli/config_generator.py 
new/bandit-1.9.2/bandit/cli/config_generator.py
--- old/bandit-1.8.6/bandit/cli/config_generator.py     2025-07-06 
05:10:12.000000000 +0200
+++ new/bandit-1.9.2/bandit/cli/config_generator.py     2025-11-23 
22:35:40.000000000 +0100
@@ -76,6 +76,9 @@
         description=help_description,
         formatter_class=argparse.RawTextHelpFormatter,
     )
+    if sys.version_info >= (3, 14):
+        parser.suggest_on_error = True
+        parser.color = False
 
     parser.add_argument(
         "--show-defaults",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/bandit/cli/main.py 
new/bandit-1.9.2/bandit/cli/main.py
--- old/bandit-1.8.6/bandit/cli/main.py 2025-07-06 05:10:12.000000000 +0200
+++ new/bandit-1.9.2/bandit/cli/main.py 2025-11-23 22:35:40.000000000 +0100
@@ -155,6 +155,10 @@
         description="Bandit - a Python source code security analyzer",
         formatter_class=argparse.RawDescriptionHelpFormatter,
     )
+    if sys.version_info >= (3, 14):
+        parser.suggest_on_error = True
+        parser.color = False
+
     parser.add_argument(
         "targets",
         metavar="targets",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/bandit/core/blacklisting.py 
new/bandit-1.9.2/bandit/core/blacklisting.py
--- old/bandit-1.8.6/bandit/core/blacklisting.py        2025-07-06 
05:10:12.000000000 +0200
+++ new/bandit-1.9.2/bandit/core/blacklisting.py        2025-11-23 
22:35:40.000000000 +0100
@@ -35,8 +35,10 @@
         func = context.node.func
         if isinstance(func, ast.Name) and func.id == "__import__":
             if len(context.node.args):
-                if isinstance(context.node.args[0], ast.Str):
-                    name = context.node.args[0].s
+                if isinstance(
+                    context.node.args[0], ast.Constant
+                ) and isinstance(context.node.args[0].value, str):
+                    name = context.node.args[0].value
                 else:
                     # TODO(??): import through a variable, need symbol tab
                     name = "UNKNOWN"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/bandit/core/context.py 
new/bandit-1.9.2/bandit/core/context.py
--- old/bandit-1.8.6/bandit/core/context.py     2025-07-06 05:10:12.000000000 
+0200
+++ new/bandit-1.9.2/bandit/core/context.py     2025-11-23 22:35:40.000000000 
+0100
@@ -178,11 +178,13 @@
         :param literal: The AST literal to convert
         :return: The value of the AST literal
         """
-        if isinstance(literal, ast.Num):
-            literal_value = literal.n
-
-        elif isinstance(literal, ast.Str):
-            literal_value = literal.s
+        if isinstance(literal, ast.Constant):
+            if isinstance(literal.value, bool):
+                literal_value = str(literal.value)
+            elif literal.value is None:
+                literal_value = str(literal.value)
+            else:
+                literal_value = literal.value
 
         elif isinstance(literal, ast.List):
             return_list = list()
@@ -205,19 +207,9 @@
         elif isinstance(literal, ast.Dict):
             literal_value = dict(zip(literal.keys, literal.values))
 
-        elif isinstance(literal, ast.Ellipsis):
-            # what do we want to do with this?
-            literal_value = None
-
         elif isinstance(literal, ast.Name):
             literal_value = literal.id
 
-        elif isinstance(literal, ast.NameConstant):
-            literal_value = str(literal.value)
-
-        elif isinstance(literal, ast.Bytes):
-            literal_value = literal.s
-
         else:
             literal_value = None
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/bandit/core/node_visitor.py 
new/bandit-1.9.2/bandit/core/node_visitor.py
--- old/bandit-1.8.6/bandit/core/node_visitor.py        2025-07-06 
05:10:12.000000000 +0200
+++ new/bandit-1.9.2/bandit/core/node_visitor.py        2025-11-23 
22:35:40.000000000 +0100
@@ -168,7 +168,7 @@
         :param node: The node that is being inspected
         :return: -
         """
-        self.context["str"] = node.s
+        self.context["str"] = node.value
         if not isinstance(node._bandit_parent, ast.Expr):  # docstring
             self.context["linerange"] = b_utils.linerange(node._bandit_parent)
             self.update_scores(self.tester.run_tests(self.context, "Str"))
@@ -181,7 +181,7 @@
         :param node: The node that is being inspected
         :return: -
         """
-        self.context["bytes"] = node.s
+        self.context["bytes"] = node.value
         if not isinstance(node._bandit_parent, ast.Expr):  # docstring
             self.context["linerange"] = b_utils.linerange(node._bandit_parent)
             self.update_scores(self.tester.run_tests(self.context, "Bytes"))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/bandit/core/utils.py 
new/bandit-1.9.2/bandit/core/utils.py
--- old/bandit-1.8.6/bandit/core/utils.py       2025-07-06 05:10:12.000000000 
+0200
+++ new/bandit-1.9.2/bandit/core/utils.py       2025-11-23 22:35:40.000000000 
+0100
@@ -273,12 +273,12 @@
 def concat_string(node, stop=None):
     """Builds a string from a ast.BinOp chain.
 
-    This will build a string from a series of ast.Str nodes wrapped in
+    This will build a string from a series of ast.Constant nodes wrapped in
     ast.BinOp nodes. Something like "a" + "b" + "c" or "a %s" % val etc.
     The provided node can be any participant in the BinOp chain.
 
-    :param node: (ast.Str or ast.BinOp) The node to process
-    :param stop: (ast.Str or ast.BinOp) Optional base node to stop at
+    :param node: (ast.Constant or ast.BinOp) The node to process
+    :param stop: (ast.Constant or ast.BinOp) Optional base node to stop at
     :returns: (Tuple) the root node of the expression, the string value
     """
 
@@ -300,7 +300,16 @@
         node = node._bandit_parent
     if isinstance(node, ast.BinOp):
         _get(node, bits, stop)
-    return (node, " ".join([x.s for x in bits if isinstance(x, ast.Str)]))
+    return (
+        node,
+        " ".join(
+            [
+                x.value
+                for x in bits
+                if isinstance(x, ast.Constant) and isinstance(x.value, str)
+            ]
+        ),
+    )
 
 
 def get_called_name(node):
@@ -361,6 +370,17 @@
 def check_ast_node(name):
     "Check if the given name is that of a valid AST node."
     try:
+        # These ast Node types don't exist in Python 3.14, but plugins may
+        # still check on them.
+        if sys.version_info >= (3, 14) and name in (
+            "Num",
+            "Str",
+            "Ellipsis",
+            "NameConstant",
+            "Bytes",
+        ):
+            return name
+
         node = getattr(ast, name)
         if issubclass(node, ast.AST):
             return name
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/bandit/formatters/json.py 
new/bandit-1.9.2/bandit/formatters/json.py
--- old/bandit-1.8.6/bandit/formatters/json.py  2025-07-06 05:10:12.000000000 
+0200
+++ new/bandit-1.9.2/bandit/formatters/json.py  2025-11-23 22:35:40.000000000 
+0100
@@ -139,7 +139,9 @@
     # timezone agnostic format
     TS_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
 
-    time_string = datetime.datetime.utcnow().strftime(TS_FORMAT)
+    time_string = datetime.datetime.now(datetime.timezone.utc).strftime(
+        TS_FORMAT
+    )
     machine_output["generated_at"] = time_string
 
     result = json.dumps(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/bandit/formatters/sarif.py 
new/bandit-1.9.2/bandit/formatters/sarif.py
--- old/bandit-1.8.6/bandit/formatters/sarif.py 2025-07-06 05:10:12.000000000 
+0200
+++ new/bandit-1.9.2/bandit/formatters/sarif.py 2025-11-23 22:35:40.000000000 
+0100
@@ -125,11 +125,11 @@
 .. versionadded:: 1.7.8
 
 """  # noqa: E501
+import datetime
 import logging
 import pathlib
 import sys
 import urllib.parse as urlparse
-from datetime import datetime
 
 import sarif_om as om
 from jschema_to_python.to_json import to_json
@@ -168,7 +168,9 @@
                 ),
                 invocations=[
                     om.Invocation(
-                        end_time_utc=datetime.utcnow().strftime(TS_FORMAT),
+                        end_time_utc=datetime.datetime.now(
+                            datetime.timezone.utc
+                        ).strftime(TS_FORMAT),
                         execution_successful=True,
                     )
                 ],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/bandit/formatters/screen.py 
new/bandit-1.9.2/bandit/formatters/screen.py
--- old/bandit-1.8.6/bandit/formatters/screen.py        2025-07-06 
05:10:12.000000000 +0200
+++ new/bandit-1.9.2/bandit/formatters/screen.py        2025-11-23 
22:35:40.000000000 +0100
@@ -205,7 +205,11 @@
 
     bits = []
     if not manager.quiet or manager.results_count(sev_level, conf_level):
-        bits.append(header("Run started:%s", datetime.datetime.utcnow()))
+        bits.append(
+            header(
+                "Run started:%s", datetime.datetime.now(datetime.timezone.utc)
+            )
+        )
 
         if manager.verbose:
             bits.append(get_verbose_details(manager))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/bandit/formatters/text.py 
new/bandit-1.9.2/bandit/formatters/text.py
--- old/bandit-1.8.6/bandit/formatters/text.py  2025-07-06 05:10:12.000000000 
+0200
+++ new/bandit-1.9.2/bandit/formatters/text.py  2025-11-23 22:35:40.000000000 
+0100
@@ -161,7 +161,9 @@
     bits = []
 
     if not manager.quiet or manager.results_count(sev_level, conf_level):
-        bits.append(f"Run started:{datetime.datetime.utcnow()}")
+        bits.append(
+            f"Run started:{datetime.datetime.now(datetime.timezone.utc)}"
+        )
 
         if manager.verbose:
             bits.append(get_verbose_details(manager))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/bandit/formatters/yaml.py 
new/bandit-1.9.2/bandit/formatters/yaml.py
--- old/bandit-1.8.6/bandit/formatters/yaml.py  2025-07-06 05:10:12.000000000 
+0200
+++ new/bandit-1.9.2/bandit/formatters/yaml.py  2025-11-23 22:35:40.000000000 
+0100
@@ -115,7 +115,9 @@
     # timezone agnostic format
     TS_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
 
-    time_string = datetime.datetime.utcnow().strftime(TS_FORMAT)
+    time_string = datetime.datetime.now(datetime.timezone.utc).strftime(
+        TS_FORMAT
+    )
     machine_output["generated_at"] = time_string
 
     yaml.safe_dump(machine_output, fileobj, default_flow_style=False)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/bandit/plugins/django_sql_injection.py 
new/bandit-1.9.2/bandit/plugins/django_sql_injection.py
--- old/bandit-1.8.6/bandit/plugins/django_sql_injection.py     2025-07-06 
05:10:12.000000000 +0200
+++ new/bandit-1.9.2/bandit/plugins/django_sql_injection.py     2025-11-23 
22:35:40.000000000 +0100
@@ -68,7 +68,10 @@
             if key in kwargs:
                 if isinstance(kwargs[key], ast.List):
                     for val in kwargs[key].elts:
-                        if not isinstance(val, ast.Str):
+                        if not (
+                            isinstance(val, ast.Constant)
+                            and isinstance(val.value, str)
+                        ):
                             insecure = True
                             break
                 else:
@@ -77,12 +80,18 @@
         if not insecure and "select" in kwargs:
             if isinstance(kwargs["select"], ast.Dict):
                 for k in kwargs["select"].keys:
-                    if not isinstance(k, ast.Str):
+                    if not (
+                        isinstance(k, ast.Constant)
+                        and isinstance(k.value, str)
+                    ):
                         insecure = True
                         break
                 if not insecure:
                     for v in kwargs["select"].values:
-                        if not isinstance(v, ast.Str):
+                        if not (
+                            isinstance(v, ast.Constant)
+                            and isinstance(v.value, str)
+                        ):
                             insecure = True
                             break
             else:
@@ -135,7 +144,9 @@
                 kwargs = keywords2dict(context.node.keywords)
                 sql = kwargs["sql"]
 
-            if not isinstance(sql, ast.Str):
+            if not (
+                isinstance(sql, ast.Constant) and isinstance(sql.value, str)
+            ):
                 return bandit.Issue(
                     severity=bandit.MEDIUM,
                     confidence=bandit.MEDIUM,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/bandit/plugins/django_xss.py 
new/bandit-1.9.2/bandit/plugins/django_xss.py
--- old/bandit-1.8.6/bandit/plugins/django_xss.py       2025-07-06 
05:10:12.000000000 +0200
+++ new/bandit-1.9.2/bandit/plugins/django_xss.py       2025-11-23 
22:35:40.000000000 +0100
@@ -96,7 +96,7 @@
                 break
             to = analyser.is_assigned(node)
             if to:
-                if isinstance(to, ast.Str):
+                if isinstance(to, ast.Constant) and isinstance(to.value, str):
                     secure = True
                 elif isinstance(to, ast.Name):
                     secure = evaluate_var(to, parent, to.lineno, ignore_nodes)
@@ -105,7 +105,9 @@
                 elif isinstance(to, (list, tuple)):
                     num_secure = 0
                     for some_to in to:
-                        if isinstance(some_to, ast.Str):
+                        if isinstance(some_to, ast.Constant) and isinstance(
+                            some_to.value, str
+                        ):
                             num_secure += 1
                         elif isinstance(some_to, ast.Name):
                             if evaluate_var(
@@ -131,7 +133,10 @@
     secure = False
     evaluate = False
     if isinstance(call, ast.Call) and isinstance(call.func, ast.Attribute):
-        if isinstance(call.func.value, ast.Str) and call.func.attr == "format":
+        if (
+            isinstance(call.func.value, ast.Constant)
+            and call.func.attr == "format"
+        ):
             evaluate = True
             if call.keywords:
                 evaluate = False  # TODO(??) get support for this
@@ -140,7 +145,7 @@
         args = list(call.args)
         num_secure = 0
         for arg in args:
-            if isinstance(arg, ast.Str):
+            if isinstance(arg, ast.Constant) and isinstance(arg.value, str):
                 num_secure += 1
             elif isinstance(arg, ast.Name):
                 if evaluate_var(arg, parent, call.lineno, ignore_nodes):
@@ -167,7 +172,9 @@
 def transform2call(var):
     if isinstance(var, ast.BinOp):
         is_mod = isinstance(var.op, ast.Mod)
-        is_left_str = isinstance(var.left, ast.Str)
+        is_left_str = isinstance(var.left, ast.Constant) and isinstance(
+            var.left.value, str
+        )
         if is_mod and is_left_str:
             new_call = ast.Call()
             new_call.args = []
@@ -212,7 +219,9 @@
         secure = evaluate_call(xss_var, parent)
     elif isinstance(xss_var, ast.BinOp):
         is_mod = isinstance(xss_var.op, ast.Mod)
-        is_left_str = isinstance(xss_var.left, ast.Str)
+        is_left_str = isinstance(xss_var.left, ast.Constant) and isinstance(
+            xss_var.left.value, str
+        )
         if is_mod and is_left_str:
             parent = node._bandit_parent
             while not isinstance(parent, (ast.Module, ast.FunctionDef)):
@@ -272,5 +281,7 @@
         ]
         if context.call_function_name in affected_functions:
             xss = context.node.args[0]
-            if not isinstance(xss, ast.Str):
+            if not (
+                isinstance(xss, ast.Constant) and isinstance(xss.value, str)
+            ):
                 return check_risk(context.node)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/bandit-1.8.6/bandit/plugins/general_hardcoded_password.py 
new/bandit-1.9.2/bandit/plugins/general_hardcoded_password.py
--- old/bandit-1.8.6/bandit/plugins/general_hardcoded_password.py       
2025-07-06 05:10:12.000000000 +0200
+++ new/bandit-1.9.2/bandit/plugins/general_hardcoded_password.py       
2025-11-23 22:35:40.000000000 +0100
@@ -83,45 +83,53 @@
         # looks for "candidate='some_string'"
         for targ in node._bandit_parent.targets:
             if isinstance(targ, ast.Name) and RE_CANDIDATES.search(targ.id):
-                return _report(node.s)
+                return _report(node.value)
             elif isinstance(targ, ast.Attribute) and RE_CANDIDATES.search(
                 targ.attr
             ):
-                return _report(node.s)
+                return _report(node.value)
 
     elif isinstance(
         node._bandit_parent, ast.Subscript
-    ) and RE_CANDIDATES.search(node.s):
+    ) and RE_CANDIDATES.search(node.value):
         # Py39+: looks for "dict[candidate]='some_string'"
         # subscript -> index -> string
         assign = node._bandit_parent._bandit_parent
-        if isinstance(assign, ast.Assign) and isinstance(
-            assign.value, ast.Str
+        if (
+            isinstance(assign, ast.Assign)
+            and isinstance(assign.value, ast.Constant)
+            and isinstance(assign.value.value, str)
         ):
-            return _report(assign.value.s)
+            return _report(assign.value.value)
 
     elif isinstance(node._bandit_parent, ast.Index) and RE_CANDIDATES.search(
-        node.s
+        node.value
     ):
         # looks for "dict[candidate]='some_string'"
         # assign -> subscript -> index -> string
         assign = node._bandit_parent._bandit_parent._bandit_parent
-        if isinstance(assign, ast.Assign) and isinstance(
-            assign.value, ast.Str
+        if (
+            isinstance(assign, ast.Assign)
+            and isinstance(assign.value, ast.Constant)
+            and isinstance(assign.value.value, str)
         ):
-            return _report(assign.value.s)
+            return _report(assign.value.value)
 
     elif isinstance(node._bandit_parent, ast.Compare):
         # looks for "candidate == 'some_string'"
         comp = node._bandit_parent
         if isinstance(comp.left, ast.Name):
             if RE_CANDIDATES.search(comp.left.id):
-                if isinstance(comp.comparators[0], ast.Str):
-                    return _report(comp.comparators[0].s)
+                if isinstance(
+                    comp.comparators[0], ast.Constant
+                ) and isinstance(comp.comparators[0].value, str):
+                    return _report(comp.comparators[0].value)
         elif isinstance(comp.left, ast.Attribute):
             if RE_CANDIDATES.search(comp.left.attr):
-                if isinstance(comp.comparators[0], ast.Str):
-                    return _report(comp.comparators[0].s)
+                if isinstance(
+                    comp.comparators[0], ast.Constant
+                ) and isinstance(comp.comparators[0].value, str):
+                    return _report(comp.comparators[0].value)
 
 
 @test.checks("Call")
@@ -176,8 +184,12 @@
     """
     # looks for "function(candidate='some_string')"
     for kw in context.node.keywords:
-        if isinstance(kw.value, ast.Str) and RE_CANDIDATES.search(kw.arg):
-            return _report(kw.value.s)
+        if (
+            isinstance(kw.value, ast.Constant)
+            and isinstance(kw.value.value, str)
+            and RE_CANDIDATES.search(kw.arg)
+        ):
+            return _report(kw.value.value)
 
 
 @test.checks("FunctionDef")
@@ -246,9 +258,12 @@
         if isinstance(key, (ast.Name, ast.arg)):
             # Skip if the default value is None
             if val is None or (
-                isinstance(val, (ast.Constant, ast.NameConstant))
-                and val.value is None
+                isinstance(val, ast.Constant) and val.value is None
             ):
                 continue
-            if isinstance(val, ast.Str) and RE_CANDIDATES.search(key.arg):
-                return _report(val.s)
+            if (
+                isinstance(val, ast.Constant)
+                and isinstance(val.value, str)
+                and RE_CANDIDATES.search(key.arg)
+            ):
+                return _report(val.value)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/bandit-1.8.6/bandit/plugins/hashlib_insecure_functions.py 
new/bandit-1.9.2/bandit/plugins/hashlib_insecure_functions.py
--- old/bandit-1.8.6/bandit/plugins/hashlib_insecure_functions.py       
2025-07-06 05:10:12.000000000 +0200
+++ new/bandit-1.9.2/bandit/plugins/hashlib_insecure_functions.py       
2025-11-23 22:35:40.000000000 +0100
@@ -11,10 +11,7 @@
 can be used to create insecure hash functions like MD4 and MD5 if they are
 passed as algorithm names to this function.
 
-For Python versions prior to 3.9, this check is similar to B303 blacklist
-except that this checks for insecure hash functions created using
-``hashlib.new`` function. For Python version 3.9 and later, this check
-does additional checking for usage of keyword usedforsecurity on all
+This check does additional checking for usage of keyword usedforsecurity on all
 function variations of hashlib.
 
 Similar to ``hashlib``, this plugin also checks for usage of one of the
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/bandit/plugins/injection_shell.py 
new/bandit-1.9.2/bandit/plugins/injection_shell.py
--- old/bandit-1.8.6/bandit/plugins/injection_shell.py  2025-07-06 
05:10:12.000000000 +0200
+++ new/bandit-1.9.2/bandit/plugins/injection_shell.py  2025-11-23 
22:35:40.000000000 +0100
@@ -15,7 +15,9 @@
 
 
 def _evaluate_shell_call(context):
-    no_formatting = isinstance(context.node.args[0], ast.Str)
+    no_formatting = isinstance(
+        context.node.args[0], ast.Constant
+    ) and isinstance(context.node.args[0].value, str)
 
     if no_formatting:
         return bandit.LOW
@@ -83,15 +85,19 @@
         for key in keywords:
             if key.arg == "shell":
                 val = key.value
-                if isinstance(val, ast.Num):
-                    result = bool(val.n)
+                if isinstance(val, ast.Constant) and (
+                    isinstance(val.value, int)
+                    or isinstance(val.value, float)
+                    or isinstance(val.value, complex)
+                ):
+                    result = bool(val.value)
                 elif isinstance(val, ast.List):
                     result = bool(val.elts)
                 elif isinstance(val, ast.Dict):
                     result = bool(val.keys)
                 elif isinstance(val, ast.Name) and val.id in ["False", "None"]:
                     result = False
-                elif isinstance(val, ast.NameConstant):
+                elif isinstance(val, ast.Constant):
                     result = val.value
                 else:
                     result = True
@@ -687,7 +693,11 @@
                 node = node.elts[0]
 
             # make sure the param is a string literal and not a var name
-            if isinstance(node, ast.Str) and not full_path_match.match(node.s):
+            if (
+                isinstance(node, ast.Constant)
+                and isinstance(node.value, str)
+                and not full_path_match.match(node.value)
+            ):
                 return bandit.Issue(
                     severity=bandit.LOW,
                     confidence=bandit.HIGH,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/bandit/plugins/injection_sql.py 
new/bandit-1.9.2/bandit/plugins/injection_sql.py
--- old/bandit-1.8.6/bandit/plugins/injection_sql.py    2025-07-06 
05:10:12.000000000 +0200
+++ new/bandit-1.9.2/bandit/plugins/injection_sql.py    2025-11-23 
22:35:40.000000000 +0100
@@ -96,7 +96,7 @@
     elif isinstance(
         node._bandit_parent, ast.Attribute
     ) and node._bandit_parent.attr in ("format", "replace"):
-        statement = node.s
+        statement = node.value
         # Hierarchy for "".format() is Wrapper -> Call -> Attribute -> Str
         wrapper = node._bandit_parent._bandit_parent._bandit_parent
         if node._bandit_parent.attr == "replace":
@@ -107,14 +107,14 @@
         substrings = [
             child
             for child in node._bandit_parent.values
-            if isinstance(child, ast.Str)
+            if isinstance(child, ast.Constant) and isinstance(child.value, str)
         ]
         # JoinedStr consists of list of Constant and FormattedValue
         # instances. Let's perform one test for the whole string
         # and abandon all parts except the first one to raise one
         # failed test instead of many for the same SQL statement.
         if substrings and node == substrings[0]:
-            statement = "".join([str(child.s) for child in substrings])
+            statement = "".join([str(child.value) for child in substrings])
             wrapper = node._bandit_parent._bandit_parent
 
     if isinstance(wrapper, ast.Call):  # wrapped in "execute" call?
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/bandit-1.8.6/bandit/plugins/tarfile_unsafe_members.py 
new/bandit-1.9.2/bandit/plugins/tarfile_unsafe_members.py
--- old/bandit-1.8.6/bandit/plugins/tarfile_unsafe_members.py   2025-07-06 
05:10:12.000000000 +0200
+++ new/bandit-1.9.2/bandit/plugins/tarfile_unsafe_members.py   2025-11-23 
22:35:40.000000000 +0100
@@ -10,8 +10,8 @@
 
 Severity are set as follows:
 
-* ``tarfile.extractalll(members=function(tarfile))`` - LOW
-* ``tarfile.extractalll(members=?)`` - member is not a function - MEDIUM
+* ``tarfile.extractall(members=function(tarfile))`` - LOW
+* ``tarfile.extractall(members=?)`` - member is not a function - MEDIUM
 * ``tarfile.extractall()`` - members from the archive is trusted - HIGH
 
 Use ``tarfile.extractall(members=function_name)`` and define a function
@@ -98,7 +98,7 @@
     for keyword in context.node.keywords:
         if keyword.arg == "filter":
             arg = keyword.value
-            return isinstance(arg, ast.Str) and arg.s == "data"
+            return isinstance(arg, ast.Constant) and arg.value == "data"
 
 
 @test.test_id("B202")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/bandit.egg-info/PKG-INFO 
new/bandit-1.9.2/bandit.egg-info/PKG-INFO
--- old/bandit-1.8.6/bandit.egg-info/PKG-INFO   2025-07-06 05:10:35.000000000 
+0200
+++ new/bandit-1.9.2/bandit.egg-info/PKG-INFO   2025-11-23 22:36:05.000000000 
+0100
@@ -1,6 +1,6 @@
-Metadata-Version: 2.1
+Metadata-Version: 2.4
 Name: bandit
-Version: 1.8.6
+Version: 1.9.2
 Summary: Security oriented static analyser for python code.
 Home-page: https://bandit.readthedocs.io/
 Author: PyCQA
@@ -12,7 +12,6 @@
 Project-URL: Issue Tracker, https://github.com/PyCQA/bandit/issues
 Project-URL: Discord, https://discord.gg/qYxpadCgkx
 Project-URL: Sponsor, 
https://psfmember.org/civicrm/contribute/transact/?reset=1&id=42
-Platform: UNKNOWN
 Classifier: Development Status :: 5 - Production/Stable
 Classifier: Environment :: Console
 Classifier: Intended Audience :: Information Technology
@@ -22,20 +21,48 @@
 Classifier: Operating System :: MacOS :: MacOS X
 Classifier: Programming Language :: Python
 Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.9
 Classifier: Programming Language :: Python :: 3.10
 Classifier: Programming Language :: Python :: 3.11
 Classifier: Programming Language :: Python :: 3.12
 Classifier: Programming Language :: Python :: 3.13
+Classifier: Programming Language :: Python :: 3.14
 Classifier: Programming Language :: Python :: 3 :: Only
 Classifier: Topic :: Security
-Requires-Python: >=3.9
+Requires-Python: >=3.10
+License-File: LICENSE
+Requires-Dist: PyYAML>=5.3.1
+Requires-Dist: stevedore>=1.20.0
+Requires-Dist: rich
+Requires-Dist: colorama>=0.3.9; platform_system == "Windows"
 Provides-Extra: yaml
+Requires-Dist: PyYAML; extra == "yaml"
 Provides-Extra: toml
+Requires-Dist: tomli>=1.1.0; python_version < "3.11" and extra == "toml"
 Provides-Extra: baseline
+Requires-Dist: GitPython>=3.1.30; extra == "baseline"
 Provides-Extra: sarif
+Requires-Dist: sarif-om>=1.0.4; extra == "sarif"
+Requires-Dist: jschema-to-python>=1.2.3; extra == "sarif"
 Provides-Extra: test
-License-File: LICENSE
+Requires-Dist: coverage>=4.5.4; extra == "test"
+Requires-Dist: fixtures>=3.0.0; extra == "test"
+Requires-Dist: flake8>=4.0.0; extra == "test"
+Requires-Dist: stestr>=2.5.0; extra == "test"
+Requires-Dist: testscenarios>=0.5.0; extra == "test"
+Requires-Dist: testtools>=2.3.0; extra == "test"
+Requires-Dist: beautifulsoup4>=4.8.0; extra == "test"
+Requires-Dist: pylint==1.9.4; extra == "test"
+Dynamic: author
+Dynamic: author-email
+Dynamic: description
+Dynamic: home-page
+Dynamic: license
+Dynamic: license-file
+Dynamic: project-url
+Dynamic: provides-extra
+Dynamic: requires-dist
+Dynamic: requires-python
+Dynamic: summary
 
 .. image:: 
https://raw.githubusercontent.com/pycqa/bandit/main/logo/logotype-sm.png
     :alt: Bandit
@@ -183,5 +210,3 @@
 
 If you also ❤️ Bandit, please consider sponsoring.
 
-
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/bandit.egg-info/entry_points.txt 
new/bandit-1.9.2/bandit.egg-info/entry_points.txt
--- old/bandit-1.8.6/bandit.egg-info/entry_points.txt   2025-07-06 
05:10:35.000000000 +0200
+++ new/bandit-1.9.2/bandit.egg-info/entry_points.txt   2025-11-23 
22:36:05.000000000 +0100
@@ -61,4 +61,3 @@
 bandit = bandit.cli.main:main
 bandit-baseline = bandit.cli.baseline:main
 bandit-config-generator = bandit.cli.config_generator:main
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/bandit.egg-info/pbr.json 
new/bandit-1.9.2/bandit.egg-info/pbr.json
--- old/bandit-1.8.6/bandit.egg-info/pbr.json   2025-07-06 05:10:35.000000000 
+0200
+++ new/bandit-1.9.2/bandit.egg-info/pbr.json   2025-11-23 22:36:05.000000000 
+0100
@@ -1 +1 @@
-{"git_version": "2d0b675", "is_release": false}
\ No newline at end of file
+{"git_version": "ea0d187", "is_release": false}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/doc/build/man/bandit.1 
new/bandit-1.9.2/doc/build/man/bandit.1
--- old/bandit-1.8.6/doc/build/man/bandit.1     2025-07-06 05:10:33.000000000 
+0200
+++ new/bandit-1.9.2/doc/build/man/bandit.1     2025-11-23 22:36:03.000000000 
+0100
@@ -27,7 +27,7 @@
 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
 .in \\n[rst2man-indent\\n[rst2man-indent-level]]u
 ..
-.TH "BANDIT" "1" "Jul 06, 2025" "" "Bandit"
+.TH "BANDIT" "1" "Nov 23, 2025" "" "Bandit"
 .SH NAME
 bandit \- Python source code security analyzer
 .SH SYNOPSIS
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/examples/hardcoded-passwords.py 
new/bandit-1.9.2/examples/hardcoded-passwords.py
--- old/bandit-1.8.6/examples/hardcoded-passwords.py    2025-07-06 
05:10:12.000000000 +0200
+++ new/bandit-1.9.2/examples/hardcoded-passwords.py    2025-11-23 
22:35:40.000000000 +0100
@@ -78,3 +78,12 @@
     self.auth_password = auth_password
     self.auth_link = auth_link
     self.kwargs = kwargs
+
+# Possible hardcoded password: None
+# Severity: High   Confidence: High
+from oslo_config import cfg
+cfg.StrOpt(
+    'metadata_proxy_shared_secret',
+    default='',
+    secret=True,
+)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/bandit-1.8.6/examples/hashlib_new_insecure_functions.py 
new/bandit-1.9.2/examples/hashlib_new_insecure_functions.py
--- old/bandit-1.8.6/examples/hashlib_new_insecure_functions.py 2025-07-06 
05:10:12.000000000 +0200
+++ new/bandit-1.9.2/examples/hashlib_new_insecure_functions.py 2025-11-23 
22:35:40.000000000 +0100
@@ -16,7 +16,6 @@
 
 hashlib.new(name='SHA', data=b'test')
 
-# usedforsecurity arg only availabe in Python 3.9+
 hashlib.new('sha1', usedforsecurity=True)
 
 # Test that plugin does not flag valid hash functions.
@@ -24,5 +23,4 @@
 
 hashlib.new('SHA512')
 
-# usedforsecurity arg only availabe in Python 3.9+
 hashlib.new(name='sha1', usedforsecurity=False)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/setup.cfg new/bandit-1.9.2/setup.cfg
--- old/bandit-1.8.6/setup.cfg  2025-07-06 05:10:36.065528000 +0200
+++ new/bandit-1.9.2/setup.cfg  2025-11-23 22:36:05.341152700 +0100
@@ -17,11 +17,11 @@
        Operating System :: MacOS :: MacOS X
        Programming Language :: Python
        Programming Language :: Python :: 3
-       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
        Programming Language :: Python :: 3 :: Only
        Topic :: Security
 project_urls = 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/setup.py new/bandit-1.9.2/setup.py
--- old/bandit-1.8.6/setup.py   2025-07-06 05:10:12.000000000 +0200
+++ new/bandit-1.9.2/setup.py   2025-11-23 22:35:40.000000000 +0100
@@ -13,7 +13,7 @@
 
 
 setuptools.setup(
-    python_requires=">=3.9",
+    python_requires=">=3.10",
     setup_requires=["pbr>=2.0.0"],
     pbr=True,
     data_files=data_files,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/tests/unit/core/test_context.py 
new/bandit-1.9.2/tests/unit/core/test_context.py
--- old/bandit-1.8.6/tests/unit/core/test_context.py    2025-07-06 
05:10:12.000000000 +0200
+++ new/bandit-1.9.2/tests/unit/core/test_context.py    2025-11-23 
22:35:40.000000000 +0100
@@ -132,39 +132,36 @@
     def test__get_literal_value(self):
         new_context = context.Context()
 
-        value = ast.Num(42)
-        expected = value.n
+        value = ast.Constant(42)
+        expected = value.value
         self.assertEqual(expected, new_context._get_literal_value(value))
 
-        value = ast.Str("spam")
-        expected = value.s
+        value = ast.Constant("spam")
+        expected = value.value
         self.assertEqual(expected, new_context._get_literal_value(value))
 
-        value = ast.List([ast.Str("spam"), ast.Num(42)], ast.Load())
-        expected = [ast.Str("spam").s, ast.Num(42).n]
+        value = ast.List([ast.Constant("spam"), ast.Constant(42)], ast.Load())
+        expected = [ast.Constant("spam").value, ast.Constant(42).value]
         self.assertListEqual(expected, new_context._get_literal_value(value))
 
-        value = ast.Tuple([ast.Str("spam"), ast.Num(42)], ast.Load())
-        expected = (ast.Str("spam").s, ast.Num(42).n)
+        value = ast.Tuple([ast.Constant("spam"), ast.Constant(42)], ast.Load())
+        expected = (ast.Constant("spam").value, ast.Constant(42).value)
         self.assertTupleEqual(expected, new_context._get_literal_value(value))
 
-        value = ast.Set([ast.Str("spam"), ast.Num(42)])
-        expected = {ast.Str("spam").s, ast.Num(42).n}
+        value = ast.Set([ast.Constant("spam"), ast.Constant(42)])
+        expected = {ast.Constant("spam").value, ast.Constant(42).value}
         self.assertSetEqual(expected, new_context._get_literal_value(value))
 
         value = ast.Dict(["spam", "eggs"], [42, "foo"])
         expected = dict(spam=42, eggs="foo")
         self.assertDictEqual(expected, new_context._get_literal_value(value))
 
-        value = ast.Ellipsis()
-        self.assertIsNone(new_context._get_literal_value(value))
-
         value = ast.Name("spam", ast.Load())
         expected = value.id
         self.assertEqual(expected, new_context._get_literal_value(value))
 
-        value = ast.Bytes(b"spam")
-        expected = value.s
+        value = ast.Constant(b"spam")
+        expected = value.value
         self.assertEqual(expected, new_context._get_literal_value(value))
 
         self.assertIsNone(new_context._get_literal_value(None))
@@ -207,7 +204,7 @@
     def test_get_call_arg_at_position(self):
         expected_arg = "spam"
         ref_call = mock.Mock()
-        ref_call.args = [ast.Str(expected_arg)]
+        ref_call.args = [ast.Constant(expected_arg)]
         ref_context = dict(call=ref_call)
         new_context = context.Context(context_object=ref_context)
         self.assertEqual(expected_arg, new_context.get_call_arg_at_position(0))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bandit-1.8.6/tox.ini new/bandit-1.9.2/tox.ini
--- old/bandit-1.8.6/tox.ini    2025-07-06 05:10:12.000000000 +0200
+++ new/bandit-1.9.2/tox.ini    2025-11-23 22:35:40.000000000 +0100
@@ -1,6 +1,6 @@
 [tox]
 minversion = 3.2.0
-envlist = py39,pep8
+envlist = py310,pep8
 
 [testenv]
 usedevelop = True

Reply via email to