How to pytest local variable like dict inside function? - python

For example I have a function like below:
def func(val):
dict = {}
# some logic to fill in dict
dict['a'] = val
Then how can I pytest the the contents of dict? Is it possible?

You can actually replace the dict constructor, for the tested module, if you can change your code slightly. Suppose that your module name is my_module.py and you can make the following changes:
Initialize the dictionary using dict() instead of {}
Rename dict into my_dict (or any other name so it doesn't shadows the builtin dict())
my_module.py would look like so:
def func(val):
my_dict = dict() # instead of dict = {}
# some logic to fill in dict
my_dict['a'] = val
Then, in your test, override the dict constructor which creates new dictionaries and return your dictionary that you can assert later on:
from my_module import func
def test_func(mocker):
my_replaced_dict = {}
mocker.patch("my_module.dict", return_value=my_replaced_dict)
func(20)
assert my_replaced_dict['a'] == 20 # the assert works since func uses our variable

Related

How to add items to a dictionary between two methods?

I'm writing a method that takes in a list and returns a dictionary. This method is to be saved in a separate Python file and imported into Main.py
The method that takes in a list calls another method that's meant to update the global dictionary.
global myDict
def addKeyValuePair(listItem):
try:
key = listItem.split(': ')[0].replace('\\','')
value = listItem.split(': ')[1].replace('\\r\\n','').replace('\\','')
myDict.update({key:value})
except:
pass
def makeDict(dataList):
myDict = {}
for listItem in dataList:
addKeyValuePair(listItem)
return(myDict)
From the main method I'm importing the makeDict module and passing it the dataList, but it returns an empty dictionary.
from Toolkit import makeDict
finalDict = makeDict(dataList)
Any idea how this can be done?

Create a dictionary with all functions from a file

Say I have a file functions.py containing
def some_function():
return "something"
def some_other_function():
return "something else"
I'm trying to create a dictionary in another file, load_functions.py, with keys being the function-names from functions.py and the items being the actual function e.g:
import functions
useable_functions = [f for f in dir(functions) if "__" not in f] #Get all functions to be used
function_dict = TO_BE_IMPLEMENTED
print(function_dict)
#{"some_function":some_function,
#"some_other_function":some_other_function}
func = function_dict["some_function"]
func()
# "something"
Is it by all means doable?
Take a look at the inspect module.
Say you have your functions.py module.
To get all functions from it, use this:
import inspect
import functions # your module
elements = inspect.getmembers(functions, inspect.isfunction)
element_dict = dict(elements)
The call will return all the function members of the functions.py module as a list of (name, value) pairs sorted by name. Note it will also include lambdas.
Then, I use dict() to convert the (name, value) pairs to a dict.
https://docs.python.org/3/library/inspect.html

Python: is it possible to compare function import origin?

I have 4 python files, the first two is the function itself, the second is functions dictionary, and the third is kind of a 'definition' parser
function_1
def increment(obj):
return obj+1
#another function
function_2
def decrement(obj):
return obj-1
#another function
function_dictionary
import fucntion1
import function2
FUNC_DICT = {
'increment': function1.increment,
'decrement': function2.decrement,
#another function
}
definition_parser
from function_dictionary import FUNC_DICT
def get_definition():
result = {}
for key, value in FUNC_DICT.items():
#check if value is from function_1 or function_2
#result[key] = 'function_1' or 'function_2', depends on its origin
return result
is it possible to compare function import? I tried it with is_in_function_1 = value is in function_1, doesn't work.
if it is not, what are the way around without much repetition?
You can get the module of functions via the __module__ property.
from function_dictionary import FUNC_DICT
def get_definition():
result = {}
for key, value in FUNC_DICT.items():
result[key] = value.__module__
return result
The output would look like the following:
{
'increment': 'function_1',
'decrement': 'function_2'
}
You could use the inspect module like so:
import inspect
print(inspect.getmodule(SequenceMatcher))
for example, if I inspect SequenceMatcher, the output is:
<module 'difflib' from 'C:\ProgramData\Anaconda2\lib\difflib.py'>
So to compare the origin of two functions, you could simply do this:
if inspect.getmodule(increment) == inspect.getmodule(decrement):
do stuff

Adding duplicate keys to JSON with python

Is there a way to add duplicate keys to json with python?
From my understanding, you can't have duplicate keys in python dictionaries. Usually, how I go about creating json is to create the dictionary and then json.dumps. However, I need duplicated keys within the JSON for testing purposes. But I can't do so because I can't add duplicate keys in a python dictionary. I am trying to doing this in python 3
You could always construct such a string value by hand.
On the other hand, one can make the CPython json module to encode duplicate keys. This is very tricky in Python 2 because json module does not respect duck-typing at all.
The straightforward solution would be to inherit from collections.Mapping - well you can't, since "MyMapping is not a JSON serializable."
Next one tries to subclass a dict - well, but if json.dumps notices that the type is dict, it skips from calling __len__, and sees the underlying dict directly - if it is empty, {} is output directly, so clearly if we fake the methods, the underlying dictionary must not be empty.
The next source of joy is that actually __iter__ is called, which iterates keys; and for each key, the __getitem__ is called, so we need to remember what is the corresponding value to return for the given key... thus we arrive to a very ugly solution for Python 2:
class FakeDict(dict):
def __init__(self, items):
# need to have something in the dictionary
self['something'] = 'something'
self._items = items
def __getitem__(self, key):
return self.last_val
def __iter__(self):
def generator():
for key, value in self._items:
self.last_val = value
yield key
return generator()
In CPython 3.3+ it is slightly easier... no, collections.abc.Mapping does not work, yes, you need to subclass a dict, yes, you need to fake that your dictionary has content... but the internal JSON encoder calls items instead of __iter__ and __getitem__!
Thus on Python 3:
import json
class FakeDict(dict):
def __init__(self, items):
self['something'] = 'something'
self._items = items
def items(self):
return self._items
print(json.dumps(FakeDict([('a', 1), ('a', 2)])))
prints out
{"a": 1, "a": 2}
Thanks a lot Antti Haapala, I figured out you can even use this to convert an array of tuples into a FakeDict:
def function():
array_of_tuples = []
array_of_tuples.append(("key","value1"))
array_of_tuples.append(("key","value2"))
return FakeDict(array_of_tuples)
print(json.dumps(function()))
Output:
{"key": "value1", "key": "value2"}
And if you change the FakeDict class to this Empty dictionaries will be correctly parsed:
class FakeDict(dict):
def __init__(self, items):
if items != []:
self['something'] = 'something'
self._items = items
def items(self):
return self._items
def test():
array_of_tuples = []
return FakeDict(array_of_tuples)
print(json.dumps(test()))
Output:
"{}"
Actually, it's very easy:
$> python -c "import json; print json.dumps({1: 'a', '1': 'b'})"
{"1": "b", "1": "a"}

need a dictionary from another function

If I have a dictionary from another function, how can I pass the dictionary within a new function?
Eg.
From another function, I have tuples like this ('falseName', 'realName', positionOfMistake), eg. ('Milter', 'Miller', 4). I have a function that make a dictionary like this:
D={realName:{falseName:[positionOfMistake], falseName:[positionOfMistake]...},
realName:{falseName:[positionOfMistake]...}...}
def addNameToDictionary(d, tup):
if not d.has_key(tup[0]):
d[tup[0]] = {}
d[tup[0]][tup[1]] = [tup[2]]
Now I need to write a function that takes a list of falseName's and return:
realName:
falseName
falseName
realName:...
My problem is how to call the dictionary from the function addNameToDictionary, to a new function?
I have tried the following:
def Names(nameList):
D=addNameToDictionary(d, tup)
print D
But I get:
NameError: global name 'd' is not defined
Anyone?
def your_new_function(d, falseNames):
# ... get data from d
return {realname:(falseName1, falseName2)}

Categories

Resources