Getty fully qualified class name from class object

2023-08-22 Thread Ian Pilcher via Python-list

How can I programmatically get the fully qualified name of a class from
its class object?  (I'm referring to the name that is shown when str()
or repr() is called on the class object.)

Neither the __name__ or __qualname__ class attributes include the
module.  For example:

  >>> import logging

  >>> str(logging.Handler)
  ""

  >>> logging.Handler.__name__
  'Handler'
  >>> logging.Handler.__qualname__
  'Handler'

How can I programmatically get 'logging.Handler' from the class object?

--

Google  Where SkyNet meets Idiocracy

--
https://mail.python.org/mailman/listinfo/python-list


Re: Getty fully qualified class name from class object

2023-08-23 Thread Ian Pilcher via Python-list

On 8/22/23 11:13, Greg Ewing via Python-list wrote:

Classes have a __module__ attribute:

 >>> logging.Handler.__module__
'logging'


Not sure why I didn't think to look for such a thing.  Looks like it's
as simple as f'{cls.__module__}.{cls.__qualname__}'.

Thanks!

--

Google  Where SkyNet meets Idiocracy


--
https://mail.python.org/mailman/listinfo/python-list


Re: Struggling to understand Callable type hinting

2025-01-18 Thread Ian Pilcher via Python-list

(Note:  I have mail delivery disabled for this list and read it through
GMane, so I am unable to respond with correct threading if I'm not cc'ed
directly.)

On 1/17/25 7:26 PM, dn via Python-list wrote:

On 18/01/25 12:33, Ian Pilcher via Python-list wrote:

I am making my first attempt to use type hinting in a new project, and
I'm quickly hitting areas that I'm having trouble understanding.  One of
them is how to write type hints for a method decorator.

Here is an example that illustrates my confusion.  (Sorry for the
length.)


import collections.abc

class BufferScanner(object):


