Metadata-Version: 2.4
Name: pynameof
Version: 0.1.0
Summary: Retrieve the name of classes, functions, and properties.
Keywords: pynameof,nameof,name
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: 3 :: Only
Requires-Python: >=3.14
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: docs
Requires-Dist: pydata_sphinx_theme; extra == "docs"
Requires-Dist: setuptools; extra == "docs"
Requires-Dist: setuptools_scm; extra == "docs"
Dynamic: license-file

# pynameof

## Installation

```pip install pynameof```

## What it is and basic usage

This package allows you to retrieve the name of entities such as types, properties, and methods. Any object declaring 
`__module__` and `__qualname__`, `__qualname__` on its own, or `__name__` gets resolved to a name. Its main purpose is 
to simplify writing error messages and other forms of user interaction (see below).

The package, for now, declares two methods which are called in a straightforward way:

```python
from pynameof import nameof, typename_of

print(nameof(str))  # prints 'str'
print(typename_of(1))  # prints 'int'
```

`nameof` returns the name of the supplied object, `typename_of` resolves the type of the object and returns its name
instead.

`nameof` additionally supports a fallback to be called if the object is not named via any of the above combinations. For
example, you can write

```python
from pynameof import nameof, typename_of

print(nameof(1, repr))  # prints '1'
```

Since `1` does not declare neither `__module__`, `__qualname__`, nor `__name__`, `nameof` falls back to `repr`.

By default, `nameof` and `typename_of` strip the module names `'builtins'` and `'__main__'`. You can deactivate this 
behavior using the respective `strip_builtins` and `strip_main` parameters. The values of the two parameters are `True`
by default, unless `strip_modules` is set to a value. `strip_modules` allows indicating a filtering callback or a single
module or iterable of strings to strip. Note that, in this case, `strip_builtins` and `strip_main` are set to `False` by
default. You must explicitly set them to `True` or filter them manually.

## Suggested usage

This package is of particular use when we want to print references to objects. As you probably know, the default
representation of types and properties in Python is not the way we actually write it in code - for property objects,
it is not even visible right away, what property was meant.

```python
class X:
    @property
    def x(self) -> int: ...


print(X)  # prints "<class '[...].X'>"
print(X.x)  # prints '<property object at 0x[...]>'
```

For example, when reporting type errors, we want to inform the user about the actual type that was expected. In such a 
case, it is natural to refer to the type with an explicit reference to the type rather than writing the full path 
manually. This is particularly relevant when we refactor code: The module or name of the class may change, but your IDE
will probably fix the imports for you while it does not recognize references inside strings properly in some cases.
For example, consider renaming `X` in the following example:

```python
from pynameof import nameof


class X:
    def __init__(self, x: int) -> None:
        self._x = x

    @property
    def x(self) -> int:
        return self._x


def some_method(value: X) -> None:
    if not isinstance(value, X):
        raise TypeError(f'Expected an instance of type `{nameof(X)}` for parameter `value`.')

    if value.x < 0:
        raise ValueError(f'`{nameof(some_method)}` expects that `{nameof(X.x)}` is non-negative.')
```

Sadly, for parameters, such as, ``` `value` ```, this is not possible, since we receive a value that does not declare 
the name of its  parameter. `nameof` only works since we call it on the member definition itself rather than on the 
value assigned in a specific instance. Note that we also referred to `X.x`, not to `value.x` for the same reason: The
property defines a function providing `__module__` and a `__qualname__` attributes.
