Initialize class more efficiently in Python - python

I have this code in which I initialize a class (Adapter) by the name I get from the request.
It seems to be a bit clumsy, and I'm sure there's a better/cleaner way of doing it.
from adapters.gofirst_adapter import GoFirstAdapter
from adapters.spicejet_adapter import SpiceJetAdapter
from adapters.airasia_adapter import AirAsiaAdapter
class Adapter():
def __init__(self, adapter_name):
if(adapter_name=='goFirst'):
gofirst_adapter = GoFirstAdapter()
self.adapter = gofirst_adapter
if(adapter_name=='spiceJet'):
spicejet_adapter = SpiceJetAdapter()
self.adapter = spicejet_adapter
if(adapter_name=='airAsia'):
airasia_adapter = AirAsiaAdapter()
self.adapter = airasia_adapter
What I'm aiming at is to have a list of the adapter names such as:
adapters = ['goFirst', 'spiceJet', 'airAsia']
and create the classes by the list.
Thank you.

You can use a dict to map the parameter to the specific class:
from adapters.gofirst_adapter import GoFirstAdapter
from adapters.spicejet_adapter import SpiceJetAdapter
from adapters.airasia_adapter import AirAsiaAdapter
class Adapter():
adapters = {'goFirst':GoFirstAdapter, 'spiceJet':SpiceJetAdapter, 'airAsia':AirAsiaAdapter}
def __init__(self, adapter_name):
self.adapter = self.adapters[adapter_name]()

something like this could work:
from adapters.gofirst_adapter import GoFirstAdapter
from adapters.spicejet_adapter import SpiceJetAdapter
from adapters.airasia_adapter import AirAsiaAdapter
class Adapter():
_adapter_builders = {
"goFirst": GoFirstAdapter,
"spiceJet": SpiceJetAdapter,
"airAsia": AirAsiaAdapter,
}
def __init__(self, adapter_name):
self.adapter = self._adapter_builders[adapter_name]()
Also it will raise an exception when the key is not available in the dictionary.

Related

Django model error with nested dictionaries

I am relatively new to Django, but not to python, My model is trying to use a class (defined in a separate file) in which data is coming from a REST API, the retrieved data is in a nested dictionary. The code will run fine in python, but when I try it in Django (makemigrations), I get an error:
File "c:\blah-blah\Clone_PR.py", line 20, in GetFoundOnSelectItems
values = self._issueEdit["fields"]["customfield_13940"]["allowedValues"]
TypeError: 'NoneType' object is not subscriptable
I tried using type hints, but that does not work either.
models.py
from dal import autocomplete
from django.db import models
from django.contrib import messages
from .Login import jlogin
from .Jira_Constants import ProductionServer, TestServer, StageServer
from .Clone_PR import Issue
jira = None
issue = Issue()
class ClonePrLogin(models.Model):
username = models.CharField(max_length=30)
password = models.CharField(max_length=30)
#classmethod
def LoginToJira(cls):
global jira
jira = jlogin(ProductionServer, cls.username, cls.password)
class PrEntry(models.Model):
prToClone = models.CharField(max_length=20)
#classmethod
def GetIssueAndMeta(cls):
global issue
issue.initialize(jira, cls.prToClone)
class ClonePr(models.Model):
issueKey = issue.issueKey
issue.GetFoundOnSelectItems()
foundOnList = issue.foundOnSelectItems
foundOn = autocomplete.Select2ListChoiceField(choice_list=foundOnList)
Clone_PR.py
from typing import List, Dict
class Issue():
def __init__(self):
self.jiraInst = None
self.issueKey = ''
self._issue = None
self._issueEdit = None
# self._issueEdit = Dict[str, Dict[str, Dict[str, List[Dict[str, str]]]]]
self.foundOnSelectItems = []
def initialize(self, jira, prKey):
self.jiraInst = jira
self.issueKey = prKey
self._issue = jira.issue(prKey)
self._issueEdit = jira.editmeta(prKey)
def GetFoundOnSelectItems(self):
values = self._issueEdit["fields"]["customfield_13940"]["allowedValues"]
items = [x["value"] for x in values]
self.foundOnSelectItems = items
In Django, running makemigrations will load all the modules. You said you're familiar with Python so you should know that the declarations inside the class:
class ClonePr(models.Model):
issueKey = issue.issueKey
issue.GetFoundOnSelectItems()
foundOnList = issue.foundOnSelectItems
foundOn = autocomplete.Select2ListChoiceField(choice_list=foundOnList)
will run when the modules load. You're calling issue.GetFoundOnSelectItems() at that time, which in turn calls values = self._issueEdit["fields"]["customfield_13940"]["allowedValues"], except that self._issueEdit = None upon the initiation of instance Issue above with this line: issue = Issue().
I highly recommend you spend some time to become more familiar with how Django starts up an app. The module-level and nested model declarations here are both antipatterns and may cause data issues in the future.

