Improving code for similar code found - python

I passed codeclimate to my code, and I obtained the following:
Similar code found in 1 other location
This is my code:
stradd = 'iterable_item_added'
if stradd in ddiff:
added = ddiff[stradd]
npos_added = parseRoots(added)
dics_added = makeAddDicts(localTable, pk, npos_added)
else:
dics_added = []
strchanged = 'values_changed'
if strchanged in ddiff:
updated = ddiff[strchanged]
npos_updated = parseRoots(updated)
dics_updated = makeUpdatedDicts(localTable, pk, npos_updated)
else:
dics_updated = []
Where iterable_item_added and values_changed are repeated. How to change it?

just abstract the parameters and create an helper method:
def testmethod(name,localTable,m,ddiff,pk):
if name in ddiff:
npos = parseRoots(ddiff[name])
rval = m(localTable, pk, npos)
else:
rval = []
return rval
the call it:
dics_added = testmethod('iterable_item_added',localTable,makeAddDicts,ddiff,pk)
dics_updated = testmethod('values_changed',localTable,makeUpdatedDicts,ddiff,pk)
note: be careful when factorizing code, you can introduce bugs (and make code better readable :)).
Also: that helper method forces to pass a lot of local variables. Maybe creating an object and member variables would simplify even more.
In that case, it appears to be a bit "overkill" to do that in order to make your review tool shut up.

Related

Django Python Where to add Auxiliary Functions to not repeat code?

I come from native POO programming languages and I'm new in Python, also Django.
I see that in Django they put all code from an app in same views.py or models.py.
Now I'm in a view called:
def create_ticket(self):
....
And inside I have this code
is_staff=User.objects.get(pk=request.user.id).is_staff
if is_staff==1:
R_Client_Accountant = LinkUserContable.objects.filter(contable=mongoId)
print(R_Client_Accountant)
accountantList = []
for relation in R_Client_Accountant:
try:
rmongosql = RMongoSql.objects.get(mongoId=relation.user.id)
user = User.objects.get(pk=rmongosql.helpdeskId)
accountantList.append((user.id,user.username))
except:
pass
else:
R_Client_Accountant = LinkUserContable.objects.filter(user=mongoId)
accountantList = []
for relation in R_Client_Accountant:
try:
rmongosql = RMongoSql.objects.get(mongoId=relation.contable.id)
user = User.objects.get(pk=rmongosql.helpdeskId)
accountantList.append((user.id,user.username))
except:
pass
As you can see I repeat code inside the 'try' just exchanging {user XOR contable}
If I want to write a function passing by parameter this {user XOR contable} where should I place it ?
To me, in corresponding model from models.py is not correct because there are so much code lines referring to different models and views.py is just for view functions right ?
Regards,
VĂ­ctor.
you can use the getattr function to use a string to get the required attribute getattr(relation, relation_attr)
your function would look like this
def create_ticket(self):
is_staff=User.objects.get(pk=request.user.id).is_staff
if is_staff==1:
relation_attr = 'user'
else:
relation_attr = 'contable'
R_Client_Accountant = LinkUserContable.objects.filter(contable=mongoId)
print(R_Client_Accountant)
accountantList = []
for relation in R_Client_Accountant:
try:
rmongosql = RMongoSql.objects.get(mongoId=getattr(relation, relation_attr).id)
user = User.objects.get(pk=rmongosql.helpdeskId)
accountantList.append((user.id, user.username))
except:
pass

Python Dict Switcher results in memory leak

I have extensively read about immutable and mutable objects in Python for a couple of months now and I seem to begin to understand the concept. Still I cannot spot the problem why my code below produces memory leaks. The dicts function as references to immutable records of specific type. In many cases, I get an update of an existing record, in this case, the existing record will only be updated if the two records (oldrecord and newrecord) are not equal. However, I have the feeling that newrecord gets never deleted if oldrecord and newrecord match, although all references appear to cease to exist in such a case.
My question:
Is the code below good practice for selecting a reference to a dict based on record type or should I do it differently (e.g. through dictSwitcher)?
class myRecordDicts():
def __init__(self, type1Dict=dict(), type2Dict=dict(),
type3Dict=dict(),type4Dict=dict(),type5Dict=dict(),type6Dict=dict(), type7Dict=dict()):
self.type1Dict = type1Dict
self.type2Dict = type2Dict
self.type3Dict = type3Dict
self.type4Dict = type4Dict
self.type5Dict = type5Dict
self.type6Dict = type6Dict
self.type7Dict = type7Dict
def dictSelector(self, record):
dictSwitcher = {
myCustomRecordType1().name: self.type1Dict,
myCustomRecordType2().name: self.type2Dict,
myCustomRecordType3().name: self.type3Dict,
myCustomRecordType4().name: self.type4Dict,
myCustomRecordType5().name: self.type5Dict,
myCustomRecordType6().name: self.type6Dict,
myCustomRecordType7().name: self.type7Dict,
}
return dictSwitcher.get(record.name)
def AddRecordToDict(self, newrecord):
dict = self.dictSelector(newrecord)
recordID = newrecord.id
if recordID in dict:
oldrecord = dict[recordID]
self.MergeExistingRecords(oldrecord,newrecord)
else:
dict[recordID] = newrecord
def MergeExistingRecords(self, oldrecord, newrecord):
# Basic Compare function
oldRecordString = oldrecord.SerializeToString()
newRecordString = newrecord.SerializeToString()
# no need to do anything if same length
if not len(oldRecordString) == len(newRecordString):
oldrecord.CustomMergeFrom(newrecord)
Well, it seems always like that: I was working for hours on this problem and could not make progress. 5 Minutes after formulating the question correctly on StackExchange, I found my issue:
I needed to remove the references in init since I was never passing dicts when instantiating myRecordsDicts(), the following code does not leak memory:
class myRecordDicts():
def __init__(self):
self.type1Dict = dict()
self.type2Dict = dict()
self.type3Dict = dict()
self.type4Dict = dict()
self.type5Dict = dict()
self.type6Dict = dict()
self.type7Dict = dict()

Redefine Class Instances in Python

I am migrating a project I have from being littered with globals variables to actually have a structure defined by classes defined in a separate module. This is my first time really using OOP so want to understand if it is safe to re-define an instance of a Class or if my code is missing something.
At the top of my code, I import my module -
import NHLGameEvents
config = configparser.ConfigParser()
config.read('config.ini')
TEAM_BOT = config['DEFAULT']['TEAM_NAME']
I then build two Team objects (defined in my NHLGameEvents module).
game_today, game_info = is_game_today(get_team(TEAM_BOT))
awayteam_info = game_info["teams"]["away"]["team"]
awayteamobj_name = awayteam_info["name"]
awayteamobj_shortname = awayteam_info["teamName"]
awayteamobj_tri = awayteam_info["abbreviation"]
away_team_obj = NHLGameEvents.Team(
awayteamobj_name, awayteamobj_shortname, awayteamobj_tri, "away")
game_obj.register_team(away_team_obj, "away")
hometeam_info = game_info["teams"]["home"]["team"]
hometeamobj_name = hometeam_info["name"]
hometeamobj_shortname = hometeam_info["teamName"]
hometeamobj_tri = hometeam_info["abbreviation"]
home_team_obj = NHLGameEvents.Team(
hometeamobj_name, hometeamobj_shortname, hometeamobj_tri, "home")
game_obj.register_team(home_team_obj, "home")
home_team_obj.preferred = bool(home_team_obj.team_name == TEAM_BOT)
away_team_obj.preferred = bool(away_team_obj.team_name == TEAM_BOT)
In some instances, I want to reference these Team objects as preferred and other as opposed to home / away so I use a method defined in my Game class to retrieve that. Since my Game object knows about both of my Teams, the method in my Game class that returns this Tuple is -
def register_team(self, team, key):
"""Registers a team to the instance of the Game."""
if key not in ('home', 'away'):
raise AttributeError(
"Key '{}' is not valid - Team key can only be home or away.".format(key))
if len(self.teams) > 1:
raise ValueError(
"Too many teams! Cannot register {} for {}".format(team, self))
self.teams[key] = team
team.game = self
team.tv_channel = self.broadcasts[key]
def get_preferred_team(self):
"""Returns a Tuple of team objects of the preferred & other teams."""
if self.teams["home"].preferred is True:
return (self.teams["home"], self.teams["away"])
return (self.teams["away"], self.teams["home"])
I can then retrieve that information from anywhere in my script.
preferred_team_obj, other_team_obj = game_obj.get_preferred_team()
Is it safe to redefine these class instances (ex - home_team_obj also known as preferred_team_obj) or should I just use an if statement whenever I want to reference these, such as -
if home_team_obj.preferred:
# Do something with home_team_obj
else:
# Do something with away_team_obj
Just as a follow up to this question, it seems that is totally safe to refer to assign an object to another name for use later in the code with no issues (as per the example below).
preferred_team = game.preferred_team
preferred_homeaway = preferred_team.home_away
on_ice = json_feed["liveData"]["boxscore"]["teams"][preferred_homeaway]["onIce"]
players = json_feed["gameData"]["players"]
if recent_event(play):
get_lineup(game, event_period, on_ice, players)

In Python 2.7, how can I return calculations without defining variables in the constructor?

