Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support python 3.13 #539

Merged
merged 3 commits into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: [3.8, 3.9, "3.10", 3.11, 3.12]
python-version: [3.8, 3.9, "3.10", 3.11, 3.12, 3.13]
include:
- os: ubuntu-latest
path: ~/.cache/pypoetry
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@f095bcc56b7c2baf48f3ac70d6d6782f4f553222
- name: Set up Python 3.12
- name: Set up Python 3.13
uses: actions/setup-python@db9987b4c1f10f0404fa60ee629f675fafbd6763
with:
python-version: 3.12
python-version: 3.13
- name: Install dependencies
run: |
pip install --upgrade pip
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
v5.0.2 - Mmmm DD 2024
---------------------

* [#539](https://github.com/godaddy/tartufo/pull/539) - Add support for python
3.13, and update dependencies to latest versions.

v5.0.1 - July 25 2024
---------------------

Expand Down
1,128 changes: 628 additions & 500 deletions poetry.lock

Large diffs are not rendered by default.

8 changes: 6 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ classifiers = [
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
"Topic :: Security",
Expand All @@ -39,10 +40,13 @@ tartufo = "tartufo.cli:main"

[tool.poetry.dependencies]
GitPython = "^3.1.43"
pygit2 = "^1.11.0"
pygit2 = [
{version = "^1.11.0", python = "<3.10"},
{version = "^1.16.0", python = ">=3.10"}
]
click = "^8.1.7"
colorama = {version = "*", markers = "sys_platform == 'win32'"}
python = ">=3.8, <3.13"
python = ">=3.8, <3.14"
tomlkit = "^0.13.0"
cached-property = "^1.5.2"

Expand Down
33 changes: 19 additions & 14 deletions tartufo/scanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,7 @@ def __init__(self, global_options: types.GlobalOptions, repo_path: str) -> None:
# Disable ownership sanity checks to maintain compatibility with
# behavior of libgit2 1.4.2 and earlier; later versions (i.e. with
# pygit2 1.9.2 and later) fail in docker context otherwise.
pygit2.option(pygit2.GIT_OPT_SET_OWNER_VALIDATION, 0)
pygit2.option(pygit2.GIT_OPT_SET_OWNER_VALIDATION, 0) # type: ignore[attr-defined]

# Load any configuration file in the target repository. This comes
# *BEFORE* load_repo() because that method may rely on configuration data
Expand Down Expand Up @@ -735,13 +735,13 @@ def _iter_diff_index(
file_path = (
delta.new_file.path if delta.new_file.path else delta.old_file.path
)
if delta.status == pygit2.GIT_DELTA_DELETED:
if delta.status == pygit2.GIT_DELTA_DELETED: # type: ignore[attr-defined]
self.logger.debug("Skipping as the file was a git delete operation")
continue
if delta.is_binary:
self.logger.debug("Binary file skipped: %s", file_path)
continue
printable_diff: str = patch.text
printable_diff: str = patch.text or ""
if not self.global_options.scan_filenames:
# The `printable_diff` contains diff header,
# so we need to strip that before analyzing it
Expand Down Expand Up @@ -773,7 +773,7 @@ def filter_submodules(self, repo: pygit2.Repository) -> None:
self.logger.info("Excluding submodules paths from scan.")
try:
for module in repo.listall_submodules():
submodule = repo.lookup_submodule(module)
submodule = repo.lookup_submodule(module) # type: ignore[attr-defined]
patterns.append(re.compile(f"^{submodule.path}"))
except AttributeError as exc:
raise TartufoException(
Expand Down Expand Up @@ -825,11 +825,14 @@ def load_repo(self, repo_path: str) -> pygit2.Repository:
raise types.GitLocalException(str(exc)) from exc

def _get_chunks(
self, commits: Iterable, already_searched: Set[bytes], branch_name: str
self,
commits: Iterable[pygit2.Commit],
already_searched: Set[bytes],
branch_name: str,
) -> Generator[types.Chunk, None, None]:
diff_hash: bytes
curr_commit: pygit2.Commit = None
prev_commit: pygit2.Commit = None
curr_commit: Optional[pygit2.Commit] = None
prev_commit: Optional[pygit2.Commit] = None
for curr_commit in commits:
try:
prev_commit = curr_commit.parents[0]
Expand All @@ -847,7 +850,7 @@ def _get_chunks(
).digest()
if diff_hash in already_searched:
continue
diff: pygit2.Diff = self._repo.diff(prev_commit, curr_commit)
diff: pygit2.Diff = self._repo.diff(prev_commit, curr_commit) # type: ignore[attr-defined]
already_searched.add(diff_hash)
diff.find_similar()
for blob, file_path in self._iter_diff_index(diff):
Expand All @@ -860,7 +863,7 @@ def _get_chunks(

# Finally, yield the first commit to the branch
if curr_commit:
tree: pygit2.Tree = self._repo.revparse_single(str(curr_commit.id)).tree
tree: pygit2.Tree = self._repo.revparse_single(str(curr_commit.id)).tree # type: ignore[attr-defined]
tree_diff: pygit2.Diff = tree.diff_to_tree(swap=True)
iter_diff = self._iter_diff_index(tree_diff)
for blob, file_path in iter_diff:
Expand All @@ -882,7 +885,7 @@ def chunks(self) -> Generator[types.Chunk, None, None]:
try:
if self.git_options.branch:
# Single branch only
branch = self._repo.branches.get(self.git_options.branch)
branch = self._repo.branches.get(self.git_options.branch) # type: ignore[attr-defined]
if not branch:
raise BranchNotFoundException(
f"Branch {self.git_options.branch} was not found."
Expand All @@ -899,7 +902,7 @@ def chunks(self) -> Generator[types.Chunk, None, None]:
# scan not only the locally checked out branches (as provided
# by self._repo.listall_branches()), but to also scan all
# available remote refs
branches = list(self._repo.branches)
branches = list(self._repo.branches) # type: ignore[attr-defined]
except pygit2.GitError as exc:
raise types.GitRemoteException(str(exc)) from exc

Expand All @@ -911,13 +914,15 @@ def chunks(self) -> Generator[types.Chunk, None, None]:
branch_len = len(branches)
for branch_name in branches:
self.logger.info("Scanning branch: %s", branch_name)
commits: Iterable[pygit2.Commit]
if branch_name == "HEAD":
commits = [self._repo.get(self._repo.head.target)]
commits = [self._repo.get(self._repo.head.target)] # type: ignore[attr-defined]
else:
branch = self._repo.branches.get(branch_name)
branch = self._repo.branches.get(branch_name) # type: ignore[attr-defined]
try:
commits = self._repo.walk(
branch.resolve().target, pygit2.GIT_SORT_TOPOLOGICAL
branch.resolve().target,
pygit2.GIT_SORT_TOPOLOGICAL, # type: ignore[attr-defined]
)

except AttributeError:
Expand Down
4 changes: 2 additions & 2 deletions tests/test_git_repo_scanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ def test_excluded_files_are_not_scanned(self, mock_should: mock.MagicMock):
test_scanner = scanner.GitRepoScanner(
self.global_options, self.git_options, "."
)
diffs = list(test_scanner._iter_diff_index([mock_diff]))
diffs = list(test_scanner._iter_diff_index([mock_diff])) # type: ignore[arg-type]
self.assertEqual(diffs, [])
mock_should.assert_called_once()

Expand Down Expand Up @@ -502,7 +502,7 @@ def test_all_files_are_yielded(self, mock_should: mock.MagicMock):
test_scanner = scanner.GitRepoScanner(
self.global_options, self.git_options, "."
)
diffs = list(test_scanner._iter_diff_index([mock_diff_1, mock_diff_2]))
diffs = list(test_scanner._iter_diff_index([mock_diff_1, mock_diff_2])) # type: ignore[arg-type]
self.assertEqual(
diffs,
[
Expand Down
3 changes: 2 additions & 1 deletion tox.ini
rbailey-godaddy marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
minversion = 3.8.0
toxworkdir = {env:TOX_WORK_DIR:.tox}
skip_missing_interpreters = True
envlist = py{38,39,pypy3,310,311,312},black,mypy,pylint,vulture,docs
envlist = py{38,39,pypy3,310,311,312,313},black,mypy,pylint,vulture,docs
parallel_show_output = True
isolated_build = True

Expand All @@ -13,6 +13,7 @@ python =
3.10: py310
3.11: py311
3.12: py312
3.13: py313
pypy3: pypy3

[testenv]
Expand Down
Loading