general: update mypy config, seems that logs of type: ignore aren't necessary anymore
This commit is contained in:
parent
a445d2cbfe
commit
c34656e8fb
52 changed files with 142 additions and 105 deletions
|
@ -40,7 +40,7 @@ class Measurement:
|
||||||
|
|
||||||
# fixme: later, rely on the timezone provider
|
# fixme: later, rely on the timezone provider
|
||||||
# NOTE: the timezone should be set with respect to the export date!!!
|
# NOTE: the timezone should be set with respect to the export date!!!
|
||||||
import pytz # type: ignore
|
import pytz
|
||||||
tz = pytz.timezone('Europe/London')
|
tz = pytz.timezone('Europe/London')
|
||||||
# TODO when I change tz, check the diff
|
# TODO when I change tz, check the diff
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ from ..core.error import Res
|
||||||
from ..core.orgmode import parse_org_datetime, one_table
|
from ..core.orgmode import parse_org_datetime, one_table
|
||||||
|
|
||||||
|
|
||||||
import pandas as pd # type: ignore
|
import pandas as pd
|
||||||
import orgparse
|
import orgparse
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ def dataframe() -> DataFrameT:
|
||||||
from ...endomondo import dataframe as EDF
|
from ...endomondo import dataframe as EDF
|
||||||
from ...runnerup import dataframe as RDF
|
from ...runnerup import dataframe as RDF
|
||||||
|
|
||||||
import pandas as pd # type: ignore
|
import pandas as pd
|
||||||
return pd.concat([
|
return pd.concat([
|
||||||
EDF(),
|
EDF(),
|
||||||
RDF(),
|
RDF(),
|
||||||
|
|
|
@ -78,7 +78,7 @@ def cross_trainer_manual_dataframe() -> DataFrameT:
|
||||||
'''
|
'''
|
||||||
Only manual org-mode entries
|
Only manual org-mode entries
|
||||||
'''
|
'''
|
||||||
import pandas as pd # type: ignore[import]
|
import pandas as pd
|
||||||
df = pd.DataFrame(cross_trainer_data())
|
df = pd.DataFrame(cross_trainer_data())
|
||||||
return df
|
return df
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ def dataframe() -> DataFrameT:
|
||||||
'''
|
'''
|
||||||
Attaches manually logged data (which Endomondo can't capture) and attaches it to Endomondo
|
Attaches manually logged data (which Endomondo can't capture) and attaches it to Endomondo
|
||||||
'''
|
'''
|
||||||
import pandas as pd # type: ignore[import]
|
import pandas as pd
|
||||||
|
|
||||||
from ...endomondo import dataframe as EDF
|
from ...endomondo import dataframe as EDF
|
||||||
edf = EDF()
|
edf = EDF()
|
||||||
|
|
|
@ -8,7 +8,7 @@ class Combine:
|
||||||
|
|
||||||
@cdf
|
@cdf
|
||||||
def dataframe(self, with_temperature: bool=True) -> DataFrameT:
|
def dataframe(self, with_temperature: bool=True) -> DataFrameT:
|
||||||
import pandas as pd # type: ignore
|
import pandas as pd
|
||||||
# todo include 'source'?
|
# todo include 'source'?
|
||||||
df = pd.concat([m.dataframe() for m in self.modules])
|
df = pd.concat([m.dataframe() for m in self.modules])
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ def from_orgmode() -> Iterator[Result]:
|
||||||
|
|
||||||
|
|
||||||
def make_dataframe(data: Iterator[Result]):
|
def make_dataframe(data: Iterator[Result]):
|
||||||
import pandas as pd # type: ignore
|
import pandas as pd
|
||||||
def it():
|
def it():
|
||||||
for e in data:
|
for e in data:
|
||||||
if isinstance(e, Exception):
|
if isinstance(e, Exception):
|
||||||
|
|
|
@ -38,8 +38,8 @@ def config() -> commits_cfg:
|
||||||
|
|
||||||
##########################
|
##########################
|
||||||
|
|
||||||
import git # type: ignore
|
import git
|
||||||
from git.repo.fun import is_git_dir # type: ignore
|
from git.repo.fun import is_git_dir
|
||||||
|
|
||||||
|
|
||||||
log = LazyLogger(__name__, level='info')
|
log = LazyLogger(__name__, level='info')
|
||||||
|
|
|
@ -135,7 +135,7 @@ def config_ok() -> bool:
|
||||||
# at this point 'my' should already be imported, so doesn't hurt to extract paths from it
|
# at this point 'my' should already be imported, so doesn't hurt to extract paths from it
|
||||||
import my
|
import my
|
||||||
try:
|
try:
|
||||||
paths: List[str] = list(my.__path__) # type: ignore[attr-defined]
|
paths: List[str] = list(my.__path__)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
errors.append(e)
|
errors.append(e)
|
||||||
error('failed to determine module import path')
|
error('failed to determine module import path')
|
||||||
|
@ -152,7 +152,7 @@ def config_ok() -> bool:
|
||||||
## check we're not using stub config
|
## check we're not using stub config
|
||||||
import my.core
|
import my.core
|
||||||
try:
|
try:
|
||||||
core_pkg_path = str(Path(my.core.__path__[0]).parent) # type: ignore[attr-defined]
|
core_pkg_path = str(Path(my.core.__path__[0]).parent)
|
||||||
if str(cfg_path).startswith(core_pkg_path):
|
if str(cfg_path).startswith(core_pkg_path):
|
||||||
error(f'''
|
error(f'''
|
||||||
Seems that the stub config is used ({cfg_path}). This is likely not going to work.
|
Seems that the stub config is used ({cfg_path}). This is likely not going to work.
|
||||||
|
|
|
@ -30,7 +30,7 @@ def disabled_cachew() -> Iterator[None]:
|
||||||
|
|
||||||
|
|
||||||
def _appdirs_cache_dir() -> Path:
|
def _appdirs_cache_dir() -> Path:
|
||||||
import appdirs # type: ignore
|
import appdirs
|
||||||
cd = Path(appdirs.user_cache_dir('my'))
|
cd = Path(appdirs.user_cache_dir('my'))
|
||||||
cd.mkdir(exist_ok=True, parents=True)
|
cd.mkdir(exist_ok=True, parents=True)
|
||||||
return cd
|
return cd
|
||||||
|
|
|
@ -21,7 +21,7 @@ def make_config(cls: Type[C], migration: Callable[[Attrs], Attrs]=lambda x: x) -
|
||||||
if k in {f.name for f in fields(cls)} # type: ignore[arg-type] # see https://github.com/python/typing_extensions/issues/115
|
if k in {f.name for f in fields(cls)} # type: ignore[arg-type] # see https://github.com/python/typing_extensions/issues/115
|
||||||
}
|
}
|
||||||
# todo maybe return type here?
|
# todo maybe return type here?
|
||||||
return cls(**params) # type: ignore[call-arg]
|
return cls(**params)
|
||||||
|
|
||||||
|
|
||||||
F = TypeVar('F')
|
F = TypeVar('F')
|
||||||
|
|
|
@ -3,6 +3,7 @@ from pathlib import Path
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import functools
|
import functools
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
import sys
|
||||||
import types
|
import types
|
||||||
from typing import Union, Callable, Dict, Iterable, TypeVar, Sequence, List, Optional, Any, cast, Tuple, TYPE_CHECKING, NoReturn
|
from typing import Union, Callable, Dict, Iterable, TypeVar, Sequence, List, Optional, Any, cast, Tuple, TYPE_CHECKING, NoReturn
|
||||||
import warnings
|
import warnings
|
||||||
|
@ -21,13 +22,12 @@ def import_file(p: PathIsh, name: Optional[str] = None) -> types.ModuleType:
|
||||||
assert spec is not None, f"Fatal error; Could not create module spec from {name} {p}"
|
assert spec is not None, f"Fatal error; Could not create module spec from {name} {p}"
|
||||||
foo = importlib.util.module_from_spec(spec)
|
foo = importlib.util.module_from_spec(spec)
|
||||||
loader = spec.loader; assert loader is not None
|
loader = spec.loader; assert loader is not None
|
||||||
loader.exec_module(foo) # type: ignore[attr-defined]
|
loader.exec_module(foo)
|
||||||
return foo
|
return foo
|
||||||
|
|
||||||
|
|
||||||
def import_from(path: PathIsh, name: str) -> types.ModuleType:
|
def import_from(path: PathIsh, name: str) -> types.ModuleType:
|
||||||
path = str(path)
|
path = str(path)
|
||||||
import sys
|
|
||||||
try:
|
try:
|
||||||
sys.path.append(path)
|
sys.path.append(path)
|
||||||
import importlib
|
import importlib
|
||||||
|
@ -94,7 +94,7 @@ def ensure_unique(
|
||||||
|
|
||||||
|
|
||||||
def test_ensure_unique() -> None:
|
def test_ensure_unique() -> None:
|
||||||
import pytest # type: ignore
|
import pytest
|
||||||
assert list(ensure_unique([1, 2, 3], key=lambda i: i)) == [1, 2, 3]
|
assert list(ensure_unique([1, 2, 3], key=lambda i: i)) == [1, 2, 3]
|
||||||
|
|
||||||
dups = [1, 2, 1, 4]
|
dups = [1, 2, 1, 4]
|
||||||
|
@ -432,7 +432,7 @@ def warn_if_empty(f):
|
||||||
def wrapped(*args, **kwargs):
|
def wrapped(*args, **kwargs):
|
||||||
res = f(*args, **kwargs)
|
res = f(*args, **kwargs)
|
||||||
return _warn_iterable(res, f=f)
|
return _warn_iterable(res, f=f)
|
||||||
return wrapped # type: ignore
|
return wrapped
|
||||||
|
|
||||||
|
|
||||||
# global state that turns on/off quick stats
|
# global state that turns on/off quick stats
|
||||||
|
@ -620,6 +620,10 @@ def assert_subpackage(name: str) -> None:
|
||||||
assert name == '__main__' or 'my.core' in name, f'Expected module __name__ ({name}) to be __main__ or start with my.core'
|
assert name == '__main__' or 'my.core' in name, f'Expected module __name__ ({name}) to be __main__ or start with my.core'
|
||||||
|
|
||||||
|
|
||||||
|
from .compat import ParamSpec
|
||||||
|
_P = ParamSpec('_P')
|
||||||
|
_T = TypeVar('_T')
|
||||||
|
|
||||||
# https://stackoverflow.com/a/10436851/706389
|
# https://stackoverflow.com/a/10436851/706389
|
||||||
from concurrent.futures import Future, Executor
|
from concurrent.futures import Future, Executor
|
||||||
class DummyExecutor(Executor):
|
class DummyExecutor(Executor):
|
||||||
|
@ -627,26 +631,31 @@ class DummyExecutor(Executor):
|
||||||
self._shutdown = False
|
self._shutdown = False
|
||||||
self._max_workers = max_workers
|
self._max_workers = max_workers
|
||||||
|
|
||||||
# TODO: once support for 3.7 is dropped,
|
if TYPE_CHECKING:
|
||||||
# can make 'fn' a positional only parameter,
|
if sys.version_info[:2] <= (3, 8):
|
||||||
# which fixes the mypy error this throws without the type: ignore
|
# 3.8 doesn't support ParamSpec as Callable arg :(
|
||||||
def submit(self, fn, *args, **kwargs) -> Future: # type: ignore[override]
|
# and any attempt to type results in incompatible supertype.. so whatever
|
||||||
if self._shutdown:
|
def submit(self, fn, *args, **kwargs): ...
|
||||||
raise RuntimeError('cannot schedule new futures after shutdown')
|
|
||||||
|
|
||||||
f: Future[Any] = Future()
|
|
||||||
try:
|
|
||||||
result = fn(*args, **kwargs)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
raise
|
|
||||||
except BaseException as e:
|
|
||||||
f.set_exception(e)
|
|
||||||
else:
|
else:
|
||||||
f.set_result(result)
|
def submit(self, fn: Callable[_P, _T], /, *args: _P.args, **kwargs: _P.kwargs) -> Future[_T]: ...
|
||||||
|
else:
|
||||||
|
def submit(self, fn, *args, **kwargs):
|
||||||
|
if self._shutdown:
|
||||||
|
raise RuntimeError('cannot schedule new futures after shutdown')
|
||||||
|
|
||||||
return f
|
f: Future[Any] = Future()
|
||||||
|
try:
|
||||||
|
result = fn(*args, **kwargs)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
raise
|
||||||
|
except BaseException as e:
|
||||||
|
f.set_exception(e)
|
||||||
|
else:
|
||||||
|
f.set_result(result)
|
||||||
|
|
||||||
def shutdown(self, wait: bool=True) -> None: # type: ignore[override]
|
return f
|
||||||
|
|
||||||
|
def shutdown(self, wait: bool=True, **kwargs) -> None:
|
||||||
self._shutdown = True
|
self._shutdown = True
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@ else:
|
||||||
|
|
||||||
def cached_property(f: Callable[[Cl], R]) -> R:
|
def cached_property(f: Callable[[Cl], R]) -> R:
|
||||||
import functools
|
import functools
|
||||||
return property(functools.lru_cache(maxsize=1)(f)) # type: ignore
|
return property(functools.lru_cache(maxsize=1)(f))
|
||||||
del Cl
|
del Cl
|
||||||
del R
|
del R
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ if sys.version_info[:2] >= (3, 8):
|
||||||
from typing import Protocol
|
from typing import Protocol
|
||||||
else:
|
else:
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing_extensions import Protocol # type: ignore[misc]
|
from typing_extensions import Protocol
|
||||||
else:
|
else:
|
||||||
# todo could also use NamedTuple?
|
# todo could also use NamedTuple?
|
||||||
Protocol = object
|
Protocol = object
|
||||||
|
@ -121,12 +121,29 @@ if sys.version_info[:2] >= (3, 8):
|
||||||
from typing import TypedDict
|
from typing import TypedDict
|
||||||
else:
|
else:
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing_extensions import TypedDict # type: ignore[misc]
|
from typing_extensions import TypedDict
|
||||||
else:
|
else:
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
TypedDict = Dict
|
TypedDict = Dict
|
||||||
|
|
||||||
|
|
||||||
|
if sys.version_info[:2] >= (3, 10):
|
||||||
|
from typing import ParamSpec
|
||||||
|
else:
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from typing_extensions import ParamSpec
|
||||||
|
else:
|
||||||
|
from typing import NamedTuple, Any
|
||||||
|
# erm.. I guess as long as it's not crashing, whatever...
|
||||||
|
class _ParamSpec:
|
||||||
|
def __call__(self, args):
|
||||||
|
class _res:
|
||||||
|
args = None
|
||||||
|
kwargs = None
|
||||||
|
return _res
|
||||||
|
ParamSpec = _ParamSpec()
|
||||||
|
|
||||||
|
|
||||||
# bisect_left doesn't have a 'key' parameter (which we use)
|
# bisect_left doesn't have a 'key' parameter (which we use)
|
||||||
# till python3.10
|
# till python3.10
|
||||||
if sys.version_info[:2] <= (3, 9):
|
if sys.version_info[:2] <= (3, 9):
|
||||||
|
@ -156,4 +173,4 @@ if sys.version_info[:2] <= (3, 9):
|
||||||
hi = mid
|
hi = mid
|
||||||
return lo
|
return lo
|
||||||
else:
|
else:
|
||||||
from bisect import bisect_left # type: ignore[misc]
|
from bisect import bisect_left
|
||||||
|
|
|
@ -7,16 +7,16 @@ from typing import Sequence, Optional
|
||||||
from . import warnings, PathIsh, Path
|
from . import warnings, PathIsh, Path
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from my.config import core as user_config # type: ignore[attr-defined]
|
from my.config import core as user_config # type: ignore[attr-defined]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
try:
|
try:
|
||||||
from my.config import common as user_config # type: ignore[attr-defined, assignment, misc]
|
from my.config import common as user_config # type: ignore[attr-defined]
|
||||||
warnings.high("'common' config section is deprecated. Please rename it to 'core'.")
|
warnings.high("'common' config section is deprecated. Please rename it to 'core'.")
|
||||||
except Exception as e2:
|
except Exception as e2:
|
||||||
# make it defensive, because it's pretty commonly used and would be annoying if it breaks hpi doctor etc.
|
# make it defensive, because it's pretty commonly used and would be annoying if it breaks hpi doctor etc.
|
||||||
# this way it'll at least use the defaults
|
# this way it'll at least use the defaults
|
||||||
# todo actually not sure if needs a warning? Perhaps it's okay without it, because the defaults are reasonable enough
|
# todo actually not sure if needs a warning? Perhaps it's okay without it, because the defaults are reasonable enough
|
||||||
user_config = object # type: ignore[assignment, misc]
|
user_config = object
|
||||||
|
|
||||||
|
|
||||||
_HPI_CACHE_DIR_DEFAULT = ''
|
_HPI_CACHE_DIR_DEFAULT = ''
|
||||||
|
|
|
@ -144,7 +144,7 @@ def all_modules() -> Iterable[HPIModule]:
|
||||||
def _iter_my_roots() -> Iterable[Path]:
|
def _iter_my_roots() -> Iterable[Path]:
|
||||||
import my # doesn't import any code, because of namespace package
|
import my # doesn't import any code, because of namespace package
|
||||||
|
|
||||||
paths: List[str] = list(my.__path__) # type: ignore[attr-defined]
|
paths: List[str] = list(my.__path__)
|
||||||
if len(paths) == 0:
|
if len(paths) == 0:
|
||||||
# should probably never happen?, if this code is running, it was imported
|
# should probably never happen?, if this code is running, it was imported
|
||||||
# because something was added to __path__ to match this name
|
# because something was added to __path__ to match this name
|
||||||
|
|
|
@ -125,7 +125,7 @@ def test_sort_res_by() -> None:
|
||||||
1,
|
1,
|
||||||
Exc('last'),
|
Exc('last'),
|
||||||
]
|
]
|
||||||
results = sort_res_by(ress, lambda x: int(x)) # type: ignore
|
results = sort_res_by(ress, lambda x: int(x))
|
||||||
assert results == [
|
assert results == [
|
||||||
1,
|
1,
|
||||||
'bad',
|
'bad',
|
||||||
|
@ -137,11 +137,11 @@ def test_sort_res_by() -> None:
|
||||||
Exc('last'),
|
Exc('last'),
|
||||||
]
|
]
|
||||||
|
|
||||||
results2 = sort_res_by(ress + [0], lambda x: int(x)) # type: ignore
|
results2 = sort_res_by(ress + [0], lambda x: int(x))
|
||||||
assert results2 == [Exc('last'), 0] + results[:-1]
|
assert results2 == [Exc('last'), 0] + results[:-1]
|
||||||
|
|
||||||
assert sort_res_by(['caba', 'a', 'aba', 'daba'], key=lambda x: len(x)) == ['a', 'aba', 'caba', 'daba']
|
assert sort_res_by(['caba', 'a', 'aba', 'daba'], key=lambda x: len(x)) == ['a', 'aba', 'caba', 'daba']
|
||||||
assert sort_res_by([], key=lambda x: x) == [] # type: ignore
|
assert sort_res_by([], key=lambda x: x) == []
|
||||||
|
|
||||||
|
|
||||||
# helpers to associate timestamps with the errors (so something meaningful could be displayed on the plots, for example)
|
# helpers to associate timestamps with the errors (so something meaningful could be displayed on the plots, for example)
|
||||||
|
@ -215,7 +215,7 @@ See {help_url}\
|
||||||
if hasattr(err, 'obj') and hasattr(err, "name"):
|
if hasattr(err, 'obj') and hasattr(err, "name"):
|
||||||
config_obj = cast(object, getattr(err, 'obj')) # the object that caused the attribute error
|
config_obj = cast(object, getattr(err, 'obj')) # the object that caused the attribute error
|
||||||
# e.g. active_browser for my.browser
|
# e.g. active_browser for my.browser
|
||||||
nested_block_name = err.name # type: ignore[attr-defined]
|
nested_block_name = err.name
|
||||||
if config_obj.__module__ == 'my.config':
|
if config_obj.__module__ == 'my.config':
|
||||||
click.secho(f"""You're likely missing the nested config block for '{getattr(config_obj, '__name__', str(config_obj))}.{nested_block_name}'.
|
click.secho(f"""You're likely missing the nested config block for '{getattr(config_obj, '__name__', str(config_obj))}.{nested_block_name}'.
|
||||||
See {help_url} or check the corresponding module.py file for an example\
|
See {help_url} or check the corresponding module.py file for an example\
|
||||||
|
|
|
@ -82,7 +82,7 @@ def kopen(path: PathIsh, *args, mode: str='rt', **kwargs) -> IO:
|
||||||
ifile.read1 = ifile.read # type: ignore
|
ifile.read1 = ifile.read # type: ignore
|
||||||
# TODO pass all kwargs here??
|
# TODO pass all kwargs here??
|
||||||
# todo 'expected "BinaryIO"'??
|
# todo 'expected "BinaryIO"'??
|
||||||
return io.TextIOWrapper(ifile, encoding=encoding) # type: ignore[arg-type]
|
return io.TextIOWrapper(ifile, encoding=encoding)
|
||||||
elif name.endswith(Ext.lz4):
|
elif name.endswith(Ext.lz4):
|
||||||
import lz4.frame # type: ignore
|
import lz4.frame # type: ignore
|
||||||
return lz4.frame.open(str(pp), mode, *args, **kwargs)
|
return lz4.frame.open(str(pp), mode, *args, **kwargs)
|
||||||
|
@ -95,7 +95,7 @@ def kopen(path: PathIsh, *args, mode: str='rt', **kwargs) -> IO:
|
||||||
tf = tarfile.open(pp)
|
tf = tarfile.open(pp)
|
||||||
# TODO pass encoding?
|
# TODO pass encoding?
|
||||||
x = tf.extractfile(*args); assert x is not None
|
x = tf.extractfile(*args); assert x is not None
|
||||||
return x # type: ignore[return-value]
|
return x
|
||||||
else:
|
else:
|
||||||
return pp.open(mode, *args, **kwargs)
|
return pp.open(mode, *args, **kwargs)
|
||||||
|
|
||||||
|
@ -209,7 +209,7 @@ class ZipPath(zipfile_Path):
|
||||||
def __truediv__(self, key) -> ZipPath:
|
def __truediv__(self, key) -> ZipPath:
|
||||||
# need to implement it so the return type is not zipfile.Path
|
# need to implement it so the return type is not zipfile.Path
|
||||||
tmp = zipfile_Path(self.root) / self.at / key
|
tmp = zipfile_Path(self.root) / self.at / key
|
||||||
return ZipPath(self.root, tmp.at) # type: ignore[attr-defined]
|
return ZipPath(self.root, tmp.at)
|
||||||
|
|
||||||
def iterdir(self) -> Iterator[ZipPath]:
|
def iterdir(self) -> Iterator[ZipPath]:
|
||||||
for s in self._as_dir().iterdir():
|
for s in self._as_dir().iterdir():
|
||||||
|
|
|
@ -19,7 +19,7 @@ def zoom(w, *keys):
|
||||||
# TODO need to support lists
|
# TODO need to support lists
|
||||||
class Zoomable:
|
class Zoomable:
|
||||||
def __init__(self, parent, *args, **kwargs) -> None:
|
def __init__(self, parent, *args, **kwargs) -> None:
|
||||||
super().__init__(*args, **kwargs) # type: ignore
|
super().__init__(*args, **kwargs)
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
|
|
||||||
# TODO not sure, maybe do it via del??
|
# TODO not sure, maybe do it via del??
|
||||||
|
@ -147,7 +147,7 @@ Expected {c} to be fully consumed by the parser.
|
||||||
|
|
||||||
from typing import cast
|
from typing import cast
|
||||||
def test_unconsumed() -> None:
|
def test_unconsumed() -> None:
|
||||||
import pytest # type: ignore
|
import pytest
|
||||||
with pytest.raises(UnconsumedError):
|
with pytest.raises(UnconsumedError):
|
||||||
with wrap({'a': 1234}) as w:
|
with wrap({'a': 1234}) as w:
|
||||||
w = cast(Wdict, w)
|
w = cast(Wdict, w)
|
||||||
|
@ -200,7 +200,7 @@ def test_consume_few() -> None:
|
||||||
|
|
||||||
|
|
||||||
def test_zoom() -> None:
|
def test_zoom() -> None:
|
||||||
import pytest # type: ignore
|
import pytest
|
||||||
with wrap({'aaa': 'whatever'}) as w:
|
with wrap({'aaa': 'whatever'}) as w:
|
||||||
w = cast(Wdict, w)
|
w = cast(Wdict, w)
|
||||||
with pytest.raises(KeyError):
|
with pytest.raises(KeyError):
|
||||||
|
|
|
@ -62,20 +62,21 @@ def setup_logger(logger: logging.Logger, level: LevelIsh) -> None:
|
||||||
lvl = mklevel(level)
|
lvl = mklevel(level)
|
||||||
try:
|
try:
|
||||||
import logzero # type: ignore[import]
|
import logzero # type: ignore[import]
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
warnings.warn("You might want to install 'logzero' for nice colored logs!")
|
||||||
|
formatter = logging.Formatter(fmt=FORMAT_NOCOLOR, datefmt=DATEFMT)
|
||||||
|
use_logzero = False
|
||||||
|
else:
|
||||||
formatter = logzero.LogFormatter(
|
formatter = logzero.LogFormatter(
|
||||||
fmt=FORMAT_COLOR,
|
fmt=FORMAT_COLOR,
|
||||||
datefmt=DATEFMT,
|
datefmt=DATEFMT,
|
||||||
)
|
)
|
||||||
use_logzero = True
|
use_logzero = True
|
||||||
except ModuleNotFoundError:
|
|
||||||
warnings.warn("You might want to install 'logzero' for nice colored logs!")
|
|
||||||
formatter = logging.Formatter(fmt=FORMAT_NOCOLOR, datefmt=DATEFMT)
|
|
||||||
use_logzero = False
|
|
||||||
|
|
||||||
logger.addFilter(AddExceptionTraceback())
|
logger.addFilter(AddExceptionTraceback())
|
||||||
if use_logzero and not COLLAPSE_DEBUG_LOGS: # all set, nothing to do
|
if use_logzero and not COLLAPSE_DEBUG_LOGS: # all set, nothing to do
|
||||||
# 'simple' setup
|
# 'simple' setup
|
||||||
logzero.setup_logger(logger.name, level=lvl, formatter=formatter)
|
logzero.setup_logger(logger.name, level=lvl, formatter=formatter) # type: ignore[possibly-undefined]
|
||||||
return
|
return
|
||||||
|
|
||||||
h = CollapseDebugHandler() if COLLAPSE_DEBUG_LOGS else logging.StreamHandler()
|
h = CollapseDebugHandler() if COLLAPSE_DEBUG_LOGS else logging.StreamHandler()
|
||||||
|
@ -101,7 +102,7 @@ class LazyLogger(logging.Logger):
|
||||||
# oh god.. otherwise might go into an inf loop
|
# oh god.. otherwise might go into an inf loop
|
||||||
if not hasattr(logger, _init_done):
|
if not hasattr(logger, _init_done):
|
||||||
setattr(logger, _init_done, False) # will setup on the first call
|
setattr(logger, _init_done, False) # will setup on the first call
|
||||||
logger.isEnabledFor = isEnabledFor_lazyinit # type: ignore[assignment]
|
logger.isEnabledFor = isEnabledFor_lazyinit # type: ignore[method-assign]
|
||||||
return cast(LazyLogger, logger)
|
return cast(LazyLogger, logger)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ logger = LazyLogger(__name__)
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
# this is kinda pointless at the moment, but handy to annotate DF returning methods now
|
# this is kinda pointless at the moment, but handy to annotate DF returning methods now
|
||||||
# later will be unignored when they implement type annotations
|
# later will be unignored when they implement type annotations
|
||||||
import pandas as pd # type: ignore
|
import pandas as pd
|
||||||
# DataFrameT = pd.DataFrame
|
# DataFrameT = pd.DataFrame
|
||||||
# TODO ugh. pretty annoying, having any is not very useful since it would allow arbitrary coercions..
|
# TODO ugh. pretty annoying, having any is not very useful since it would allow arbitrary coercions..
|
||||||
# ideally want to use a type that's like Any but doesn't allow arbitrary coercions??
|
# ideally want to use a type that's like Any but doesn't allow arbitrary coercions??
|
||||||
|
@ -26,7 +26,7 @@ else:
|
||||||
|
|
||||||
|
|
||||||
def check_dateish(s) -> Iterable[str]:
|
def check_dateish(s) -> Iterable[str]:
|
||||||
import pandas as pd # type: ignore # noqa: F811 not actually a redefinition
|
import pandas as pd # noqa: F811 not actually a redefinition
|
||||||
ctype = s.dtype
|
ctype = s.dtype
|
||||||
if str(ctype).startswith('datetime64'):
|
if str(ctype).startswith('datetime64'):
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
def get_mycfg_dir() -> Path:
|
def get_mycfg_dir() -> Path:
|
||||||
import appdirs # type: ignore[import]
|
import appdirs
|
||||||
import os
|
import os
|
||||||
# not sure if that's necessary, i.e. could rely on PYTHONPATH instead
|
# not sure if that's necessary, i.e. could rely on PYTHONPATH instead
|
||||||
# on the other hand, by using MY_CONFIG we are guaranteed to load it from the desired path?
|
# on the other hand, by using MY_CONFIG we are guaranteed to load it from the desired path?
|
||||||
|
|
|
@ -495,7 +495,7 @@ Will attempt to call iter() on the value""")
|
||||||
unsortable, itr = _handle_unsorted(itr, order_by_chosen, drop_unsorted, wrap_unsorted)
|
unsortable, itr = _handle_unsorted(itr, order_by_chosen, drop_unsorted, wrap_unsorted)
|
||||||
|
|
||||||
# run the sort, with the computed order by function
|
# run the sort, with the computed order by function
|
||||||
itr = iter(sorted(itr, key=order_by_chosen, reverse=reverse)) # type: ignore[arg-type, type-var]
|
itr = iter(sorted(itr, key=order_by_chosen, reverse=reverse)) # type: ignore[arg-type]
|
||||||
|
|
||||||
# re-attach unsortable values to the front/back of the list
|
# re-attach unsortable values to the front/back of the list
|
||||||
if reverse:
|
if reverse:
|
||||||
|
|
|
@ -40,7 +40,7 @@ def parse_timedelta_string(timedelta_str: str) -> timedelta:
|
||||||
if parts is None:
|
if parts is None:
|
||||||
raise ValueError(f"Could not parse time duration from {timedelta_str}.\nValid examples: '8h', '1w2d8h5m20s', '2m4s'")
|
raise ValueError(f"Could not parse time duration from {timedelta_str}.\nValid examples: '8h', '1w2d8h5m20s', '2m4s'")
|
||||||
time_params = {name: float(param) for name, param in parts.groupdict().items() if param}
|
time_params = {name: float(param) for name, param in parts.groupdict().items() if param}
|
||||||
return timedelta(**time_params) # type: ignore[arg-type]
|
return timedelta(**time_params)
|
||||||
|
|
||||||
|
|
||||||
def parse_timedelta_float(timedelta_str: str) -> float:
|
def parse_timedelta_float(timedelta_str: str) -> float:
|
||||||
|
@ -83,7 +83,7 @@ def parse_datetime_float(date_str: str) -> float:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import dateparser # type: ignore[import]
|
import dateparser
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -188,8 +188,8 @@ def test_nt_serialize() -> None:
|
||||||
|
|
||||||
# test orjson option kwarg
|
# test orjson option kwarg
|
||||||
data = {datetime.date(year=1970, month=1, day=1): 5}
|
data = {datetime.date(year=1970, month=1, day=1): 5}
|
||||||
res = jsn.loads(dumps(data, option=orjson.OPT_NON_STR_KEYS))
|
res2 = jsn.loads(dumps(data, option=orjson.OPT_NON_STR_KEYS))
|
||||||
assert res == {'1970-01-01': 5}
|
assert res2 == {'1970-01-01': 5}
|
||||||
|
|
||||||
|
|
||||||
def test_default_serializer() -> None:
|
def test_default_serializer() -> None:
|
||||||
|
|
|
@ -22,7 +22,7 @@ def test_sqlite_connect_immutable(tmp_path: Path) -> None:
|
||||||
with sqlite3.connect(db) as conn:
|
with sqlite3.connect(db) as conn:
|
||||||
conn.execute('CREATE TABLE testtable (col)')
|
conn.execute('CREATE TABLE testtable (col)')
|
||||||
|
|
||||||
import pytest # type: ignore
|
import pytest
|
||||||
with pytest.raises(sqlite3.OperationalError, match='readonly database'):
|
with pytest.raises(sqlite3.OperationalError, match='readonly database'):
|
||||||
with sqlite_connect_immutable(db) as conn:
|
with sqlite_connect_immutable(db) as conn:
|
||||||
conn.execute('DROP TABLE testtable')
|
conn.execute('DROP TABLE testtable')
|
||||||
|
|
|
@ -62,7 +62,7 @@ def _iter_all_importables(pkg: ModuleType) -> Iterable[HPIModule]:
|
||||||
_discover_path_importables(Path(p), pkg.__name__)
|
_discover_path_importables(Path(p), pkg.__name__)
|
||||||
# todo might need to handle __path__ for individual modules too?
|
# todo might need to handle __path__ for individual modules too?
|
||||||
# not sure why __path__ was duplicated, but it did happen..
|
# not sure why __path__ was duplicated, but it did happen..
|
||||||
for p in set(pkg.__path__) # type: ignore[attr-defined]
|
for p in set(pkg.__path__)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -133,7 +133,7 @@ def dataframe() -> DataFrameT:
|
||||||
dicts.append(d)
|
dicts.append(d)
|
||||||
|
|
||||||
|
|
||||||
import pandas # type: ignore
|
import pandas
|
||||||
return pandas.DataFrame(dicts)
|
return pandas.DataFrame(dicts)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ def dataframe(defensive: bool=True) -> DataFrameT:
|
||||||
# todo check for 'defensive'
|
# todo check for 'defensive'
|
||||||
d = {'error': f'{e} {w}'}
|
d = {'error': f'{e} {w}'}
|
||||||
yield d
|
yield d
|
||||||
import pandas as pd # type: ignore
|
import pandas as pd
|
||||||
df = pd.DataFrame(it())
|
df = pd.DataFrame(it())
|
||||||
# pandas guesses integer, which is pointless for this field (might get coerced to float too)
|
# pandas guesses integer, which is pointless for this field (might get coerced to float too)
|
||||||
df['id'] = df['id'].astype(str)
|
df['id'] = df['id'].astype(str)
|
||||||
|
|
|
@ -133,7 +133,7 @@ def _parse_repository(d: Dict) -> Event:
|
||||||
rt = d['type']
|
rt = d['type']
|
||||||
assert url.startswith(pref); name = url[len(pref):]
|
assert url.startswith(pref); name = url[len(pref):]
|
||||||
eid = EventIds.repo_created(dts=dts, name=name, ref_type=rt, ref=None)
|
eid = EventIds.repo_created(dts=dts, name=name, ref_type=rt, ref=None)
|
||||||
return Event( # type: ignore[misc]
|
return Event(
|
||||||
**_parse_common(d),
|
**_parse_common(d),
|
||||||
summary='created ' + name,
|
summary='created ' + name,
|
||||||
eid=eid,
|
eid=eid,
|
||||||
|
@ -143,7 +143,7 @@ def _parse_repository(d: Dict) -> Event:
|
||||||
def _parse_issue_comment(d: Dict) -> Event:
|
def _parse_issue_comment(d: Dict) -> Event:
|
||||||
url = d['url']
|
url = d['url']
|
||||||
is_bot = "[bot]" in d["user"]
|
is_bot = "[bot]" in d["user"]
|
||||||
return Event( # type: ignore[misc]
|
return Event(
|
||||||
**_parse_common(d),
|
**_parse_common(d),
|
||||||
summary=f'commented on issue {url}',
|
summary=f'commented on issue {url}',
|
||||||
eid='issue_comment_' + url,
|
eid='issue_comment_' + url,
|
||||||
|
@ -155,7 +155,7 @@ def _parse_issue(d: Dict) -> Event:
|
||||||
url = d['url']
|
url = d['url']
|
||||||
title = d['title']
|
title = d['title']
|
||||||
is_bot = "[bot]" in d["user"]
|
is_bot = "[bot]" in d["user"]
|
||||||
return Event( # type: ignore[misc]
|
return Event(
|
||||||
**_parse_common(d),
|
**_parse_common(d),
|
||||||
summary=f'opened issue {title}',
|
summary=f'opened issue {title}',
|
||||||
eid='issue_comment_' + url,
|
eid='issue_comment_' + url,
|
||||||
|
@ -168,7 +168,7 @@ def _parse_pull_request(d: Dict) -> Event:
|
||||||
url = d['url']
|
url = d['url']
|
||||||
title = d['title']
|
title = d['title']
|
||||||
is_bot = "[bot]" in d["user"]
|
is_bot = "[bot]" in d["user"]
|
||||||
return Event( # type: ignore[misc]
|
return Event(
|
||||||
**_parse_common(d),
|
**_parse_common(d),
|
||||||
# TODO distinguish incoming/outgoing?
|
# TODO distinguish incoming/outgoing?
|
||||||
# TODO action? opened/closed??
|
# TODO action? opened/closed??
|
||||||
|
@ -195,7 +195,7 @@ def _parse_project(d: Dict) -> Event:
|
||||||
|
|
||||||
def _parse_release(d: Dict) -> Event:
|
def _parse_release(d: Dict) -> Event:
|
||||||
tag = d['tag_name']
|
tag = d['tag_name']
|
||||||
return Event( # type: ignore[misc]
|
return Event(
|
||||||
**_parse_common(d),
|
**_parse_common(d),
|
||||||
summary=f'released {tag}',
|
summary=f'released {tag}',
|
||||||
eid='release_' + tag,
|
eid='release_' + tag,
|
||||||
|
@ -204,7 +204,7 @@ def _parse_release(d: Dict) -> Event:
|
||||||
|
|
||||||
def _parse_commit_comment(d: Dict) -> Event:
|
def _parse_commit_comment(d: Dict) -> Event:
|
||||||
url = d['url']
|
url = d['url']
|
||||||
return Event( # type: ignore[misc]
|
return Event(
|
||||||
**_parse_common(d),
|
**_parse_common(d),
|
||||||
summary=f'commented on {url}',
|
summary=f'commented on {url}',
|
||||||
eid='commit_comment_' + url,
|
eid='commit_comment_' + url,
|
||||||
|
|
|
@ -71,7 +71,7 @@ def estimate_location(dt: DateExact) -> Iterator[FallbackLocation]:
|
||||||
|
|
||||||
# search to find the first possible location which contains dt (something that started up to
|
# search to find the first possible location which contains dt (something that started up to
|
||||||
# config.for_duration ago, and ends after dt)
|
# config.for_duration ago, and ends after dt)
|
||||||
idx = bisect_left(fl, dt_ts - config.for_duration.total_seconds(), key=lambda l: l.dt.timestamp()) # type: ignore[operator,call-arg,type-var]
|
idx = bisect_left(fl, dt_ts - config.for_duration.total_seconds(), key=lambda l: l.dt.timestamp())
|
||||||
|
|
||||||
# all items are before the given dt
|
# all items are before the given dt
|
||||||
if idx == len(fl):
|
if idx == len(fl):
|
||||||
|
|
|
@ -22,7 +22,7 @@ from datetime import datetime, timezone
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Iterator, Sequence, List
|
from typing import Iterator, Sequence, List
|
||||||
|
|
||||||
import gpxpy # type: ignore[import]
|
import gpxpy
|
||||||
from more_itertools import unique_everseen
|
from more_itertools import unique_everseen
|
||||||
|
|
||||||
from my.core import Stats, LazyLogger
|
from my.core import Stats, LazyLogger
|
||||||
|
|
|
@ -36,7 +36,7 @@ _rgx = re.compile(orgparse.date.gene_timestamp_regex(brtype='inactive'), re.VERB
|
||||||
def _created(n: orgparse.OrgNode) -> Tuple[Optional[datetime], str]:
|
def _created(n: orgparse.OrgNode) -> Tuple[Optional[datetime], str]:
|
||||||
heading = n.heading
|
heading = n.heading
|
||||||
# meh.. support in orgparse?
|
# meh.. support in orgparse?
|
||||||
pp = {} if n.is_root() else n.properties # type: ignore
|
pp = {} if n.is_root() else n.properties
|
||||||
createds = pp.get('CREATED', None)
|
createds = pp.get('CREATED', None)
|
||||||
if createds is None:
|
if createds is None:
|
||||||
# try to guess from heading
|
# try to guess from heading
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
||||||
import PIL.Image # type: ignore
|
import PIL.Image
|
||||||
from PIL.ExifTags import TAGS, GPSTAGS # type: ignore
|
from PIL.ExifTags import TAGS, GPSTAGS
|
||||||
|
|
||||||
|
|
||||||
Exif = Dict
|
Exif = Dict
|
||||||
|
|
|
@ -224,9 +224,9 @@ def events(*args, **kwargs) -> List[Event]:
|
||||||
inp = inputs()
|
inp = inputs()
|
||||||
# 2.2s for 300 files without cachew
|
# 2.2s for 300 files without cachew
|
||||||
# 0.2s for 300 files with cachew
|
# 0.2s for 300 files with cachew
|
||||||
evit = _get_events(inp, *args, **kwargs) # type: ignore[call-arg]
|
evit = _get_events(inp, *args, **kwargs)
|
||||||
# todo mypy is confused here and thinks it's iterable of Path? perhaps something to do with mcachew?
|
# todo mypy is confused here and thinks it's iterable of Path? perhaps something to do with mcachew?
|
||||||
return list(sorted(evit, key=lambda e: e.cmp_key)) # type: ignore[attr-defined,arg-type]
|
return list(sorted(evit, key=lambda e: e.cmp_key))
|
||||||
|
|
||||||
|
|
||||||
def stats() -> Stats:
|
def stats() -> Stats:
|
||||||
|
|
|
@ -33,7 +33,7 @@ from typing import Iterable
|
||||||
from .common import SubscriptionState
|
from .common import SubscriptionState
|
||||||
def states() -> Iterable[SubscriptionState]:
|
def states() -> Iterable[SubscriptionState]:
|
||||||
# meh
|
# meh
|
||||||
from dateutil.parser import isoparse # type: ignore
|
from dateutil.parser import isoparse
|
||||||
for f in inputs():
|
for f in inputs():
|
||||||
# TODO ugh. depends on my naming. not sure if useful?
|
# TODO ugh. depends on my naming. not sure if useful?
|
||||||
dts = f.stem.split('_')[-1]
|
dts = f.stem.split('_')[-1]
|
||||||
|
|
|
@ -78,7 +78,7 @@ def dataframe() -> DataFrameT:
|
||||||
yield error_to_row(w)
|
yield error_to_row(w)
|
||||||
else:
|
else:
|
||||||
yield w
|
yield w
|
||||||
import pandas as pd # type: ignore
|
import pandas as pd
|
||||||
df = pd.DataFrame(it())
|
df = pd.DataFrame(it())
|
||||||
if 'error' not in df:
|
if 'error' not in df:
|
||||||
df['error'] = None
|
df['error'] = None
|
||||||
|
|
|
@ -22,7 +22,7 @@ from datetime import datetime, timezone
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import NamedTuple, Iterator, Set, Tuple, Optional
|
from typing import NamedTuple, Iterator, Set, Tuple, Optional
|
||||||
|
|
||||||
from lxml import etree # type: ignore
|
from lxml import etree
|
||||||
|
|
||||||
from my.core.common import get_files, Stats
|
from my.core.common import get_files, Stats
|
||||||
from my.core.error import Res
|
from my.core.error import Res
|
||||||
|
|
|
@ -65,7 +65,7 @@ logger = LazyLogger(__name__, level='warning')
|
||||||
def _timezone_finder(fast: bool) -> Any:
|
def _timezone_finder(fast: bool) -> Any:
|
||||||
if fast:
|
if fast:
|
||||||
# less precise, but faster
|
# less precise, but faster
|
||||||
from timezonefinder import TimezoneFinderL as Finder # type: ignore
|
from timezonefinder import TimezoneFinderL as Finder
|
||||||
else:
|
else:
|
||||||
from timezonefinder import TimezoneFinder as Finder # type: ignore
|
from timezonefinder import TimezoneFinder as Finder # type: ignore
|
||||||
return Finder(in_memory=True)
|
return Finder(in_memory=True)
|
||||||
|
@ -158,7 +158,7 @@ def _iter_local_dates_fallback() -> Iterator[DayWithZone]:
|
||||||
|
|
||||||
|
|
||||||
def most_common(lst: List[DayWithZone]) -> DayWithZone:
|
def most_common(lst: List[DayWithZone]) -> DayWithZone:
|
||||||
res, _ = Counter(lst).most_common(1)[0] # type: ignore[var-annotated]
|
res, _ = Counter(lst).most_common(1)[0]
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ except ImportError as ie:
|
||||||
# must be caused by something else
|
# must be caused by something else
|
||||||
raise ie
|
raise ie
|
||||||
try:
|
try:
|
||||||
from my.config import twitter as user_config # type: ignore[misc,assignment]
|
from my.config import twitter as user_config # type: ignore[assignment]
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise ie # raise the original exception.. must be something else
|
raise ie # raise the original exception.. must be something else
|
||||||
else:
|
else:
|
||||||
|
|
12
mypy.ini
12
mypy.ini
|
@ -1,9 +1,19 @@
|
||||||
[mypy]
|
[mypy]
|
||||||
|
namespace_packages = True
|
||||||
pretty = True
|
pretty = True
|
||||||
show_error_context = True
|
show_error_context = True
|
||||||
show_error_codes = True
|
show_error_codes = True
|
||||||
|
show_column_numbers = True
|
||||||
|
show_error_end = True
|
||||||
|
warn_unused_ignores = True
|
||||||
check_untyped_defs = True
|
check_untyped_defs = True
|
||||||
namespace_packages = True
|
enable_error_code = possibly-undefined
|
||||||
|
strict_equality = True
|
||||||
|
|
||||||
|
# a bit annoying, it has optional ipython import which should be ignored in mypy-core configuration..
|
||||||
|
[mypy-my.core.__main__]
|
||||||
|
warn_unused_ignores = False
|
||||||
|
|
||||||
# todo ok, maybe it wasn't such a good idea..
|
# todo ok, maybe it wasn't such a good idea..
|
||||||
# mainly because then tox picks it up and running against the user config, not the repository config
|
# mainly because then tox picks it up and running against the user config, not the repository config
|
||||||
# mypy_path=~/.config/my
|
# mypy_path=~/.config/my
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import pytest # type: ignore
|
import pytest
|
||||||
|
|
||||||
from my.calendar.holidays import is_holiday
|
from my.calendar.holidays import is_holiday
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ def test_dynamic_configuration(notes: Path) -> None:
|
||||||
0.0,
|
0.0,
|
||||||
]
|
]
|
||||||
|
|
||||||
import pytest # type: ignore
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
def test_environment_variable(tmp_path: Path) -> None:
|
def test_environment_variable(tmp_path: Path) -> None:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import pytest # type: ignore
|
import pytest
|
||||||
|
|
||||||
# I guess makes sense by default
|
# I guess makes sense by default
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
|
|
|
@ -6,7 +6,7 @@ import zipfile
|
||||||
|
|
||||||
from my.core.kompress import kopen, kexists, CPath
|
from my.core.kompress import kopen, kexists, CPath
|
||||||
|
|
||||||
import pytest # type: ignore
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
structure_data: Path = Path(__file__).parent / "structure_data"
|
structure_data: Path = Path(__file__).parent / "structure_data"
|
||||||
|
|
|
@ -38,7 +38,7 @@ def test_dynamic_config_2(tmp_path: Path) -> None:
|
||||||
assert item1.username == 'user2'
|
assert item1.username == 'user2'
|
||||||
|
|
||||||
|
|
||||||
import pytest # type: ignore
|
import pytest
|
||||||
|
|
||||||
@pytest.mark.skip(reason="won't work at the moment because of inheritance")
|
@pytest.mark.skip(reason="won't work at the moment because of inheritance")
|
||||||
def test_dynamic_config_simplenamespace(tmp_path: Path) -> None:
|
def test_dynamic_config_simplenamespace(tmp_path: Path) -> None:
|
||||||
|
|
|
@ -7,7 +7,7 @@ ROOT = Path(__file__).parent.absolute()
|
||||||
OUTPUTS = ROOT / 'outputs'
|
OUTPUTS = ROOT / 'outputs'
|
||||||
|
|
||||||
|
|
||||||
import pytest # type: ignore
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
def test_hpi(prepare: str) -> None:
|
def test_hpi(prepare: str) -> None:
|
||||||
|
@ -19,7 +19,7 @@ def test_orger(prepare: str, tmp_path: Path) -> None:
|
||||||
om = import_file(ROOT / 'orger/modules/polar.py')
|
om = import_file(ROOT / 'orger/modules/polar.py')
|
||||||
# reload(om)
|
# reload(om)
|
||||||
|
|
||||||
pv = om.PolarView() # type: ignore
|
pv = om.PolarView()
|
||||||
# TODO hmm. worth making public?
|
# TODO hmm. worth making public?
|
||||||
OUTPUTS.mkdir(exist_ok=True)
|
OUTPUTS.mkdir(exist_ok=True)
|
||||||
out = OUTPUTS / (get_valid_filename(prepare) + '.org')
|
out = OUTPUTS / (get_valid_filename(prepare) + '.org')
|
||||||
|
|
|
@ -5,7 +5,7 @@ from typing import TYPE_CHECKING
|
||||||
from my.core.compat import windows
|
from my.core.compat import windows
|
||||||
from my.core.common import get_files
|
from my.core.common import get_files
|
||||||
|
|
||||||
import pytest # type: ignore
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
# hack to replace all /tmp with 'real' tmp dir
|
# hack to replace all /tmp with 'real' tmp dir
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import pytest # type: ignore
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
def test() -> None:
|
def test() -> None:
|
||||||
|
|
|
@ -49,7 +49,7 @@ def with_config():
|
||||||
|
|
||||||
import my.core.cfg as C
|
import my.core.cfg as C
|
||||||
with C.tmp_config() as config:
|
with C.tmp_config() as config:
|
||||||
config.pdfs = user_config # type: ignore
|
config.pdfs = user_config
|
||||||
try:
|
try:
|
||||||
yield
|
yield
|
||||||
finally:
|
finally:
|
||||||
|
|
|
@ -64,7 +64,7 @@ def test_preserves_extra_attr() -> None:
|
||||||
assert isinstance(getattr(config, 'please_keep_me'), str)
|
assert isinstance(getattr(config, 'please_keep_me'), str)
|
||||||
|
|
||||||
|
|
||||||
import pytest # type: ignore
|
import pytest
|
||||||
@pytest.fixture(autouse=True, scope='module')
|
@pytest.fixture(autouse=True, scope='module')
|
||||||
def prepare():
|
def prepare():
|
||||||
from .common import testdata
|
from .common import testdata
|
||||||
|
|
|
@ -18,7 +18,7 @@ def test_location_perf() -> None:
|
||||||
|
|
||||||
# in theory should support any HTML takeout file?
|
# in theory should support any HTML takeout file?
|
||||||
# although IIRC bookmarks and search-history.html weren't working
|
# although IIRC bookmarks and search-history.html weren't working
|
||||||
import pytest # type: ignore
|
import pytest
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'path', [
|
'path', [
|
||||||
'YouTube/history/watch-history.html',
|
'YouTube/history/watch-history.html',
|
||||||
|
|
|
@ -10,7 +10,7 @@ def _init_default_config() -> None:
|
||||||
import my.config
|
import my.config
|
||||||
class default_config:
|
class default_config:
|
||||||
count = 5
|
count = 5
|
||||||
my.config.simple = default_config # type: ignore[attr-defined,assignment,misc]
|
my.config.simple = default_config # type: ignore[assignment,misc]
|
||||||
|
|
||||||
|
|
||||||
def test_tmp_config() -> None:
|
def test_tmp_config() -> None:
|
||||||
|
|
|
@ -2,8 +2,8 @@ import sys
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import pytest # type: ignore
|
import pytest
|
||||||
import pytz # type: ignore
|
import pytz
|
||||||
|
|
||||||
from my.core.error import notnone
|
from my.core.error import notnone
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue