[issue45755] Specialized generic class does not return class attributes in dir

2021-12-17 Thread miss-islington


miss-islington  added the comment:


New changeset 87539cc716fab47cd4f501f2441c4ab8e80bce6f by Miss Islington (bot) 
in branch '3.10':
bpo-45755: [typing] Reveal class attributes of generic in generic aliases in 
`dir()` (GH-29962)
https://github.com/python/cpython/commit/87539cc716fab47cd4f501f2441c4ab8e80bce6f


--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue45755] Specialized generic class does not return class attributes in dir

2021-12-17 Thread miss-islington


Change by miss-islington :


--
nosy: +miss-islington
nosy_count: 4.0 -> 5.0
pull_requests: +28383
pull_request: https://github.com/python/cpython/pull/30166

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue45755] Specialized generic class does not return class attributes in dir

2021-12-16 Thread Guido van Rossum


Guido van Rossum  added the comment:

I think a 3.10 backport would be appreciated.

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue45755] Specialized generic class does not return class attributes in dir

2021-12-16 Thread Ken Jin


Ken Jin  added the comment:

Hi, I won't be backporting this to 3.9 since I don't like having jarring 
behavior changes so late into the bugfix cycle of a Python version.

I'm tempted to backport to 3.10. For now, I'll be conservative and just merge 
it in main. Please do tell me if any of you feel that I should backport to 3.10 
too.

3.6-3.8 are in security-fix only mode so they won't get any bugfixes.

Thanks Kevin for the interesting bug report, and Karthikeyan for saving me a 
ton of time debugging this!

--
resolution:  -> fixed
stage: patch review -> resolved
status: open -> closed

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue45755] Specialized generic class does not return class attributes in dir

2021-12-16 Thread Ken Jin


Ken Jin  added the comment:


New changeset d6e13747161d7b634b47d2d3d212ed3be4a21fab by Ken Jin in branch 
'main':
bpo-45755: [typing] Reveal class attributes of generic in generic aliases in 
`dir()` (GH-29962)
https://github.com/python/cpython/commit/d6e13747161d7b634b47d2d3d212ed3be4a21fab


--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue45755] Specialized generic class does not return class attributes in dir

2021-12-07 Thread Ken Jin


Change by Ken Jin :


--
keywords: +patch
pull_requests: +28187
stage:  -> patch review
pull_request: https://github.com/python/cpython/pull/29962

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue45755] Specialized generic class does not return class attributes in dir

2021-12-06 Thread Ken Jin


Ken Jin  added the comment:

Not exactly sure if this is a bug, but the reason is that Foo[int] used to be a 
class, now it's a plain object. It's a change brought in 3.7 by PEP 560.

3.6:
>>> isinstance(Foo[int], type)
True
>>> Foo[int].__dir__
>> type(Foo[int].__dir__)


main:
>>> isinstance(Foo[int], type)
False
>>> Foo[int].__dir__

>>> type(Foo[int].__dir__)


The fix is just a 2-line change in either _GenericAlias or _BaseGenericAlias:
+def __dir__(self):
+return dir(self.__origin__)

Should we go ahead with this?

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue45755] Specialized generic class does not return class attributes in dir

2021-11-13 Thread Guido van Rossum

Guido van Rossum  added the comment:

Isn’t the solution to use the unspecialized class?

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue45755] Specialized generic class does not return class attributes in dir

2021-11-12 Thread Karthikeyan Singaravelan


Karthikeyan Singaravelan  added the comment:

This seems to be an issue with typing than mock since mock just uses the output 
from dir() . I am not able to bisect the relevant change but below is the 
output of dir(Foo[int]) in Python 3.6 and master.

Python 3.6.9

['__abstractmethods__', '__args__', '__class__', '__delattr__', '__dict__', 
'__dir__', '__doc__', '__eq__', '__extra__', '__format__', '__ge__', 
'__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', 
'__le__', '__lt__', '__module__', '__ne__', '__new__', '__next_in_mro__', 
'__orig_bases__', '__origin__', '__parameters__', '__reduce__', 
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', 
'__str__', '__subclasshook__', '__tree_hash__', '__weakref__', '_abc_cache', 
'_abc_generic_negative_cache', '_abc_generic_negative_cache_version', 
'_abc_registry', '_gorg', 'bar']


