'Mock' object has no attribute '__getitem__' - python

After following the example Mocking a Dictionary with MagicMock I have the following mock setup:
mock_writer = Mock()
mock_reader = Mock()
mock_format = Mock()
mock_option = Mock()
mock_load = MagicMock()
test_dict = {"Bus_No": Mock(), "Team_No": Mock()}
def getitem(name):
return test_dict[name]
mock_load.__getitem__.side_effect = getitem
mock_option.load.return_value = mock_load
mock_format.option.return_value = mock_option
mock_reader.format.return_value = mock_format
mock_reader.write.return_value = mock_writer
mock_spark = Mock()
mock_spark.read.return_value = mock_reader
Driver(mock_spark).run()
And here is the driver class:
def __init__(self, spark):
self.spark = spark
def run(self):
partition_names = ["Bus_No", "Team_No"]
df = self.spark.read\
.format("com.databricks.spark.avro")\
.option("avroSchema", schema)\
.load("{0}{1}*.avro".format(job.SourcePath, os.path.sep))
partition_columns = [df[x] for x in partition_names]
And then it returns this error:
partition_columns = [df[x] for x in partition_names]
TypeError: 'Mock' object has no attribute '__getitem__'

Turns out that because read is not a method I should not be using return_value from mock_spark.read. Here's the change:
mock_spark.read = mock_reader

Related

Pytest mocking nested object

I am trying to understand how to overcome an issue with mocking a python attribute coming from an imported module within a constructor.
I have a simplified Tableau python class which is defined like this:
import tableauserverclient as TSC
import pandas as pd
from os import environ
class Tableau(object):
def __init__(self):
# BYPASS ALL OF THIS AUTHENTICATION?
self.server = TSC.Server(environ.get("TABLEAU_URL"), use_server_version=False)
self.server.version = environ.get("TABLEAU_API_VERSION")
self.tableau_auth = TSC.PersonalAccessTokenAuth(
environ.get("TABLEAU_TOKEN_NAME"),
environ.get("TABLEAU_TOKEN_VALUE"),
site_id="",
)
self.tableau_server = self.server.auth.sign_in(self.tableau_auth)
def get_all_views(self) -> pd.DataFrame:
data = []
# HOW TO MOCK self.tableau_server.views?
for view in TSC.Pager(self.tableau_server.views):
data.append([view.name, view.id, view.workbook_id])
df = pd.DataFrame(data, columns=["View", "Id", "Workbook_Id"])
return df
How can I mock the output of self.tableau_server.views in get_all_views() from pytest to return a mocked list of views...
[
(id=1, name="view_a", "workbook_id"=1),
(id=2, name="view_b", "workbook_id"=2),
(id=3, name="view_c", "workbook_id"=3),
]
*Note - the return value needs to be iterable
Here's what I tried so far... I have been running into "module not found" errors and errors within the constructor - so I think mocking is not working correctly.
from pytest_mock import mocker
from connectors import Tableau
import tableauserverclient as TSC
import pandas as pd
from pandas.testing import assert_frame_equal
def get_mocked_tableau_views(mocker):
a = mocker.Mock()
a.name = "a"
a.id = 1
a.workbook_id = 1
b = mocker.Mock()
b.name = "b"
b.id = 2
b.workbook_id = 2
c = mocker.Mock()
c.name = "c"
c.id = 3
c.workbook_id = 3
return mocker.Mock(return_value=iter([a, b, c]))
def test_initialize(mocker):
mocker.patch.object(TSC, "__init__", return_value=None)
mocker.patch.object(TSC.__init__, "server", return_value=None)
mocker.patch.object(TSC.__init__, "server.version", return_value=None)
def test_get_all_views(mocker):
mocked_tsc = mocker.MagicMock()
mocked_tsc.Server.auth.sign_in = "test"
with mocker.patch(
"connectors.tableau.Tableau.tableau_server.views",
return_value=get_mocked_tableau_views,
):
tab = Tableau()
df_actual = tab.get_all_views()
df_expected = pd.DataFrame(
{"Id": [1, 2, 3], "View": ["a", "b", "c"], "Workbook_Id": [1, 2, 3]}
)
assert_frame_equal(df_actual, df_expected)
Thanks in advance!
I try to answer to the question:
# HOW TO MOCK self.tableau_server.views?
present in the method get_all_views() of the class Tableau.
I don't use pytest, but only the module mock.
import unittest
from unittest import mock
def get_mocked_tableau_views():
a = mock.Mock()
a.name = "a"
a.id = 1
a.workbook_id = 1
b = mock.Mock()
b.name = "b"
b.id = 2
b.workbook_id = 2
c = mock.Mock()
c.name = "c"
c.id = 3
c.workbook_id = 3
return iter([a, b, c])
class MyTestCase(unittest.TestCase):
def test_get_all_views(self):
tab = Tableau()
with mock.patch.object(tab, 'tableau_server') as mock_tableau_server:
mock_tableau_server.views.side_effect = self.get_mocked_tableau_views
df_actual = tab.get_all_views()
df_expected = pd.DataFrame({"Id": [1, 2, 3], "View": ["a", "b", "c"], "Workbook_Id": [1, 2, 3]})
self.assertEqual(df_expected, df_actual)
I think you have to adjust a bit my code to execute it on your system. I hope this answer can be useful for you.

