Monkeypatch PEP 461 in Python 3.0-3.4 - python

Is is possible to monkeypatch PEP 461 functionality in to Python 3.0-3.4?
(I'm working on porting dulwich to python 3, and as it has a lot of protocol and file format code, it relies heavily on byte formatting.)

To monkeypatch it in, you would need to assign a relevant function to bytes.format. Trying it with a dummy function does this:
>>> bytes.format = lambda *s: None
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'bytes'
So, no, you can't do this. You would need to modify the C code that creates the bytes class - at which point, you might as well just apply the patch from the relevant bug.

Related

How to use self-docummenting equals (debugging) specifier with str.format()?

Python 3.8 introduced = specifier in f-strings (see this issue and pull request).
It allows to quickly represent both the value and the name of the variable:
from math import pi as π
f'{π=}'
# 'π=3.141592653589793'
I would like to use this feature on a pre-defined string with str.format():
'{π=}'.format(π=π)
However, it raises an exception:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'π='
Is there a way to make it work (e.g. with a special dunder method)?
Why it may be useful?
one could have a programmatic template for multiple values of the same variable (in a loop)
in contrasts, f-strings have to be hardcoded; think about internationalization
one could reference constants defined in a module in its docstring (module.__doc__.format(**vars(module));
workaround: define an f-string variable at the end of the module, overwrite the module.__doc__ at runtime.

TypeError message uses name instead of qualname

I find the following behavior:
>>> def f():
... def g(a,b):
... return a+b
... return g
>>> f().__name__
... 'g'
>>> f().__qualname__
... 'f.<locals>.g'
>>> f()(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: g() missing 1 required positional argument: 'b'
I would like the error message to show the __qualname__ of the function involved instead of just the __name__. This is afaik also the recommended practice when writing such messages yourself.
Can I do anything about this (e.g. configuration on startup)?
Or is this a bug/feature?
Showing the qualname would make debugging a lot easier, especially when working with decorators or lambdas.
python 3.6.1
This isn't configurable; it's hard coded in the interpreter internals. If you feel strongly about it, file a bug with the CPython folks. Given that __qualname__ is a newer feature, they may not have considered or gotten around to using it in this context.
Update: Looks like there is a bug already filed, but it hasn't seen any activity in the last couple years.

How / why does Python type hinting syntax work?

I have just seen the following example in PEP 484:
def greeting(name: str) -> str:
return 'Hello ' + name
print(greeting('Martin'))
print(greeting(1))
As expected, this does not work in Python 2:
File "test.py", line 1
def greeting(name: str) -> str:
^
SyntaxError: invalid syntax
However, it works for Python 3:
Hello Martin
Traceback (most recent call last):
File "test.py", line 5, in <module>
print(greeting(1))
File "test.py", line 2, in greeting
return 'Hello ' + name
TypeError: Can't convert 'int' object to str implicitly
This was unexpected. It does not really check types yet, as you can see with the following example (it runs, but does not throw an exception):
def greeting(name: str) -> int:
return 'Hello ' + name
print(greeting('Martin'))
It seems as if after the : has to be the name of a function, but the function seems to be ignored:
def aha(something):
print("aha")
return something+"!"
def greeting(name: aha, foo) -> int:
return 'Hello ' + name + foo
print(greeting('Martin', 'ad'))
The same seems to be true for the name after ->.
Is this type hinting syntax using something else (like Java Modeling language makes use of comments)? When was this syntax introduced to Python? Is there a way to do static type checking already with this Syntax? Does it always break Python 2 compatibility?
There is no type hinting going on here. All you did was provide annotations; these were introduced with PEP 3107 (only in Python 3, there is no support for this in Python 2); they let you annotate arguments and return values with arbitrary information for later inspection:
>>> greeting.__annotations__
{'name': <class 'str'>, 'return': <class 'str'>}
They are otherwise not consulted at all here. Instead, the error message you got is from trying to concatenate string and integer values in the body of the function:
>>> 'Hello ' + 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't convert 'int' object to str implicitly
It is a custom type error aimed at providing additional information as to why the str + int concatenation failed; it is thrown by the str.__add__ method for any type that is not str:
>>> ''.__add__(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't convert 'int' object to str implicitly
>>> ''.__add__(True)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't convert 'bool' object to str implicitly
PEP 484 then proposes to make use of those annotations to do actual static type checking with additional tools, but as the introduction of the PEP states:
While these annotations are available at runtime through the usual __annotations__ attribute, no type checking happens at runtime. Instead, the proposal assumes the existence of a separate off-line type checker which users can run over their source code voluntarily. Essentially, such a type checker acts as a very powerful linter.
Emphasis in the original.
The PEP was inspired by existing tools that use PEP 3107 annotations; specifically the mypy project (which is looping right back by adopting PEP 484), but also the type hinting support in the PyCharm IDE and the pytypedecl project. See Guido van Rossum's original email kickstarting this effort as well as a follow-up email.
mypy apparently supports Python 2 by preprocessing the annotations, removing them before byte-compiling the source code for you, but you otherwise cannot normally use the syntax Python code meant to work in Python 2.
PEP 484 also describes the use of stub files, which sit next to the regular Python files; these use the .pyi extension and only contain the signatures (with type hints), leaving the main .py files annotation free and thus usable on Python 2 (provided you wrote Polyglot Python code otherwise).

Does a variable override method here

I am starting to play around with python a little, and as a novice i tried this:
>>> s="";str=""
>>> for x in [ 1,2,3,4,5,6 ] :
... s += str(x)
...
Traceback (most recent call last):
File "<console>", line 3, in <module>
TypeError: 'str' object is not callable
I accidentally declared a variable called str (str is supposed to be a function).
Assuming it would break the semantics too much, even in a dynamically
typed language, is there a namespace i can use to qualify methods
like str and ensure this does not happen or make it difficult?
This is what import <module> instead of from <module> import * is used for. As long as you use str in the only meaning of local variable value in <module>, you can use
module.str elswhere, without mangling namespace.
The only tokens that can't be clashed are keywords. This is intended functionality and there is no way to prevent this: everything is an object in Python
You might want to use some IDE tools, p.ex. Eclipse+PyDev, that checks your code and warn for possible errors.
As per your question you have already defined str=""
so when you will call str method which converts values into string it will not call actual method in place of that it will call str="".
that's why you are getting error because you can not call a str object to convert int to string.

Python "NoneType is not callable" error

I have a function that looks like the following, with a whole lot of optional parameters. One of these parameters, somewhere amidst all the others, is text.
I handle text specially because if it is a boolean, then I want to run to do something based on that. If it's not (which means it's just a string), then I do something else. The code looks roughly like this:
def foo(self, arg1=None, arg2=None, arg3=None, ..., text=None, argN=None, ...):
...
if text is not None:
if type(text)==bool:
if text:
# Do something
else:
# Do something else
else:
# Do something else
I get the following error on the type(text)==bool line:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "...", line 79, in foo
if type(text)==bool:
TypeError: 'NoneType' object is not callable
Not sure what the problem is. Should I be testing the type differently? Experimenting on the python command line seems to confirm that my way of doing it should work.
I guess you have an argument called type somewhere, I can easily reproduce your error with the following code:
>>> type('abc')
<class 'str'>
>>> type = None
>>> type('abc')
Traceback (most recent call last):
File "<pyshell#62>", line 1, in <module>
type('abc')
TypeError: 'NoneType' object is not callable
I bet you have a type=None among your arguments.
Just a special case of the general rule: "don't hide built-in identifiers with your own -- it may or may not bite in any specific give case, but it will bite you nastily in some cases in the future unless you develop the right habit about it"!-)

Categories