Anaconda Spyder - Class Attributes Autocompletion - python

I have a couple of Classes defined.
Both of these classes take a json file as input, and extract the data into a class instance, and places them into a dictionary.
So all of my EmployeeProfile instances are stored in a dictionary called SP, with the employees email as the key, and the class instance as the value.
All of my RiskProfile instances are stored in a dictionary called RISKS, with the risk_ID as the key and the class instance as the value.
class EmployeeProfile:
def __init__(self, profile):
self.displayname = profile.get('displayName')
self.email = profile.get('email')
self.firstname = profile.get('firstName')
self.surname = profile.get('surname')
self.fullname = profile.get('fullName')
self.costcode = profile.get('work').get('custom')\
.get('Cost Category_t9HHc')
self.title = profile.get('work').get('title')
self.department = profile.get('work').get('department')
self.city = profile.get('work').get('site')
self.id = profile.get('work').get('employeeIdInCompany')
self.manageremail = ''
self.costline = 'N/A'
self.groups = {}
self.attest = {}
class RiskProfile:
def __init__(self, risk_profile):
self.ID = risk_profile.get('ID')
self.key = risk_profile.get('Key')
self.name = risk_profile.get('Name')
self.description = risk_profile.get('Description', '')
self.owner = risk_profile.get("Owner_DisplayName")
self.assignedto = risk_profile.get("AssignedTo_DisplayName")
self.email = None
self.costline = ''
self.notes = ''
self.assessmentlevel = int(risk_profile.get("AssessmentLevel"))
self.rating = ''
self.workflow = risk_profile.get('WorkflowState')
Now when I do something like:
for profile in SP:
print(SP[profile].{here i see the attribute of the class instance})
So I can see a selection of the attributes I may want to print or change etc...
print(SP[profile].department)
or
print(SP[profile].name)
However when I do the same for RiskProfile instances I do not get the list of attributes.
If I enter them manually my code still works, but does anyone know why this is not working the same way?
for profile in RISKS:
print(RISK[profile].{I never get a list of attributes})
I use Anaconda with Spyder.

Related

Creating a class property using a function

