Skip to content

Commit

Permalink
Merge pull request #56 from cfv-project/ci-py3.12-py3.12
Browse files Browse the repository at this point in the history
Add support for Python 3.12/3.13
  • Loading branch information
lxp authored May 20, 2024
2 parents c968dfe + cdb009a commit 7d77a76
Show file tree
Hide file tree
Showing 10 changed files with 82 additions and 64 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci-python3-dependencies.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
const latestPythonMinorVersion = pythonVersions[0].split('.').slice(0, 2).join('.')
// Check if new Python minor version exists
if (latestPythonMinorVersion === '3.12') {
if (latestPythonMinorVersion === '3.13') {
return
}
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/ci-python3-freebsd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,13 @@ jobs:
pip list
# Check syntax by compiling code
python -m compileall -f .
python -W error -bb -m compileall -f .
# Run unit tests
su runner -c 'python -bb test/test.py --unit --exit-early'
su runner -c 'python -W error -bb test/test.py --unit --exit-early'
# Run integration tests (internal)
su runner -c 'ulimit -n; ulimit -n 4096; python -bb test/test.py -i --exit-early'
su runner -c 'ulimit -n; ulimit -n 4096; python -W error -bb test/test.py -i --exit-early'
# Run integration tests (external process)
su runner -c 'ulimit -n; ulimit -n 4096; test/test.py -e --exit-early'
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/ci-python3.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
strategy:
matrix:
os: [ ubuntu-24.04, ubuntu-22.04, ubuntu-20.04 ]
python-version: [ '3.6', '3.7', '3.8', '3.9', '3.10', '3.11' ]
python-version: [ '3.6', '3.7', '3.8', '3.9', '3.10', '3.11', '3.12', '3.13' ]
# Exclude unsupported OS/Python version combinations
exclude:
- os: ubuntu-22.04
Expand Down Expand Up @@ -58,16 +58,16 @@ jobs:
pip list
- name: Check syntax by compiling code
run: python -m compileall -f .
run: python -W error -bb -m compileall -f .

- name: Run unit tests
run: python -bb test/test.py --unit --exit-early
run: python -W error -bb test/test.py --unit --exit-early

- name: Run integration tests (internal)
run: |
ulimit -n
ulimit -n 4096
python -bb test/test.py -i --exit-early
python -W error -bb test/test.py -i --exit-early
- name: Run integration tests (external process)
run: |
Expand Down
3 changes: 3 additions & 0 deletions Changelog
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
* WARNING: This is a development snapshot, not a stable release.
* Drop support for Python 3.5.
* Python 3.6 is now the minimum supported version.
* Add support for Python 3.12 (Thanks to Louis Sautier).
* Add support for Python 3.13.
* Correctly close files in various situations.

2022-10-30 - v3.0.0:
* Tested platforms: Linux and FreeBSD. If there is interest in supporting more platforms (e.g. OSX and Windows), please get in contact with the project.
Expand Down
36 changes: 21 additions & 15 deletions lib/cfv/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
__version__ = '3.0.1.dev0'
__homepage__ = 'https://github.com/cfv-project/cfv'

import contextlib
import copy
import errno
import getopt
Expand Down Expand Up @@ -466,8 +467,6 @@ def test_chksumfile(self, file, filename):
cache.set_verified(filename)
try:
cf_stats = stats.make_sub_stats()
if not file:
file = fileutil.open_read(filename, config)
self.do_test_chksumfile(file)
cf_stats.sub_stats_end(stats)
view.ev_test_cf_done(filename, cf_stats)
Expand Down Expand Up @@ -1532,8 +1531,8 @@ def getimagedimensions(filename):
return '0', '0'
try:
from PIL import Image
im1 = Image.open(filename)
return list(map(str, im1.size))
with Image.open(filename) as im1:
return list(map(str, im1.size))
except (ImportError, IOError):
return '0', '0'

Expand Down Expand Up @@ -1694,26 +1693,33 @@ def visit_dir(name, st=None, noisy=1):


def test(filename, typename, restrict_typename='auto'):
if typename != 'auto':
cf = cftypes.get_handler(typename)()
cf.test_chksumfile(None, filename)
return
class UnexpectedHandlerException(Exception):
pass

try:
file = fileutil.open_read(filename, config)
def get_cf_handler(file, typename, restrict_typename):
if typename != 'auto':
return cftypes.get_handler(typename)()
cftype = cftypes.auto_chksumfile_match(file)
if restrict_typename != 'auto' and cftypes.get_handler(restrict_typename) != cftype:
return
raise UnexpectedHandlerException()
if cftype:
cf = cftype()
return cftype()

try:
with contextlib.closing(fileutil.open_read(filename, config)) as file:
cf = get_cf_handler(file, typename, restrict_typename)
if not cf:
view.ev_test_cf_unrecognized(filename, file._decode_errs)
stats.cferror += 1
return

cf.test_chksumfile(file, filename)
return
except UnexpectedHandlerException:
return
except EnvironmentError as a:
stats.cferror += 1
view.ev_cf_enverror(filename, a)
return -1
view.ev_test_cf_unrecognized(filename, file._decode_errs)
stats.cferror += 1


def make(cftype, ifilename, testfiles):
Expand Down
4 changes: 4 additions & 0 deletions lib/cfv/fileutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ def _done_peeking(self, raw):
self.readline = self._readline
self.read = fileobj.read
self.seek = fileobj.seek
self.close = fileobj.close

def seek(self, *args):
self._done_peeking(raw=1)
Expand All @@ -117,6 +118,9 @@ def read(self, *args):
self._done_peeking(raw=1)
return self.read(*args)

def close(self):
self.fileobj.close()


def PeekFileNonseekable(fileobj, filename, encoding):
return PeekFile(BytesIO(fileobj.read()), filename, encoding)
Expand Down
46 changes: 25 additions & 21 deletions lib/cfv/hash.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,27 +45,31 @@ def finish(m, s):
if callback:
callback(s)

if f == sys.stdin.buffer or _nommap or callback:
return finish(hasher(), 0)
else:
s = os.path.getsize(filename)
try:
if s > _MAX_MMAP:
# Work around python 2.[56] problem with md5 of large mmap objects
raise OverflowError
m = hasher(dommap(f.fileno(), s))
except OverflowError:
# mmap size is limited by C's int type, which even on 64 bit
# arches is often 32 bits, so we can't use sys.maxint
# either. If we get the error, just assume 32 bits.
mmapsize = min(s, _FALLBACK_MMAP)
m = hasher(dommap(f.fileno(), mmapsize))
f.seek(mmapsize)
# unfortunatly, python's mmap module doesn't support the
# offset parameter, so we just have to do the rest of the
# file the old fashioned way.
return finish(m, mmapsize)
return m.digest(), s
try:
if f == sys.stdin.buffer or _nommap or callback:
return finish(hasher(), 0)
else:
s = os.path.getsize(filename)
try:
if s > _MAX_MMAP:
# Work around python 2.[56] problem with md5 of large mmap objects
raise OverflowError
m = hasher(dommap(f.fileno(), s))
except OverflowError:
# mmap size is limited by C's int type, which even on 64 bit
# arches is often 32 bits, so we can't use sys.maxint
# either. If we get the error, just assume 32 bits.
mmapsize = min(s, _FALLBACK_MMAP)
m = hasher(dommap(f.fileno(), mmapsize))
f.seek(mmapsize)
# unfortunatly, python's mmap module doesn't support the
# offset parameter, so we just have to do the rest of the
# file the old fashioned way.
return finish(m, mmapsize)
return m.digest(), s
finally:
if filename != '':
f.close()


def getfilechecksumgeneric(algo):
Expand Down
2 changes: 2 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ def _get_version(path):
'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',
],
keywords='cfv checksum verify sfv csv crc bsdmd5 md5sum sha1sum sha224sum sha256sum sha384sum sha512sum torrent par par2',
project_urls={
Expand Down
2 changes: 1 addition & 1 deletion test/cfvtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ def all_unittests_suite():
assert modules_to_test
alltests = unittest.TestSuite()
for module in map(my_import, modules_to_test):
alltests.addTest(unittest.findTestCases(module))
alltests.addTest(unittest.defaultTestLoader.loadTestsFromModule(module))

import cfv.common
libdir = os.path.split(cfv.common.__file__)[0]
Expand Down
37 changes: 18 additions & 19 deletions test/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1354,7 +1354,7 @@ def test_encoding2():
raw_fnok += 1
flag_ok_raw = True
try:
open(os.path.join(d, fn), 'rb')
open(os.path.join(d, fn), 'rb').close()
except (EnvironmentError, UnicodeError):
files_fnerrs += 1
else:
Expand Down Expand Up @@ -1394,14 +1394,13 @@ def test_encoding2():
def largefile2GB_test():
# hope you have sparse file support ;)
fn = os.path.join('bigfile2', 'bigfile')
f = open(fn, 'wb')
try:
f.write(b'hi')
f.seek(2 ** 30)
f.write(b'foo')
f.seek(2 ** 31)
f.write(b'bar')
f.close()
with open(fn, 'wb') as f:
f.write(b'hi')
f.seek(2 ** 30)
f.write(b'foo')
f.seek(2 ** 31)
f.write(b'bar')
test_generic(cfvcmd + ' -v -T -p %s' % 'bigfile2', rcurry(cfv_all_test, ok=6))
finally:
os.unlink(fn)
Expand All @@ -1410,16 +1409,15 @@ def largefile2GB_test():
def largefile4GB_test():
# hope you have sparse file support ;)
fn = os.path.join('bigfile', 'bigfile')
f = open(fn, 'wb')
try:
f.write(b'hi')
f.seek(2 ** 30)
f.write(b'foo')
f.seek(2 ** 31)
f.write(b'bar')
f.seek(2 ** 32)
f.write(b'baz')
f.close()
with open(fn, 'wb') as f:
f.write(b'hi')
f.seek(2 ** 30)
f.write(b'foo')
f.seek(2 ** 31)
f.write(b'bar')
f.seek(2 ** 32)
f.write(b'baz')
test_generic(cfvcmd + ' -v -T -p %s' % 'bigfile', rcurry(cfv_all_test, ok=10))
finally:
os.unlink(fn)
Expand Down Expand Up @@ -1766,7 +1764,7 @@ def sfvverify(f):
else:
if t == 'par':
try:
open('data1'.encode('utf-16le').decode('utf-16be'), 'rb')
open('data1'.encode('utf-16le').decode('utf-16be'), 'rb').close()
except UnicodeError:
nf = 0
err = 4
Expand All @@ -1778,7 +1776,7 @@ def sfvverify(f):
test_generic(cfvcmd + ' --encoding=cp500 -i -T -f test.' + t, rcurry(cfv_all_test, cferror=4))
else:
try:
open(b'data1'.decode('cp500'), 'rb')
open(b'data1'.decode('cp500'), 'rb').close()
except UnicodeError:
nf = 0
err = 4
Expand Down Expand Up @@ -1890,3 +1888,4 @@ def copytree(src, dst, ignore=None):
sys.exit(failed)
finally:
shutil.rmtree(tmpdatapath)
logfile.close()

0 comments on commit 7d77a76

Please sign in to comment.