From fe88380499e16b6412b08e96a426a8d3c4c52adb Mon Sep 17 00:00:00 2001 From: Dima Gerasimov Date: Tue, 16 May 2023 01:01:48 +0100 Subject: [PATCH] general: switch to using native 3.8 versions for cached_property/Literal/Protocol instead of compat --- my/coding/codeforces.py | 5 +-- my/coding/topcoder.py | 5 +-- my/config.py | 2 +- my/core/common.py | 10 ++--- my/core/compat.py | 68 ++++---------------------------- my/core/dataset.py | 3 +- my/core/error.py | 4 +- my/core/pandas.py | 4 +- my/core/sqlite.py | 6 +-- my/fbmessenger/common.py | 3 +- my/instagram/common.py | 3 +- my/location/common.py | 3 +- my/location/fallback/via_home.py | 2 +- my/reddit/common.py | 3 +- my/rtm.py | 4 +- my/twitter/archive.py | 2 +- 16 files changed, 29 insertions(+), 98 deletions(-) diff --git a/my/coding/codeforces.py b/my/coding/codeforces.py index a4c7de2..a8b0f65 100644 --- a/my/coding/codeforces.py +++ b/my/coding/codeforces.py @@ -3,13 +3,12 @@ from my.config import codeforces as config # type: ignore[attr-defined] from datetime import datetime, timezone -from typing import NamedTuple +from functools import cached_property import json -from typing import Dict, Iterator +from typing import NamedTuple, Dict, Iterator from ..core import get_files, Res, unwrap -from ..core.compat import cached_property from ..core.konsume import ignore, wrap diff --git a/my/coding/topcoder.py b/my/coding/topcoder.py index 32a9ff8..96bcdf7 100644 --- a/my/coding/topcoder.py +++ b/my/coding/topcoder.py @@ -3,13 +3,12 @@ from my.config import topcoder as config # type: ignore[attr-defined] from datetime import datetime -from typing import NamedTuple +from functools import cached_property import json -from typing import Dict, Iterator +from typing import NamedTuple, Dict, Iterator from ..core import get_files, Res, unwrap, Json -from ..core.compat import cached_property from ..core.error import Res, unwrap from ..core.konsume import zoom, wrap, ignore diff --git a/my/config.py b/my/config.py index 8d958f1..a59eadd 100644 --- a/my/config.py +++ b/my/config.py @@ -98,7 +98,7 @@ class location: accuracy: float = 100 -from my.core.compat import Literal +from typing import Literal class time: class tz: policy: Literal['keep', 'convert', 'throw'] diff --git a/my/core/common.py b/my/core/common.py index 0b3dc1e..359f451 100644 --- a/my/core/common.py +++ b/my/core/common.py @@ -366,10 +366,6 @@ def isoparse(s: str) -> tzdatetime: return datetime.fromisoformat(s) -# legacy import -- we should use compat directly instead -from .compat import Literal - - import re # https://stackoverflow.com/a/295466/706389 def get_valid_filename(s: str) -> str: @@ -664,5 +660,7 @@ def assert_never(value: NoReturn) -> NoReturn: assert False, f'Unhandled value: {value} ({type(value).__name__})' -# legacy deprecated import -from .compat import cached_property as cproperty +## legacy imports, keeping them here for backwards compatibility +from functools import cached_property as cproperty +from typing import Literal +## \ No newline at end of file diff --git a/my/core/compat.py b/my/core/compat.py index 0b47bdd..d7937f9 100644 --- a/my/core/compat.py +++ b/my/core/compat.py @@ -3,6 +3,7 @@ Some backwards compatibility stuff/deprecation helpers ''' import sys from types import ModuleType +from typing import TYPE_CHECKING from . import warnings from .common import LazyLogger @@ -53,20 +54,10 @@ import os windows = os.name == 'nt' +# keeping just for backwards compatibility, used to have compat implementation for 3.6 import sqlite3 def sqlite_backup(*, source: sqlite3.Connection, dest: sqlite3.Connection, **kwargs) -> None: - if sys.version_info[:2] >= (3, 7): - source.backup(dest, **kwargs) - else: - # https://stackoverflow.com/a/10856450/706389 - import io - tempfile = io.StringIO() - for line in source.iterdump(): - tempfile.write('%s\n' % line) - tempfile.seek(0) - - dest.cursor().executescript(tempfile.read()) - dest.commit() + source.backup(dest, **kwargs) # can remove after python3.9 @@ -76,55 +67,10 @@ def removeprefix(text: str, prefix: str) -> str: return text -# can remove after python3.8 -if sys.version_info[:2] >= (3, 8): - from functools import cached_property -else: - from typing import TypeVar, Callable - Cl = TypeVar('Cl') - R = TypeVar('R') - - def cached_property(f: Callable[[Cl], R]) -> R: - import functools - return property(functools.lru_cache(maxsize=1)(f)) - del Cl - del R - - -from typing import TYPE_CHECKING - - -if sys.version_info[:2] >= (3, 8): - from typing import Literal -else: - if TYPE_CHECKING: - from typing_extensions import Literal - else: - # erm.. I guess as long as it's not crashing, whatever... - class _Literal: - def __getitem__(self, args): - pass - Literal = _Literal() - - -if sys.version_info[:2] >= (3, 8): - from typing import Protocol -else: - if TYPE_CHECKING: - from typing_extensions import Protocol - else: - # todo could also use NamedTuple? - Protocol = object - - -if sys.version_info[:2] >= (3, 8): - from typing import TypedDict -else: - if TYPE_CHECKING: - from typing_extensions import TypedDict - else: - from typing import Dict - TypedDict = Dict +## used to have compat function before 3.8 for these +from functools import cached_property +from typing import Literal, Protocol, TypedDict +## if sys.version_info[:2] >= (3, 10): diff --git a/my/core/dataset.py b/my/core/dataset.py index 070b9b3..31de4f4 100644 --- a/my/core/dataset.py +++ b/my/core/dataset.py @@ -2,11 +2,10 @@ from __future__ import annotations from .common import assert_subpackage; assert_subpackage(__name__) from .common import PathIsh -from .compat import Protocol from .sqlite import sqlite_connect_immutable ## sadly dataset doesn't have any type definitions -from typing import Iterable, Iterator, Dict, Optional, Any +from typing import Iterable, Iterator, Dict, Optional, Any, Protocol from contextlib import AbstractContextManager diff --git a/my/core/error.py b/my/core/error.py index 236bd30..e1737c1 100644 --- a/my/core/error.py +++ b/my/core/error.py @@ -4,9 +4,7 @@ See https://beepb00p.xyz/mypy-error-handling.html#kiss for more detail """ from itertools import tee -from typing import Union, TypeVar, Iterable, List, Tuple, Type, Optional, Callable, Any, cast, Iterator - -from .compat import Literal +from typing import Union, TypeVar, Iterable, List, Tuple, Type, Optional, Callable, Any, cast, Iterator, Literal T = TypeVar('T') diff --git a/my/core/pandas.py b/my/core/pandas.py index ee4bcff..4ce62fe 100644 --- a/my/core/pandas.py +++ b/my/core/pandas.py @@ -5,7 +5,7 @@ Various pandas helpers and convenience functions # NOTE: this file is meant to be importable without Pandas installed from datetime import datetime from pprint import pformat -from typing import Optional, TYPE_CHECKING, Any, Iterable, Type, Dict +from typing import Optional, TYPE_CHECKING, Any, Iterable, Type, Dict, Literal from . import warnings, Res from .common import LazyLogger, Json, asdict @@ -45,8 +45,6 @@ def check_dateish(s) -> Iterable[str]: '''.strip() -from .compat import Literal - ErrorColPolicy = Literal[ 'add_if_missing', # add error column if it's missing 'warn' , # warn, but do not modify diff --git a/my/core/sqlite.py b/my/core/sqlite.py index e712a77..e04f6fc 100644 --- a/my/core/sqlite.py +++ b/my/core/sqlite.py @@ -6,11 +6,10 @@ from pathlib import Path import shutil import sqlite3 from tempfile import TemporaryDirectory -from typing import Tuple, Any, Iterator, Callable, Optional, Union +from typing import Tuple, Any, Iterator, Callable, Optional, Union, Literal from .common import PathIsh, assert_never -from .compat import Literal def sqlite_connect_immutable(db: PathIsh) -> sqlite3.Connection: @@ -86,8 +85,7 @@ def sqlite_copy_and_open(db: PathIsh) -> sqlite3.Connection: for p in tocopy: shutil.copy(p, tdir / p.name) with sqlite3.connect(str(tdir / dp.name)) as conn: - from .compat import sqlite_backup - sqlite_backup(source=conn, dest=dest) + conn.backup(target=dest) conn.close() return dest diff --git a/my/fbmessenger/common.py b/my/fbmessenger/common.py index a498952..33d1b20 100644 --- a/my/fbmessenger/common.py +++ b/my/fbmessenger/common.py @@ -1,8 +1,7 @@ from my.core import __NOT_HPI_MODULE__ -from typing import Iterator, Optional +from typing import Iterator, Optional, Protocol -from my.core.compat import Protocol from my.core import datetime_aware diff --git a/my/instagram/common.py b/my/instagram/common.py index a172ac8..4df07a1 100644 --- a/my/instagram/common.py +++ b/my/instagram/common.py @@ -1,10 +1,9 @@ from dataclasses import replace from datetime import datetime from itertools import chain -from typing import Iterator, Dict, Any +from typing import Iterator, Dict, Any, Protocol from my.core import warn_if_empty, Res -from my.core.compat import Protocol class User(Protocol): diff --git a/my/location/common.py b/my/location/common.py index 5c03d5e..7824bef 100644 --- a/my/location/common.py +++ b/my/location/common.py @@ -1,9 +1,8 @@ from datetime import date, datetime -from typing import Union, Tuple, Optional, Iterable, TextIO, Iterator +from typing import Union, Tuple, Optional, Iterable, TextIO, Iterator, Protocol from dataclasses import dataclass from my.core import __NOT_HPI_MODULE__ -from my.core.compat import Protocol DateIsh = Union[datetime, date, str] diff --git a/my/location/fallback/via_home.py b/my/location/fallback/via_home.py index 240da84..590c028 100644 --- a/my/location/fallback/via_home.py +++ b/my/location/fallback/via_home.py @@ -73,7 +73,7 @@ def get_location(dt: datetime) -> LatLon: return loc[0].lat, loc[0].lon -# TODO: in python3.9, use functools.cached_property instead? +# TODO: in python3.8, use functools.cached_property instead? @lru_cache(maxsize=None) def homes_cached() -> List[Tuple[datetime, LatLon]]: return list(config._history) diff --git a/my/reddit/common.py b/my/reddit/common.py index d33e02b..c01258b 100644 --- a/my/reddit/common.py +++ b/my/reddit/common.py @@ -4,10 +4,9 @@ type of shared models have a standardized interface """ from my.core import __NOT_HPI_MODULE__ -from typing import Set, Iterator +from typing import Set, Iterator, Protocol from itertools import chain -from my.core.compat import Protocol from my.core import datetime_aware, Json diff --git a/my/rtm.py b/my/rtm.py index b4fc7a9..8d41e7a 100644 --- a/my/rtm.py +++ b/my/rtm.py @@ -6,12 +6,12 @@ REQUIRES = [ 'icalendar', ] +from datetime import datetime +from functools import cached_property import re from typing import Dict, List, Iterator -from datetime import datetime from .core.common import LazyLogger, get_files, group_by_key, make_dict -from .core.compat import cached_property from my.config import rtm as config diff --git a/my/twitter/archive.py b/my/twitter/archive.py index 3f56fa0..d9ba562 100644 --- a/my/twitter/archive.py +++ b/my/twitter/archive.py @@ -22,9 +22,9 @@ except ImportError as ie: from dataclasses import dataclass +from functools import cached_property import html from ..core.common import Paths, datetime_aware -from ..core.compat import cached_property from ..core.error import Res from ..core.kompress import ZipPath