I found this fantasy name generator here.
I am trying to adapt the code to suit my purpose. I want to create an NPC name automatically, using the function name_gen within the class NPC. With the NPC characteristics being:
class NPC:
def __init__(self, name, age, gender):
self.name = name_gen
self.age = 25
self.gender = M
The code from the name generator I need is the following:
from random import randrange
def line_appender(file_path, target):
file = open(file_path, "r")
splitfile = file.read().splitlines()
for line in splitfile:
target.append(line)
def name_selector(target_list):
selected = target_list[randrange(len(target_list))]
return selected
def name_builder(first_name_list_path, last_name_list_path):
first_name_list = []
last_name_list = []
line_appender(first_name_list_path, first_name_list)
line_appender(last_name_list_path, last_name_list)
first_name_selected = name_selector(first_name_list)
last_name_selected = name_selector(last_name_list)
name = first_name_selected+" "+last_name_selected
return name
Now the only thing I think I still need to do, is to generate the name from within the class NPC. I thought doing something like:
def name_gen
if gender == "M":
name = name_builder("first_name_male.txt", "last_name.txt")
elif gender == "F":
name = name_builder("first_name_female.txt", "last_name.txt")
But I don't understand how to make the name_gen function check the class NPC properties,
so that it generates the desired name.
Could someone perhaps help me out?
EDIT
Thank you for all the solutions! I am pretty new to Python; In order to test Samwises solution, I tried to run it as a separate script (in order to check whether I would get a name) with the code below. It does however not print anything. I'm putting this in an EDIT because I think it might be a trivial question. If it is worth posting a separate question, please let me know:
import random
running = True
npc_input_messsage = "npc = NPC(25, 'M')"
class NameChooser:
def __init__(self, file_path):
with open(file_path) as f:
self._names = f.read().splitlines()
def choice(self):
return random.choice(self._names)
first_choosers = {
"M": NameChooser("first_name_male.txt"),
"F": NameChooser("first_name_female.txt"),
}
last_chooser = NameChooser("last_name.txt")
def name_gen(gender):
return f"{first_choosers[gender].choice()} {last_chooser.choice()}"
class NPC:
def __init__(self, age, gender):
self.name = name_gen(gender)
self.age = age
self.gender = gender
while running:
npc = input(npc_input_messsage)
# I'm entering npc = NPC(25, "M")
print(npc)
Your name generator is a little over-complicated IMO. I'd suggest wrapping all the file reading and name selection stuff in a simple class so you can define it once and then instantiate it for each of your name lists. Putting the file reading part in __init__ means you only do it once per list instead of re-reading the file each time you need to pick a name.
import random
class NameChooser:
def __init__(self, file_path):
with open(file_path) as f:
self._names = f.read().splitlines()
def choice(self):
return random.choice(self._names)
Now you can define three NameChoosers and a name_gen function that picks among them:
first_choosers = {
"M": NameChooser("first_name_male.txt"),
"F": NameChooser("first_name_female.txt"),
}
last_chooser = NameChooser("last_name.txt")
def name_gen(gender):
return f"{first_choosers[gender].choice()} {last_chooser.choice()}"
And now you can define an NPC class that takes age and gender as arguments to the constructor, and picks a random name using name_gen():
class NPC:
def __init__(self, age, gender):
self.name = name_gen(gender)
self.age = age
self.gender = gender
def __str__(self):
return f"{self.name} ({self.age}/{self.gender})"
npc = NPC(25, "M")
print(npc) # prints "Bob Small (25/M)"
I think you're confused about OOP concepts.
First, let's edit your class:
class NPC:
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
See, I have assigned parameter values to the attributes.
Now let's make changes to your function:
def name_gen(gender):
if gender == "M":
name = name_builder("first_name_male.txt", "last_name.txt")
elif gender == "F":
name = name_builder("first_name_female.txt", "last_name.txt")
return name
Here I have added a parameter to your function since you're using its value.
Now let's create an instance for your class.
npc = NPC("Vishwas", 25, "M") # Instance of the class
print(name_gen(npc.gender)) # Print generated name
A straightforward way to make happen automatically would be to simply call the name generator from with the NPC.__init__() method. In the code below it's been made a private method of the class by starting its name with an underscore character. Note that the call to it has to wait until all the instance attributes it references have been assigned value.
from random import randrange
class NPC:
def __init__(self, age, gender):
self.age = age
self.gender = gender
self.name = self._name_gen()
def _name_gen(self):
if self.gender == "M":
name = name_builder("first_name_male.txt", "last_name.txt")
elif self.gender == "F":
name = name_builder("first_name_female.txt", "last_name.txt")
return name
def line_appender(file_path, target):
file = open(file_path, "r")
splitfile = file.read().splitlines()
for line in splitfile:
target.append(line)
def name_selector(target_list):
selected = target_list[randrange(len(target_list))]
return selected
def name_builder(first_name_list_path, last_name_list_path):
first_name_list = []
last_name_list = []
line_appender(first_name_list_path, first_name_list)
line_appender(last_name_list_path, last_name_list)
first_name_selected = name_selector(first_name_list)
last_name_selected = name_selector(last_name_list)
name = first_name_selected+" "+last_name_selected
return name
if __name__ == '__main__':
npc1 = NPC(25, 'M')
print(f'{npc1.name!r}')
npc2 = NPC(21, 'F')
print(f'{npc2.name!r}')

Get object from a list in Python?

I am trying to get one account from some branch but somewhere i am missing something. This line is from method -> but the result is <main.SavingAccount object at 0x000001F2563CEFD0>
class Branch:
def __init__(self, branch_code, city):
self.branch_code = branch_code
self.city = city
self.account_list = []
self.loan_list = []
def getAccount(self, acc_no):
for account in self.account_list:
if account.acc_no == acc_no:
return account
print(f2.getAccount(300005))
try this:
class Branch:
def __init__(self, branch_code, city):
self.branch_code = branch_code
self.city = city
self.account_list = []
self.loan_list = []
def getAccount(self, acc_no):
for account in self.account_list:
if account == acc_no:
return account
f2 = Branch(123,"NY")
f2.account_list=[111,222,300005]
print(f2.getAccount(300005))

Create Model for 4-D kind of array in Django

