Skip to content

Instantly share code, notes, and snippets.

@xthesaintx
Last active April 5, 2020 23:50
Show Gist options
  • Save xthesaintx/fc1e0bdee90810c522418ed48009f8bc to your computer and use it in GitHub Desktop.
Save xthesaintx/fc1e0bdee90810c522418ed48009f8bc to your computer and use it in GitHub Desktop.
Creates X number of Job Folders and Sub Folders, checks to see if the job number is in use and other validation. Allows to output the folders as a csv split by job number and name.
#!/usr/bin/env python3
import sys
import getopt
import os
import re
import csv
###---HOUSEKEEPING---###
#define home dir
from os.path import expanduser
home = expanduser("~")
#Set jobDir variable to nothing
jobDir = ""
mkCount =10
outputDir = ""
outputFN = "HP-list.csv"
args = sys.argv
#path to preferences (script location) only changed if run as command
if (os.path.splitext(__file__)[1]) == ".command":
pPath = os.path.dirname(__file__)+"/odprf.py"
ePath = os.path.dirname(__file__)+"/log.txt"
else:
pPath ="odprf.py"
ePath ="log.txt"
#import settings
if os.path.isfile(pPath):
try:
from odprf import *
except:
file1 = open(pPath,"w")
file1.close()
#### import Tk depending on version of python
if sys.version_info[0] < 3:
import Tkinter as tk
import tkFileDialog as tkf
from tkinter import ttk
else:
import tkinter as tk
from tkinter import filedialog as tkf
from tkinter import *
from tkinter import ttk
### END IMPORTS ###
## Colours ##
lY='#fffbe5'
dY='#FFEE99'
dG='#666666'
lG='#dddddd'
setWarn = ["",dG]
### Functions ###
#make dir structre
def mkTree(stdir):
os.mkdir(stdir)
os.mkdir(stdir+'/'+'Links')
os.mkdir(stdir+'/'+'_History')
os.mkdir(stdir+'/'+'_Supplied')
os.mkdir(stdir+'/'+'_Copy')
#set the dir name
def dName(innum):
dn = 'HP'+str(innum)+' - '
if innum<10:
dn = 'HP000'+str(innum)+' - '
elif innum<100:
dn = 'HP00'+str(innum)+' - '
elif innum<1000:
dn = 'HP0'+str(innum)+' - '
return dn
#write preferences
def mkChVal(mcv):
global mkCount
if mkCount+mcv > 0:
mkCount += mcv
lbl_mkDirCount["text"] = str(mkCount)
def writePref(prefIN,prefOut):
file1 = open(pPath,"w")
file1.write ('jobDir="'+prefIN+'"\n')
file1.write ('outputDir="'+prefOut+'"')
file1.close()
def btnDir(btnDirName):
global jobDir
global outputDir
tmpDir = chooseDir(home)
if tmpDir !="":
if btnDirName == "in":
jobDir = tmpDir
lbl_inD["text"] = tmpDir
elif btnDirName =="out":
outputDir = tmpDir
lbl_outD["text"] = tmpDir
writePref (jobDir, outputDir)
#function to output
def numNam(rawDir):
splitDir = re.search (r"\A(\w{2}\d{4})( - )?(.+)?",rawDir)
if (splitDir):
return [splitDir.group(1),splitDir.group(3)]
else:
print ("Directory name invalid: "+rawDir)
return ['#INVALID',rawDir]
#dir chooser dialog
def chooseDir(intDir):
root = tk.Tk()
root.withdraw()
chooseDirName = tkf.askdirectory(parent=root,initialdir=intDir,title='Please select a directory')
return chooseDirName
def validateDirList():
dirList = os.listdir (jobDir)
dirList.sort ()
#validate dirs only and remove files from the list
vDL = []
for i in dirList:
if os.path.isdir(jobDir+"/"+i):
tx =numNam(i)
vDL.append(tx[0])
return vDL
def outToCSV():
#put dirs into a list
dirList = os.listdir (jobDir)
dirList.sort ()
#validate dirs only and remove files from the list
validDirList = []
for i in dirList:
if os.path.isdir(jobDir+"/"+i):
validDirList.append(i)
#output file
oFN = outputDir+"/"+outputFN
with open(oFN, mode='w') as joblist:
jobWriter = csv.writer(joblist, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
for i in validDirList:
csvIn=numNam(i)
jobWriter.writerow([csvIn[0], csvIn[1]])
lbl_outCounter["text"] = str(len(validDirList))+" records written from "+str(len(dirList))+" items"
## End of functions ##
### MAIN CODE ###
### preference file validation ###
if not os.path.isfile(pPath):
setWarn = ["File not found, using default settings.","Darkred"]
outputDir = home
jobDir = home
if os.path.isfile(pPath) and jobDir == None or not os.path.isdir(jobDir):
setWarn = ["Job folder not set, using default.","Darkred"]
jobDir = home
if os.path.isfile(pPath) and outputDir == None or not os.path.isdir(outputDir):
setWarn = ["CSV directory not set, using default.","Darkred"]
outputDir = home
writePref (jobDir, outputDir)
### End of validation ###
def onValidate(P):
if len(P)<=4 and int(P.isdigit()) or P=="":
return True
else:
return False
def createDirs(x,startHP,jD):
file2 = open(ePath,"w")
errCnt = 0
i = 0
cVDL = validateDirList()
while i < x:
tNum = startHP+i
if os.path.exists(jD+"/"+dName(tNum)):
errCnt +=1
lbl_warn0["bg"]="Orange"
lbl_warn0["text"]="Error: "+dName(tNum)+" exists"
file2.write ("Error: "+dName(tNum)+" exists\n")
elif dName(tNum)[:-3] in cVDL:
errCnt +=1
lbl_warn0["bg"]="Orange"
lbl_warn0["text"]="Error: "+dName(tNum)+" in use"
file2.write ("Error: "+dName(tNum)+" in use\n")
else:
mkTree(jD+"/"+dName(tNum))
lbl_warn0["bg"]="Green"
lbl_warn0["text"]=dName(tNum)+" created"
i += 1
lbl_warn0["text"]="["+dName(startHP)+"] to ["+dName(tNum)+"] created\n"+str(errCnt)+" skipped, already exists"
file2.write ("\n["+dName(startHP)+"] to ["+dName(tNum)+"] created\n"+str(errCnt)+" skipped, already exists\n")
file2.close()
def testEntry(x,startHP,tjD):
if startHP != None:
if str.isdigit(startHP) and int(startHP)>=0 and int(startHP)<=9990:
createDirs(int(x),int(startHP),tjD)
else:
lbl_warn0["bg"]="Darkred"
lbl_warn0["text"]="Error: use digits only (0-9989)"
else:
lbl_warn0["bg"]="Darkred"
lbl_warn0["text"]="Error: Entry Empty"
### GUI UP ###
window = tk.Tk()
window.title("Jobs to CSV")
window.resizable(width=False, height=False)
window.configure(background = "WHITE")
window.columnconfigure([0, 1], minsize=250, weight=1)
window.rowconfigure([0, 1, 2,3,4,5,6,7,8,9,10], minsize=1, weight=1)
vcmd = (window.register(onValidate),'%P')
tkrow=0
## ROW 0 ##
lbl_static1 = tk.Label(master=window, anchor="w",justify=LEFT,text="CREATE JOB FOLDERS",font=("font",16), bg=dG, fg="White", padx=10, pady=5, height=2)
lbl_static1.grid(row=tkrow, column=0,columnspan=1, rowspan=1, sticky="news")
lbl_warn0 = tk.Label(master=window,text=setWarn[0],font=("font",10), bg=dG, fg="White", padx=10, pady=5, height=2)
lbl_warn0.grid(row=tkrow, column=1,columnspan=1, rowspan=1, sticky="news")
## ROW 1 ##
tkrow +=1
lbl_static4 = tk.Label(master=window, anchor="center",justify=CENTER,text="STARTING JOB NUMBER:",font=("font",12,"bold"), bg=dY, padx=10, pady=5, height=1)
lbl_static4.grid(row=tkrow, column=1, rowspan=1, sticky="news")
lbl_static5 = tk.Label(master=window, anchor="center",justify=CENTER,text="NUMBER OF FOLDERS TO CREATE:",font=("font",12,"bold"), bg=dY, padx=10, pady=5, height=1)
lbl_static5.grid(row=tkrow, column=0, rowspan=1, sticky="news")
sep_vSepa =ttk.Separator (master=window,orient="vertical")
sep_vSepa.grid(row=tkrow, column=0,rowspan=1,sticky="NSE")
sep_vSepb =ttk.Separator (master=window,orient="vertical")
sep_vSepb.grid(row=tkrow, column=1,rowspan=1,sticky="NSW")
## ROW 2 ##
tkrow +=1
hpEnt = StringVar()
ent_hpNUM = Entry (window, validate="key", validatecommand=vcmd,textvariable=hpEnt,justify=CENTER)
ent_hpNUM.grid (row=tkrow, column=1, sticky="NEWS", ipadx=10, ipady=10)
lbl_mkDirCount = tk.Label(master=window ,text=mkCount,font=("font",12), bg="WHITE")
lbl_mkDirCount.grid(row=tkrow, column=0, columnspan=1, sticky="we", ipadx=10, ipady=10)
inmkDirMinus = tk.Button(master=window, text="-", command=lambda: mkChVal(-1))
inmkDirMinus.grid(row=tkrow, column=0, sticky = "NSW", ipadx=15, ipady=5)
inmkDirAdd = tk.Button(master=window, text="+", command=lambda: mkChVal(1))
inmkDirAdd.grid(row=tkrow, column=0, sticky = "NSE", ipadx=15, ipady=5)
## ROW 3 ##
tkrow +=1
inmkDirBtn = tk.Button(master=window, text="CREATE", command=lambda: testEntry(mkCount,hpEnt.get(),jobDir))
inmkDirBtn.grid(row=tkrow, column=0, columnspan=2, sticky = "NEWS", ipadx=5, ipady=5)
## ROW 4 ##
tkrow +=1
lbl_static2 = tk.Label(master=window, anchor="w",justify=LEFT,text="CREATE CSV FILE",font=("font",16), bg=dG, fg="White", padx=10, pady=5, height=2)
lbl_static2.grid(row=tkrow, column=0,columnspan=2, rowspan=1, sticky="news")
## ROW 5 ##
tkrow +=1
lbl_outCounter = tk.Label(master=window ,text="0 records from 0 items in directory",font=("font",12), bg="WHITE", padx=10)
lbl_outCounter.grid(row=tkrow, column=0, columnspan=1, sticky="we", ipadx=10, ipady=10)
inDoItBtn = tk.Button(master=window, text="Output CSV", command=lambda: outToCSV(), bd=10)
inDoItBtn.grid(row=tkrow, column=1, columnspan=1,sticky="NEWS", ipadx=10, ipady=10)
## ROW 6 ##
tkrow +=1
lbl_static3 = tk.Label(master=window, anchor="w",justify=LEFT,text="DIRECTORY LOCATIONS",font=("font",16), bg=dG, fg="White", padx=10, pady=5, height=2)
lbl_static3.grid(row=tkrow, column=0,columnspan=1, rowspan=1, sticky="news")
lbl_warn = tk.Label(master=window,text=setWarn[0],font=("font",10), bg=setWarn[1], fg="White", padx=10, pady=5, height=2)
lbl_warn.grid(row=tkrow, column=1,columnspan=1, rowspan=1, sticky="news")
## ROW 7 ##
tkrow +=1
lbl_in = tk.Label(master=window, anchor="w",justify=LEFT,text="JOB FOLDER DIRECTORY:",font=("font",12, "bold"), bg=dY, padx=10, pady=5)
lbl_in.grid(row=tkrow, column=0,columnspan=2,sticky="news")
## ROW 8 ##
tkrow +=1
lbl_inD = tk.Label(master=window, justify=LEFT,text=jobDir,font=("font",12), bg=lY, anchor="w", padx=10)
lbl_inD.grid(row=tkrow, column=0, columnspan=2, sticky="we", ipadx=10, ipady=10)
inChDirBtn = tk.Button(master=window, text="Change", command=lambda: btnDir("in"))
inChDirBtn.grid(row=tkrow, column=1, sticky = "e", ipadx=5, ipady=5, padx=10)
## ROW 9 ##
tkrow +=1
lbl_out = tk.Label(master=window, anchor="w",justify=LEFT,text="CSV SAVE DIRECTORY:",font=("font",12, "bold"), bg=dY, padx=10, pady=5)
lbl_out.grid(row=tkrow, column=0,columnspan=2,sticky="news")
## ROW 10 ##
tkrow +=1
lbl_outD = tk.Label(master=window, justify=LEFT, text=outputDir,font=("font",12), bg=lY, anchor="w", padx=10)
lbl_outD.grid(row=tkrow, column=0, columnspan=2, sticky="we", ipadx=10, ipady=10)
outChDirBtn = tk.Button(master=window, text="Change",command=lambda: btnDir("out"))
outChDirBtn.grid(row=tkrow, column=1, sticky = "e", ipadx=5, ipady=5, padx=10)
##END OF GUI ROWS ##
## CENTRE WINDOW ###
# Gets the requested values of the height and widht.
windowWidth = window.winfo_reqwidth()
windowHeight = window.winfo_reqheight()
# Gets both half the screen width/height and window width/height
positionRight = int(window.winfo_screenwidth()/2 - windowWidth/2)
positionDown = int(window.winfo_screenheight()/2 - windowHeight/2)
# Positions the window in the center of the page.
window.geometry("+{}+{}".format(positionRight, positionDown))
### End Centre ##
window.mainloop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment