Accessing a list in a Class Object, Python - python

Would like some direction on how to pull a "bucket" of data from a return object in python. The statuses is a bucket that contains a list of data to display. I've tried a few different ways and can't seem to display anything but the object reference. Basically, what's the best way to display this type of data in this "bucket" or list of data. ":type: list[ObjectedCreatedName]"
fetch = client.fetch('2Oe3UKM_Nt_NG1UG');
print(fetch.statuses)
print(type(fetch.statuses))
Output:
[<ObjectCreatedName object at 0x03CC07F0>]
<class 'list'>
class ObjectCreatedName(object):
def __init__(self):
self.code = None
self.status = None
self.count = None

You can just:
def print_sequence(sequence):
seq_type = sequence.__class__.__name__
elem_type = sequence[0].__class__.__name__ if len(sequence) > 0 else ''
print('{}[{}]'.format(seq_type, elem_type))
e.g.:
fetch = client.fetch('2Oe3UKM_Nt_NG1UG');
print_sequence(fetch.statuses)
# list[ObjectCreatedName]

Related

Dynamic O.O.P and instances

EDIT
I m trying to make a function to dynamic change the object to get acess to those classes easier.
How can i pass the "test" variable inside that object?
I'v tryied this so far.
EDIT
class Vision:
def find():
pass
class visionInstances:
visionPao = Vision(f'{PathMissionProducts}Pao.jpg')
visionLeite = Vision(f'{PathMissionProducts}Leite.jpg')
xabuska = visionInstances() #Classe
def catch_screenshot(wincap):
return wincap.get_screenshot()
def getpoints(VisionInstanceName=None, threshold=0.7):
test = VisionInstanceName
points = xabuska.visionPao.find(catch_screenshot(xabuska.wincap),threshold,"points")
points2 = xabuska.test.find(catch_screenshot(xabuska.wincap),threshold,"points")
return points2
This code returns "None"
Note on the code that "xabuska.visionPao.find" are 3 diferent objects.
I want to make the second object "test" dynamic.
points1 = is the value i want.
points2 = is the test, and return None

How to create object from another object in Python unit test

I'm having trouble understanding unit testing in Python. I have an object, retailer, which creates another object, deal. deal refers to an attribute created in retailer, so I'm passing it a reference:
class deal():
def __init__(self, deal_container, parent):
The deal_container attribute also comes from retailer, which calls its own methods to create it. So how do I create everything I need to easily make a deal object?
Do I have to create an instance of retailer in my unit test and then call the method in that object that creates deal?
Can I use FactoryBoy to create an instance of retailer and how do I include the method that creates deal in that object?
What's the best way to approach this?
Here's the unit test. I'm setting up the soup_obj I need to give deal:
class TestExtractString(TestCase):
fixtures = ['deals_test_data.json']
def setUp(self):
with open('/home/danny/PycharmProjects/askarby/deals/tests/BestBuyTest.html', 'r') as myfile:
text = myfile.read().replace('\n', '')
self.soup_obj = bs4.BeautifulSoup(text,"html.parser")
self.deal = self.soup_obj.find_all('div',attrs={'class':'list-item'})[0]
def test_extracts_title(self):
z = Retailer.objects.get(pk=1)
s = dealscan.retailer(z)
d = dealscan.deal(self.deal,s)
result = d.extract_string(self.deal,'title')
and here's the relevant bit of the deal class in dealscan. There's a retailer class that creates a deal, but I haven't even written the bit in retailer that creates deal yet. I'm hoping I can mock the bits I need for deal without having to invoke retailer at all, but then how do I deal with the fact that deal references retailer?
class deal():
def __init__(self, deal_container, parent):
'''
Initializes deal object
Precondition: 0 > price
Precondition: 0 > old_price
Precondition: len(currency) = 3
:param deal_container: obj
'''
self.css = self.parent.css
self.deal_container = deal_container
self.parent = parent
self.title = self.extract_string('title')
self.currency = self.parent.currency
self.price = self.extract_price('price')
self.old_price = self.extract_price('old_price')
self.brand = self.extract_string('brand')
self.image = self.extract_image('image')
self.description = self.extract_string('description')
#define amazon category as clearance_url
#define all marketplace deals
def __str__(self):
return self.title
def extract_string(self, element, deal):
'''
:param object deal: deal object to extract title from
:param string element: element to look for in CSS
:return string result: result of string extract from CSS
'''
tag = self.css[element]['tag']
attr = self.css[element]['attr']
name = self.css[element]['name']
result = deal.find(tag, attrs={attr: name})
if result:
if element == 'title':
return result.text
elif element == 'price':
result = self.extract_price(result).text
if result:
return result
elif element == 'image':
result = self.extract_image(result)
return False
The problem is that the deal object is referencing the parent before it sets the self.parent attribute. Use:
self.parent = parent
self.css = self.parent.css
self.deal_container = deal_container
and the AttributeError goes away.
As for the question about whether it's good form to use an object to create another object in a unit test, the answer is that you can use mocks, but it's fine to do it this way. Using a helper method to set up the parent object once in setUp is acceptable and will make the code easier to read, and may improve test performance a little.