I have some logic constructed for my Database for a Django webapp but I am quite unable to convert it into Model form that can be used in Models.py :
User : U
Transaction-ID : T
Datetime : D
Transaction-ID Status-1 for a today : A[0]
Transaction-ID Status-2 for a today : A[1]
Transaction-ID Status-3 for a today : A[2]
For above a logic can be constructed with N users : U[N] where U[i] -> T[i][] transaction, and each transaction has 3 transactional attributes T[j] -> A[j][3]. How should I proceed with constructing a model for the given details. Also if possible how can I store date wise Model for the three A[k] statuses of Transaction and add them for a week wise and month wise average and proceed with making the db.
meaning :
A particular user could have done variable number of Transactions, and for each transaction there is a key provided used to get the status of that particular transaction. Like the power points earned, bonus points earned and fame points earned. For periodically updating the 3 points earned daily, weekly and monthly across all transactions done by that user and storing them in the Database for each and every user what should be done.
It would have been easier in C++ but since my project is based on SQLite that runs inbuilt with Django framework it's hard to understand how many models should be used and how to link them to implement this system. Any advice would be appreciated.
4-D perspective is because of : entry = U[N][M][3][D]
I put some part of my project for this purpose and apologize for not summarizing the code in this answer (because I think summarizing it maybe would have mistakes without test so I decided used copy-paste a tested code).
When I want to read four nested Django admin model (4D) and use them in the code, I did the following procedures:
models.py:
from __future__ import unicode_literals
from django.db import models
from django.db.models.deletion import CASCADE
MODBUS_TYPES = (('tcp', 'Tcp'), ('udp', 'Udp'), ('ascii', 'Ascii'), ('rtu', 'Rtu'))
class BatteryMonitoringServer(models.Model):
enable = models.BooleanField(default=True)
name = models.CharField(max_length=150)
server_ip = models.GenericIPAddressField(default='0.0.0.0', null=True)
def __str__(self):
return self.name
class BatteryMonitoringDevice(models.Model):
bm_id = models.ForeignKey(BatteryMonitoringServer, on_delete=CASCADE)
enable = models.BooleanField(default=True)
name = models.CharField(max_length=100, null=True)
method = models.CharField(max_length=5, choices=MODBUS_TYPES)
bm_device_ip = models.GenericIPAddressField(default='127.0.0.1', null=True)
bm_device_port = models.IntegerField(default=5558, null=True)
baud_rate = models.IntegerField(null=True, default=9600)
class BatteryMonitoringSubDevice(models.Model):
enable = models.BooleanField(default=True)
name = models.CharField(max_length=100)
unit = models.IntegerField(default=1)
sub_bm_count = models.IntegerField(default=4, null=True, blank=True, name='bm')
fk = models.ForeignKey(BatteryMonitoringDevice, on_delete=CASCADE)
class BatteryMonitoringMeta(models.Model):
key = models.CharField(max_length=100)
value = models.CharField(max_length=100)
module = models.ForeignKey(BatteryMonitoringSubDevice, on_delete=CASCADE)
conf_reader.py
from battery_monitoring.models import BatteryMonitoringServer
from delta_device.utility import DictEncoder
class BMSubDeviceConf(object):
def __init__(
self,
start,
name,
unit,
bm,
meta_data):
self._start = start
self._name = name
self._unit = unit
self._bm = bm
self._meta_data = meta_data
#property
def start(self):
return self._start
#property
def name(self):
return self._name
#property
def unit(self):
return self._unit
#property
def bm(self):
return self._bm
#property
def meta_data(self):
return self._meta_data
class BMDeviceConf(object):
def __init__(
self,
bm_id,
start,
name,
method,
bm_device_ip,
bm_device_port,
baud_rate,
sub_devices=None):
self._id = bm_id
self._start = start
self._name = name
self._method = method
self._bm_device_ip = bm_device_ip
self._bm_device_port = bm_device_port
self._baud_rate = baud_rate
self._sub_devices = sub_devices or []
def add_sub_device(self, sub_device):
self._sub_devices.append(sub_device)
def get_sub_devices(self):
return self._sub_devices
#property
def start(self):
return self._start
#property
def id(self):
return self._id
#property
def name(self):
return self._name
#property
def bm_device_ip(self):
return self._bm_device_ip
#property
def bm_device_port(self):
return self._bm_device_port
#property
def baud_rate(self):
return self._baud_rate
class BMConf(object):
def __init__(
self,
start,
name,
server_ip,
devices=None,
): # :( :| :) (: :p
self._start = 'ON' if start else 'OFF'
self._name = name
self._server_ip = server_ip
self._devices = devices or []
def add_device(self, device):
self._devices.append(device)
def get_devices(self):
return self._devices
#property
def start(self):
return self._start
#property
def name(self):
return self._name
#property
def server_ip(self):
return self._server_ip
def get_server():
"""Using list method to make a fast sql reading."""
return list(BatteryMonitoringServer.objects.all())
def get_devices(dev):
return list(dev.batterymonitoringdevice_set.all())
def get_sub_devices(sub_dev):
return list(sub_dev.batterymonitoringsubdevice_set.all())
def get_metadata(metric):
return list(metric.batterymonitoringmeta_set.all())
class BMReadConf(object):
"""BM configuration Reader"""
def __init__(self):
pass
#classmethod
def get_bm_config(cls):
"""Read BM metrics and return it on a object list"""
result = list()
for srv in get_server():
data = BMConf(srv.enable,
srv.name,
srv.server_ip,)
for dev in get_devices(srv):
device = BMDeviceConf(
dev.bm_id,
dev.enable,
dev.name,
dev.method,
dev.bm_device_ip,
dev.bm_device_port,
dev.baud_rate,
)
for sub_dev in get_sub_devices(dev):
meta_data = {}
for meta in get_metadata(sub_dev):
meta_data[meta.key] = meta.value
sub_device = BMSubDeviceConf(
sub_dev.enable,
sub_dev.name,
sub_dev.unit,
sub_dev.bm,
meta_data,
)
device.add_sub_device(sub_device)
data.add_device(device)
result.append(data)
return result
Usage (test.py)
from battery_monitoring.conf_reader import BMReadConf
conf_obj = BMReadConf()
configs = conf_obj.get_bm_config()
for cnf in configs:
print(cnf.name) # This is name field in BatteryMonitoringServer Table.
devices = cnf.get_devices()
for dev in devices:
print(dev.baud_rate) # This is baud_rate field in second nested table.
sub_devices = dev.get_sub_devices()
for sub_dev in sub_devices:
print(sub_dev.unit) # This is unit field in third nested table.
print(sub_dev.meta_data) # This is meta_data table (fourth nested table).
I hope this would be useful.
[NOTE]:
Fourth nested table (meta_data) has a incremented key/value fields.

