View difference between Paste ID: 4yYU2v6i and 5E4eS6db
SHOW: | | - or go back to the newest paste.
1-
import sqlite3 as sqlite, argparse
1+
import sqlite3 as sqlite, argparse
2-
2+
3-
class HourTracker:
3+
class HourTracker:
4-
	class CursorInstance:
4+
	class CursorInstance:
5-
		def __init__(self, con):
5+
		def __init__(self, con):
6-
			self.cursor = con.cursor()
6+
			self.cursor = con.cursor()
7-
			self.con = con
7+
			self.con = con
8-
		def __call__(self,*a,**k):return self.cursor.execute(*a,**k)
8+
		def __call__(self,*a,**k):return self.cursor.execute(*a,**k)
9-
		def __enter__(self):return self
9+
		def __enter__(self):return self
10-
		def __exit__(self,et,ev,tb):
10+
		def __exit__(self,et,ev,tb):
11-
			self.cursor.close()
11+
			self.cursor.close()
12-
			self.con.commit()
12+
			self.con.commit()
13-
	def __init__(self):
13+
	def __init__(self):
14-
		self.connection = sqlite.connect("hours.sql")
14+
		self.connection = sqlite.connect("hours.sql")
15-
		self.connection.row_factory = sqlite.Row
15+
		self.connection.row_factory = sqlite.Row
16-
	def cursor(self):return self.CursorInstance(self.connection)
16+
	def cursor(self):return self.CursorInstance(self.connection)
17-
	def __enter__(self):
17+
	def __enter__(self):
18-
		with self.cursor() as cursor:
18+
		with self.cursor() as cursor:
19-
			jq = """CREATE TABLE if not exists "jobs" (
19+
			jq = """CREATE TABLE if not exists "jobs" (
20-
					"id" INTEGER PRIMARY KEY AUTOINCREMENT,
20+
					"id" INTEGER PRIMARY KEY AUTOINCREMENT,
21-
					"name" TEXT NOT NULL
21+
					"name" TEXT NOT NULL
22-
				)"""
22+
				)"""
23-
			sq = """CREATE TABLE if not exists shifts (
23+
			sq = """CREATE TABLE if not exists shifts (
24-
				"job" INTEGER NOT NULL,
24+
				"job" INTEGER NOT NULL,
25-
				"minutes" TEXT NOT NULL,
25+
				"minutes" TEXT NOT NULL,
26-
				"date" DATE
26+
				"date" DATE default (date('now','localtime'))
27-
			)"""
27+
			)"""
28-
			wq = """REATE TABLE if not exists"wages" (
28+
			wq = """REATE TABLE if not exists"wages" (
29-
				"job" INTEGER NOT NULL,
29+
				"job" INTEGER NOT NULL,
30-
				"wage" INTEGER NOT NULL,
30+
				"wage" INTEGER NOT NULL,
31-
				"start" DATE default (date('now','localtime'))
31+
				"start" DATE default (date('now','localtime'))
32-
			)"""
32+
			)"""
33-
			asv = """CREATE VIEW if not exists "active_shifts" AS select
33+
			asv = """CREATE VIEW if not exists "active_shifts" AS select
34-
			  sum(shifts.minutes) / 60.0 as 'hours',
34+
			  sum(shifts.minutes) / 60.0 as 'hours',
35-
			  shifts.job as 'job'
35+
			  shifts.job as 'job'
36-
			from shifts
36+
			from shifts
37-
			where shifts.date >= date('now','start of month')
37+
			where shifts.date >= date('now','start of month')
38-
			and shifts.date < date('now','start of month',"+1 month")
38+
			and shifts.date < date('now','start of month',"+1 month")
39-
			group by(shifts.job)
39+
			group by(shifts.job)
40-
			"""
40+
			"""
41-
			epv = """CREATE VIEW "expected_pay" AS select
41+
			epv = """CREATE VIEW "expected_pay" AS select
42-
			  (select jobs.name from jobs where jobs.id==active_shifts.job) as 'job',
42+
			  (select jobs.name from jobs where jobs.id==active_shifts.job) as 'job',
43-
			  active_shifts.hours as 'hours',
43+
			  active_shifts.hours as 'hours',
44-
			  (select wages.wage from wages where wages.job==active_shifts.job)
44+
			  (select wages.wage from wages where wages.job==active_shifts.job)
45-
			  * active_shifts.hours as 'expected_pay'
45+
			  * active_shifts.hours as 'expected_pay'
46-
			from active_shifts
46+
			from active_shifts
47-
			"""
47+
			"""
48-
			cursor(jq)
48+
			cursor(jq)
49-
			cursor(sq)
49+
			cursor(sq)
50-
			cursor(wq)
50+
			cursor(wq)
51-
			cursor(asv)
51+
			cursor(asv)
52-
			cursor(epv)
52+
			cursor(epv)
53-
		return self
53+
		return self
54-
	def __exit__(self,et,eb,tb):
54+
	def __exit__(self,et,eb,tb):
55-
		self.connection.commit()
55+
		self.connection.commit()
56-
	def add_job(self, name, wage):
56+
	def add_job(self, name, wage):
57-
		with self.cursor() as cursor:
57+
		with self.cursor() as cursor:
58-
			cursor("insert into jobs(name) values(?)",(name,))
58+
			cursor("insert into jobs(name) values(?)",(name,))
59-
			cursor("insert into wages(job,wage) values(last_insert_rowid(),?)",(wage,))
59+
			cursor("insert into wages(job,wage) values(last_insert_rowid(),?)",(wage,))
60-
	def job_id(self, name):
60+
	def job_id(self, name):
61-
		with self.cursor() as cursor:
61+
		with self.cursor() as cursor:
62-
			q="select id from jobs where name like ?"
