Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-cyclopts for openSUSE:Factory 
checked in at 2026-07-10 17:42:36
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-cyclopts (Old)
 and      /work/SRC/openSUSE:Factory/.python-cyclopts.new.1991 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-cyclopts"

Fri Jul 10 17:42:36 2026 rev:3 rq:1364811 version:4.21.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-cyclopts/python-cyclopts.changes  
2026-06-30 15:13:35.984379260 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-cyclopts.new.1991/python-cyclopts.changes    
    2026-07-10 17:45:00.540800478 +0200
@@ -1,0 +2,13 @@
+Fri Jul 10 05:14:54 UTC 2026 - Martin Pluskal <[email protected]>
+
+- Update to 4.21.0:
+  * Add Parameter.negative_alias to append extra names to a flag's
+    negative form without dropping the generated --no-*/--empty-*
+    names
+  * Fix a spurious "Input should be a valid list" validation error
+    for dataclass commands with a default_factory field when
+    pydantic is imported; factory defaults are now invoked during
+    introspection so the produced value is used as the default and
+    shown in help text
+
+-------------------------------------------------------------------

Old:
----
  cyclopts-4.20.0.tar.gz

New:
----
  cyclopts-4.21.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-cyclopts.spec ++++++
--- /var/tmp/diff_new_pack.E9ZdXF/_old  2026-07-10 17:45:02.300860769 +0200
+++ /var/tmp/diff_new_pack.E9ZdXF/_new  2026-07-10 17:45:02.308861043 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           python-cyclopts
-Version:        4.20.0
+Version:        4.21.0
 Release:        0
 Summary:        Intuitive, easy CLIs based on python type hints
 License:        Apache-2.0

++++++ cyclopts-4.20.0.tar.gz -> cyclopts-4.21.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cyclopts-4.20.0/PKG-INFO new/cyclopts-4.21.0/PKG-INFO
--- old/cyclopts-4.20.0/PKG-INFO        2020-02-02 01:00:00.000000000 +0100
+++ new/cyclopts-4.21.0/PKG-INFO        2020-02-02 01:00:00.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: cyclopts
-Version: 4.20.0
+Version: 4.21.0
 Summary: Intuitive, easy CLIs based on type hints.
 Project-URL: Homepage, https://github.com/BrianPugh/cyclopts
 Project-URL: Repository, https://github.com/BrianPugh/cyclopts
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cyclopts-4.20.0/cyclopts/_version.py 
new/cyclopts-4.21.0/cyclopts/_version.py
--- old/cyclopts-4.20.0/cyclopts/_version.py    2020-02-02 01:00:00.000000000 
+0100
+++ new/cyclopts-4.21.0/cyclopts/_version.py    2020-02-02 01:00:00.000000000 
+0100
@@ -18,7 +18,7 @@
 commit_id: str | None
 __commit_id__: str | None
 
-__version__ = version = '4.20.0'
-__version_tuple__ = version_tuple = (4, 20, 0)
+__version__ = version = '4.21.0'
+__version_tuple__ = version_tuple = (4, 21, 0)
 
 __commit_id__ = commit_id = None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cyclopts-4.20.0/cyclopts/argument/_argument.py 
new/cyclopts-4.21.0/cyclopts/argument/_argument.py
--- old/cyclopts-4.20.0/cyclopts/argument/_argument.py  2020-02-02 
01:00:00.000000000 +0100
+++ new/cyclopts-4.21.0/cyclopts/argument/_argument.py  2020-02-02 
01:00:00.000000000 +0100
@@ -275,7 +275,10 @@
                     continue
                 if field_info.kind is field_info.VAR_KEYWORD:
                     self._default = field_info.annotation
-                else:
+                elif field_info.name not in self._lookup:
+                    # Fields already registered via ``get_field_infos`` have 
richer metadata
+                    # (e.g. resolved ``default_factory`` values) than the raw 
``__init__``
+                    # signature; don't re-register them.
                     self._update_lookup({field_info.name: field_info})
 
         if self._accepts_keywords and len(hints) > 1:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cyclopts-4.20.0/cyclopts/field_info.py 
new/cyclopts-4.21.0/cyclopts/field_info.py
--- old/cyclopts-4.20.0/cyclopts/field_info.py  2020-02-02 01:00:00.000000000 
+0100
+++ new/cyclopts-4.21.0/cyclopts/field_info.py  2020-02-02 01:00:00.000000000 
+0100
@@ -202,11 +202,23 @@
         else:
             annotation = pydantic_field.annotation
 
