diff --git a/.github/workflows/autoformat-pixeebot-prs.yaml b/.github/workflows/autoformat-pixeebot-prs.yaml index 56be6256..992c3066 100644 --- a/.github/workflows/autoformat-pixeebot-prs.yaml +++ b/.github/workflows/autoformat-pixeebot-prs.yaml @@ -18,7 +18,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v6 with: - python-version: "3.13" + python-version: "3.14" - name: Install black run: pip install black diff --git a/.github/workflows/codemod_pygoat.yml b/.github/workflows/codemod_pygoat.yml index f6436d2c..04b2e1f6 100644 --- a/.github/workflows/codemod_pygoat.yml +++ b/.github/workflows/codemod_pygoat.yml @@ -26,7 +26,7 @@ jobs: - name: Set Up Python uses: actions/setup-python@v6 with: - python-version: '3.13' + python-version: '3.14' cache: 'pip' - name: Install Codemodder Package run: pip install . diff --git a/.github/workflows/deploy_to_pypi.yml b/.github/workflows/deploy_to_pypi.yml index ccba01b9..fbf8cada 100644 --- a/.github/workflows/deploy_to_pypi.yml +++ b/.github/workflows/deploy_to_pypi.yml @@ -14,7 +14,7 @@ jobs: - name: Set Up Python uses: actions/setup-python@v6 with: - python-version: '3.13' + python-version: '3.14' - name: Check out code uses: actions/checkout@v5 - name: Install build dependencies diff --git a/.github/workflows/integration_test.yml b/.github/workflows/integration_test.yml index 806f4466..d0691744 100644 --- a/.github/workflows/integration_test.yml +++ b/.github/workflows/integration_test.yml @@ -22,7 +22,7 @@ jobs: timeout-minutes: 15 strategy: matrix: - python-version: ['3.10', '3.11', '3.12'] + python-version: ['3.12', '3.13', '3.14'] steps: - name: Check out code uses: actions/checkout@v5 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 04aadf97..30dbcfec 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -26,7 +26,7 @@ jobs: - name: Set Up Python uses: actions/setup-python@v6 with: - python-version: '3.13' + python-version: '3.14' cache: 'pip' - name: Install Dependencies run: | diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 00fdf1ba..d44c4b55 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -30,7 +30,7 @@ jobs: - name: Set Up Python uses: actions/setup-python@v6 with: - python-version: '3.13' + python-version: '3.14' cache: 'pip' - name: Install build dependencies run: pip install build twine @@ -49,7 +49,7 @@ jobs: - name: Set Up Python uses: actions/setup-python@v6 with: - python-version: '3.13' + python-version: '3.14' cache: 'pip' - name: Install Codemodder Package # Only install what most users would, not optional dependencies @@ -62,7 +62,7 @@ jobs: timeout-minutes: 25 strategy: matrix: - python-version: ['3.10', '3.11', '3.12'] + python-version: ['3.12', '3.13', '3.14'] steps: - name: Check out code uses: actions/checkout@v5 diff --git a/Dockerfile b/Dockerfile index 5823f4be..5898f9c3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.13 +FROM python:3.14 WORKDIR /codemodder COPY . . diff --git a/integration_tests/sonar/test_sonar_use_secure_protocols.py b/integration_tests/sonar/test_sonar_use_secure_protocols.py index e7acef9a..63dae2aa 100644 --- a/integration_tests/sonar/test_sonar_use_secure_protocols.py +++ b/integration_tests/sonar/test_sonar_use_secure_protocols.py @@ -10,7 +10,7 @@ class TestSonarUseSecureProtocols(SonarIntegrationTest): code_path = "tests/samples/use_secure_protocols.py" replacement_lines = [ ( - 5, + 4, """url = "https://example.com"\n""", ), ] @@ -18,13 +18,13 @@ class TestSonarUseSecureProtocols(SonarIntegrationTest): expected_diff = ( """--- \n""" """+++ \n""" - """@@ -2,4 +2,4 @@\n""" + """@@ -1,4 +1,4 @@\n""" + ''' import ftplib\n''' ''' import smtplib\n''' - ''' import telnetlib\n''' ''' \n''' '''-url = "http://example.com"\n''' '''+url = "https://example.com"\n''' ) # fmt: on - expected_line_change = "5" + expected_line_change = "4" change_description = SonarUseSecureProtocolsTransformer.change_description diff --git a/pyproject.toml b/pyproject.toml index 549a8cf5..35f01909 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,7 +16,7 @@ dependencies = [ "isort>=6.1,<7", "libcst>=1.8,<1.9", "packaging>=24.2,<25.1", - "pydantic~=2.11.5", + "pydantic~=2.12.3", "pylint>=4,<4.1", "python-json-logger~=4.0.0", "PyYAML~=6.0.0", @@ -24,7 +24,7 @@ dependencies = [ "tomlkit~=0.13.0", "wrapt~=1.17.0", "chardet~=5.2.0", - "sarif-pydantic~=0.5.1", + "sarif-pydantic~=0.6.1", "setuptools~=80.0", ] keywords = ["codemod", "codemods", "security", "fix", "fixes"] @@ -32,6 +32,8 @@ classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: GNU Affero General Public License v3", + "Programming Language :: Python :: 3.14", + "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.10", @@ -51,11 +53,11 @@ get-hashes = 'codemodder.scripts.get_hashes:main' [project.optional-dependencies] semgrep = [ - "semgrep>=1.134,<1.135", + "semgrep>=1.140,<1.141", ] test = [ "azure-ai-inference>=1.0.0b1,<2.0", - "coverage>=7.10,<7.11", + "coverage>=7.11,<7.12", "coverage-threshold~=0.4", "defusedxml==0.7.1", "types-defusedxml==0.7.0.20250822", @@ -86,7 +88,7 @@ test = [ "fickling~=0.1.0,>=0.1.3", "graphql-server~=3.0.0b9", "unidiff>=0.7.5", - "semgrep>=1.134,<1.135", + "semgrep>=1.140,<1.141", ] complexity = [ "radon==6.0.*", diff --git a/src/codemodder/codemods/base_codemod.py b/src/codemodder/codemods/base_codemod.py index bd36afb4..ea46ae22 100644 --- a/src/codemodder/codemods/base_codemod.py +++ b/src/codemodder/codemods/base_codemod.py @@ -2,14 +2,19 @@ import functools import importlib.resources +import sys from abc import ABCMeta, abstractmethod from concurrent.futures import ThreadPoolExecutor from dataclasses import dataclass, field from enum import Enum from functools import cached_property -from importlib.abc import Traversable from pathlib import Path +if sys.version_info >= (3, 14): + from importlib.resources.abc import Traversable +else: + from importlib.abc import Traversable + from codemodder.code_directory import file_line_patterns from codemodder.codemods.base_detector import BaseDetector from codemodder.codemods.base_transformer import BaseTransformerPipeline diff --git a/tests/samples/sonar_hotspots.json b/tests/samples/sonar_hotspots.json index cf79c044..8be6e0b7 100644 --- a/tests/samples/sonar_hotspots.json +++ b/tests/samples/sonar_hotspots.json @@ -136,13 +136,13 @@ "securityCategory": "encrypt-data", "vulnerabilityProbability": "LOW", "status": "TO_REVIEW", - "line": 5, + "line": 4, "message": "Using http protocol is insecure. Use https instead", "creationDate": "2025-01-22T13:20:10+0100", "updateDate": "2025-01-22T13:29:45+0100", "textRange": { - "startLine": 5, - "endLine": 5, + "startLine": 4, + "endLine": 4, "startOffset": 6, "endOffset": 26 }, diff --git a/tests/samples/use_secure_protocols.py b/tests/samples/use_secure_protocols.py index 9d0f3511..8c02ef20 100644 --- a/tests/samples/use_secure_protocols.py +++ b/tests/samples/use_secure_protocols.py @@ -1,5 +1,4 @@ import ftplib import smtplib -import telnetlib url = "http://example.com"