def test_get_jobs_for_user_different_users_some_jobs(self): num_of_jobs_user1 = ONE # Add one job to the tabfile for user1 test_jobs_user1 = create_test_tab(num_of_jobs_user1, user1) api.set_jobs(test_jobs_user1, user1) jobs_list_user1 = api.get_jobs_for_user(user1) num_of_jobs_user2 = ZERO # Add zero jobs to the tabfile for user2 test_jobs_user2 = create_test_tab(num_of_jobs_user2, user2) api.set_jobs(test_jobs_user2, user2) jobs_list_user2 = api.get_jobs_for_user(user2) num_of_jobs_user3 = SOME # Add some jobs to the tabfile for user3 test_jobs_user3 = create_test_tab(num_of_jobs_user3, user3) api.set_jobs(test_jobs_user3, user3) jobs_list_user3 = api.get_jobs_for_user(user3) # Verify that the jobs list for user1 contains # the correct number of jobs self.assertEqual(len(jobs_list_user1), num_of_jobs_user1) # Verify that the jobs list for user2 contains # the correct number of jobs self.assertEqual(len(jobs_list_user2), num_of_jobs_user2) # Verify that the jobs list for user3 contains # the correct number of jobs self.assertEqual(len(jobs_list_user3), num_of_jobs_user3) # Verify that the information we get matches what was set check_job_fields(self, jobs_list_user1, test_jobs_user1, user1) # Verify that the information we get matches what was set check_job_fields(self, jobs_list_user2, test_jobs_user2, user2) # Verify that the information we get matches what was set check_job_fields(self, jobs_list_user3, test_jobs_user3, user3)
def test_get_jobs_for_user_some_users_empty_jobs(self): jobs_list_user4 = api.get_jobs_for_user(user4) # Verify that the jobs_list for user4 is empty self.assertFalse(len(jobs_list_user4)) num_of_jobs_user1 = ONE # Add one job to the tabfile user1 test_jobs_user1 = create_test_tab(num_of_jobs_user1, user1) api.set_jobs(test_jobs_user1, user1) jobs_list_user4 = api.get_jobs_for_user(user4) # Verify that the jobs_list for user4 is empty self.assertFalse(len(jobs_list_user4))
def main(): uid = os.getuid() if len(sys.argv) < 3: jobs_old = api.get_jobs_for_user(uid) with tempfile.NamedTemporaryFile('w', delete=False) as temp: for job in jobs_old: temp.write("%s %s\n" % (job.interval, job.command)) tb_file = temp.name editor = os.getenv('EDITOR') if editor is not None: os.system("%s %s" % (editor, tb_file)) else: subprocess.call("vim %s" % tb_file, shell=True) elif sys.argv[1] == '-u': tb_file = sys.argv[2] jobs_new = [] with open(tb_file, 'r') as tab: for job in tab: tmp = job.strip().split(' ') interval = string.joinfields(tmp[:5], ' ') cmd = string.joinfields(tmp[5:], ' ') jobs_new.append(api.Job(interval, cmd, uid, datetime.now())) if len(sys.argv) < 3: os.unlink(tb_file) api.set_jobs(jobs_new, uid)
def test_get_jobs_for_user_empty_jobs(self): num_of_jobs = ZERO # Create a crontab with zero jobs test_jobs = create_test_tab(num_of_jobs, user1) api.set_jobs(test_jobs, user1) jobs_list_user1 = api.get_jobs_for_user(user1) # Verify that the jobs list for user1 is empty self.assertFalse(len(jobs_list_user1))
def test_get_jobs_for_user_many_jobs(self): num_of_jobs = MANY # Create a crontab with many jobs test_jobs = create_test_tab(num_of_jobs, user1) api.set_jobs(test_jobs, user1) jobs_list_user1 = api.get_jobs_for_user(user1) # Verify that the jobs list for user1 # contains the correct number of jobs self.assertEqual(len(jobs_list_user1), num_of_jobs)
def process_edits(uid, tb_file, using_local_file, old_tab): crontab = [] jobs = [] old_jobs = api.get_jobs_for_user(uid) with open(tb_file, "r") as tab: for line in tab: line = line.strip() crontab.append(line) # Ignore newlines and full line comments if line and (line[0] != "#"): split = line.split() interval = " ".join(split[:5]) cmd = " ".join(split[5:]) try: # Ensure the crontab line is valid croniter(interval) if not cmd: raise ValueError except (KeyError, ValueError): # Otherwise prompt user to edit crontab e_str = "The crontab you entered has invalid entries, " "would you like to edit it again? (y/n) " while True: cnt = _input(e_str) if (cnt == "n") or (cnt == "N"): if using_local_file is False: os.unlink(tb_file) sys.exit(1) elif (cnt == "y") or (cnt == "Y"): return False e_str = "Please enter y or n: " # Check if job was already there job = None if line in old_tab: for old_job in old_jobs: if old_job.interval == interval and old_job.command == cmd: job = old_job old_jobs.remove(old_job) break if not job: old_tab.discard(line) job = api.Job(interval, cmd, uid, datetime.now()) jobs.append(job) if using_local_file is False: os.unlink(tb_file) api.set_crontab("\n".join(crontab), uid) api.set_jobs(jobs, uid) return True
def process_edits(uid, tb_file, using_local_file, old_tab): e_str = "" jobs = [] crontab = [] old_jobs = api.get_jobs_for_user(uid) with open(tb_file, 'r') as tab: for i, line in enumerate(tab): line = line.strip() crontab.append(line) # Ignore newlines and comments if line and (line[0] != '#'): split = line.split() # Check for special interval syntax if split[0][0] == '@': try: interval = _special_intervals[split[0]] except KeyError: e_str += ("Error in line %i: Bad special interval " "syntax, %s\n" % (i + 1, split[0])) continue cmd = ' '.join(split[1:]) # Check if setting variable elif '=' in ''.join(split[:5]): name, _, value = line.partition('=') # Check if var name is zero or multiple words name = name.strip() num_names = len(name.split()) if num_names != 1: if num_names: e_str += ("Error in line %i: Bad variable " "assignment syntax; multiple variable " "names given\n" % (i + 1)) else: e_str += ("Error in line %i: Bad variable " "assignment syntax; no variable name " "given\n" % (i + 1)) else: value = value.strip() if (((value[0] == "'") or (value[0] == '"')) and (value[-1] == value[0])): # If properly wrapped in quotes, check if escaped for i, char in enumerate(reversed(value[:-1])): if char != '\\': i += 1 break if i % 2 != 0: value = value[1:-1] os.environ[name] = value continue else: # Check if five or six time/date fields if (len(split) > 5 and not any(c.isalpha() for c in split[5]) and ('*' in split[5] or any(c.isdigit() for c in split[5])) and split[5][0] != '/'): # Could print warning that using 6 time fields interval = ' '.join(split[:6]) cmd = ' '.join(split[6:]) else: interval = ' '.join(split[:5]) cmd = ' '.join(split[5:]) # Check for un-escaped %s in command job_input = None index = cmd.find('%') while (index != -1) and (cmd[index - 1] == '\\'): index = cmd.find('%', index + 1) if index != -1: job_input = _escaped_pct.sub( '%', _unescaped_pct.sub(r"\1\n", cmd[index + 1:])) cmd = cmd[:index] cmd = _escaped_pct.sub('%', cmd) # Ensure the crontab line is valid try: croniter(interval) if not cmd: raise ValueError("Missing command") except (KeyError, ValueError) as e: if isinstance(e, KeyError): e = "Bad time interval syntax, %s " % e # Replace croniter's typo-riddled error msg elif str(e) == ("Exactly 5 or 6 columns has to be " "specified for iteratorexpression."): e = ("Less than 5 fields separated by whitespace in " "the time interval (requires 5 or 6)") e_str += "Error in line %i: %s\n" % (i + 1, e) else: if not e_str: job = None # Check if job was in the old crontab if line in old_tab: for old_job in old_jobs: if (old_job.interval == interval and old_job.command == cmd and old_job.job_input == job_input and old_job.environment == os.environ): job = old_job old_jobs.remove(old_job) break if not job: old_tab.discard(line) job = api.Job(interval, cmd, uid, os.environ.copy(), job_input, datetime.now()) jobs.append(job) # Prompt user to edit crontab on error if e_str: e_str += ("The crontab you entered has invalid entries, " "would you like to edit it again? (y/n) ") while True: cnt = _input(e_str) if (cnt == 'n') or (cnt == 'N'): if using_local_file is False: os.unlink(tb_file) sys.exit(1) elif (cnt == 'y') or (cnt == 'Y'): return False e_str = "Please enter y or n: " if using_local_file is False: os.unlink(tb_file) api.set_crontab('\n'.join(crontab), uid) api.set_jobs(jobs, uid) return True
def process_edits(uid, tb_file, using_local_file, old_tab): e_str = "" jobs = [] crontab = [] old_jobs = api.get_jobs_for_user(uid) with open(tb_file, 'r') as tab: for i, line in enumerate(tab): line = line.strip() crontab.append(line) # Ignore newlines and comments if line and (line[0] != '#'): split = line.split() # Check for special interval syntax if split[0][0] == '@': try: interval = _special_intervals[split[0]] except KeyError: e_str += ("Error in line %i: Bad special interval " "syntax, %s\n" % (i + 1, split[0])) continue cmd = ' '.join(split[1:]) # Check if setting variable elif '=' in ''.join(split[:5]): name, _, value = line.partition('=') # Check if var name is zero or multiple words name = name.strip() num_names = len(name.split()) if num_names != 1: if num_names: e_str += ("Error in line %i: Bad variable " "assignment syntax; multiple variable " "names given\n" % (i + 1)) else: e_str += ("Error in line %i: Bad variable " "assignment syntax; no variable name " "given\n" % (i + 1)) else: value = value.strip() if (((value[0] == "'") or (value[0] == '"')) and (value[-1] == value[0])): # If properly wrapped in quotes, check if escaped for i, char in enumerate(reversed(value[:-1])): if char != '\\': i += 1 break if i % 2 != 0: value = value[1:-1] os.environ[name] = value continue else: # Check if five or six time/date fields if (len(split) > 5 and not any(c.isalpha() for c in split[5]) and ('*' in split[5] or any(c.isdigit() for c in split[5])) and split[5][0] != '/'): # Could print warning that using 6 time fields interval = ' '.join(split[:6]) cmd = ' '.join(split[6:]) else: interval = ' '.join(split[:5]) cmd = ' '.join(split[5:]) # Check for un-escaped %s in command job_input = None index = cmd.find('%') while (index != -1) and (cmd[index-1] == '\\'): index = cmd.find('%', index + 1) if index != -1: job_input = _escaped_pct.sub('%', _unescaped_pct.sub( r"\1\n", cmd[index+1:])) cmd = cmd[:index] cmd = _escaped_pct.sub('%', cmd) # Ensure the crontab line is valid try: croniter(interval) if not cmd: raise ValueError("Missing command") except (KeyError, ValueError) as e: if isinstance(e, KeyError): e = "Bad time interval syntax, %s " % e # Replace croniter's typo-riddled error msg elif str(e) == ("Exactly 5 or 6 columns has to be " "specified for iteratorexpression."): e = ("Less than 5 fields separated by whitespace in " "the time interval (requires 5 or 6)") e_str += "Error in line %i: %s\n" % (i + 1, e) else: if not e_str: job = None # Check if job was in the old crontab if line in old_tab: for old_job in old_jobs: if (old_job.interval == interval and old_job.command == cmd and old_job.job_input == job_input and old_job.environment == os.environ): job = old_job old_jobs.remove(old_job) break if not job: old_tab.discard(line) job = api.Job(interval, cmd, uid, os.environ.copy(), job_input, datetime.now()) jobs.append(job) # Prompt user to edit crontab on error if e_str: e_str += ("The crontab you entered has invalid entries, " "would you like to edit it again? (y/n) ") while True: cnt = _input(e_str) if (cnt == 'n') or (cnt == 'N'): if using_local_file is False: os.unlink(tb_file) sys.exit(1) elif (cnt == 'y') or (cnt == 'Y'): return False e_str = "Please enter y or n: " if using_local_file is False: os.unlink(tb_file) api.set_crontab('\n'.join(crontab), uid) api.set_jobs(jobs, uid) return True