Python object scoping issues

I need some help understanding python scoping with classes.
For instance this is a perfectly valid program, which makes sense to me
import json
class Person(object):
def __init__(self, firstname, lastname, age,address):
self.firstname = firstname
self.age = age
self.lastname = lastname
self.address = address
class Address(object):
def __init__(self,zipcode,state):
self.zipcode = zipcode
self.state = state
personlist = []
for count in range(5):
address = Address("41111","statename")
person = Person("test","test",21,address)
print(count)
personlist.append(person)
jsonlist = []
for Person in personlist:
print Person.firstname
d = {}
d['firstname'] = Person.firstname
d['lastname'] = Person.lastname
d['age'] = Person.age
d['zipcode'] = Person.address.zipcode
d['state'] = Person.address.state
jsonlist.append(d)
jsondict = {}
jsondict["People"] = jsonlist
jsondict["success"] = 1
json_data = json.dumps(jsondict, indent =4)
print json_data
But this next program gives me an error
import json
class Person(object):
def __init__(self, firstname, lastname, age,address):
self.firstname = firstname
self.age = age
self.lastname = lastname
self.address = address
class Address(object):
def __init__(self,zipcode,state):
self.zipcode = zipcode
self.state = state
def main():
personlist = []
for count in range(5):
address = Address("41111","statename")
person = Person("test","test",21,address)
print(count)
personlist.append(person)
jsonlist = []
for Person in personlist:
print Person.firstname
d = {}
d['firstname'] = Person.firstname
d['lastname'] = Person.lastname
d['age'] = Person.age
d['zipcode'] = Person.address.zipcode
d['state'] = Person.address.state
jsonlist.append(d)
jsondict = {}
jsondict["People"] = jsonlist
jsondict["success"] = 1
json_data = json.dumps(jsondict, indent =4)
print json_data
main()
My question is why creating the classes in white space valid but creating them inside a function not valid. Is there any way to create them in the main function and it be valid?
EDIT:
Error is
File "jsontest.py", line 9, in main
person = Person("test","test",21,address)
UnboundLocalError: local variable 'Person' referenced before assignment
The problem is that you use a variable with the same name as your class Person (also called "shadowing"):
for Person in personlist:
Python detects that you use it as a local variable and raises an error:
UnboundLocalError: local variable 'Person' referenced before
assignment
which means that you try to use a local variable before it was assigned in the following line:
person = Person("test","test",21,address)
You can find more information about it here