How to Instantiate a Completely Fresh Temporary Object that Contains Lists

I'm currently using Python to parse CAN database files. I ran into a problem with lists during implementation and gave it a quick patch that makes it work, but it's kind of ugly and seems as if there's a more elegant solution.
I have defined an object CAN database and one of it's methods takes the file to be parsed, which contains definitions of messages in the database. I loop through each line in the file and when I come across a line indicating a message description, I create a temporary variable referencing an object I've defined for CAN messages, some of the members of which are lists. I put elements in these lists with a method based on the next handful of lines in the file.
Now when I'm done with this temporary object, I add it to the CAN database object. Since I no longer need the data referenced by this variable, I assign the value None to it and reinstantiate the clean slate variable on the next iteration through that detects a message descriptor. Or that was the plan.
When I go through the next iteration and need to use this variable, I add some values to these lists and find that they're not actually empty. It seems that despite assigning the variable to reference None the values in the lists persisted and were not cleaned up.
Below you can see my solution which was to stack more methods on specifically to get rid of the persisting list elements.
Here's some relevant portions of the file:
Parsing Loop
for line in file:
line = line.rstrip('\n')
line_number += 1 # keep track of the line number for error reporting
if line.startswith("BU_:"):
self._parseTransmittingNodes(line)
elif line.startswith("BO_"):
can_msg = self._parseMessageHeader(line).ResetSignals().ResetAttributes()
building_message = True
elif line.startswith(" SG_") and building_message:
can_msg.AddSignal(self._parseSignalEntry(line))
# can_msg.updateSubscribers()
elif line == "":
if building_message:
building_message = False
self._messages += [can_msg]
can_msg = None
Reset Methods
def ResetSignals(self):
"""
Flushes all the signals from the CANMessage object.
"""
self._signals = []
return self
def ResetAttributes(self):
"""
Flushes all the attributes from the CANMessage object.
"""
self._attributes = []
return self
How can I make this variable a fresh object every time? Should I have a method that clears all of it's internals instead of assigning it None like the IDispose interface in C#?
EDIT: Here's the full source for the CANMessage object:
class CANMessage:
"""
Contains information on a message's ID, length in bytes, transmitting node,
and the signals it contains.
"""
_name = ""
_canID = None
_idType = None
_dlc = 0
_txNode = ""
_comment = ""
_signals = list()
_attributes = list()
_iter_index = 0
_subscribers = list()
def __init__(self, msg_id, msg_name, msg_dlc, msg_tx):
"""
Constructor.
"""
self._canID = msg_id
self._name = msg_name
self._dlc = msg_dlc
self._txNode = msg_tx
def __iter__(self):
"""
Defined to make the object iterable.
"""
self._iter_index = 0
return self
def __next__(self):
"""
Defines the next CANSignal object to be returned in an iteration.
"""
if self._iter_index == len(self._signals):
self._iter_index = 0
raise StopIteration
self._iter_index += 1
return self._signals[self._iter_index-1]
def AddSignal(self, signal):
"""
Takes a CANSignal object and adds it to the list of signals.
"""
self._signals += [signal]
return self
def Signals(self):
"""
Gets the signals in a CANMessage object.
"""
return self._signals
def SetComment(self, comment_str):
"""
Sets the Comment property for the CANMessage.
"""
self._comment = comment_str
return self
def CANID(self):
"""
Gets the message's CAN ID.
"""
return self._canID
def AddValue(self, value_tuple):
"""
Adds a enumerated value mapping to the appropriate signal.
"""
for signal in self:
if signal.Name() == value_tuple[0]:
signal.SetValues(value_tuple[2])
break
return self
def AddAttribute(self, attr_tuple):
"""
Adds an attribute to the message.
"""
self._attributes.append(attr_tuple)
return self
def ResetSignals(self):
"""
Flushes all the signals from the CANMessage object.
"""
self._signals = []
return self
def ResetAttributes(self):
"""
Flushes all the attributes from the CANMessage object.
"""
self._attributes = []
return self
def Name(self):
return self._name
def TransmittingNode(self):
return self._txNode
def DLC(self):
return self._dlc
The problem you're seeing is because you used class attributes instead of instance attributes. If you move the initialization of the attributes you don't pass to __init__ from class scope into __init__, each instance will have its own set of lists.
Here's what that would look like:
class CANMessage:
"""
Contains information on a message's ID, length in bytes, transmitting node,
and the signals it contains.
"""
def __init__(self, msg_id, msg_name, msg_dlc, msg_tx):
"""
Constructor.
"""
self._canID = msg_id
self._name = msg_name
self._dlc = msg_dlc
self._txNode = msg_tx
self._name = ""
self._canID = None
self._idType = None
self._dlc = 0
self._txNode = ""
self._comment = ""
self._signals = list()
self._attributes = list()
self._iter_index = 0
self._subscribers = list()
# the rest of the class is unchanged, and not repeated here...