Problem whith SQLAlquemy using SQLServer - Column, parameter, or variable #1: Cannot find data type 52. (2715) (SQLExecDirectW)')

I need a little help!
I'm developing an API (Python) and using SQLAlchemy with SqlServer.When I send the PUT request to my database application return an error:
Column, parameter, or variable #1: Cannot find data type 52. (2715) (SQLExecDirectW)')
entities
class Adress():
def __init__(self,
int_codEndLoja,
str_codigoLoja,
str_enderecoLoja,
str_numeroLoja,
str_complementoLoja,
str_bairroLoja,
str_cidadeLoja,
str_estadoLoja,
str_ufLoja,
str_cepLoja,
str_telefoneUmLoja,
str_telefoneDoisLoja,
str_telefoneTresLoja):
self.__int_codEndLoja = int_codEndLoja
self.__str_codigoLoja = str_codigoLoja
self.__str_enderecoLoja = str_enderecoLoja
self.__str_numeroLoja = str_numeroLoja
self.__str_complementoLoja = str_complementoLoja
self.__str_bairroLoja = str_bairroLoja
self.__str_cidadeLoja = str_cidadeLoja
self.__str_estadoLoja = str_estadoLoja
self.__str_ufLoja = str_ufLoja
self.__str_cepLoja = str_cepLoja
self.__str_telefoneUmLoja = str_telefoneUmLoja
self.__str_telefoneDoisLoja = str_telefoneDoisLoja
self.__str_telefoneTresLoja = str_telefoneTresLoja
#property
def int_codEndLoja(self):
return self.__int_codEndLoja
#int_codEndLoja.setter
def int_codEndLoja(self, int_codEndLoja):
self.__int_codEndLoja = int_codEndLoja
#property
def str_codigoLoja(self):
return self.__str_codigoLoja
#str_codigoLoja.setter
def str_codigoLoja(self, str_codigoLoja):
self.__str_codigoLoja = str_codigoLoja
#property
def str_enderecoLoja(self):
return self.__str_enderecoLoja
#str_enderecoLoja.setter
def str_enderecoLoja(self, str_enderecoLoja):
self.__str_enderecoLoja = str_enderecoLoja
#property
def str_numeroLoja(self):
return self.__str_numeroLoja
#str_numeroLoja.setter
def str_numeroLoja(self, str_numeroLoja):
self.__str_numeroLoja = str_numeroLoja
#property
def str_complementoLoja(self):
return self.__str_complementoLoja
#str_complementoLoja.setter
def str_complementoLoja(self, str_complementoLoja):
self.__str_complementoLoja = str_complementoLoja
#property
def str_bairroLoja(self):
return self.__str_bairroLoja
#str_bairroLoja.setter
def str_bairroLoja(self, str_bairroLoja):
self.__str_bairroLoja = str_bairroLoja
#property
def str_cidadeLoja(self):
return self.__str_cidadeLoja
#str_cidadeLoja.setter
def str_cidadeLoja(self, str_cidadeLoja):
self.__str_cidadeLoja = str_cidadeLoja
#property
def str_estadoLoja(self):
return self.__str_estadoLoja
#str_estadoLoja.setter
def str_estadoLoja(self, str_estadoLoja):
self.__str_estadoLoja = str_estadoLoja
#property
def str_ufLoja(self):
return self.__str_ufLoja
#str_ufLoja.setter
def str_ufLoja(self, str_ufLoja):
self.__str_ufLoja = str_ufLoja
#property
def str_cepLoja(self):
return self.__str_cepLoja
#str_cepLoja.setter
def str_cepLoja(self, str_cepLoja):
self.__str_cepLoja = str_cepLoja
#property
def str_telefoneUmLoja(self):
return self.__str_telefoneUmLoja
#str_telefoneUmLoja.setter
def str_telefoneUmLoja(self, str_telefoneUmLoja):
self.__str_telefoneUmLoja = str_telefoneUmLoja
#property
def str_telefoneDoisLoja(self):
return self.__str_telefoneDoisLoja
#str_telefoneDoisLoja.setter
def str_telefoneDoisLoja(self, str_telefoneDoisLoja):
self.__str_telefoneDoisLoja = str_telefoneDoisLoja
#property
def str_telefoneTresLoja(self):
return self.__str_telefoneTresLoja
#str_telefoneTresLoja.setter
def str_telefoneTresLoja(self, str_telefoneTresLoja):
self.__str_telefoneTresLoja = str_telefoneTresLoja
model.py
class Adress(db.Model):
__tablename__ = "tbl_afeet_dim_endereco_loja"
int_codEndLoja = db.Column(db.Integer, primary_key=True, autoincrement=True, nullable=True)
str_codigoLoja = db.Column((db.String(5)), db.ForeignKey("tbl_afeet_dim_loja.str_codigoLoja"))
str_enderecoLoja = db.Column(db.String(255))
str_numeroLoja = db.Column(db.String(10))
str_complementoLoja = db.Column(db.String(80))
str_bairroLoja = db.Column(db.String(30))
str_cidadeLoja = db.Column(db.String(30))
str_estadoLoja = db.Column(db.String(30))
str_ufLoja = db.Column(db.String(30))
str_cepLoja = db.Column(db.String(9))
str_telefoneUmLoja = db.Column(db.String(14))
str_telefoneDoisLoja = db.Column(db.String(14))
str_telefoneTresLoja = db.Column(db.String(14))
service.py
def update_adress(old_adress, new_adress):
old_adress.int_codEndLoja = new_adress.int_codEndLoja,
old_adress.str_codigoLoja = new_adress.str_codigoLoja,
old_adress.str_enderecoLoja = new_adress.str_enderecoLoja,
old_adress.str_numeroLoja = new_adress.str_numeroLoja,
old_adress.str_complementoLoja = new_adress.str_complementoLoja,
old_adress.str_bairroLoja = new_adress.str_bairroLoja,
old_adress.str_cidadeLoja = new_adress.str_cidadeLoja,
old_adress.str_estadoLoja = new_adress.str_estadoLoja,
old_adress.str_ufLoja = new_adress.str_ufLoja,
old_adress.str_cepLoja = new_adress.str_cepLoja,
old_adress.str_telefoneUmLoja = new_adress.str_telefoneUmLoja,
old_adress.str_telefoneDoisLoja = new_adress.str_telefoneDoisLoja,
old_adress.str_telefoneTresLoja = new_adress.str_telefoneTresLoja
db.session.commit()
views
def put(self, int_codEndLoja):
adress_id = adress_service.list_adress_id(int_codEndLoja)
if adress_id is None:
return make_response(jsonify("STORE NOT FOUND"), 400)
ad = adress_schema.AdressSchema()
validate = ad.validate(request.json)
if validate:
return make_response(jsonify(validate), 400)
else:
str_codigoLoja = request.json["str_codigoLoja"]
str_enderecoLoja = request.json["str_enderecoLoja"]
str_numeroLoja = request.json["str_numeroLoja"]
str_complementoLoja = request.json["str_complementoLoja"]
str_bairroLoja = request.json["str_bairroLoja"]
str_cidadeLoja = request.json["str_cidadeLoja"]
str_estadoLoja = request.json["str_estadoLoja"]
str_ufLoja = request.json["str_ufLoja"]
str_cepLoja = request.json["str_cepLoja"]
str_telefoneUmLoja = request.json["str_telefoneUmLoja"]
str_telefoneDoisLoja = request.json["str_telefoneDoisLoja"]
str_telefoneTresLoja = request.json["str_telefoneTresLoja"]
update_adress = adress.Adress(
str_codigoLoja=str_codigoLoja,
str_enderecoLoja=str_enderecoLoja,
str_numeroLoja=str_numeroLoja,
str_complementoLoja=str_complementoLoja,
str_bairroLoja=str_bairroLoja,
str_cidadeLoja=str_cidadeLoja,
str_estadoLoja=str_estadoLoja,
str_ufLoja=str_ufLoja,
str_cepLoja=str_cepLoja,
str_telefoneUmLoja=str_telefoneUmLoja,
str_telefoneDoisLoja=str_telefoneDoisLoja,
str_telefoneTresLoja=str_telefoneTresLoja)
adress_service.update_adress(adress_id, update_adress)
updated = adress_service.list_adress_id(adress_id)
return make_response(ad.jsonify(updated), 200)
Error
sqlalchemy.exc.ProgrammingError: (pyodbc.ProgrammingError) ('42000', '[42000] [Microsoft][ODBC Driver 17 for
SQL Server][SQL Server]Column, parameter, or variable #1: Cannot find data type 52. (2715) (SQLExecDirectW)')
[SQL: UPDATE tbl_afeet_dim_endereco_loja SET [int_codEndLoja]=?, [str_codigoLoja]=?, [str_enderecoLoja]=?,
[str_numeroLoja]=?, [str_complementoLoja]=?, [str_bairroLoja]=?, [str_cidadeLoja]=?, [str_estadoLoja]=?,
[str_ufLoja]=?, [str_cepLoja]=?, [str_telefoneUmLoja]=?, [str_telefoneDoisLoja]=?, [str_telefoneTresLoja]=?
WHERE tbl_afeet_dim_endereco_loja.[int_codEndLoja] = ?]
[parameters: (('XX',), ('XX',), ('XXX',), ('XX',), ('TESTE',), ('XXXXX',), ('XX
XX',), ('XX',), ('XX',), ('XXXXX',), ('XXXX',), ('XX',), 'XX', XX)]
Honestly, I don't know to find the problem, can someone help me?
Thank you 👊🏻

Getting access to class's variables inside another class's def

I'm trying override a str method in Person() class:
'''class Person(object):
def __init__(self, Nose = None, Neck = None, RShoulder = None, RElbow = None, RWrist = None, LShoulder = None, LElbow = None, LWrist = None, MidHip = None, RHip = None, RKnee = None, RAnkle = None, LHip = None, LKnee = None, LAnkle = None, REye = None, LEye = None, REar = None, LEar = None, LBigToe = None, LSmallToe = None, LHeel = None, RBigToe = None, RSmallToe = None, RHeel = None):
self.Nose = Nose
self.Neck = Neck
self.RShoulder = RShoulder
self.RElbow = RElbow
self.RWrist = RWrist
self.LShoulder = LShoulder
self.LElbow = LElbow
self.LWrist = LWrist
self.MidHip = MidHip
self.RHip = RHip
self.RKnee = RKnee
self.RAnkle = RAnkle
self.LHip = LHip
self.LKnee = LKnee
self.LAnkle = LAnkle
self.REye = REye
self.LEye = LEye
self.REar = REar
self.LEar = LEar
self.LBigToe = LBigToe
self.LSmallToe = LSmallToe
self.LHeel = LHeel
self.RBigToe = RBigToe
self.RSmallToe = RSmallToe
self.RHeel = RHeel
def __str__(self):
return 'Nose = %s\nNeck = \n%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s'%(self.Nose,self.Neck,self.RShoulder,self.RElbow,self.RWrist,self.LShoulder,self.LElbow,self.LWrist,self.MidHip,self.RHip,self.RKnee,self.RAnkle,self.LHip,self.LKnee,self.LAnkle,self.REye,self.LEye,self.REar,self.LEar,self.LBigToe,self.LSmallToe,self.LHeel,self.RBigToe,self.RSmallToe,self.RHeel)'''
And I want to find more elegant way to return a string which will look like that:
Nose = something
Neck = something
...
...
...
Question: elegant way to return a string which will look like ...
You can use the built-in vars function to get the __dict__ of the class variable and format it using .format(... and .join(....
Reference:
vars([object])
Return the __dict__ attribute for a module, class, instance, or any other object with a __dict__ attribute.
.format(value[, format_spec])
Convert a value to a “formatted” representation, as controlled by a standard formatting syntax that is used by most built-in types: Format Specification Mini-Language.
<str>.join(iterable)
Return a string which is the concatenation of the strings in iterable.
class Person:
def __init__(self, **kwargs):
self.Nose = kwargs.get('Nose', None)
self.Neck = kwargs.get('Neck', None)
self.RShoulder = kwargs.get('RShoulder', None)
def __str__(self):
return '\n'.join(('{} = {}'
.format(k, v) for k, v in vars(self).items()))
p = Person(Nose=1, Neck=1)
print(p)
Output:
Nose = 1
Neck = 1
RShoulder = None
Tested with Python: 3.6

ctypes: c_ulong type magically changed to long

I am writing the deepcopy function using python2.7 for my class. I encountered a weird problem
My code is the following
import copy
from ctypes import *
class Graph (Structure):
_fields_ = [("numVertices", c_ulong),
("numEdges", c_ulong)]
def __init__(self):
self.numVertices = c_ulong(0)
self.numEdges = c_ulong(0)
def __deepcopy__(self,memo={}):
newInstance = Graph()
newInstance.numVertices = c_ulong(self.numVertices.value)
newInstance.numEdges = c_ulong(self.numEdges.value)
return newInstance
graph = Graph()
anotherGraph = copy.deepcopy(graph)
I get the following error:
<ipython-input-46-a0cdaa4ef3f7> in __deepcopy__(self, memo)
9 def __deepcopy__(self,memo={}):
10 newInstance = Graph()
---> 11 newInstance.numVertices = c_ulong(self.numVertices.value)
12 newInstance.numEdges = c_ulong(self.numEdges.value)
13 return newInstance
AttributeError: 'long' object has no attribute 'value'
If you try:
type(graph.numVertices)
The result is long
I declared the numVertices as c_ulong(). Why does it become long?
The type of the fields in the structure is still maintained, but ctypes has some "helpful" conversions when reading the values:
from ctypes import *
class Test(Structure):
_fields_ = [('a',c_ulong),
('b',c_char_p)]
t = Test(1,b'hello')
print(type(t.a),type(t.b))
print(t._fields_)
Output:
<class 'int'> <class 'bytes'>
[('a', <class 'ctypes.c_ulong'>), ('b', <class 'ctypes.c_char_p'>)]
So you can write your code as the following and it will work correctly:
import copy
from ctypes import *
class Graph (Structure):
_fields_ = [("numVertices", c_ulong),
("numEdges", c_ulong)]
def __init__(self):
self.numVertices = 0
self.numEdges = 0
def __deepcopy__(self,memo={}):
newInstance = Graph()
newInstance.numVertices = self.numVertices
newInstance.numEdges = self.numEdges
return newInstance
graph = Graph()
anotherGraph = copy.deepcopy(graph)
You can suppress the conversions by deriving from the classes, but it is usually unnecessary. One use case is when using ctypes to call a function that returns an allocated string. You need to suppress the c_char_p to Python byte string conversion so you can later free the c_char_p.
from ctypes import *
class ulong(c_ulong): pass
class char_p(c_char_p): pass
class Test(Structure):
_fields_ = [('a',ulong),
('b',char_p)]
t = Test(1,b'hello')
print(type(t.a),type(t.b))
print(t.a,t.b)
Output:
<class '__main__.ulong'> <class '__main__.char_p'>
<ulong object at 0x0000000006263748> char_p(b'hello')

id type in mongoengine objects

I use mongoengine and when I call a class mongoengine give me error
for example when I use : Site.objects()
I get this
TypeError: id must be an instance of (str, unicode, ObjectId), not <type 'dict'>
and it's my class definition :
class Site(db.Document):
siteURL = db.URLField('''required = True''')
name = db.StringField(required = True)
pages = db.ListField(ReferenceField(Page))
siteId = db.IntField(required = True , unique = True )
views = db.IntField(required = True , default = 0)
visitors = db.IntField(required = True , default = 0)
stat_by_hour = LimitedListField(EmbeddedDocumentField(HourStat))
weekday_stat = db.ListField(EmbeddedDocumentField(WeekdayStat))
os = db.ListField(ReferenceField(OS))
countries = db.ListField(ReferenceField(Country))
cities = db.ListField(ReferenceField(City))
browsers = db.ListField(ReferenceField(Browser))
resolutions = db.ListField(ReferenceField(Resolution))
mostVisitedDays = db.SortedListField(EmbeddedDocumentField(MostVisitedDay) , ordering="visitors")

Categories

Resources