python 3.9 compat: introduce typehelpers.py for NoneType, UnionType, TypeAlias
This commit is contained in:
parent
c357b0a968
commit
b84d2202db
9 changed files with 34 additions and 27 deletions
|
@ -3,11 +3,10 @@ from __future__ import annotations
|
||||||
from munch import Munch
|
from munch import Munch
|
||||||
from typing import Any, Optional, Mapping, Union
|
from typing import Any, Optional, Mapping, Union
|
||||||
|
|
||||||
from dataclass import DataClass, munchclass
|
from dataclass import DataClass
|
||||||
from constants import Arch
|
from constants import Arch
|
||||||
|
|
||||||
|
|
||||||
@munchclass()
|
|
||||||
class SparseProfile(DataClass):
|
class SparseProfile(DataClass):
|
||||||
parent: Optional[str]
|
parent: Optional[str]
|
||||||
device: Optional[str]
|
device: Optional[str]
|
||||||
|
@ -23,7 +22,6 @@ class SparseProfile(DataClass):
|
||||||
return f'{type(self)}{dict.__repr__(self.toDict())}'
|
return f'{type(self)}{dict.__repr__(self.toDict())}'
|
||||||
|
|
||||||
|
|
||||||
@munchclass()
|
|
||||||
class Profile(SparseProfile):
|
class Profile(SparseProfile):
|
||||||
parent: Optional[str]
|
parent: Optional[str]
|
||||||
device: str
|
device: str
|
||||||
|
@ -36,12 +34,10 @@ class Profile(SparseProfile):
|
||||||
size_extra_mb: Union[str, int]
|
size_extra_mb: Union[str, int]
|
||||||
|
|
||||||
|
|
||||||
@munchclass()
|
|
||||||
class WrapperSection(DataClass):
|
class WrapperSection(DataClass):
|
||||||
type: str # NOTE: rename to 'wrapper_type' if this causes problems
|
type: str # NOTE: rename to 'wrapper_type' if this causes problems
|
||||||
|
|
||||||
|
|
||||||
@munchclass()
|
|
||||||
class BuildSection(DataClass):
|
class BuildSection(DataClass):
|
||||||
ccache: bool
|
ccache: bool
|
||||||
clean_mode: bool
|
clean_mode: bool
|
||||||
|
@ -50,20 +46,17 @@ class BuildSection(DataClass):
|
||||||
threads: int
|
threads: int
|
||||||
|
|
||||||
|
|
||||||
@munchclass()
|
|
||||||
class PkgbuildsSection(DataClass):
|
class PkgbuildsSection(DataClass):
|
||||||
git_repo: str
|
git_repo: str
|
||||||
git_branch: str
|
git_branch: str
|
||||||
|
|
||||||
|
|
||||||
@munchclass()
|
|
||||||
class PacmanSection(DataClass):
|
class PacmanSection(DataClass):
|
||||||
parallel_downloads: int
|
parallel_downloads: int
|
||||||
check_space: bool
|
check_space: bool
|
||||||
repo_branch: str
|
repo_branch: str
|
||||||
|
|
||||||
|
|
||||||
@munchclass()
|
|
||||||
class PathsSection(DataClass):
|
class PathsSection(DataClass):
|
||||||
cache_dir: str
|
cache_dir: str
|
||||||
chroots: str
|
chroots: str
|
||||||
|
@ -101,7 +94,6 @@ class ProfilesSection(DataClass):
|
||||||
return f'{type(self)}{dict.__repr__(self.toDict())}'
|
return f'{type(self)}{dict.__repr__(self.toDict())}'
|
||||||
|
|
||||||
|
|
||||||
@munchclass()
|
|
||||||
class Config(DataClass):
|
class Config(DataClass):
|
||||||
wrapper: WrapperSection
|
wrapper: WrapperSection
|
||||||
build: BuildSection
|
build: BuildSection
|
||||||
|
@ -138,7 +130,6 @@ class Config(DataClass):
|
||||||
return Config(_vals, validate=validate)
|
return Config(_vals, validate=validate)
|
||||||
|
|
||||||
|
|
||||||
@munchclass()
|
|
||||||
class RuntimeConfiguration(DataClass):
|
class RuntimeConfiguration(DataClass):
|
||||||
verbose: bool
|
verbose: bool
|
||||||
no_wrap: bool
|
no_wrap: bool
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from typing_extensions import TypeAlias
|
from typehelpers import TypeAlias
|
||||||
|
|
||||||
FASTBOOT = 'fastboot'
|
FASTBOOT = 'fastboot'
|
||||||
FLASH_PARTS = {
|
FLASH_PARTS = {
|
||||||
|
|
10
dataclass.py
10
dataclass.py
|
@ -3,15 +3,11 @@ from __future__ import annotations
|
||||||
import logging
|
import logging
|
||||||
import toml
|
import toml
|
||||||
|
|
||||||
from dataclasses import dataclass
|
|
||||||
from munch import Munch
|
from munch import Munch
|
||||||
from toml.encoder import TomlEncoder, TomlPreserveInlineDictEncoder
|
from toml.encoder import TomlEncoder, TomlPreserveInlineDictEncoder
|
||||||
from typing import ClassVar, Generator, Optional, Union, Mapping, Any, get_type_hints, get_origin, get_args, Iterable
|
from typing import ClassVar, Generator, Optional, Union, Mapping, Any, get_type_hints, get_origin, get_args, Iterable
|
||||||
from types import UnionType, NoneType
|
|
||||||
|
|
||||||
|
from typehelpers import UnionType, NoneType
|
||||||
def munchclass(*args, init=False, **kwargs):
|
|
||||||
return dataclass(*args, init=init, slots=True, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def resolve_type_hint(hint: type, ignore_origins: list[type] = []) -> Iterable[type]:
|
def resolve_type_hint(hint: type, ignore_origins: list[type] = []) -> Iterable[type]:
|
||||||
|
@ -73,12 +69,12 @@ class DataClass(Munch):
|
||||||
type_hints = cls._type_hints if type_hints is None else type_hints
|
type_hints = cls._type_hints if type_hints is None else type_hints
|
||||||
if key in type_hints:
|
if key in type_hints:
|
||||||
_classes = tuple[type](resolve_type_hint(type_hints[key]))
|
_classes = tuple[type](resolve_type_hint(type_hints[key]))
|
||||||
optional = NoneType in _classes
|
optional = bool(set([NoneType, None]).intersection(_classes))
|
||||||
if optional and value is None:
|
if optional and value is None:
|
||||||
results[key] = None
|
results[key] = None
|
||||||
continue
|
continue
|
||||||
if issubclass(_classes[0], dict):
|
if issubclass(_classes[0], dict):
|
||||||
assert isinstance(value, dict) or optional
|
assert isinstance(value, dict) or (optional and value is None), f'{key=} is not dict: {value!r}, {_classes=}'
|
||||||
target_class = _classes[0]
|
target_class = _classes[0]
|
||||||
if target_class in [None, NoneType, Optional]:
|
if target_class in [None, NoneType, Optional]:
|
||||||
for target in _classes[1:]:
|
for target in _classes[1:]:
|
||||||
|
|
|
@ -5,7 +5,7 @@ from typing import Optional
|
||||||
|
|
||||||
from config.state import config
|
from config.state import config
|
||||||
from constants import Arch, ARCHES
|
from constants import Arch, ARCHES
|
||||||
from config.scheme import DataClass, munchclass
|
from dataclass import DataClass
|
||||||
from distro.distro import get_kupfer_local
|
from distro.distro import get_kupfer_local
|
||||||
from distro.package import LocalPackage
|
from distro.package import LocalPackage
|
||||||
from packages.pkgbuild import Pkgbuild, _pkgbuilds_cache, discover_pkgbuilds, get_pkgbuild_by_path, init_pkgbuilds
|
from packages.pkgbuild import Pkgbuild, _pkgbuilds_cache, discover_pkgbuilds, get_pkgbuild_by_path, init_pkgbuilds
|
||||||
|
@ -43,7 +43,6 @@ class DeviceSummary(DataClass):
|
||||||
return separator.join([f"{color_str(name, bold=True, use_colors=colors)}: {value}" for name, value in fields.items()])
|
return separator.join([f"{color_str(name, bold=True, use_colors=colors)}: {value}" for name, value in fields.items()])
|
||||||
|
|
||||||
|
|
||||||
@munchclass()
|
|
||||||
class Device(DataClass):
|
class Device(DataClass):
|
||||||
name: str
|
name: str
|
||||||
arch: Arch
|
arch: Arch
|
||||||
|
|
|
@ -2,7 +2,7 @@ import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from shutil import copyfileobj
|
from shutil import copyfileobj
|
||||||
from typing import Optional
|
from typing import Optional, Union
|
||||||
from urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
|
|
||||||
from exec.file import get_temp_dir, makedir
|
from exec.file import get_temp_dir, makedir
|
||||||
|
@ -17,7 +17,7 @@ class BinaryPackage(PackageInfo):
|
||||||
arch: str
|
arch: str
|
||||||
filename: str
|
filename: str
|
||||||
resolved_url: Optional[str]
|
resolved_url: Optional[str]
|
||||||
_desc: Optional[dict[str, str | list[str]]]
|
_desc: Optional[dict[str, Union[str, list[str]]]]
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
@ -39,7 +39,7 @@ class BinaryPackage(PackageInfo):
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse_desc(clss, desc_str: str, resolved_repo_url=None):
|
def parse_desc(clss, desc_str: str, resolved_repo_url=None):
|
||||||
"""Parses a desc file, returning a PackageInfo"""
|
"""Parses a desc file, returning a PackageInfo"""
|
||||||
desc: dict[str, str | list[str]] = {}
|
desc: dict[str, Union[str, list[str]]] = {}
|
||||||
for segment in f'\n{desc_str}'.split('\n%'):
|
for segment in f'\n{desc_str}'.split('\n%'):
|
||||||
if not segment.strip():
|
if not segment.strip():
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -6,7 +6,7 @@ import toml
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from typing import ClassVar, Optional, Mapping
|
from typing import ClassVar, Optional, Mapping, Union
|
||||||
|
|
||||||
from config.state import config
|
from config.state import config
|
||||||
from constants import Arch, BASE_DISTROS, KUPFER_HTTPS, REPOS_CONFIG_FILE, REPOSITORIES
|
from constants import Arch, BASE_DISTROS, KUPFER_HTTPS, REPOS_CONFIG_FILE, REPOSITORIES
|
||||||
|
@ -33,7 +33,7 @@ class BaseDistroRepo(AbstrRepoConfig):
|
||||||
|
|
||||||
|
|
||||||
class RepoConfig(AbstrRepoConfig):
|
class RepoConfig(AbstrRepoConfig):
|
||||||
remote_url: Optional[str | dict[Arch, str]]
|
remote_url: Optional[Union[str, dict[Arch, str]]]
|
||||||
local_only: Optional[bool]
|
local_only: Optional[bool]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,9 @@ import subprocess
|
||||||
|
|
||||||
from subprocess import CompletedProcess # make it easy for users of this module
|
from subprocess import CompletedProcess # make it easy for users of this module
|
||||||
from shlex import quote as shell_quote
|
from shlex import quote as shell_quote
|
||||||
from typing import IO, Optional, Union, TypeAlias
|
from typing import IO, Optional, Union
|
||||||
|
|
||||||
|
from typehelpers import TypeAlias
|
||||||
|
|
||||||
ElevationMethod: TypeAlias = str
|
ElevationMethod: TypeAlias = str
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import multiprocessing
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from joblib import Parallel, delayed
|
from joblib import Parallel, delayed
|
||||||
from typing import Iterable, Optional, TypeAlias
|
from typing import Iterable, Optional
|
||||||
|
|
||||||
from config.state import config, ConfigStateHolder
|
from config.state import config, ConfigStateHolder
|
||||||
from constants import Arch
|
from constants import Arch
|
||||||
|
@ -16,6 +16,7 @@ from exec.file import remove_file
|
||||||
from logger import setup_logging
|
from logger import setup_logging
|
||||||
from utils import git, git_get_branch
|
from utils import git, git_get_branch
|
||||||
from wrapper import check_programs_wrap
|
from wrapper import check_programs_wrap
|
||||||
|
from typehelpers import TypeAlias
|
||||||
|
|
||||||
from .srcinfo_cache import SrcinfoMetaFile
|
from .srcinfo_cache import SrcinfoMetaFile
|
||||||
|
|
||||||
|
|
18
typehelpers.py
Normal file
18
typehelpers.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
try:
|
||||||
|
from typing import TypeAlias # type: ignore[attr-defined]
|
||||||
|
except ImportError:
|
||||||
|
from typing_extensions import TypeAlias
|
||||||
|
|
||||||
|
TypeAlias = TypeAlias
|
||||||
|
|
||||||
|
try:
|
||||||
|
from types import UnionType
|
||||||
|
except ImportError:
|
||||||
|
UnionType: TypeAlias = Union # type: ignore[no-redef]
|
||||||
|
|
||||||
|
try:
|
||||||
|
from types import NoneType
|
||||||
|
except ImportError:
|
||||||
|
NoneType: TypeAlias = type(None) # type: ignore[no-redef]
|
Loading…
Add table
Add a link
Reference in a new issue