Getting a class from inside a package - python

I am trying to use the functions __import__(...) and getattr(...) to make an object of a class that is located inside a module. That module itself is included inside a package.
The class is named TestScript. It is located in a file named TestScript.py. The file is inside a folder named TestScripts. So from my understanding of python, the file TestScript.py is interpreted as module and the folder TestScripts is interpreted as package.
So, I tried it like this:
moduleName = 'TestScripts.TestScript'
className = 'TestScript'
module = __import__(moduleName)
targetClass = getattr(module, className)
instance = targetClass()
But an AttributeError occurs with the message "module 'TestScripts' has no attribute 'TestScript'".
I expected instance to be an object of the TestScript class after the execution of this code snippet. What do I miss?

For the full explanation see __import__
To make your code do what you want:
moduleName = 'Testscripts.TestScript'
className = 'TestClass'
module = __import__(moduleName) #could use fromlist here as #Iguananaut suggests
targetModule = getattr(module, "TestScript")
targetClass = getattr(targetModule, className)
instance = targetClass()
As a note - python docs strongly discourage direct use of __import__

Related

NameError: name 'parse_config' is not defined

I am trying to set up a set of scripts I got from github. I have a utils.py file that has the bellow python code:
p_dir = os.path.dirname(os.path.realpath(__file__)) + "/"
username = getpass.getuser()
myData = parse_config(p_dir+"../config/data.config")
myPars = parse_config(p_dir+"../config/parameters.config")
myPipelines = parse_config(p_dir+"../config/pipeline.config")
When I run the script I get the bellow error:
myData = parse_config(p_dir+"../config/data.config")
NameError: name 'parse_config' is not defined
I thought that the required module has not been imported but it seems that thats not the case as I get the same error when I import configparser. Any idea on which module the parse_config()might belong or in general on how to fix the error?
Thanks in advance :) !

object not callable python when parsing a json response