master branch : 

['__args__', '__call__', '__class__', '__delattr__', '__dict__', '__dir__', 
'__doc__', '__eq__', '__format__', '__ge__', '__getattr__', '__getattribute__', 
'__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', 
'__instancecheck__', '__le__', '__lt__', '__module__', '__mro_entries__', 
'__ne__', '__new__', '__or__', '__origin__', '__parameters__', '__reduce__', 
'__reduce_ex__', '__repr__', '__ror__', '__setattr__', '__sizeof__', 
'__slots__', '__str__', '__subclasscheck__', '__subclasshook__', '__weakref__', 
'_inst', '_name', '_paramspec_tvars', '_typevar_types', 'copy_with']

--
nosy: +gvanrossum, kj
title: Mock spec with a specialized generic class does not mock class 
attributes -> Specialized generic class does not return class attributes in dir

___
Python tracker 
<https://bugs.python.org/issue45755>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



Return class.

2014-07-26 Thread Satish ML
Hi,

What does return Wrapper do in the following piece of code? Which method does 
it invoke?
I mean return Wrapper invokes __init__ method?

def Tracer(aClass):
class Wrapper:
def __init__(self, *args, **kargs):
self.fetches = 0
self.wrapped = aClass(*args, **kargs)
def __getattr__(self, attrname):
print('Trace: ' + attrname)
self.fetches += 1
print(self.fetches)
return getattr(self.wrapped, attrname)
return Wrapper


Actual program:

def Tracer(aClass):
class Wrapper:
def __init__(self, *args, **kargs):
self.fetches = 0
self.wrapped = aClass(*args, **kargs)
def __getattr__(self, attrname):
print('Trace: ' + attrname)
self.fetches += 1
print(self.fetches)
return getattr(self.wrapped, attrname)
return Wrapper
@Tracer
class Spam:
def __init__(self, *args):
print(*args)
def display(self):
print('Spam!' * 8)

@Tracer
class Person:
def __init__(self, name, hours, rate):
self.name = name
self.hours = hours
self.rate = rate
def pay(self):
return self.hours * self.rate

food = Spam(CARST)
food.display()
print([food.fetches])

bob = Person('Bob', 40, 50)
print(bob.name)
print(bob.pay())

print('')
sue = Person('Sue', rate=100, hours=60)
print(sue.name)
print(sue.pay())

print(bob.name)
print(bob.pay())
print([bob.fetches, sue.fetches])
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Return class.

2014-07-26 Thread Chris Angelico
On Sun, Jul 27, 2014 at 4:29 AM, Satish ML satishmlwiz...@gmail.com wrote:
 What does return Wrapper do in the following piece of code? Which method 
 does it invoke?
 I mean return Wrapper invokes __init__ method?

 def Tracer(aClass):
 class Wrapper:
 def __init__(self, *args, **kargs):
 self.fetches = 0
 self.wrapped = aClass(*args, **kargs)
 def __getattr__(self, attrname):
 print('Trace: ' + attrname)
 self.fetches += 1
 print(self.fetches)
 return getattr(self.wrapped, attrname)
 return Wrapper


It doesn't invoke anything. It returns the class itself - a callable,
subclassable thing, which wraps the passed-in class. When it's used as
a decorator, what happens is that first the basic class gets
constructed, then it gets passed to this function, and whatever this
function returns becomes the resulting class. So, taking the simplest
example:

@Tracer
class Spam:
def __init__(self, *args):
print(*args)
def display(self):
print('Spam!' * 8)

This is like doing this:

class Spam:
def __init__(self, *args):
print(*args)
def display(self):
print('Spam!' * 8)
Spam = Tracer(Spam)

