Skip to content

Commit

Permalink
Upgrade typing syntax
Browse files Browse the repository at this point in the history
By using 'from __future__ import annotations', we can remove Union and Optional
imports from typing.
  • Loading branch information
dlax committed Nov 12, 2024
1 parent edcad2c commit 7c40974
Show file tree
Hide file tree
Showing 10 changed files with 151 additions and 134 deletions.
12 changes: 7 additions & 5 deletions pgtoolkit/_helpers.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from __future__ import annotations

import json
import sys
from datetime import datetime, timedelta, timezone
from pathlib import Path
from typing import IO, Any, Generic, NoReturn, Optional, TypeVar, Union, overload
from typing import IO, Any, Generic, NoReturn, TypeVar, overload


def format_timedelta(delta: timedelta) -> str:
Expand All @@ -22,7 +24,7 @@ def format_timedelta(delta: timedelta) -> str:


class JSONDateEncoder(json.JSONEncoder):
def default(self, obj: Union[timedelta, datetime, object]) -> Any:
def default(self, obj: timedelta | datetime | object) -> Any:
if isinstance(obj, datetime):
return obj.isoformat()
elif isinstance(obj, timedelta):
Expand Down Expand Up @@ -71,8 +73,8 @@ def open_or_return(


def open_or_return(
fo_or_path: Optional[Union[str, Path, IO[str]]], mode: str = "r"
) -> Union[IO[str], PassthroughManager[IO[str]]]:
fo_or_path: str | Path | IO[str] | None, mode: str = "r"
) -> IO[str] | PassthroughManager[IO[str]]:
# Returns a context manager around a file-object for fo_or_path. If
# fo_or_path is a file-object, the context manager keeps it open. If it's a
# path, the file is opened with mode and will be closed upon context exit.
Expand All @@ -93,7 +95,7 @@ def open_or_return(


class Timer:
def __enter__(self) -> "Timer":
def __enter__(self) -> Timer:
self.start = datetime.now(timezone.utc)
return self

Expand Down
36 changes: 19 additions & 17 deletions pgtoolkit/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
"""

from __future__ import annotations

import contextlib
import copy
import enum
Expand All @@ -49,7 +51,7 @@
from collections import OrderedDict
from collections.abc import Iterable, Iterator
from datetime import timedelta
from typing import IO, Any, NoReturn, Optional, Union
from typing import IO, Any, NoReturn, Union
from warnings import warn

from ._helpers import JSONDateEncoder, open_or_return
Expand All @@ -70,7 +72,7 @@ class IncludeType(enum.Enum):
include = enum.auto()


def parse(fo: Union[str, pathlib.Path, IO[str]]) -> "Configuration":
def parse(fo: str | pathlib.Path | IO[str]) -> Configuration:
"""Parse a configuration file.
The parser tries to return Python object corresponding to value, based on
Expand Down Expand Up @@ -98,12 +100,12 @@ def parse(fo: Union[str, pathlib.Path, IO[str]]) -> "Configuration":
return conf


def _consume(conf: "Configuration", content: Iterable[str]) -> Iterator[None]:
def _consume(conf: Configuration, content: Iterable[str]) -> Iterator[None]:
for include_path, include_type in conf.parse(content):
yield from parse_include(conf, include_path, include_type)


def parse_string(string: str, source: Optional[str] = None) -> "Configuration":
def parse_string(string: str, source: str | None = None) -> Configuration:
"""Parse configuration data from a string.
Optional *source* argument can be used to set the context path of built
Expand All @@ -118,11 +120,11 @@ def parse_string(string: str, source: Optional[str] = None) -> "Configuration":


def parse_include(
conf: "Configuration",
conf: Configuration,
path: pathlib.Path,
include_type: IncludeType,
*,
_processed: Optional[set[pathlib.Path]] = None,
_processed: set[pathlib.Path] | None = None,
) -> Iterator[None]:
"""Parse on include directive with 'path' value of type 'include_type' into
'conf' object.
Expand All @@ -131,7 +133,7 @@ def parse_include(
_processed = set()

def notfound(
path: pathlib.Path, include_type: str, reference_path: Optional[str]
path: pathlib.Path, include_type: str, reference_path: str | None
) -> FileNotFoundError:
ref = (
f"{reference_path!r}" if reference_path is not None else "<string literal>"
Expand Down Expand Up @@ -270,8 +272,8 @@ def __init__(
name: str,
value: Value,
commented: bool = False,
comment: Optional[str] = None,
raw_line: Optional[str] = None,
comment: str | None = None,
raw_line: str | None = None,
) -> None:
self._name = name
# We parse value only if not already parsed from a file
Expand All @@ -294,7 +296,7 @@ def value(self) -> Value:
return self._value

@value.setter
def value(self, value: Union[str, Value]) -> None:
def value(self, value: str | Value) -> None:
if isinstance(value, str):
value = parse_value(value)
self._value = value
Expand Down Expand Up @@ -412,7 +414,7 @@ def add(
value: Value,
*,
commented: bool = False,
comment: Optional[str] = None,
comment: str | None = None,
) -> None:
"""Add a new entry."""
if name in self:
Expand Down Expand Up @@ -479,7 +481,7 @@ class Configuration:

lines: list[str]
entries: dict[str, Entry]
path: Optional[str]
path: str | None

_parameter_re = re.compile(
r"^(?P<name>[a-z_.]+)(?: +(?!=)| *= *)(?P<value>.*?)"
Expand All @@ -492,7 +494,7 @@ class Configuration:
# the serialized line is updated accordingly. This allows to keep comments
# and serialize only what's needed. Other lines are just written as-is.

def __init__(self, path: Optional[str] = None) -> None:
def __init__(self, path: str | None = None) -> None:
self.__dict__.update(
dict(
lines=[],
Expand Down Expand Up @@ -557,7 +559,7 @@ def parse(self, fo: Iterable[str]) -> Iterator[tuple[pathlib.Path, IncludeType]]
def parse_string(self, string: str) -> None:
list(_consume(self, string.splitlines(keepends=True)))

def __add__(self, other: Any) -> "Configuration":
def __add__(self, other: Any) -> Configuration:
cls = self.__class__
if not isinstance(other, cls):
return NotImplemented
Expand All @@ -566,7 +568,7 @@ def __add__(self, other: Any) -> "Configuration":
s.entries.update(other.entries)
return s

def __iadd__(self, other: Any) -> "Configuration":
def __iadd__(self, other: Any) -> Configuration:
cls = self.__class__
if not isinstance(other, cls):
return NotImplemented
Expand Down Expand Up @@ -602,7 +604,7 @@ def __setitem__(self, key: str, value: Value) -> None:
else:
self._add_entry(Entry(name=key, value=value))

def get(self, key: str, default: Optional[Value] = None) -> Optional[Value]:
def get(self, key: str, default: Value | None = None) -> Value | None:
try:
return self[key]
except KeyError:
Expand Down Expand Up @@ -702,7 +704,7 @@ def edit(self) -> Iterator[EntriesProxy]:
if entry.raw_line is not None:
self.lines.remove(entry.raw_line)

def save(self, fo: Optional[Union[str, pathlib.Path, IO[str]]] = None) -> None:
def save(self, fo: str | pathlib.Path | IO[str] | None = None) -> None:
"""Write configuration to a file.
Configuration entries order and comments are preserved.
Expand Down
Loading

0 comments on commit 7c40974

Please sign in to comment.