+        if pydantic_field.default_factory is not None:
+            try:
+                default = pydantic_field.get_default(call_default_factory=True)
+            except (TypeError, ValueError):
+                # Factories that require validated data cannot be invoked 
during introspection;
+                # treat those fields as having no introspectable default.
+                default = FieldInfo.empty
+        elif pydantic_field.default is PydanticUndefined:
+            default = FieldInfo.empty
+        else:
+            default = pydantic_field.default
+
         out[python_name] = FieldInfo(
             names=tuple(names),
             kind=inspect.Parameter.KEYWORD_ONLY if pydantic_field.kw_only else 
inspect.Parameter.POSITIONAL_OR_KEYWORD,
             annotation=annotation,
-            default=FieldInfo.empty if pydantic_field.default is 
PydanticUndefined else pydantic_field.default,
+            default=default,
             required=pydantic_field.is_required(),
             help=help,
         )
@@ -238,7 +250,9 @@
 
         if isinstance(attribute.default, attrs.Factory):  # pyright: ignore
             required = False
-            default = None  # Not strictly True, but we don't want to invoke 
factory
+            # ``takes_self`` factories cannot be invoked without an instance; 
treat those
+            # fields as having no introspectable default.
+            default = FieldInfo.empty if attribute.default.takes_self else 
attribute.default.factory()
         elif attribute.default is attrs.NOTHING:
             required = True
             default = FieldInfo.empty
@@ -360,4 +374,16 @@
     for name, iparam in inspect.signature(f).parameters.items():
         annotation = type_hints.get(name, iparam.annotation)
         out[name] = FieldInfo.from_iparam(iparam, annotation=annotation)
+
+    if inspect.isclass(func):
+        # ``inspect.signature`` on a class surfaces raw ``__init__`` defaults, 
which use
+        # library-private sentinels for factory fields (dataclasses' 
``_HAS_DEFAULT_FACTORY``
+        # — also reused by pydantic's generated ``__signature__`` — and attrs' 
``NOTHING``).
+        # ``get_field_infos`` already resolves defaults per-library; merge its
+        # default/requiredness over the raw signature values.
+        for name, field_info in get_field_infos(func).items():
+            for candidate in field_info.names or (name,):
+                if candidate in out:
+                    out[candidate] = 
out[candidate].evolve(default=field_info.default, required=field_info.required)
+
     return out
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cyclopts-4.20.0/cyclopts/parameter.py 
new/cyclopts-4.21.0/cyclopts/parameter.py
--- old/cyclopts-4.20.0/cyclopts/parameter.py   2020-02-02 01:00:00.000000000 
+0100
+++ new/cyclopts-4.21.0/cyclopts/parameter.py   2020-02-02 01:00:00.000000000 
+0100
@@ -237,6 +237,13 @@
         kw_only=True,
     )
 
+    # This can ONLY ever be a Tuple[str, ...]
+    negative_alias: None | str | Iterable[str] = field(
+        default=None,
+        converter=_str_tuple_converter,
+        kw_only=True,
+    )
+
     # This can ONLY ever be a Tuple[Union[Group, str], ...]
     group: None | Group | str | Iterable[Group | str] = field(
         default=None,
@@ -419,7 +426,7 @@
                 (out if negative.startswith("-") else 
user_negatives).append(negative)
 
             if not user_negatives:
-                return tuple(out)
+                return self._extend_negative_aliases(out)
 
         assert isinstance(self.name, tuple)
         for name in self.name:
@@ -445,7 +452,20 @@
             else:
                 for negative in user_negatives:
                     out.append(f"--{name_prefix}{negative}")
-        return tuple(out)
+        return self._extend_negative_aliases(out)
+
+    def _extend_negative_aliases(self, negatives: list[str]) -> tuple[str, 
...]:
+        """Append :attr:`negative_alias` entries to the computed negative 
names.
+
+        Unlike :attr:`negative` (which *replaces* the generated negative 
names),
+        aliases are additive — mirroring the :attr:`name`/:attr:`alias`
+        relationship for positive names.
+        """
+        assert isinstance(self.negative_alias, tuple)
+        for negative_alias in self.negative_alias:
+            if negative_alias not in negatives:
+                negatives.append(negative_alias)
+        return tuple(negatives)
 
     def __repr__(self):
         """Only shows non-default values."""

Reply via email to