...


 @staticmethod
 def _check_eof(method: collections.abc.Callable -> (
 collections.abc.Callable
 ):

...


I cannot figure out how to correctly specify the Callable argument and
return type for _check_eof().  As indicated by the name, method should
be a method (of the BufferScanner class), so its first positional
argument should always be an instance of BufferScanner, but it could
have any combination of positional and/or keyword arguments after that.


Is it a typing problem?
The def is not syntactically-correct (parentheses).


Yes, but only when I re-typed it in my email client to avoid word-
wrapping issues.


What happens once corrected?


Once the missing parenthesis is added, the version in my original post
works just fine, but it's incomplete, because the Callables aren't
parameterized.

Based on what I've read, I would expect to be able to replace:

@staticmethod
def _check_eof(method: collections.abc.Callable) -> (
collections.abc.Callable
):
...

with something like this:

@staticmethod
def _check_eof(
method: collections.abc.Callable[[BufferScanner, ...], None]
) -> (
collections.abc.Callable[[BufferScanner, ...], bool]
):
...

But Mypy gives me a bunch of errors when I do that.

bs.py:19: error: Unexpected "..."  [misc]
bs.py:21: error: Unexpected "..."  [misc]
bs.py:32: error: Argument 1 to "_check_eof" of "BufferScanner" has
  incompatible type "Callable[[BufferScanner], None]"; expected
  "Callable[[BufferScanner, Any], None]"  [arg-type]
Found 3 errors in 1 file (checked 1 source file)

(And even that wouldn't really be correct, if it worked, because it
doesn't express the fact that the arguments of the two Callables are the
same.  I believe that ParamSpecs are supposed to address this, but there
doesn't seem to be any way to use a ParamSpec when one or more of the
parameter types is known.


Also, which tool is 'complaining', and what does it have to say?


Mypy 1.14.1.


General comment: as far as type-hints go, rather than trying to learn 
how to deal with complex situations, it might be better to ease-in 
gradually - add the easy stuff now, and come back to deal with the rest 
later (otherwise the typing 'tail' is wagging the coding 'dog'!)


Makes sense ... except that this decorator is what motivated me to use
type hinting in this project in the first place.

--

If your user interface is intuitive in retrospect ... it isn't intuitive


--
https://mail.python.org/mailman/listinfo/python-list


[SOLVED] Struggling to understand Callable type hinting

2025-01-18 Thread Ian Pilcher via Python-list

(Note:  I have mail delivery disabled for this list and read it through
GMane, so I am unable to respond with correct threading if I'm not cc'ed
directly.)

On 1/18/25 8:52 AM, Ian Pilcher wrote:

(And even that wouldn't really be correct, if it worked, because it
doesn't express the fact that the arguments of the two Callables are the
same.  I believe that ParamSpecs are supposed to address this, but there
doesn't seem to be any way to use a ParamSpec when one or more of the
parameter types is known.


I think that I figured it out.

__P = typing.ParamSpec('__P')

@staticmethod
def _check_eof(
method: collections.abc.Callable[
typing.Concatenate[BufferScanner, __P], None
]
) -> (
collections.abc.Callable[
typing.Concatenate[BufferScanner, __P], bool
]
):
...

Mypy is happy, and it catches me if I try to use the decorator on some-
thing that isn't a method of BufferScanner (or some other callable that
takes an instance of BufferScanner as its first positional argument).

--

If your user interface is intuitive in retrospect ... it isn't intuitive

--
https://mail.python.org/mailman/listinfo/python-list


Struggling to understand Callable type hinting

2025-01-17 Thread Ian Pilcher via Python-list

I am making my first attempt to use type hinting in a new project, and
I'm quickly hitting areas that I'm having trouble understanding.  One of
them is how to write type hints for a method decorator.

Here is an example that illustrates my confusion.  (Sorry for the
length.)


import collections.abc

class BufferScanner(object):

def __init__(self, buf: str) -> None:
self._buffer = buf
self._index = 0
self._eof = False
self._line = 1
self._column = 1

@property
def eof(self) -> bool:
return self._eof

@staticmethod
def _check_eof(method: collections.abc.Callable -> (
collections.abc.Callable
):
def wrapper(*args, **kwargs):
self = args[0]
if not self._eof:
method(*args, **kwargs)
if self._index >= len(self._buffer):
self._eof = True
return self._eof
return wrapper

@_check_eof
def next_line(self) -> None:
"""Advance the scanner to the beginning of the next line."""
try:
i = self._buffer.index('\n', self._index)
except ValueError:
self._index = len(self._buffer)  # decorator will set _eof
return
self._index = i + 1  # move past the newline
self._line += 1
self._column = 1


I cannot figure out how to correctly specify the Callable argument and
return type for _check_eof().  As indicated by the name, method should
be a method (of the BufferScanner class), so its first positional
argument should always be an instance of BufferScanner, but it could
have any combination of positional and/or keyword arguments after that.

I've read the TypeVar and ParamSpec documentation, and me head is
spinning, but neither one really seems to help with this situation.

Any pointers to good resources or the correct way to do this are
appreciated.

Thanks!

--

If your user interface is intuitive in retrospect ... it isn't intuitive


--
https://mail.python.org/mailman/listinfo/python-list


Any way to "subclass" typing.Annotated?

2025-01-28 Thread Ian Pilcher via Python-list

(Note:  I have mail delivery disabled for this list and read it through
GMane.  Please copy me on any responses, so that I can respond with
proper threading.)

From the things that I probably shouldn't spend my free time on
department ...

As background, I'm working on a project that is going to involve a bunch
of abstract classes and dynamic types, and I've found that Python's
existing abstract class implementation leaves a lot to be desired,
particularly the inability to create abstract class variables and class
methods.  Having been seduced by the Siren song of Python's flexibility,
I've been rolling my own implementation.

Now to my question.

I'm currently using annotations to create abstract class variables, for
example:

  class Foo(object, metaclass=AbstractType):

  acv: Annotated[int, abstract]

('abstract' is simply a unique "flag" object.)

This works just fine, but it's somewhat un-idiomatic.  What I'd like to
be able to do is create my own type, so that I could do something like
this:

  class Foo(object, metaclass=AbstractType):

  acv: AbstractClassVariable[int]

Essentially I'd like to create "subclass" of typing.Annotated that
always sets the metadata to 'abstract'.  Thus far, I haven't found a
way to do this, as typing.Annotated can't be subclassed.

Anyone have any ideas?

--

If your user interface is intuitive in retrospect ... it isn't intuitive


--
https://mail.python.org/mailman/listinfo/python-list