crcutil 2.0.3__tar.gz → 2.0.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {crcutil-2.0.3/src/crcutil.egg-info → crcutil-2.0.4}/PKG-INFO +1 -1
- {crcutil-2.0.3 → crcutil-2.0.4}/pyproject.toml +1 -1
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/core/checksum.py +32 -32
- {crcutil-2.0.3 → crcutil-2.0.4/src/crcutil.egg-info}/PKG-INFO +1 -1
- {crcutil-2.0.3 → crcutil-2.0.4}/.github/workflows/python-publish.yml +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/.gitignore +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/LICENSE +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/README.md +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/__init__.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/git-hooks/commit-msg +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/git-hooks/pre-commit +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/init.sh +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/requirements.txt +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/ruff.toml +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/setup.cfg +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/__init__.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/__main__.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/config/log_config.yaml +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/core/__init__.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/core/checksum_manager.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/core/keyboard_monitor.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/core/keyboard_monitor_factory.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/core/keyboard_monitor_wayland.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/core/keyboard_monitor_windows.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/core/keyboard_monitor_x11.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/core/prompt.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/dto/__init__.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/dto/bootstrap_paths_dto.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/dto/checksum_dto.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/dto/crc_diff_report_dto.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/dto/user_instructions_dto.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/enums/__init__.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/enums/user_request.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/exception/__init__.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/exception/bootstrap_error.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/exception/corrupt_crc_error.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/exception/device_error.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/exception/unexpected_argument_error.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/exception/user_error.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/serializer/__init__.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/serializer/checksum_serializer.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/serializer/crc_diff_report_serializer.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/util/__init__.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/util/crcutil_logger.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/util/file_importer.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/util/path_ops.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil/util/static.py +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil.egg-info/SOURCES.txt +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil.egg-info/dependency_links.txt +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil.egg-info/entry_points.txt +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil.egg-info/requires.txt +0 -0
- {crcutil-2.0.3 → crcutil-2.0.4}/src/crcutil.egg-info/top_level.txt +0 -0
|
@@ -5,7 +5,7 @@ from pathlib import Path
|
|
|
5
5
|
|
|
6
6
|
from crcutil.util.crcutil_logger import CrcutilLogger
|
|
7
7
|
|
|
8
|
-
CHUNK_SIZE =
|
|
8
|
+
CHUNK_SIZE = 4096 * 1024
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class Checksum:
|
|
@@ -87,7 +87,9 @@ class Checksum:
|
|
|
87
87
|
- location: a/b/c
|
|
88
88
|
Returns -> b'b/c'
|
|
89
89
|
"""
|
|
90
|
-
return str(location.relative_to(root_location)).encode(
|
|
90
|
+
return str(location.relative_to(root_location).as_posix()).encode(
|
|
91
|
+
"utf-8"
|
|
92
|
+
)
|
|
91
93
|
|
|
92
94
|
def __get_checksum_from_file_contents(self, location: Path) -> bytes:
|
|
93
95
|
"""
|
|
@@ -108,7 +110,32 @@ class Checksum:
|
|
|
108
110
|
bytes: 4-byte little-endian representation of the CRC32 checksum
|
|
109
111
|
"""
|
|
110
112
|
file_checksum = 0
|
|
113
|
+
is_text_file = self.__is_likely_text_file(location)
|
|
114
|
+
|
|
115
|
+
if is_text_file:
|
|
116
|
+
try:
|
|
117
|
+
with location.open("r", encoding="utf-8") as f:
|
|
118
|
+
content = f.read().replace("\r\n", "\n")
|
|
119
|
+
content_bytes = content.encode("utf-8")
|
|
120
|
+
file_checksum = zlib.crc32(content_bytes) & 0xFFFFFFFF
|
|
121
|
+
return file_checksum.to_bytes(4, "little", signed=False)
|
|
122
|
+
except UnicodeDecodeError:
|
|
123
|
+
description = (
|
|
124
|
+
f"Understood as text file: {location!s} "
|
|
125
|
+
"but encountered decoding error. Proceeding w/ binary"
|
|
126
|
+
)
|
|
127
|
+
CrcutilLogger.get_logger().debug(description)
|
|
111
128
|
|
|
129
|
+
with location.open("rb") as f:
|
|
130
|
+
for chunk in iter(lambda: f.read(CHUNK_SIZE), b""):
|
|
131
|
+
file_checksum = zlib.crc32(chunk, file_checksum) & 0xFFFFFFFF
|
|
132
|
+
|
|
133
|
+
return file_checksum.to_bytes(4, "little", signed=False)
|
|
134
|
+
|
|
135
|
+
def __is_likely_text_file(self, location: Path) -> bool:
|
|
136
|
+
"""
|
|
137
|
+
Check if a file is likely to be text by sampling the beginning.
|
|
138
|
+
"""
|
|
112
139
|
# Known text extensions to consider for line ending normalization
|
|
113
140
|
text_extensions = {
|
|
114
141
|
".txt",
|
|
@@ -148,44 +175,17 @@ class Checksum:
|
|
|
148
175
|
".cmd",
|
|
149
176
|
".log",
|
|
150
177
|
}
|
|
151
|
-
|
|
152
178
|
extension = location.suffix.lower()
|
|
153
|
-
is_text_file = self.__is_likely_text_file(location)
|
|
154
|
-
|
|
155
|
-
if extension in text_extensions and is_text_file:
|
|
156
|
-
try:
|
|
157
|
-
with location.open("r", encoding="utf-8") as f:
|
|
158
|
-
content = f.read().replace("\r\n", "\n")
|
|
159
|
-
content_bytes = content.encode("utf-8")
|
|
160
|
-
file_checksum = zlib.crc32(content_bytes) & 0xFFFFFFFF
|
|
161
|
-
return file_checksum.to_bytes(4, "little", signed=False)
|
|
162
|
-
except UnicodeDecodeError:
|
|
163
|
-
description = (
|
|
164
|
-
f"Understood as text file: {location!s} "
|
|
165
|
-
"but encountered decoding error. Proceeding w/ binary"
|
|
166
|
-
)
|
|
167
|
-
CrcutilLogger.get_logger().debug(description)
|
|
168
|
-
|
|
169
|
-
with location.open("rb") as f:
|
|
170
|
-
for chunk in iter(lambda: f.read(CHUNK_SIZE), b""):
|
|
171
|
-
file_checksum = zlib.crc32(chunk, file_checksum) & 0xFFFFFFFF
|
|
172
|
-
|
|
173
|
-
return file_checksum.to_bytes(4, "little", signed=False)
|
|
174
|
-
|
|
175
|
-
def __is_likely_text_file(self, location: Path) -> bool:
|
|
176
|
-
"""
|
|
177
|
-
Check if a file is likely to be text by sampling the beginning.
|
|
178
|
-
"""
|
|
179
179
|
# Only read a sample
|
|
180
180
|
with location.open("rb") as f:
|
|
181
|
-
sample = f.read(
|
|
181
|
+
sample = f.read(8192)
|
|
182
182
|
|
|
183
183
|
# Empty file, treat as empty text
|
|
184
|
-
if not sample:
|
|
184
|
+
if not sample and extension in text_extensions:
|
|
185
185
|
return True
|
|
186
186
|
|
|
187
187
|
# Null byte presence, likely a binary file
|
|
188
|
-
if b"\0" in sample:
|
|
188
|
+
if b"\0" in sample and extension not in text_extensions:
|
|
189
189
|
return False
|
|
190
190
|
|
|
191
191
|
ascii_lower_range = 32
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|