Python: referencing class object list of lists

I am fairly new to python. I have tried to define a class, I then want to create an instance from a file, then refer to specific pieces of it, but cannot seem to. This is Python 3.3.0
Here's the class....
class Teams():
def __init__(self, ID = None, Team = None, R = None, W = None, L = None):
self._items = [ [] for i in range(5) ]
self.Count = 0
def addTeam(self, ID, Team, R=None, W = 0, L = 0):
self._items[0].append(ID)
self._items[1].append(Team)
self._items[2].append(R)
self._items[3].append(W)
self._items[4].append(L)
self.Count += 1
def addTeamsFromFile(self, filename):
inputFile = open(filename, 'r')
for line in inputFile:
words = line.split(',')
self.addTeam(words[0], words[1], words[2], words[3], words[4])
def __len__(self):
return self.Count
Here's the code in Main
startFileName = 'file_test.txt'
filename = startFileName
###########
myTestData = Teams()
myTestData.addTeamsFromFile(startFileName)
sample data in file
100,AAAA,106,5,0
200,BBBB,88,3,2
300,CCCC,45,1,4
400,DDDD,67,3,2
500,EEEE,90,4,1
I think I am good to here (not 100% sure), but now how do I reference this data to see... am i not creating the class correctly? How do I see if one instance is larger than another...
ie, myTestData[2][2] > myTestData[3][2] <----- this is where I get confused, as this doesn't work
Why don't you create a Team class like this :
class Team():
def __init__(self, ID, Team, R=None, W = 0, L = 0)
# set up fields here
Then in Teams
class Teams():
def __init__(self):
self._teams = []
def addTeam (self, ID, Team, R=None, W = 0, L = 0)
team = Team (ID, Team, R=None, W = 0, L = 0)
self._teams.append (team)
Now If i got it right you want to overwrite the > operator's behaviour.
To do that overload __gt__(self, other) [link]
So it will be
class Team ():
# init code from above for Team
def __gt__ (self, otherTeam):
return self.ID > otherTeam.ID # for example
Also be sure to convert those strings to numbers because you compare strings not numbers. Use int function for that.
The immediate problem you're running into is that your code to access the team data doesn't account for your myTestData value being an object rather than a list. You can fix it by doing:
myTestData._items[2][2] > myTestData._items[3][2]
Though, if you plan on doing that much, I'd suggest renaming _items to something that's obviously supposed to be public. You might also want to make the addTeamsFromFile method convert some of the values it reads to integers (rather than leaving them as strings) before passing them to the addTeam method.
An alternative would be to make your Teams class support direct member access. You can do that by creating a method named __getitem__ (and __setitem__ if you want to be able to assign values directly). Something like:
def __getitem__(self, index):
return self._items[index]
#Aleksandar's answer about making a class for the team data items is also a good one. In fact, it might be more useful to have a class for the individual teams than it is to have a class containing several. You could replace the Teams class with a list of Team instances. It depends on what you're going to be doing with it I guess.

Class design: Last Modified

My class:
class ManagementReview:
"""Class describing ManagementReview Object.
"""
# Class attributes
id = 0
Title = 'New Management Review Object'
fiscal_year = ''
region = ''
review_date = ''
date_completed = ''
prepared_by = ''
__goals = [] # List of <ManagementReviewGoals>.
__objectives = [] # List of <ManagementReviewObjetives>.
__actions = [] # List of <ManagementReviewActions>.
__deliverables = [] # List of <ManagementReviewDeliverable>.
__issues = [] # List of <ManagementReviewIssue>.
__created = ''
__created_by = ''
__modified = ''
__modified_by = ''
The __modified attribute is a datetime string in isoformat. I want that attribute to be automatically to be upated to datetime.now().isoformat() every time one of the other attributes is updated. For each of the other attributes I have a setter like:
def setObjectives(self,objectives):
mro = ManagementReviewObjective(args)
self.__objectives.append(mro)
So, is there an easier way to than to add a line like:
self.__modified = datetime.now().isoformat()
to every setter?
Thanks! :)
To update __modified when instance attributes are modified (as in your example of self.__objectives), you could override __setattr__.
For example, you could add this to your class:
def __setattr__(self, name, value):
# set the value like usual and then update the modified attribute too
self.__dict__[name] = value
self.__dict__['__modified'] = datetime.now().isoformat()
Perhaps adding a decorator before each setter?
If you have a method that commits the changes made to these attributes to a database (like a save() method or update_record() method. Something like that), you could just append the
self.__modified = datetime.now().isoformat()
just before its all committed, since thats the only time it really matters anyway.

Categories