Python Mock - Can't Figure Out How to Mock This Class/Function

I have this class and function to simply copy files from one place to another. As I am new to Mocking, I can't figure out how to properly test this, any assistance would be greatly appreciated, (note CFG_Dict is a dictionary with values I pass), note that this is an example and i have init that is used for multiple functions in this class.
from shutil import copy
import os
from pathlib2 import Path
class FileMover(object):
def __init__(self, cfg_dict):
self.copyto = str(Path(cfg_dict['GENERAL']['filecopylocation']))
self.worklocation = str(Path(cfg_dict['GENERAL']['fileworklocation']))
def run_file_mover(self, filename):
filename = str(Path(filename))
try:
copy(filename, self.copyto)
except ValueError:
raise
return str(Path('%s/%s' % (self.copyto, os.path.basename(filename))))
Edit:
I made some more modifications and this is my new code for testing,
class TestMover(TestCase):
def test_file_move(self):
cfg_test = {'GENERAL': {'filecopylocation': '/test/temp/', 'fileworklocation': '/test/'},
'SFTP': {'sftpserver': 'localhost', 'sftpport': '22', 'sftpuser': 'test', 'sftppw': 'test', 'sftpdestination': 'test'}}
with mock.patch('generate_reports.tools.file_mover.copy') as test_copy_function:
FileMover(cfg_test).run_file_mover("foo")
assert test_copy_function.called

Is there a way to get the parent of a dataset or group while using Group.visititems?

I am trying to put an h5py File object into a tree structure so that I can use its ability to print out a representation of the tree to display the contents of a file in the same way the linux "tree" command recursively displays the contents of a directory. The best way to recursively visit all of the items in the file is with the Group.visititems method and passing in the function I will use to add nodes to the tree. Here is what I have so far:
import h5py
import argparse
import sys
from anytree import Node, RenderTree
class HDFTree:
def __init__(self,filename):
self._file = h5py.File(filename,'r')
self._root = Node(filename)
self._node_map = {filename:self._root}
self._create_tree()
def _add_node(self,name,item):
#TODO: Figure out way to get parent of fnode
parent_node = self._node_map[item.parent] # I don't think item.parent is a thing so this wont work
self._node_map[name] = Node(name,parent=parent_node)
def _create_tree(self):
self._file.visititems(self._add_node)
def print_tree(self):
print(RenderTree(self._root))
def __del__(self):
self._file.close()
After realizing that the Dataset and Group class both indeed have a parent attribute (also pointed out by hpaulj in a comment on the question) and some cleaning up of the data, I was able to get the output that I want:
import h5py
import os
from anytree import Node, RenderTree
class HDFTree:
def __init__(self,filepath):
self._file = h5py.File(filepath,'r')
_,filename = os.path.split(filepath)
root_name,_ = os.path.splitext(filename)
self._root = Node(root_name)
self._node_map = {'':self._root}
self._create_tree()
def _add_node(self,name,item):
_,parent_name = os.path.split(item.parent.name)
parent_node = self._node_map[parent_name]
_,child_name = os.path.split(name)
self._node_map[child_name] = Node(child_name,parent=parent_node)
def _create_tree(self):
self._file.visititems(self._add_node)
def print_tree(self):
print(RenderTree(self._root))
def __del__(self):
self._file.close()
The name attribute of Dataset and Group classes apparently gives the full hdf5 path so I cleaned it up with some os.path functions.

