diff --git a/nxdrive/client/local/base.py b/nxdrive/client/local/base.py index 77e01bb1a3..3040cfb95e 100644 --- a/nxdrive/client/local/base.py +++ b/nxdrive/client/local/base.py @@ -3,10 +3,11 @@ import errno import os import shutil +import sqlite3 import unicodedata import uuid from contextlib import suppress -from datetime import datetime +from datetime import datetime, timezone, UTC from logging import getLogger from pathlib import Path from tempfile import mkdtemp @@ -263,12 +264,18 @@ def get_info(self, ref: Path, /, *, check: bool = True) -> FileInfo: stat_info = os_path.stat() size = 0 if folderish else stat_info.st_size try: - mtime = datetime.utcfromtimestamp(stat_info.st_mtime) + def adapt_datetime_iso(val): + return val.isoformat() + + mtime = sqlite3.register_adapter(stat_info.st_mtime, adapt_datetime_iso) except (ValueError, OverflowError, OSError) as e: log.warning( f"{e} file path: {os_path}. st_mtime value: {stat_info.st_mtime}" ) - mtime = datetime.utcfromtimestamp(0) + def adapt_datetime_iso(val): + return val.isoformat() + + mtime = sqlite3.register_adapter(0, adapt_datetime_iso) # TODO Do we need to load it every time ? remote_ref = self.get_remote_id(ref) diff --git a/nxdrive/dao/base.py b/nxdrive/dao/base.py index 24bce57600..da8a24c181 100644 --- a/nxdrive/dao/base.py +++ b/nxdrive/dao/base.py @@ -1,6 +1,8 @@ """ Query formatting in this file is based on http://www.sqlstyle.guide/ """ +import datetime +import sqlite3 import sys from contextlib import suppress from logging import getLogger @@ -20,12 +22,20 @@ class AutoRetryCursor(Cursor): + def adapt_datetime_iso(self, val): + return datetime.datetime.fromtimestamp(str(val), datetime.UTC) def execute(self, sql: str, parameters: Iterable[Any] = ()) -> Cursor: count = 1 while True: count += 1 try: - return super().execute(sql, parameters) + if not parameters: + return super().execute(sql, parameters) + new_param = tuple( + adapt_datetime_iso(param) if isinstance(param, datetime.datetime) else param + for param in parameters + ) + return super().execute(sql, new_param) except OperationalError as exc: log.info( f"Retry locked database #{count}, {sql=}, {parameters=}", diff --git a/tests/conftest.py b/tests/conftest.py index c08b9b0496..8a2de4fb85 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -95,10 +95,6 @@ def no_warnings(recwarn): continue elif "Cryptography will be significantly faster" in message: continue - elif "The default datetime adapter is deprecated as of Python 3.12" in message: - continue - elif "datetime.datetime" in message: - continue warn = f"{warning.filename}:{warning.lineno} {message}" print(warn, file=sys.stderr) diff --git a/tests/unit/test_utils.py b/tests/unit/test_utils.py index 5c0d96cc95..2fcf84222d 100644 --- a/tests/unit/test_utils.py +++ b/tests/unit/test_utils.py @@ -3,7 +3,7 @@ from collections import namedtuple from datetime import datetime from math import pow -from pathlib import Path, _posix_flavour, _windows_flavour +from pathlib import Path #, _posix_flavour, _windows_flavour from time import sleep from unittest.mock import patch @@ -75,16 +75,18 @@ Stat = namedtuple("Stat", "st_size") +""" class MockedPath(Path): - """Simple way to test Path methods. + ""Simple way to test Path methods. Using mock did not make it. - """ + "" _flavour = _windows_flavour if WINDOWS else _posix_flavour def resolve(self, *_, **__): - """Raise a PermissionError.""" + ""Raise a PermissionError."" raise PermissionError("Boom!") +""" @pytest.mark.parametrize(