And then Tracer begins executing, with the Spam class as aClass. It
constructs a new class with two methods: an __init__ which passes
everything through to the wrapped class and retains the resulting
object, and a __getattr__ which proxies through to the original with
tracing facilities.

But all it does is construct and return that class. It doesn't call
anything, yet. Calling the class (instantiating an object of it)
happens when the Spam(CARST) call happens; instead of calling the
original Spam class, it calls the special wrapper, which then calls on
the original.

You can look up class decorators in the Python docs; they're not
something you'll use often (and they're something you'll write even
less often), but they can give you a lot of flexibility.

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


Re: Return class.

2014-07-26 Thread Satish ML
Which line of code is printing [4] and [4, 5, 6, 7] in the output?

from tracer import Tracer
@Tracer
class MyList(list):
def __init__(self, *args):
print(INSIDE MyList)
print(*args)
x = MyList([1, 2, 3])
x.append(4)
print(x.wrapped)
WrapList = Tracer(list)
x = WrapList([4, 5, 6])
x.append(7)
print(x.wrapped)

OUTPUT:

CARST
Trace: display
1
Spam!Spam!Spam!Spam!Spam!Spam!Spam!Spam!
[1]
Trace: name
1
Bob
Trace: pay
2
2000

Trace: name
1
Sue
Trace: pay
2
6000
Trace: name
3
Bob
Trace: pay
4
2000
[4, 2]
INSIDE MyList
[1, 2, 3]
Trace: append
1
[4]
Trace: append
1
[4, 5, 6, 7]
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Return class.

2014-07-26 Thread Satish ML
Which line of code is printing [4] and [4, 5, 6, 7] in the output?

from tracer import Tracer
@Tracer
class MyList(list):
def __init__(self, *args):
print(INSIDE MyList)
print(*args)
x = MyList([1, 2, 3])
x.append(4)
print(x.wrapped)
WrapList = Tracer(list)
x = WrapList([4, 5, 6])
x.append(7)
print(x.wrapped)

OUTPUT:

CARST
Trace: display
1
Spam!Spam!Spam!Spam!Spam!Spam!Spam!Spam!
[1]
Trace: name
1
Bob
Trace: pay
2
2000

Trace: name
1
Sue
Trace: pay
2
6000
Trace: name
3
Bob
Trace: pay
4
2000
[4, 2]
INSIDE MyList
[1, 2, 3]
Trace: append
1
[4]
Trace: append
1
[4, 5, 6, 7]
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Return class.

2014-07-26 Thread Satish ML
Which line of code is printing [4] and [4, 5, 6, 7] in the output?

from tracer import Tracer
@Tracer
class MyList(list):
def __init__(self, *args):
print(INSIDE MyList)
print(*args)
x = MyList([1, 2, 3])
x.append(4)
print(x.wrapped)
WrapList = Tracer(list)
x = WrapList([4, 5, 6])
x.append(7)
print(x.wrapped)

OUTPUT:

CARST
Trace: display
1
Spam!Spam!Spam!Spam!Spam!Spam!Spam!Spam!
[1]
Trace: name
1
Bob
Trace: pay
2
2000

Trace: name
1
Sue
Trace: pay
2
6000
Trace: name
3
Bob
Trace: pay
4
2000
[4, 2]
INSIDE MyList
[1, 2, 3]
Trace: append
1
[4]
Trace: append
1
[4, 5, 6, 7]
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Return class.

2014-07-26 Thread Chris Angelico
On Sun, Jul 27, 2014 at 5:04 AM, Satish ML satishmlwiz...@gmail.com wrote:
 Which line of code is printing [4] and [4, 5, 6, 7] in the output?

These lines:

 print(x.wrapped)

The .wrapped attribute has the wrapped object, so you're printing out
the thing that would be in x if you weren't using the decorator. Since
that's a subclass of list and doesn't change __str__ or __repr__, it
prints out like a list.

Tip: If you're not sure what line produces what output, tag them all.
Instead of print(x.wrapped), put print(1,x.wrapped), and have a
different number on every line of output. Then you'll easily see which
is which.

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


Re: Return class.

2014-07-26 Thread Satish ML
Actual program: 

