Dynamically import in python through a Dictionary - python-3.x

I need to import modules using a dictionary, I would like to loop through the dictionary and import it. For example
items = {
'Initial_Load': 'initial_load',
'Disclaimer': 'disclaimer_tests',
'Menu': 'menu_tests'
}
Those items should convert into
from Inital_Load import initial_load
from Disclaimer import disclaimer_tests
from Menu import menu_tests
Is it even possible?

This uses importlib.import_module to import the module, then getattr to resolve the name from that modules namespace:
from importlib import import_module
def import_dict(d):
result = {}
for module_name, attr_name in d.items():
module = import_module(module_name)
result[attr_name] = getattr(module, attr_name)
return result
import_dict({"math": "sqrt"})["sqrt"](4)
# 2.0

Related

Not able to create mock object using mocker

I am trying to create mock object for unit testing but somehow always actual object is called.
Below is the code for reference:-
utility_functions.py
import os
import json
def get_module_configurations(key):
config = os.getcwd()
config = config + "\\xyz.json"
with open(config) as f:
module_config = json.load(f)
module_config = module_config[key]
return module_config
load_class
from importlib import import_module
from inspect import isclass, isabstract
def load_module(data):
package_path = data['Package']
module_name = data['ModuleName']
class_name = data['ClassName']
try:
module_name = str(module_name.split('.py')[0])
module = import_module('.' + module_name, package_path)
except Exception as error:
pass
try:
_class = getattr(module, class_name)
except Exception as error:
pass
if isclass(_class) and not (isabstract(_class)):
return _class
else:
return None
function1.py
import load_class
from utility_functions import get_module_configurations
def load_helpers(task_name):
module = get_module_configurations(task_name)
cls = load_class.load_module(module)
return cls
test_function.py
import pytest
from function1 import load_helpers
def test_mock(mocker):
class_to_load = {"Package": "Test", "ModuleName": "default_class.py", "ClassName":
"DefaultClass"}
mocker.patch('function1.load_helpers', return_value= class_to_load)
result = load_helpers('c')
assert result is not None
Since I am mocking, load helpers should not be called but it always calls actual implementation saying path is invalid.
I am missing something basic but cannot figure out what.
Any help will be great.
If you are importing the function into your module (from function1 import load_helpers), you need to patch it as if it was part of it. This means that instead of...
mocker.patch('function1.load_helpers', return_value=class_to_load)
...you should use...
mocker.patch('test_function.load_helpers', return_value=class_to_load)
PS: I assume that you are just practicing mocking because otherwise your test function doesn't make sense.

How to use a variable/list in a nested function that is imported

I have multiple functions that I intent to import that will be using a certain number of variables/lists in the main module.
The only issue is that I keep getting an error:
for lst in arr:
NameError: name 'arr' is not defined
My code is this:
#main code
#mine.py
import my_unique
import numpy as np
from numpy import asarray
from numpy import save, load
my_data = np.load('my_things.npz', allow_pickle=True )
moa = my_data['x']
def pay():
global arr
arr = np.array(list(def_moa))
similies = my_unique.simily()
pay()
#my_unique.py
def simily():
for lst in arr:
exportable_model = bjw.build_exportable_model(lst)
runtime_model = bjw.build_runtime_model(exportable_model)
# more code...
Is there a way to male the 'arr' accessible to the 'simily' function?
Kindest regards

Is it possible to make a module available as an import from another module?

I'm refactoring some code and have moved around some files. But for backwards compatibility, I would like to make all of my modules keep their old import paths.
my file structure is as follows
--| calcs/
----| __init__.py
----| new_dir
------| new_file1.py
------| new_file2.py
What do I need to do ensure that I can use an import like
import calcs.newfile1.foo
# OR
from calcs.newfile1 import foo
I have tried a few methods of adding the imports to the top level __init__.py file. As is reccommended here
But while this seems to allow an import such as import calcs.newfile1, An import such as import calcs.newfile1.foo raises ModuleNotFoundError: No module named calcs.newfile1
I expect that I need python to recognize calcs.newfile1 as a **module **. At the moment it seems to just be importing it as a class or other object of some sort
The only way i know how to do it is by creating a custom import hook.
Here is the PEP for more information.
If you need some help on how to implement one, i'll suggest you to take a look at the six module,
here
and here
Basically your calcs/__init__.py will become like this:
''' calcs/__init__.py '''
from .new_dir import new_file1, new_file2
import sys
__path__ = []
__package__ = __name__
class CalcsImporter:
def __init__(self, exported_mods):
self.exported_mods = {
f'{__name__}.{key}': value for key, value in exported_mods.items()
}
def find_module(self, fullname, path=None):
if fullname in self.exported_mods:
return self
return None
def load_module(self, fullname):
try:
return sys.modules[fullname]
except KeyError:
pass
try:
mod = self.exported_mods[fullname]
except KeyError:
raise ImportError('Unable to load %r' % fullname)
mod.__loader__ = self
sys.modules[fullname] = mod
return mod
_importer = CalcsImporter({
'new_file1': new_file1,
'new_file2': new_file2,
})
sys.meta_path.append(_importer)
and you should be able to do from calcs.new_file1 import foo

how to import class object in python from another file

Suppose I have a directory with files classfile.py and a test_classfile.py
here's classfile.py
class Student:
def __init__(self, fname, lname):
self.firstname = fname
self.lastname = lname
def printname(self):
return (self.firstname + self.lastname)
if __name__ == '__main__':
s = Student('John', 'Doe')
What I'd like to do is import just the object s
into the test_file.py
something like this,
from dir.classfile.Student import s
def test_classfile():
assert str(s.printname()).isalpha()
I get the following error
ModuleNotFoundError: No module named 'dir.classfile.Student'; 'dir.classfile' is not a package
As it is said 'dir.classfile' is not a package. If your .py files are both in the same directory, you just do 'import classfile'. Suppose the classfile.py was in the different directory, you would have to do the following:
import os.path
path_to_mods = os.path.abspath('path/to/classfile')
sys.path.insert(0, path_to_mods)
import classfile
You cannot import from 'Student' - this is an object. But you can import Student like this:
from classfile import Student
Also you cannot import instance of the class which is s. You should import the object like it it said above and then create an instance of it.

python mocking function calls that are called during module import

I need to perform mocking for python code that is running during module import
For example I have code like this
import configparser
config = configparser.ConfigParser()
config.read('test.ini')
a = float(config['config']['a'])
b = float(config['config']['b'])
c = float(config['config']['c'])
print(a)
print(b)
print(c)
I need mock "config" for testing
import pytest
import mock
import app
#mock.patch('app.configparser.ConfigParser')
def test_config_mock(config_mock):
config_mock.return_value = {'config': { 'a' : 1 } }
However, this testing function being called after actual import so my mocking is not making any sense
What's the right way of doing this kind of thing?
What you can do in this case is to instead patch the config instance using mock.patch.dict:
# test_coolio.py
import mock
from app.fun import coolio
#mock.patch.dict('app.configparser.config', values={'config': {'a': 15}})
def test_config_mock():
assert coolio() == '15'
# app/fun.py
from app.configparser import config
def coolio():
return config['config']['a']

Resources