[issue4331] Add functools.partialmethod
alon horev added the comment: I've changed the test according to the code review. Thanks -- Added file: http://bugs.python.org/file32409/4331.v2.patch ___ Python tracker <http://bugs.python.org/issue4331> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue4331] Add functools.partialmethod
alon horev added the comment: Adding a patch with tests and documentation. Please feel free to comment on anything: my English, coding/testing style. I'm pretty sure the documentation can be better but it turns out I speak better Python than English. Two decisions I've made and unsure of: 1. I didn't use @wraps or copied attributes from the wrapped function (__doc__, __dict__) to the partialmethod object. This is intentionally so partial and partialmethod would have similar semantics. 2. I've implemented a __repr__ although in all cases __get__ returns a partial object or bound method. I consider it nice for debugging when looking at an object's __dict__. -- Added file: http://bugs.python.org/file32405/4331.v1.patch ___ Python tracker <http://bugs.python.org/issue4331> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue4331] Add functools.partialmethod
alon horev added the comment: I think the following test demonstrates the API we're looking for. 1. Am I missing any functionality? 2. How does partialmethod relate to @absolutemethod? from functools import partial class partialmethod(object): def __init__(self, func, *args, **keywords): # func could be a descriptor like classmethod which isn't callable, # so we can't inherit from partial (it verifies func is callable) if isinstance(func, partialmethod): # flattening is mandatory in order to place cls/self before all other arguments # it's also more efficient since only one function will be called self.func = func.func self.args = func.args + args self.keywords = {} self.keywords.update(func.keywords) self.keywords.update(keywords) else: self.func = func self.args = args self.keywords = keywords def _make_unbound_method(self): def _method(*args, **keywords): keywords.update(self.keywords) cls_or_self, *rest = args call_args = (cls_or_self,) + self.args + tuple(rest) return self.func(*call_args, **keywords) return _method def __get__(self, obj, cls): get = getattr(self.func, "__get__", None) if get is None: if obj is None: return self._make_unbound_method() return partial(self._make_unbound_method(), obj) # returns a bound method else: callable = get(obj, cls) if callable is self.func: return self._make_unbound_method() return partial(callable, *self.args, **self.keywords) class A(object): def add(self, x, y): return self, x + y add10 = partialmethod(add, 10) add10class = partialmethod(classmethod(add), 10) add10static = partialmethod(staticmethod(add), 'self', 10) return15 = partialmethod(add10, 5) # nested partialmethod add2partial = partial(add, x=2) return12 = partialmethod(add2partial, y=10) # partialmethod over partial def test(): cls = A instance = cls() assert instance.add10class(5) == (cls, 15) assert cls.add10class(5) == (cls, 15) assert instance.add10static(5) == ('self', 15) assert cls.add10static(5) == ('self', 15) assert instance.add10(5) == (instance, 15) assert cls.add10(instance, 5) == (instance, 15) assert instance.return15() == (instance, 15) assert cls.return15(instance) == (instance, 15) assert instance.return12() == (instance, 12) assert cls.return12(instance) == (instance, 12) test() -- ___ Python tracker <http://bugs.python.org/issue4331> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue4331] Add functools.partialmethod
alon horev added the comment: Here's another attempt at a consistent api with regular methods. I'm contemplating whether partialmethod should support __call__. Given the fact partial is used to bind positional arguments, it will do the 'wrong' thing when calling the partialmethod directly and will shift all positional arguments (example at the last line of the snippet). I also think staticmethod in this context is useless but agree consistency is a thing (you could just use partial instead). If consistency hadn't held us back, the first proposal of partialmethod, working both for instances and classes, would have been most elegant. from functools import partial class partialmethod(object): def __init__(self, func, *args, **keywords): self.func = func self.args = args self.keywords = keywords def __call__(self, *args, **keywords): call_keywords = {} call_keywords.update(self.keywords) call_keywords.update(keywords) return self.func(*(self.args + args), **call_keywords) def __get__(self, obj, cls): return partial(self.func.__get__(obj, cls), *self.args, **self.keywords) class A(object): def add(self, x, y): print(self) return x + y add10 = partialmethod(add, 10) add10class = partialmethod(classmethod(add), 10) add10static = partialmethod(staticmethod(add), 'self', 10) assert A().add10(5) == 15 # prints <__main__.A object at 0x1097e1390> assert A.add10class(5) == 15 # prints assert A.add10static(5) == 15 # prints self assert A.add10(2, 3) == 5 # prints 10 because the first positional argument is self.. Once we approve of the API I'll provide a full fledged patch. -- ___ Python tracker <http://bugs.python.org/issue4331> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue4331] Add functools.partialmethod
alon horev added the comment: I just want to make sure I understand the semantics concerning class methods, the following example demonstrates a usage similar to regular methods as much as possible: class A(object): def add(self, x, y): print(self) return x + y add10 = partialmethod(add, 10) add10class = classmethod(partialmethod(add, 10)) assert A().add10(5) == 15 # prints <__main__.A object at 0x1097e1390> assert A.add10class(5) == 15 # prints Another option would be to return a class-bound partial from the __get__ method. It's not as consistent as the first example but perhaps nicer: class A(object): def add(self, x, y): print(self) return x + y add10 = partialmethod(add, 10) assert A().add10(5) == 15 # prints <__main__.A object at 0x1097e1390> assert A.add10(5) == 15 # prints Is the first option what you had in mind? -- nosy: +alonho ___ Python tracker <http://bugs.python.org/issue4331> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue19080] Enrich SyntaxError with additional information
New submission from alon horev: Some context for this feature request: I'm using the wonderful ast module for a library that translates python code to MongoDB queries (https://github.com/alonho/pql). I also did the same for SQL queries using sqlalchemy as a part of another project (https://github.com/alonho/pytrace). One of the things I find lacking in python's parser is additional information about SyntaxErrors. This could help users of the 'ast' module, IDE and developers. Here are some examples of what I'd like to see 1. ast.parse('* 2') -> SyntaxError('Unexpected operator at start of an expression') 2. ast.parse('2 *') -> SyntaxError('Missing right hand side operand') 3. ast.parse('if a = 1: pass') -> SyntaxError('Cannot assign inside an expression') There are several challenges here: 1. Does the parser have this information and doesn't surface it? 2. Can such messages be automatically generated without filling the code with error handling code? 3. Which part of the code could be responsible for this kind of a task? I've looked at the BNF and it contains more than just syntax legality but operator precedence and such. Perhaps there's another (simpler) grammar definition somewhere? I was curious to see what Ruby does, and it uses a simple solution of providing raw information along with the exception: >> a == * 1 SyntaxError: compile error (irb):17: syntax error, unexpected tSTAR a == * 1 ^ from (irb):17 -- components: Interpreter Core messages: 198341 nosy: alonho priority: normal severity: normal status: open title: Enrich SyntaxError with additional information type: enhancement ___ Python tracker <http://bugs.python.org/issue19080> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue7317] Display full tracebacks when an error occurs asynchronously
alon horev added the comment: Hi Antoine, can you please have a look at the patch? It's been over a year since it's submitted. (-: thanks! -- ___ Python tracker <http://bugs.python.org/issue7317> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue14963] Use an iterative implementation for contextlib.ExitStack.__exit__
alon horev added the comment: after #14969 has closed, can this be closed? any more action items? -- ___ Python tracker <http://bugs.python.org/issue14963> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue14969] Use __suppress_context__ in contextlib.ExitStack.__exit__
alon horev added the comment: Ok, so turns out this was just a stupid bug: we set the __context__ attr only if an exception is raised, but not when an exception has been previously 'cleared'. so the context is filled (by python) with the last exception raised which is the outer one. deleting the 'if last context is an exception' solved it. This is how I understood it: the exception's __context__ is set when it's raised and not in its except clause, meaning there is no way the outer with is mutating our inner exceptions. using pdb I saw the outer exception being explicitly set. -- keywords: +patch Added file: http://bugs.python.org/file25785/14963.3.patch ___ Python tracker <http://bugs.python.org/issue14969> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue14969] Restore sys.exc_clear()?
alon horev added the comment: Another possible solution is to explicitly set an exception's __supress_context__ attribute to False (right now impossible because it's the default value). If a user can 'turn on' the flag when attaching a different exception (raise X from Y), why not allow 'turning it off'? (symmetry anyone?) right now it is set to False by default and changed to true when 'raising from'. I suggest changing the default to None, allowing the user to explicitly say: I'm no longer in the previous exception's context. Feels a bit like solving our hack with another hack (: And about the PSF contrib agreement, I'll do it as soon as I'm near a printer. too bad we're using pens and not RSA private keys for signatures (-: thanks, Alon -- nosy: +alonho ___ Python tracker <http://bugs.python.org/issue14969> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue14963] Use an iterative implementation for contextlib.ExitStack.__exit__
alon horev added the comment: that was indeed trickier, but overriding the __context__ attribute did the trick. -- Added file: http://bugs.python.org/file25770/14963.2.patch ___ Python tracker <http://bugs.python.org/issue14963> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue14963] Use an iterative implementation for contextlib.ExitStack.__exit__
alon horev added the comment: The iterative approach turned out elegant and concise. It actually now resembeles the implementation of nested's __exit__. -- keywords: +patch nosy: +alonho Added file: http://bugs.python.org/file25763/14963.patch ___ Python tracker <http://bugs.python.org/issue14963> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue7317] Display full tracebacks when an error occurs asynchronously
alon horev added the comment: how does one get his patch reviewed? (it's been 6 months) -- ___ Python tracker <http://bugs.python.org/issue7317> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue7317] Display full tracebacks when an error occurs asynchronously
alon horev added the comment: Here's the next attempt (took your advice about the convention): Exception ignored in: > Traceback (most recent call last): File "/tmp/bla.py", line 4, in __del__ None.someattr AttributeError: 'NoneType' object has no attribute 'someattr' reminder of the current format for comparison: Exception AttributeError: "'NoneType' object has no attribute 'someattr'" in > ignored I thought about a more elaborate explanation than "Exception ignored" but grepping this function through the code shows it can be called from various places making it too generic. The reason I wanted to add a header/footer is for stating the message and the traceback go together (I print tracebacks to screen all the time), but it might be TMI.. -- Added file: http://bugs.python.org/file23414/7317.patch ___ Python tracker <http://bugs.python.org/issue7317> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue7317] Display full tracebacks when an error occurs asynchronously
alon horev added the comment: Submitting a patch proposing this format: -BEGIN UNRAISABLE EXCEPTION- Class: AttributeError Instance: "'NoneType' object has no attribute 'someattr'" Function: > Traceback (most recent call last): File "/tmp/bla.py", line 4, in __del__ None.someattr -END UNRAISABLE EXCEPTION- I've wrapped the exception information with header/footer differentiating it from a user's error handling code that also prints tracebacks (is it too much?). I've considered using the warnings module, But I dislike the suppression of already warned messages. (2 instances will raise exception in __del__ but only one message will be printed) This is my first patch submission so feel free giving me a hard time. -- keywords: +patch nosy: +alonho Added file: http://bugs.python.org/file23413/7317.patch ___ Python tracker <http://bugs.python.org/issue7317> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue8733] list type and UserList do not call super in __init__ and therefore, they cannot be parents in a multiple inheritence scheme
Changes by alon horev : -- components: Extension Modules nosy: alonho priority: normal severity: normal status: open title: list type and UserList do not call super in __init__ and therefore, they cannot be parents in a multiple inheritence scheme type: behavior versions: Python 3.3 ___ Python tracker <http://bugs.python.org/issue8733> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com