My question is about getter/setter-type functionality in Python. I have a class, Week_Of_Meetings, that takes a blob of data from my Google Calendar and does some calculations on it.
wom = Week_Of_Meetings(google_meetings_blob)
I want to be able to return something like:
wom.total_seconds_in_meetings() # returns 36000
But, I'm not understanding how the getters/setters-type #property decorator can help me do this. In Java, I would use member variables, but you don't interact with them the same way in Python. How can I return calculations without starting with them in the constructor?
Class Week_Of_Meetings:
def __init__(self, google_meetings_blob)
self.google_meetings_blob = google_meetings_blob
def get_meetings_list(self, google_meetings_blob):
meetings_list = []
for meeting_id, meeting in enumerate(self.google_meetings_blob, 1):
summary = self._get_summary(meeting)
start = parse(meeting['start'].get('dateTime', meeting['start'].get('date')))
end = parse(meeting['end'].get('dateTime', meeting['end'].get('date')))
duration = end - start
num_attendees = self._get_num_attendees(meeting.get('attendees'))
m = Meeting(meeting_id, summary, start, end, duration, num_attendees)
meetings_list.append(m)
return meetings_list
def _get_summary(self, meeting):
summary = meeting.get('summary', 'No summary given')
return summary
def _get_num_attendees(self, num_attendees):
if num_attendees == None:
num_attendees = 1 # if invited only self to meeting
else:
num_attendees = len(num_attendees)
return num_attendees
When I add self.total_seconds_in_meetings to the
__init__()
I get "NameError: global name 'total_seconds_in_meetings' is not defined." That makes sense. It hasn't been defined. But I can't define it when it's supposed to be the result of calculations done on the google_meetings_blob. So, I'm confused where the 'total_seconds_in_meetings' goes in the class.
Thank you for the help!
Of course Python has member variables. How would classes work without them? You can set and get any instance data via self, as you are already doing with self.google_meetings_blob in __init__.

how to get entities which don't have certain attribute in datastore

I'm trying to make an appraisal system
This is my class
class Goal(db.Expando):
GID = db.IntegerProperty(required=True)
description = db.TextProperty(required=True)
time = db.FloatProperty(required=True)
weight = db.IntegerProperty(required=True)
Emp = db.UserProperty(auto_current_user=True)
Status = db.BooleanProperty(default=False)
Following things are given by employee,
class SubmitGoal(webapp.RequestHandler):
def post(self):
dtw = simplejson.loads(self.request.body)
try:
maxid = Goal.all().order("-GID").get().GID + 1
except:
maxid = 1
try:
g = Goal(GID=maxid, description=dtw[0], time=float(dtw[1]), weight=int(dtw[2]))
g.put()
self.response.out.write(simplejson.dumps("Submitted"))
except:
self.response.out.write(simplejson.dumps("Error"))
Now, here Manager checks the goals and approve it or not.. if approved then status will be stored as true in datastore else false
idsta = simplejson.loads(self.request.body)
try:
g = db.Query(Goal).filter("GID =", int(idsta[0])).get()
if g:
if idsta[1]:
g.Status=True
try:
del g.Comments
except:
None
else:
g.Status=False
g.Comments=idsta[2]
db.put(g)
self.response.out.write(simplejson.dumps("Submitted"))
except:
self.response.out.write(simplejson.dumps("Error"))
Now, this is where im stuck..."filter('status=',True)".. this is returning all the entities which has status true.. means which are approved.. i want those entities which are approved AND which have not been assessed by employee yet..
def get(self):
t = []
for g in Goal.all().filter("Status = ",True):
t.append([g.GID, g.description, g.time, g.weight, g.Emp])
self.response.out.write(simplejson.dumps(t))
def post(self):
idasm = simplejson.loads(self.request.body)
try:
g = db.Query(Goal).filter("GID =", int(idasm[0])).get()
if g:
g.AsmEmp=idasm[1]
db.put(g)
self.response.out.write(simplejson.dumps("Submitted"))
except:
self.response.out.write(simplejson.dumps("Error"))
How am I supposed to do this? as I know that if I add another filter like "filter('AsmEmp =', not None)" this will only return those entities which have the AsmEmp attribute what I need is vice versa.
You explicitly can't do this. As the documentation states:
It is not possible to query for entities that are missing a given property.
Instead, create a property for is_assessed which defaults to False, and query on that.
could you not simply add another field for when employee_assessed = db.user...
and only populate this at the time when it is assessed?
The records do not lack the attribute in the datastore, it's simply set to None. You can query for those records with Goal.all().filter('status =', True).filter('AsmEmp =', None).
A few incidental suggestions about your code:
'Status' is a rather unintuitive name for a boolean.
It's generally good Python style to begin properties and attributes with a lower-case letter.
You shouldn't iterate over a query directly. This fetches results in batches, and is much less efficient than doing an explicit fetch. Instead, fetch the number of results you need with .fetch(n).
A try/except with no exception class specified and no action taken when an exception occurs is a very bad idea, and can mask a wide variety of issues.
Edit: I didn't notice that you were using an Expando - in which case #Daniel's answer is correct. There doesn't seem to be any good reason to use Expando here, though. Adding the property to the model (and updating existing entities) would be the easiest solution here.

Categories