62+
			q="select id from jobs where name like ?"
63-
			r=[row['id']for row in cursor(q,(name,))]
63+
			r=[row['id']for row in cursor(q,(name,))]
64-
			if len(r)>1:return r
64+
			if len(r)>1:return r
65-
			return r[0] if len(r)>0 else None
65+
			return r[0] if len(r)>0 else None
66-
	def log_time(self, job, minutes):
66+
	def log_time(self, job, minutes):
67-
		with self.cursor() as cursor:
67+
		with self.cursor() as cursor:
68-
			if isinstance(job,str):
68+
			if isinstance(job,str):
69-
				jt=self.job_id(job)
69+
				jt=self.job_id(job)
70-
				if jt is None:
70+
				if jt is None:
71-
					raise RuntimeError("No such job as '{}'".format(job))
71+
					raise RuntimeError("No such job as '{}'".format(job))
72-
				job=jt
72+
				job=jt
73-
			q="insert into shifts(job,minutes) values(?,?)"
73+
			q="insert into shifts(job,minutes) values(?,?)"
74-
			cursor(q,(job,minutes))
74+
			cursor(q,(job,minutes))
75-
	def wage_report(self):
75+
	def wage_report(self):
76-
		q="select * from expected_pay"
76+
		q="select * from expected_pay"
77-
		with self.cursor() as cursor:
77+
		with self.cursor() as cursor:
78-
			for row in cursor(q):
78+
			for row in cursor(q):
79-
				yield (row['job'],row['hours'],row['expected_pay'])
79+
				yield (row['job'],row['hours'],row['expected_pay'])
80-
80+
81-
class Main(argparse.ArgumentParser):
81+
class Main(argparse.ArgumentParser):
82-
	def __init__(self):
82+
	def __init__(self):
83-
		d="Hour Logging"
83+
		d="Hour Logging"
84-
		super().__init__(description=d)
84+
		super().__init__(description=d)
85-
		self.tracker = None
85+
		self.tracker = None
86-
		self.add_argument('--display', dest="mode", action='store_const',
86+
		self.add_argument('--display', dest="mode", action='store_const',
87-
		                  help="Displays expected payments from all jobs for this month.",
87+
		                  help="Displays expected payments from all jobs for this month.",
88-
		                  const=self.display_wages, default=self.log_minutes)
88+
		                  const=self.display_wages, default=self.log_minutes)
89-
		self.add_argument('--time', dest='time', action='store',type=int, default="0")
89+
		self.add_argument('--time', dest='time', action='store',type=int, default="0")
90-
		self.add_argument('--job', dest='job', action='store', default=None)
90+
		self.add_argument('--job', dest='job', action='store', default=None)
91-
		self.add_argument("--hire", dest='mode', action='store_const',
91+
		self.add_argument("--hire", dest='mode', action='store_const',
92-
		                  const=self.get_hired, default=self.log_minutes)
92+
		                  const=self.get_hired, default=self.log_minutes)
93-
		self.add_argument("--wage", dest="wage", action='store', default="7.25", type=float)
93+
		self.add_argument("--wage", dest="wage", action='store', default="7.25", type=float)
94-
	def __enter__(self):
94+
	def __enter__(self):
95-
		self.tracker = HourTracker()
95+
		self.tracker = HourTracker()
96-
		return self
96+
		return self
97-
	def __exit__(self,et,ev,tb):pass
97+
	def __exit__(self,et,ev,tb):pass
98-
	def __call__(self):
98+
	def __call__(self):
99-
		ns = self.parse_args()
99+
		ns = self.parse_args()
100-
		return ns.mode(ns)
100+
		return ns.mode(ns)
101-
	def display_wages(self,parsed):
101+
	def display_wages(self,parsed):
102-
		job = parsed.job
102+
		job = parsed.job
103-
		report = self.tracker.wage_report()
103+
		report = self.tracker.wage_report()
104-
		job = job.lower() if isinstance(job,str) else None
104+
		job = job.lower() if isinstance(job,str) else None
105-
		s = "Currently expecting {:.4n}$ from {} after {:.3n} hours."
105+
		s = "Currently expecting {:.4n}$ from {} after {:.3n} hours."
106-
		for rjob, hours, pay in report:
106+
		for rjob, hours, pay in report:
107-
			if (job is not None and job==rjob.lower()) or job is None:
107+
			if (job is not None and job==rjob.lower()) or job is None:
108-
				print(s.format(pay, rjob, hours))
108+
				print(s.format(pay, rjob, hours))
109-
	def log_minutes(self, parsed):
109+
	def log_minutes(self, parsed):
110-
		job, time = parsed.job, parsed.time
110+
		job, time = parsed.job, parsed.time
111-
		if job is not None and time > 0:
111+
		if job is not None and time > 0:
112-
			self.tracker.log_time(job,time)
112+
			self.tracker.log_time(job,time)
113-
			print("Successfully logged {} minutes for {}".format(time,job))
113+
			print("Successfully logged {} minutes for {}".format(time,job))
114-
	def get_hired(self, parsed):
114+
	def get_hired(self, parsed):
115-
		job,wage = parsed.job,parsed.wage
115+
		job,wage = parsed.job,parsed.wage
116-
		s = "Successfully added {} to jobs index, setting wage to {:.4}$"
116+
		s = "Successfully added {} to jobs index, setting wage to {:.4}$"
117-
		if job is not None:
117+
		if job is not None:
118-
			self.tracker.add_job(job,wage)
118+
			self.tracker.add_job(job,wage)
119-
			print(s.format(job,wage))
119+
			print(s.format(job,wage))
120-
120+
121-
if __name__=="__main__":
121+
if __name__=="__main__":
122
	with Main() as prog:prog()