def Tracer(aClass): 
class Wrapper: 
def __init__(self, *args, **kargs): 
self.fetches = 0 
self.wrapped = aClass(*args, **kargs) 
def __getattr__(self, attrname): 
print('Trace: ' + attrname) 
self.fetches += 1 
print(self.fetches) 
return getattr(self.wrapped, attrname) 
return Wrapper 
@Tracer 
class Spam: 
def __init__(self, *args): 
print(*args) 
def display(self): 
print('Spam!' * 8) 

@Tracer 
class Person: 
def __init__(self, name, hours, rate): 
self.name = name 
self.hours = hours 
self.rate = rate 
def pay(self): 
return self.hours * self.rate 

food = Spam(CARST) 
food.display() 
print([food.fetches]) 

bob = Person('Bob', 40, 50) 
print(bob.name) 
print(bob.pay()) 

print('') 
sue = Person('Sue', rate=100, hours=60) 
print(sue.name) 
print(sue.pay()) 

print(bob.name) 
print(bob.pay()) 
print([bob.fetches, sue.fetches]) 


Which line of code is printing [4] and [4, 5, 6, 7] in the output? 
Another module.
from tracer import Tracer 
@Tracer 
class MyList(list): 
def __init__(self, *args): 
print(INSIDE MyList) 
print(*args) 
x = MyList([1, 2, 3]) 
x.append(4) 
print(x.wrapped) 
WrapList = Tracer(list) 
x = WrapList([4, 5, 6]) 
x.append(7) 
print(x.wrapped) 

OUTPUT: 

CARST 
Trace: display 
1 
Spam!Spam!Spam!Spam!Spam!Spam!Spam!Spam! 
[1] 
Trace: name 
1 
Bob 
Trace: pay 
2 
2000 

Trace: name 
1 
Sue 
Trace: pay 
2 
6000 
Trace: name 
3 
Bob 
Trace: pay 
4 
2000 
[4, 2] 
INSIDE MyList 
[1, 2, 3] 
Trace: append 
1 
[4] 
Trace: append 
1 
[4, 5, 6, 7] 
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Return class.

2014-07-26 Thread Satish ML
Hi,

Which lines of code prints [4] and [4, 5, 6, 7] in the output?


Output:

CARST
Trace: display
1
Spam!Spam!Spam!Spam!Spam!Spam!Spam!Spam!
[1]
Trace: name
1
Bob
Trace: pay
2
2000

Trace: name
1
Sue
Trace: pay
2
6000
Trace: name
3
Bob
Trace: pay
4
2000
[4, 2]
INSIDE MyList
[1, 2, 3]
Trace: append
1
[4]
Trace: append
1
[4, 5, 6, 7]

Actual Code:
def Tracer(aClass):
class Wrapper:
def __init__(self, *args, **kargs):
self.fetches = 0
self.wrapped = aClass(*args, **kargs)
def __getattr__(self, attrname):
print('Trace: ' + attrname)
self.fetches += 1
print(self.fetches)
return getattr(self.wrapped, attrname)
return Wrapper
@Tracer
class Spam:
def __init__(self, *args):
print(*args)
def display(self):
print('Spam!' * 8)

@Tracer
class Person:
def __init__(self, name, hours, rate):
self.name = name
self.hours = hours
self.rate = rate
def pay(self):
return self.hours * self.rate

food = Spam(CARST)
food.display()
print([food.fetches])

bob = Person('Bob', 40, 50)
print(bob.name)
print(bob.pay())

print('')
sue = Person('Sue', rate=100, hours=60)
print(sue.name)
print(sue.pay())


Another module that is producing output:

from tracer import Tracer
@Tracer
class MyList(list):
def __init__(self, *args):
print(INSIDE MyList)
print(*args)
  
x = MyList([1, 2, 3])
x.append(4)
print(x.wrapped)
WrapList = Tracer(list)
x = WrapList([4, 5, 6])
x.append(7)
print(x.wrapped)
-- 
https://mail.python.org/mailman/listinfo/python-list