Why does monkeypatching os.path require a path argument? - python

pytest has this example in the monkeypatching docs:
import os.path
def getssh(): # pseudo application code
return os.path.join(os.path.expanduser("~admin"), '.ssh')
def test_mytest(monkeypatch):
def mockreturn(path):
return '/abc'
monkeypatch.setattr(os.path, 'expanduser', mockreturn)
x = getssh()
assert x == '/abc/.ssh'
When I remove the path argument from the mockreturn function, I get the error
def getssh(): # pseudo application code
> return os.path.join(os.path.expanduser("~admin"), '.ssh')
E TypeError: mockreturn() takes 0 positional arguments but 1 was given
I don't understand what is providing that positional argument?
Also, when I reimplement the same thing for pathlib.Path.home() I cannot have this argument path there, otherwise it won't work. Unfortunately, the documentation does not say anything about that ominous path argument.
Any illumination for what magic is happening here would be very helpful!

You're trying to replace os.path.expanduser that takes one argument with a mock that doesn't take arguments at all which results to an error when called.
Under the hood monkeypatch.setattr uses builtin setattr so the original version is basically doing following which works since both expanduser and mock take single argument:
>>> import os.path
>>> def mock(path):
... return '/abc'
...
>>> setattr(os.path, 'expanduser', mock)
>>> os.path.expanduser('~admin')
'/abc'
Now if you try to replace expanduser with a method that doesn't take arguments and keep calling it the same way you'll get an error:
>>> setattr(os.path, 'expanduser', mock)
>>> os.path.expanduser('~admin')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: mock() takes 0 positional arguments but 1 was given
Note that you'll get exactly the same error if you try to call mock directly:
>>> mock('~admin')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: mock() takes 0 positional arguments but 1 was given

Related

Can't instantiate objects using cli python interpreter

Can't instantiate objects using python interpreter, please help.
So inside of my python file expresser.py I have something like
class Expresser:
def __init__(self):
pass
...
Now when I type in the terminal
python
and then
>>> import expresser
>>> test_object = Expresser()
I get:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'Expresser' is not defined
I'm using PyCharm
when I type where python I get three diff locations so I suspect that but don't know how to rectify
I guess you meant:
from expresser import Expresser
Or:
from expresser import *

Python function that takes the name of another Python function as an argument

I would like to define a general function that calls another python function. I wrote the general function that takes the path to another python function and the name of another python function as arguments.
import sys
def general_function(path, func):
sys.path.insert(0, path)
import func
However, when I ran the general function (saved in /MY/PATH/general_function.py), I received the following error:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/MY/PATH/general_function.py", line 4
import func
^
ModuleNotFoundError: No module named 'func'
How can I fix this? I tried import * but it did not work either. I really appreciate your help!
Try this?
import os
def general_function(path, func):
os.chdir(path)
import func

Python error: 'bool' not iterable

I'm trying to run a code:
import os
from os import listdir
for f in sorted(os.listdir("/path")):
if f in f.startswith("20"):
for f in sorted(os.listdir(f)):
if f.endswith(".txt"):
pass
else:
try:
os.system("/path/script.py %s" % f)
except:
pass
I have received this error:
Traceback (most recent call last):
File "files_correct_phase.py", line 5, in <module>
if f in f.startswith("20"):
TypeError: argument of type 'bool' is not iterable
code here
I ran it inside the python prompt and it worked fine after line 5, but when I run it as
python python_script.py
in the command line, it gives me this error. I would be grateful for any advice and/or help.
(Python version 2.7.6)
if f in f.startswith("20"):
is not valid. startswith returns a bool the in keyword trys to check for containment inside your bool. That only works for iterables (which bool is not). You probably want:
if f.startswith("20"):

C function with pointer of points wrapping

I have a method define in C/C++ DLL that takes 2 args
void SetLines(char** args,int argCount);
I need to call it from Python, what is the proper way to do so.
from ctypes import *
path="test.dll"
lib = cdll.LoadLibrary(path)
Lines=["line 2","line 2"]
lib.SetLines(Lines,len(lines))
print(code)
Excuting the Python code gives the following error:
Traceback (most recent call last):
File "<test.py>", line 6, in <module>
ctypes.ArgumentError: argument 1: <class 'TypeError'>: Don't know how to convert parameter 1
After some code digging I figure it out:
any C/C++ parameter that accepts a pointer to a list of values should be wrapped in python with
MyType=ctypes.ARRAY(/*any ctype*/,len)
MyList=MyType()
and filled with
MyList[index]=/*that ctype*/
in mycase the solution was:
from ctypes import *
path="test.dll"
lib = cdll.LoadLibrary(path)
Lines=["line 1","line 2"]
string_pointer= ARRAY(c_char_p,len(Lines))
c_Lines=string_pointer()
for i in range(len(Lines)):
c_Lines[i]=c_char_p(Lines[i].encode("utf-8"))
lib.SetLines(c_Lines,len(lines))

TypeError: iter() takes no keyword arguments

I'm working with xml.etree.cElementTree, and regarding to official documentation - want find element in Element:
$ python --version
Python 2.7.8
My script:
#!/usr/bin/env python
import os, re
import xml.etree.ElementTree as ET
XML_FILE = '/cygdrive/****.csproj'
try:
tree = ET.ElementTree(file=XML_FILE)
root = tree.getroot()
print type(root)
for item in root.iter(tag='OutputPath'):
print item.tag, item.attrib, item.text
....
But when I run it - have an error:
$ ./xm_par.py
<type 'Element'>
Traceback (most recent call last):
File "./xm_par.py", line 21, in <module>
for item in root.iter(tag='OutputPath'):
TypeError: iter() takes no keyword arguments
What I'm miss here?
This is a known bug; the C accelerated version of the API is missing support for the tag parameter as a keyword argument. See issue #16849:
Element.{get,iter} doesn't handle keyword arguments when using _elementtree C accelerator.
The bug was fixed in Python 3.3 and up but not in Python 2.7 yet.
You can omit the keyword and pass in the argument as a positional instead:
for item in root.iter('OutputPath'):
Demo:
>>> import xml.etree.cElementTree as ET
>>> tree = ET.fromstring('''\
... <root>
... <OutputPath></OutputPath>
... </root>
... ''')
>>> tree.iter(tag='OutputPath')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: iter() takes no keyword arguments
>>> tree.iter('OutputPath')
<generator object iter at 0x1045cc5a0>

Categories