Skip to content

Commit 112dd1d

Browse files
authored
Expose effective class construction properties (#1454)
* Implement _AttrsParams ref #602 * Set __attrs_base_of_slotted__ for unused base classes * Rename to ClassProps This reflects that the instance is NOT just the parameters as passed to the decorator, but how the class is actually constructed. * Start renaming fields so it's clearer these aren't just arguments * Reorder * Dont's expose has_custom_setattr * Make KeywordOnly an Enum And make Hashability public * Make cache_hash part of the Hashability Enum * Add attrs.inspect() * Refactor enums into class since they're only used by that class * Docs * Move back, rip out type hints * Revert "Move back, rip out type hints" This reverts commit 84bb6da. * Use internal mechanisms instead of NamedTuple Mostly to prevent Mypy from looking at our code, but sadly it wasn't enough courtesy of enums for some reason. * Add news fragment * Document it's experimental * Improve ClassProps documentation * Add type information to docs * Improve field names To make it clearer these are derived values and nothing you can pass into define/attr.s * Avoid repeated attribute lookups * More more helpful field names * Add warning to class too * Add explanation * Add to changelog, too * Nicer phrasing * Grammar * docs * Consistency * Make inspect/ClassProps NG-only * Remove stray empty line * Don't half-ass next_gen-ing _funcs is terribly generic too * Avoid attribute lookups in hot loop * Add field access type tests * A docstring is not appropriate here * Move typing example to baseline
1 parent 4737f0e commit 112dd1d

File tree

11 files changed

+665
-139
lines changed

11 files changed

+665
-139
lines changed

changelog.d/1454.change.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Added a new **experimental** way to inspect classes:
2+
3+
`attrs.inspect(cls)` returns the _effective_ class-wide parameters that were used by *attrs* to construct the class.
4+
5+
The returned class is the same data structure that *attrs* uses internally to decide how to construct the final class.

docs/api.rst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,24 @@ Helpers
190190
>>> attrs.has(object)
191191
False
192192

193+
.. autofunction:: attrs.inspect
194+
195+
For example:
196+
197+
.. doctest::
198+
199+
>>> @define
200+
... class CInspect:
201+
... pass
202+
>>> attrs.inspect(CInspect) # doctest: +ELLIPSIS
203+
ClassProps(is_exception=False, is_slotted=True, has_weakref_slot=True, is_frozen=False, kw_only=<KeywordOnly.NO: 'no'>, collected_fields_by_mro=True, added_init=True, added_repr=True, added_eq=True, added_ordering=False, hashability=<Hashability.UNHASHABLE: 'unhashable'>, added_match_args=True, added_str=False, added_pickling=True, on_setattr_hook=<function pipe.<locals>.wrapped_pipe at ...>, field_transformer=None)
204+
205+
.. autoclass:: attrs.ClassProps
206+
.. autoclass:: attrs.ClassProps.Hashability
207+
:members: HASHABLE, HASHABLE_CACHED, UNHASHABLE, LEAVE_ALONE
208+
.. autoclass:: attrs.ClassProps.KeywordOnly
209+
:members: NO, YES, FORCE
210+
193211
.. autofunction:: attrs.resolve_types
194212

195213
For example:

docs/how-does-it-work.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ No magic, no meta programming, no expensive introspection at runtime.
3939
Everything until this point happens exactly *once* when the class is defined.
4040
As soon as a class is done, it's done.
4141
And it's just a regular Python class like any other, except for a single `__attrs_attrs__` attribute that *attrs* uses internally.
42-
Much of the information is accessible via {func}`attrs.fields` and other functions which can be used for introspection or for writing your own tools and decorators on top of *attrs* (like {func}`attrs.asdict`).
42+
Much of the information is accessible via {func}`attrs.inspect`, {func}`attrs.fields` and other functions which can be used for introspection or for writing your own tools and decorators on top of *attrs* (like {func}`attrs.asdict`).
4343

4444
And once you start instantiating your classes, *attrs* is out of your way completely.
4545

0 commit comments

Comments
 (0)