Unit testing: More Actions than Expected after calling addAction Method

Here is my class:
class ManagementReview(object):
"""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 = ''
def __init__(self,Title='',id=0,fiscal_year='',region='',review_date='',
date_completed='',prepared_by='',created='',created_by='',
modified='',modified_by=''):
"""Instantiate object.
"""
if id:
self.setId(id)
if Title:
self.setTitle(Title)
if fiscal_year:
self.setFiscal_year(fiscal_year)
if region:
self.setRegion(region)
if review_date:
self.setReview_date(review_date)
if date_completed:
# XXX TODO: validation to see if date_completed pattern matches ISO-8601
self.setDate_completed(date_completed)
if prepared_by:
self.setPrepared_by(prepared_by)
if created:
# XXX TODO: validation to see if date_completed pattern matches ISO-8601
self.setCreated(created)
else:
self.setCreated(self.getNow())
if created_by:
self.setCreated_by(created_by)
self.__modified = self.getNow()
if modified_by:
self.__modified_by = modified_by
def __str__(self):
return "<ManagementReview '%s (%s)'>" % (self.Title,self.id)
def __setattr__(self, name, value): # Override built-in setter
# set the value like usual and then update the modified attribute too
object.__setattr__(self, name, value) # Built-in
self.__dict__['__modified'] = datetime.now().isoformat()
def getActions(self):
return self.__actions
def addAction(self,mra):
self.__actions.append(mra)
def removeAction(self,id):
pass # XXX TODO
I have this test:
from datetime import datetime
import random
import unittest
from ManagementReview import ManagementReview, ManagementReviewAction
# Default Values for ManagementReviewAction Object Type
DUMMY_ID = 1
DUMMY_ACTION = 'Action 1'
DUMMY_OWNER = 'Owner 1'
DUMMY_TITLE = 'Test MR'
DUMMY_FISCAL_YEAR = '2011'
DUMMY_REGION = 'WO'
DUMMY_REVIEW_DATE = '2009-01-18T10:50:21.766169',
DUMMY_DATE_COMPLETED = '2008-07-18T10:50:21.766169'
DUMMY_PREPARED_BY = 'test user'
DUMMY_CREATED = '2002-07-18T10:50:21.766169'
DUMMY_CREATED_BY = 'test user 2'
DUMMY_MODIFIED = datetime.now().isoformat()
DUMMY_MODIFIED_BY = 'test user 3'
class TestManagementReviewSetAction(unittest.TestCase):
def setUp(self):
self.mr = ManagementReview(DUMMY_TITLE,DUMMY_ID,fiscal_year=DUMMY_FISCAL_YEAR,region=DUMMY_REGION,
review_date=DUMMY_REVIEW_DATE,date_completed=DUMMY_DATE_COMPLETED,
prepared_by=DUMMY_PREPARED_BY,created=DUMMY_CREATED,
created_by=DUMMY_CREATED_BY,modified=DUMMY_MODIFIED,
modified_by=DUMMY_MODIFIED_BY)
def tearDown(self):
self.mr = None
def test_add_action(self):
for i in range(1,11):
mra = ManagementReviewAction(i,'action '+str(i),'owner '+str(i))
self.mr.addAction(mra)
self.assertEqual(len(self.mr.getActions()),10)
def test_remove_action(self):
print len(self.mr.getActions())
for i in range(1,11):
mra = ManagementReviewAction(i,'action '+str(i),'owner '+str(i))
self.mr.addAction(mra)
self.mr.removeAction(3)
self.assertEqual(len(self.mr.getActions()),9)
if __name__ == '__main__':
unittest.main()
The first test passes. That is, self.mr.getActions() has 10 actions.
However, when I run the 2nd test, test_remove_action, the value for len(self.mr.getActions()) is 10. At this point, though, it should be 0.
Why is this?
Thanks
see if you are keeping track of actions in a class attribute of ManagementReview as opposed to an instance attribute
A class attribute will be something like
class Spam(object):
actions = []
and an instance attribute will look something like
class Spam(object):
def __init__(self):
self.actions = []
What happens is that actions = [] is executed when the class is created and all instances of the class share the same list.
EDIT:
In light of your update, I can see that this is definitely what is going on

Categories

Resources