Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions confuse/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
from .exceptions import * # noqa: F403
from .sources import * # noqa: F403
from .templates import * # noqa: F403
from .templates import Path as Path
from .util import * # type: ignore[no-redef] # noqa: F403
from .yaml_util import * # noqa: F403
8 changes: 4 additions & 4 deletions confuse/templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
T = TypeVar("T")
T_co = TypeVar("T_co", covariant=True)
K = TypeVar("K", bound=Hashable, default=str)
P = TypeVar("P", bound=pathlib.PurePath | str, default=str)
P = TypeVar("P", bound=pathlib.Path | str, default=str)
V = TypeVar("V", default=object)
ConfigKey = int | str | bytes
ConfigKeyT = TypeVar("ConfigKeyT", bound=ConfigKey, default=str)
Expand Down Expand Up @@ -738,7 +738,7 @@ def value(
return os.path.abspath(path_str)


class Path(Filename[pathlib.PurePath]):
class Path(Filename[pathlib.Path]):
"""A template that validates strings as `pathlib.Path` objects.

Filenames are parsed equivalent to the `Filename` template and then
Expand Down Expand Up @@ -863,7 +863,7 @@ def as_template(value: set[T]) -> Choice[T, T]: ...
@overload
def as_template(value: list[T]) -> OneOf[T]: ...
@overload
def as_template(value: pathlib.PurePath) -> Path: ...
def as_template(value: pathlib.Path) -> Path: ...
@overload
def as_template(value: None) -> Template[None]: ...
@overload
Expand Down Expand Up @@ -897,7 +897,7 @@ def as_template(value: Any) -> Template[Any]:
return Number()
elif isinstance(value, float):
return Number(value)
elif isinstance(value, pathlib.PurePath):
elif isinstance(value, pathlib.Path):
return Path(value)
elif value is None:
return Template(None)
Expand Down
4 changes: 4 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ Unreleased

- Require `typing_extensions` on older Python versions (and use `typing` on
newer versions). [#189](https://github.com/beetbox/confuse/issues/189)
- Narrow `Path` template shorthand handling to concrete `pathlib.Path` values
for more accurate type checking.
- Fix `confuse.Path` which now points to `confuse.templates.Path` instead of
`pathlib.Path`.

v2.2.0
------
Expand Down
15 changes: 11 additions & 4 deletions test/test_valid.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import enum
import os
import pathlib
import unittest
from collections.abc import Mapping, Sequence
from typing import Any

import pytest

try:
from typing import assert_type # type: ignore[attr-defined]
except ImportError: # Python < 3.11
from typing_extensions import assert_type

import confuse

from . import _root
Expand Down Expand Up @@ -461,19 +467,20 @@ def test_filename_wrong_type(self):

class PathTest(unittest.TestCase):
def test_path_value(self):
import pathlib

config = _root({"foo": "foo/bar"})
valid = config["foo"].get(confuse.Path())
assert valid == pathlib.Path(os.path.abspath("foo/bar"))

def test_default_value(self):
import pathlib

config = _root({})
valid = config["foo"].get(confuse.Path("foo/bar"))
assert valid == pathlib.Path("foo/bar")

def test_optional_value_type(self):
config = _root({"foo": "foo/bar"})
valid = config["foo"].get(confuse.Optional(confuse.Path()))
assert_type(valid, pathlib.Path | None)

def test_default_none(self):
config = _root({})
valid = config["foo"].get(confuse.Path(None))
Expand Down
Loading