Skip to content

Commit

Permalink
release: v0.4.0 (#157)
Browse files Browse the repository at this point in the history
  • Loading branch information
eonu authored Sep 28, 2024
2 parents 4ac82d2 + 9cd7741 commit ae3a38c
Show file tree
Hide file tree
Showing 15 changed files with 516 additions and 51 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

All notable changes to this project will be documented in this file.

## [v0.4.0](https://github.com/eonu/feud/releases/tag/v0.4.0) - 2024-09-28

### Features

- support postponed type hint evaluation ([#150](https://github.com/eonu/feud/issues/150))
- add `Group.add_commands` ([#156](https://github.com/eonu/feud/issues/156))

## [v0.3.2](https://github.com/eonu/feud/releases/tag/v0.3.2) - 2024-04-01

### Documentation
Expand Down
9 changes: 0 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -778,15 +778,6 @@ This installs Feud with the optional dependencies:

To install Feud without any optional dependencies, simply run `pip install feud`.

> [!CAUTION]
> Feud **will break** if used with postponed type hint evaluation ([PEP563](https://peps.python.org/pep-0563/)), i.e.:
>
> ```python
> from __future__ import annotations
> ```
>
> This is because Feud relies on type hint evaluation in order to determine the expected input type for command parameters.
### Improved formatting with Rich

Below is a comparison of Feud with and without `rich-click`.
Expand Down
2 changes: 1 addition & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
project = "feud"
copyright = "2023-2025, Feud Developers" # noqa: A001
author = "Edwin Onuonga (eonu)"
release = "0.3.2"
release = "0.4.0"

# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
Expand Down
26 changes: 21 additions & 5 deletions docs/source/sections/typing/pydantic_extra_types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,22 @@ Country types
- :py:obj:`pydantic_extra_types.country.CountryOfficialName` (``>= 2.1.0, <2.4.0``)
- :py:obj:`pydantic_extra_types.country.CountryShortName` (``>= 2.1.0``)

ISBN type
---------

- :py:obj:`pydantic_extra_types.isbn.ISBN` (``>= 2.4.0``)

Language types
--------------

- :py:obj:`pydantic_extra_types.language_code.LanguageAlpha2` (``>= 2.7.0``)
- :py:obj:`pydantic_extra_types.language_code.LanguageName` (``>= 2.7.0``)

MAC address type
----------------

- :py:obj:`pydantic_extra_types.mac_address.MacAddress` (``>= 2.1.0``)

Phone number type
-----------------

Expand All @@ -73,16 +89,16 @@ Payment types
- :py:obj:`pydantic_extra_types.payment.PaymentCardBrand` (``>= 2.1.0``)
- :py:obj:`pydantic_extra_types.payment.PaymentCardNumber` (``>= 2.1.0``)

MAC address type
----------------

- :py:obj:`pydantic_extra_types.mac_address.MacAddress` (``>= 2.1.0``)

Routing number type
-------------------

- :py:obj:`pydantic_extra_types.routing_number.ABARoutingNumber` (``>= 2.1.0``)

Semantic version type
---------------------

- :py:obj:`pydantic_extra_types.semantic_version.SemanticVersion` (``>= 2.9.0``)

ULID type
---------

Expand Down
12 changes: 6 additions & 6 deletions feud/_internal/_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class CommandState:
description: str | None = None

def decorate( # noqa: PLR0915
self: CommandState,
self: t.Self,
func: t.Callable,
) -> click.Command:
meta_vars: dict[str, str] = {}
Expand All @@ -66,7 +66,7 @@ def decorate( # noqa: PLR0915
var_positional: str | None = None
params: list[click.Parameter] = []

sig: inspect.signature = inspect.signature(func)
sig: inspect.signature = inspect.signature(func, eval_str=True)

for i, (param_name, param_spec) in enumerate(sig.parameters.items()):
# store names of positional arguments
Expand Down Expand Up @@ -164,7 +164,7 @@ def decorate( # noqa: PLR0915

return command

def get_meta_var(self: CommandState, param: click.Parameter) -> str:
def get_meta_var(self: t.Self, param: click.Parameter) -> str:
match param:
case click.Argument():
return param.make_metavar()
Expand Down Expand Up @@ -246,13 +246,13 @@ def build_command_state( # noqa: PLR0915
else:
doc = docstring_parser.parse_from_object(func)

state.description: str | None = _docstring.get_description(doc)
state.description = _docstring.get_description(doc)

sig: inspect.Signature = inspect.signature(func)
sig: inspect.Signature = inspect.signature(func, eval_str=True)

for param, spec in sig.parameters.items():
meta = ParameterSpec()
meta.hint: type = spec.annotation
meta.hint = spec.annotation

# get renamed parameter if @feud.rename used
name: str = state.names["params"].get(param, param)
Expand Down
30 changes: 25 additions & 5 deletions feud/_internal/_types/click.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,26 @@
from pydantic_extra_types.country import CountryOfficialName

EXTRA_TYPES[CountryOfficialName] = click.STRING

if version >= packaging.version.parse("2.4.0"):
from pydantic_extra_types.isbn import ISBN

EXTRA_TYPES[ISBN] = click.STRING

if version >= packaging.version.parse("2.7.0"):
from pydantic_extra_types.language_code import (
LanguageAlpha2,
LanguageName,
)

EXTRA_TYPES[LanguageAlpha2] = click.STRING
EXTRA_TYPES[LanguageName] = click.STRING

if version >= packaging.version.parse("2.9.0"):
from pydantic_extra_types.semantic_version import SemanticVersion

EXTRA_TYPES[SemanticVersion] = click.STRING

except ImportError:
EXTRA_TYPES = {}

Expand All @@ -131,7 +151,7 @@

class DateTime(click.DateTime):
def __init__(
self: DateTime,
self: t.Self,
*args: t.Any,
datetime_type: type,
show_default_format: bool,
Expand All @@ -143,7 +163,7 @@ def __init__(
super().__init__(*args, **kwargs)

def get_metavar(
self: DateTime,
self: t.Self,
param: click.Parameter, # noqa: ARG002
) -> str:
return (
Expand All @@ -153,7 +173,7 @@ def get_metavar(
)

def _try_to_convert_date(
self: DateTime,
self: t.Self,
value: t.Any,
format: str, # noqa: A002, ARG002
) -> t.Any | None:
Expand All @@ -165,7 +185,7 @@ def _try_to_convert_date(

class Union(click.ParamType):
def __init__(
self: DateTime,
self: t.Self,
*args: t.Any,
types: list[click.ParamType],
**kwargs: t.Any,
Expand All @@ -182,7 +202,7 @@ def _get_metavar(
return click_type.get_metavar(param) or click_type.name.upper()
return None

def get_metavar(self: DateTime, param: click.Parameter) -> str:
def get_metavar(self: t.Self, param: click.Parameter) -> str:
metavars = [
metavar
for click_type in self.types
Expand Down
16 changes: 8 additions & 8 deletions feud/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from __future__ import annotations

import inspect
from typing import Any
import typing as t

import pydantic as pyd

Expand Down Expand Up @@ -42,16 +42,16 @@ class Config(pyd.BaseModel):

#: Validation settings for
#: :py:func:`pydantic.validate_call_decorator.validate_call`.
pydantic_kwargs: dict[str, Any] = {}
pydantic_kwargs: dict[str, t.Any] = {}

#: Styling settings for ``rich-click``.
#:
#: See all available options
#: `here <https://github.com/ewels/rich-click/blob/e6a3add46c591d49079d440917700dfe28cf0cfe/src/rich_click/rich_help_configuration.py#L50>`__
#: (as of ``rich-click`` v1.7.2).
rich_click_kwargs: dict[str, Any] = {"show_arguments": True}
rich_click_kwargs: dict[str, t.Any] = {"show_arguments": True}

def __init__(self: Config, **kwargs: Any) -> Config:
def __init__(self: t.Self, **kwargs: t.Any) -> None:
caller: str = inspect.currentframe().f_back.f_code.co_name
if caller != Config._create.__name__:
msg = (
Expand All @@ -63,11 +63,11 @@ def __init__(self: Config, **kwargs: Any) -> Config:

@classmethod
def _create(
cls: type[Config], base: Config | None = None, **kwargs: Any
cls: type[Config], base: Config | None = None, **kwargs: t.Any
) -> Config:
config_kwargs = base.model_dump(exclude_unset=True) if base else {}
for field in cls.model_fields:
value: Any | None = kwargs.get(field)
value: t.Any | None = kwargs.get(field)
if value is not None:
config_kwargs[field] = value
return cls(**config_kwargs)
Expand All @@ -79,8 +79,8 @@ def config(
show_help_defaults: bool | None = None,
show_help_datetime_formats: bool | None = None,
show_help_envvars: bool | None = None,
pydantic_kwargs: dict[str, Any] | None = None,
rich_click_kwargs: dict[str, Any] | None = None,
pydantic_kwargs: dict[str, t.Any] | None = None,
rich_click_kwargs: dict[str, t.Any] | None = None,
) -> Config:
"""Create a reusable configuration for :py:func:`.command` or
:py:class:`.Group` objects.
Expand Down
Loading

0 comments on commit ae3a38c

Please sign in to comment.