Return DataFrame using ipywidgets Button

I'm currently creating a Class that inherits a DataFrame from pandas. I'm interested in developing a method called 'new_filter' that is a fancier execution of a DataFrame command:
import pandas as pd
from ipywidgets import widgets
from IPython.display import display
import numpy as np
class Result(pd.DataFrame):
#property
def _constructor(self):
return Result
def _filter_done(self, c):
self._column_name = self._filter_dd.value
self._expression = self._filter_txt.value
return self[eval('self.'+ self._column_name +' '+self._expression)]
def new_filter(self):
self._filter_dd = widgets.Dropdown(options=list(self.columns),
description='Column:')
self._filter_txt = widgets.Text(description='Expr:')
self._filter_button = widgets.Button(description = 'Done')
self._filter_box = widgets.VBox([self._filter_dd, self._filter_txt, self._filter_button])
display(self._filter_box)
self._filter_button.on_click(self._filter_done)
After creating an object like:
test = Result(np.random.randn(3,4), columns=['A','B','C','D']) #just an example
test_2 = test.new_filter()
Then, for example:
Widget Output
What I want is that 'test_2' be an object from 'Result' class. Is there any solution to this?
First, you will have to return something in the function new_filter. Second, if you want the same object to be modified, it is a bit hard I think. One thing you can do is to have an object which has a trait which can be updated in _filter_done.
Here is a small example of how you can do it:
import pandas as pd
from ipywidgets import widgets
from IPython.display import display
import numpy as np
class Result(pd.DataFrame):
#property
def _constructor(self):
return Result
def _filter_done(self, obj, c):
## obj is the obejct to be modified.
## Updating its data attribute to have the filtered data.
self._column_name = self._filter_dd.value
self._expression = self._filter_txt.value
obj.data = self[eval('self.'+ self._column_name +' '+self._expression)]
def new_filter(self):
self._filter_dd = widgets.Dropdown(options=list(self.columns),
description='Column:')
self._filter_txt = widgets.Text(description='Expr:')
self._filter_button = widgets.Button(description = 'Done')
self._filter_box = widgets.VBox([self._filter_dd, self._filter_txt, self._filter_button])
display(self._filter_box)
result_obj = FilterResult()
self._filter_button.on_click(lambda arg: self._filter_done(result_obj, arg))
return result_obj
from traitlets import HasTraits
from traittypes import DataFrame
class FilterResult(HasTraits):
data = DataFrame()
With the same example code as in your question, i.e.,
test = Result(np.random.randn(3,4), columns=['A', 'B', 'C','D']) #just an example
test_2 = test.new_filter()
You can see that whenever you click on done, the updated dataframe is in test_2.data.

Python evernote api Error

Trying to build app that connects with Evernote API, in Python/Django. For the below code i get the following error message: " 'Store' object has no attribute 'NoteFilter' " from http://dev.evernote.com/documentation/reference/NoteStore.html#Svc_NoteStore One can see, that NoteFilter is attribute of NoteStore.
def list(request):
nbname="mihkel's notebook"
client = EvernoteClient(token=token, sandbox=False)
note_store = client.get_note_store()
notebooks = note_store.listNotebooks()
for nb in notebooks:
if nbname == nb.name:
nb = nb
filter = note_store.NoteFilter()
filter.notebookGuid = nb.guid
notelist = note_store.findNotes(token,filter,0,10)
break
return render_to_response('list.html', {'nb': nb, 'notelist':notelist})
Solution:
from evernote.edam.notestore import NoteStore
....
....
def list.. :
...
Filter = NoteStore.NoteFilter()
notestore/ttypes.py has the definition for NoteFilter
Some of the examples in the API code import like this
import evernote.edam.notestore.NoteStore as NoteStore
import evernote.edam.type.ttypes as Types
Not sure if this would be an acceptable way to correct, but I added this:
import evernote.edam.notestore.ttypes as NoteStoreTypes
and created my filter like this:
filter = NoteStoreTypes.NoteFilter()

Categories