EasyGui interface

This commit is contained in:
Tyrel Souza 2015-07-16 16:21:22 -04:00
parent 0ca5217ddc
commit 66b5fd6b31
2 changed files with 149 additions and 72 deletions

218
main.py
View File

@ -2,9 +2,9 @@ import os
import json import json
import datetime import datetime
import logging import logging
import sys
import pandas as pd import pandas as pd
import dropbox
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
import easygui import easygui
@ -21,63 +21,89 @@ class AttributionReport(object):
def __init__(self, credentials_file, months=6, footer_length=None): def __init__(self, credentials_file, months=6, footer_length=None):
self.months = months self.months = months
self.footer_length = footer_length self.footer_length = footer_length
self.PI_COLUMN = "PI_Name" self.PI_COLUMN = "PI_Name"
self.ORG_COLUMN = "Org Name" self.ORG_COLUMN = "Org Name"
self.column_order = ["Addgene Assigned", self.OUTPUT_COLUMN_ORDER = ["Addgene Assigned",
"Plasmid ID", "Plasmid ID",
"Deposit ID", "Deposit ID",
"Institute", "Institute",
"PI Name", "PI Name",
"Date Received", "Date Received",
"Original Date", "Original Date",
"Original ORG", "Original ORG",
"Original PI"] "Original PI"]
with open(credentials_file, "r") as cred_f: self.ACCEPTABLE_EXTENSIONS = ["*.csv",
creds = json.loads(cred_f.read()) "*.xls",
"*.xlsx"]
self.app_key = creds['app_key'] # columns that need to be in the files
self.app_secret = creds['app_secret'] self.REQUIRED_SF_COLUMNS = ["First Name",
"Last Name",
"Account Name",
"Date",
"Assigned"]
self.REQUIRED_DP_COLUMNS = ["Org Name",
"Deposit ID",
"Plasmid ID",
"PI_Name",
"Date Received"]
if not creds.get("access_token", None): # After load and merging, delete these columns
self.authorize() self.SF_TRIM_COLUMNS = ["Subject",
"First Name",
"Last Name",
"Created Date",
"LIMS Organization ID",
"Account Description"]
self.DP_TRIM_COLUMNS = ["Org ID",
"Deposit Status",
"PI_ID",
"Date Available",
"# Orders",
"# Plasmids in the Deposit",
"Addgene Contact",
"Country"]
self.DEFAULT_DIR = self.get_dropbox_dir()
def get_dropbox_dir(self):
"""
Windows and Mac get dropox dir for Business or fallback to personal
"""
if os.name == "nt":
dropbox_file = os.path.join(os.getenv('APPDATA'), 'Dropbox', 'info.json')
else: else:
self.access_token = creds['access_token'] dropbox_file = os.path.expanduser("~/.dropbox/info.json")
self.user_id = creds['user_id'] with open(dropbox_file) as dbf:
dbconfig = json.loads(dbf.read())
def authorize(self): if "business" in dbconfig:
flow = dropbox.client.DropboxOAuth2FlowNoRedirect(self.app_key, self.app_secret) dropbox_dir = dbconfig['business']['path'] + "/*.xls"
authorize_url = flow.start() elif "personal" in dbconfig:
print '1. Go to: ' + authorize_url dropbox_dir = dbconfig['personal']['path'] + "/*.xls"
print '2. Click "Allow" (you might have to log in first)'
print '3. Copy the authorization code.'
code = raw_input("Enter the authorization code here: ").strip()
access_token, user_id = flow.finish(code)
self.access_token = access_token
self.user_id = user_id
creds = {"app_key": self.app_key,
"app_secret": self.app_secret,
"access_token": self.access_token,
"user_id": self.user_id}
# Save so we don't have to do this again.
with open("credentials.json", "w") as f:
f.write(json.dumps(creds))
def _open_file_frame(self, filename, date_cols):
if DROPBOX:
L.info("Getting file from Dropbox")
client = dropbox.client.DropboxClient(self.access_token)
L.info("Got file from Dropbox")
f = client.get_file(filename)
else: else:
f = os.path.normpath(local_dropbox_path + filename) dropbox_dir = os.path.expanduser("~")
if filename[-4:] == ".csv": return dropbox_dir
df = pd.read_csv(f, parse_dates=date_cols, encoding='utf-8')
def _get_dataframe_by_extension(self, path, date_cols):
"""
Gets a dataframe either by .csv, or .xls(x),
or erroring and exiting.
"""
_, ext = os.path.splitext(path)
if ext == ".csv":
df = pd.read_csv(path, parse_dates=date_cols, encoding='utf-8')
elif ext in [".xlsx", ".xls"]:
df = pd.read_excel(path, parse_dates=date_cols, encoding='utf-8')
else: else:
df = pd.read_excel(f, parse_dates=date_cols, encoding='utf-8') easygui.msgbox("File was not of type {0}.\nQuitting".format(
" ".join(self.ACCEPTABLE_EXTENSIONS)),
"ERROR")
sys.exit(1)
return df return df
def get_dataframes(self): def get_dataframes(self):
@ -85,28 +111,67 @@ class AttributionReport(object):
This gets the Salesforce and the Deposit dataframes. This gets the Salesforce and the Deposit dataframes.
Then it does some cleanup of the columns Then it does some cleanup of the columns
""" """
salesforce_data_name = '/Addgene Shared/Dev/Attribution Report/salesforce_report.xlsx' salesforce_df, deposit_df = self.get_files()
salesforce_df = self._open_file_frame(salesforce_data_name, date_cols=[4, 5])
# Get rid of the footer that Salesforce adds.
if self.footer_length: if self.footer_length:
length_with_footer = len(salesforce_df.index) length_with_footer = len(salesforce_df.index)
salesforce_df = salesforce_df.head(length_with_footer - self.footer_length) salesforce_df = salesforce_df.head(length_with_footer - self.footer_length)
deposit_data_name = 'Addgene Shared/Dev/Attribution Report/deposit_data.csv'
deposit_df = self._open_file_frame(deposit_data_name, date_cols=[7, 8])
# Clean up Salesforce # Clean up Salesforce
salesforce_df['Account Description'].fillna('', inplace=True)
salesforce_df.sort(SF_DATE, ascending=1) salesforce_df.sort(SF_DATE, ascending=1)
salesforce_df["Full Name"] = salesforce_df["First Name"].map(unicode) + " " + salesforce_df["Last Name"] salesforce_df["Full Name"] = salesforce_df["First Name"].map(unicode) + " " + salesforce_df["Last Name"]
del salesforce_df["First Name"]
del salesforce_df["Last Name"]
# Cleanup Deposit Data # Cleanup Deposit Data
deposit_df['Org Name'].fillna('', inplace=True) deposit_df['Org Name'].fillna('', inplace=True)
deposit_df.sort(DP_DATE, ascending=1) deposit_df.sort(DP_DATE, ascending=1)
deposit_df['PI_Name'].astype(unicode) deposit_df['PI_Name'].astype(unicode)
# Cleanup not needed columns
for col in self.SF_TRIM_COLUMNS:
del salesforce_df[col]
for col in self.DP_TRIM_COLUMNS:
del deposit_df[col]
return salesforce_df, deposit_df
def get_files(self):
salesforce_data_name = easygui.fileopenbox("Salesforce Export",
default=self.DEFAULT_DIR,
filetypes=self.ACCEPTABLE_EXTENSIONS)
if salesforce_data_name == ".":
easygui.msgbox("You did not select a Salesforce Export, stopping program.",
"Good Bye")
sys.exit(1)
salesforce_df = self._get_dataframe_by_extension(salesforce_data_name, date_cols=[4, 5])
if set(self.REQUIRED_SF_COLUMNS) < set(salesforce_df.columns):
L.info("Proper columns")
else:
L.info("Wrong columns")
easygui.msgbox("At a minimum, the Salesforce file must have the following columns:\n\n"
"{0}\n\n"
"Please re-run and select a proper file.".format(", ".join(self.REQUIRED_SF_COLUMNS)),
"Incorrect columns")
sys.exit(1)
deposit_data_name = easygui.fileopenbox("Deposit Data",
default=self.DEFAULT_DIR,
filetypes=self.ACCEPTABLE_EXTENSIONS)
if deposit_data_name == ".":
easygui.msgbox("You did not select a Deposit Data Export, stopping program.",
"Good Bye")
sys.exit(1)
deposit_df = self._get_dataframe_by_extension(deposit_data_name, date_cols=[7, 8])
if set(self.REQUIRED_DP_COLUMNS) < set(deposit_df.columns):
L.info("Proper columns")
else:
L.info("Wrong columns")
easygui.msgbox("At a minimum, the Deposit Data file must have the following columns:\n\n"
"{0}\n\n"
"Please re-run and select a proper file.".format(", ".join(self.REQUIRED_DP_COLUMNS)),
"Incorrect columns")
sys.exit(1)
return salesforce_df, deposit_df return salesforce_df, deposit_df
def get_filtered(self, filtered_df, sf_row, pi_name, pi_org, kind): def get_filtered(self, filtered_df, sf_row, pi_name, pi_org, kind):
@ -176,31 +241,42 @@ class AttributionReport(object):
mismatches.extend(by_org) mismatches.extend(by_org)
double_matches.extend(by_both) double_matches.extend(by_both)
return {"PI": pd.DataFrame(name_matches, columns=self.column_order), return (
"Institute": pd.DataFrame(org_matches, columns=self.column_order), ("PI", pd.DataFrame(name_matches, columns=self.OUTPUT_COLUMN_ORDER)),
"Double": pd.DataFrame(double_matches, columns=self.column_order), ("Institute", pd.DataFrame(org_matches, columns=self.OUTPUT_COLUMN_ORDER)),
"Single": pd.DataFrame(mismatches, columns=self.column_order)} ("Double", pd.DataFrame(double_matches, columns=self.OUTPUT_COLUMN_ORDER)),
("Single", pd.DataFrame(mismatches, columns=self.OUTPUT_COLUMN_ORDER))
)
def run(self): def run(self):
frames = self.get_attribution_dataframes() frames = self.get_attribution_dataframes()
for key, df in frames.items(): dirname = easygui.diropenbox("Where to save reports?", "Select Report Output Directory", self.DEFAULT_DIR)
fname = '{0}_Attribution_Report_{1}_Match.xlsx'.format( if not dirname:
datetime.date.today(), dirname = self.DEFAULT_DIR
key)
print "Writing", fname
writer = pd.ExcelWriter(
fname,
engine='xlsxwriter') for key, df in frames:
fname = '{0}_Attribution_Report_{1}_Match.xlsx'.format(datetime.date.today(), key)
xls_path = os.path.join(dirname, fname)
print "Writing", xls_path
writer = pd.ExcelWriter(xls_path,
engine='xlsxwriter')
df.to_excel(writer, df.to_excel(writer,
sheet_name='Sheet1', sheet_name='Sheet1',
index=False) index=False)
writer.save() writer.save()
if __name__ == '__main__': def main():
report = AttributionReport(credentials_file="credentials.json", try:
report = AttributionReport(credentials_file="credentials.json",
months=6, months=6,
footer_length=6) footer_length=6)
report.run() report.run()
except:
easygui.exceptionbox()
if __name__ == '__main__':
main()

View File

@ -5,4 +5,5 @@ python-dateutil
xlwt xlwt
#openpyxl==1.8.6 #openpyxl==1.8.6
xlsxwriter xlsxwriter
progressbar==2.3 progressbar==2.3
easygui