I have a response from a URL which is of this format.
'history': {'all': [[u'09 Aug', 1,5'],[u'16 Aug', 2, 6]]}
And code is :
response = urllib.urlopen(url)
data = json.loads(response.read())
print data["fixture_history"]['all']
customObject = MyObject (
history = data["history"]['all']
)
Printing works but in my custom class I am seeing this error :
history = data["history"]['all']
TypeError: 'module' object is not callable
My class is :
class MyObject:
#init
def _init_(self,history):
self.hstory = history
Printing works but in my custom class I am seeing this error :
TypeError: 'module' object is not callable
I bet your your class is defined in a module named MyObject.py and that you imported it as import MyObject instead of from MyObject import MyObject, so in your calling code, name MyObject is bound to the module, not the class.
If you Class is defined in a different Module please make sure that that you have imported it the right way ie. you need to use from X import Y format but not Import X and expect it to work as if we do it that way we need to let python know the module we are calling it from.
And i am not very sure but i think the typo in the constructor might case the issue as stated
bigOTHER

Deserialize Protobuf in python from class name

How can I deserialize a protocol buffer message, knowing only the string name of the protoc-generated class?
For some reason, the fully qualified name of the message that I get with DESCRIPTOR.full_name does not match the actual location of the python class, so I am unable to deserialize it with the following function:
def get_class( kls ):
"""Get class given a fully qualified name of a class"""
parts = kls.split('.')
module = ".".join(parts[:-1])
m = __import__( module )
for comp in parts[1:]:
m = getattr(m, comp)
return m
I just get ImportError no module (name).
Any help appreciated.
P.S.: In case it helps, the bigger problem I am trying to solve is to serialize the protobuf message to the database, and then deserialize it back out (I am using postgresql with sqlalchemy in this case). Since regular python pickle doesn't work - I am hoping to store a tuple (message_cls_name, message_binary) where message_cls_name is a fully qualified name of the protobuf message, and message_binary is a result of called SerializeToString on the message. The part I am not clear about is how to get the message out and deserialize it into proper protobuf class.
Here is an example solution..
from ocmg_common.protobuf.rpc_pb2 import Exception as PBException
from importlib import import_module
pb_message = PBException(message='hello world')
pb_message_string = pb_message.SerializeToString()
def deserialize(message, typ):
module_, class_ = typ.rsplit('.', 1)
class_ = getattr(import_module(module_), class_)
rv = class_()
rv.ParseFromString(message)
return rv
print(deserialize(pb_message_string, 'ocmg_common.protobuf.rpc_pb2.Exception'))
will output
(env)➜ httppost git:(master) ✗ python test.py
message: "hello world"
If you dont know the module, but only have the DESCRIPTOR.full_name you have to name them the same way, or create a function that maps a full descriptor name to a module. Otherwise you are stuck and dont know from where to import the module.
I hope it will help you.. ;)
Best of luck..

Python unittest mock ... mock a module statement

I'm having difficuly getting my head around python's mock test methodology.
I want to do some mocking on this file.
Since packages xbmc, xbmcaddon and xbmcgui cannot be imported in a normal python environment I've managed to mock them out like this:
class XBMCTestCase(unittest.TestCase):
def setUp(self):
#Mock up any calls to modules that cannot be imported
self.xbmc = Mock()
self.xbmcgui = Mock()
self.xbmcaddon = Mock()
modules = {
'xbmc' : self.xbmc,
'xbmcgui': self.xbmcgui,
'xbmcaddon': self.xbmcaddon
}
self.module_patcher = patch.dict('sys.modules', modules) ##UndefinedVariable
self.module_patcher.start()
See it in action here.
So when I import setlocation.py I get an error like this:
File "/home/paulo/workspace/weather.metoffice/src/metoffice/utils/utilities.py", line 21, in <module>
CACHE_FOLDER = os.path.join(ADDON_DATA_PATH, 'cache')
File "/usr/lib/python2.7/posixpath.py", line 78, in join
path += b
TypeError: unsupported operand type(s) for +=: 'Mock' and 'str'
Even if I mock out 'metoffice.utils' (by adding it to the list of modules in the patch created at setup) I get a similar error in setlocation.py
File "/home/paulo/workspace/weather.metoffice/src/metoffice/setlocation.py", line 32, in <module>
GEOIP_PROVIDER = int(__addon__.getSetting('GeoIPProvider'))
TypeError: int() argument must be a string or a number, not 'Mock'
So I need __addon__.getSetting() to return a string.
Any ideas?
All attempts have failed, but I don't think I have a full grasp of the capabilities of the mock package.
Note I'm on Python 2.7.3 with mock 1.0.1
You need to tell your mocks what to return. The __addon__ value is the result of a xbmcaddon.Addon() call, so you can get access to that mock object with:
addon = self.xbmcaddon.Addon.return_value
because .return_value gives you the actual Mock object that calling Addon() would return.
Now you can tell that Mock object what to return when the getSetting() method is called; there are two values to provide here, so you could use the side_effect to set a sequence of values to return:
addon.getSetting.side_effect = ['some_api_key', '42']
where the first call to __addon__.getSetting() will produce the first value 'some_api_key', the second cal will produce '42'.

How is calling module and function by string handled in python?

Calling a function of a module from a string with the function's name in Python shows us how to call a function by using getattr("bar")(), but this assumes that we have the module foo imported already.
How would would we then go about calling for the execution of "foo.bar" assuming that we probably also have to perform the import of foo (or from bar import foo)?
Use the __import__(....) function:
http://docs.python.org/library/functions.html#import
(David almost had it, but I think his example is more appropriate for what to do if you want to redefine the normal import process - to e.g. load from a zip file)
You can use find_module and load_module from the imp module to load a module whose name and/or location is determined at execution time.
The example at the end of the documentation topic explains how:
import imp
import sys
def __import__(name, globals=None, locals=None, fromlist=None):
# Fast path: see if the module has already been imported.
try:
return sys.modules[name]
except KeyError:
pass
# If any of the following calls raises an exception,
# there's a problem we can't handle -- let the caller handle it.
fp, pathname, description = imp.find_module(name)
try:
return imp.load_module(name, fp, pathname, description)
finally:
# Since we may exit via an exception, close fp explicitly.
if fp:
fp.close()
Here is what i finally came up with to get the function i wanted back out from a dottedname
from string import join
def dotsplit(dottedname):
module = join(dottedname.split('.')[:-1],'.')
function = dottedname.split('.')[-1]
return module, function
def load(dottedname):
mod, func = dotsplit(dottedname)
try:
mod = __import__(mod, globals(), locals(), [func,], -1)
return getattr(mod,func)
except (ImportError, AttributeError):
return dottedname
this solution is not working?
Calling a function of a module from a string with the function's name in Python

Categories