def parse_expression(self): options = Options() options.throw_exception_on_parse_error = True options.casing_type = CasingTypeEnum.Sentence options.use_24hour_time_format = True return ExpressionDescriptor(self.expression, options).get_description( DescriptionTypeEnum.FULL)
def test_full(self): options = Options() options.use_24hour_time_format = True ceh = ExpressionDescriptor("* * * * *", options) self.assertEqual( "Every minute", ceh.get_description(DescriptionTypeEnum.FULL))
def test_every_2_day_of_the_week_in_range_with_sunday_start_one(self): options = Options() options.day_of_week_start_index_zero = False self.assertEqual( "Every second, every 2 days of the week, Monday through Friday", get_description("* * * ? * 2-6/2", options))
def test_inline_import(self): from cron_descriptor import Options, DescriptionTypeEnum, ExpressionDescriptor options = Options() options.use_24hour_time_format = True ceh = ExpressionDescriptor("* * * * *", options) self.assertEqual("Every minute", ceh.get_description(DescriptionTypeEnum.FULL))
def test_locale_de(self): options = Options() options.locale_code = 'de_DE' options.use_24hour_time_format = True self.assertEqual( "Jede Minute", ExpressionDescriptor("* * * * *", options).get_description())
def test_day_of_week_modifier_with_sunday_start_one(self): options = Options() options.day_of_week_start_index_zero = False self.assertEqual("At 12:23 PM, on the second Sunday of the month", get_description("23 12 * * 1#2", options))
def test_invalid_cron_expression_error(self): options = Options() options.throw_exception_on_parse_error = False ceh = ExpressionDescriptor("INVALID CRON", options) self.assertEqual( "Error: Expression only has 2 parts. At least 5 part are required.", ceh.get_description(DescriptionTypeEnum.FULL))
def test_full_import(self): from cron_descriptor.Options import Options from cron_descriptor.DescriptionTypeEnum import DescriptionTypeEnum from cron_descriptor.ExpressionDescriptor import ExpressionDescriptor options = Options() options.use_24hour_time_format = True ceh = ExpressionDescriptor("* * * * *", options) self.assertEqual('Every minute', ceh.get_description(DescriptionTypeEnum.FULL))
def format_poll_data(poll: Poll): options = Options() options.locale_code = "ru_RU" return (poll.question or "Нет", ("\n\t\\- " + "\n\t\\- ".join(poll.answers)) if poll.answers else "Нет", "Да" if poll.is_anonymous else "Нет", "Да" if poll.is_multiple else "Нет", str(ExpressionDescriptor(poll.schedule, options)) if poll.schedule else "Не установлено")
def build_schedule_html(html_top: str = "<div>", html_bottom: str = "</div>") -> str: """Create a basic HTML table with the currently scheduled jobs. Args: html_top (str, optional): HTML to go before the table. Defaults to "<div>". html_bottom (str, optional): HTML to go at hte end of the table. Defaults to "</div>". Returns: str: HTML code. """ # Ensure scheduler is shut down, then re-add jobs and retrieve scheduled jobs from okr/scrapers/scheduler.py scheduler.setup() scheduler.scheduler.shutdown() scheduler.add_jobs() jobs_list = scheduler.scheduler.get_jobs() options = Options() options.locale_code = "de_DE" options.use_24hour_time_format = True # parse and convert job information into list table_lines = [] for job in jobs_list: cron_expression = " ".join(map(str, reversed(job.trigger.fields[1:]))) table_lines.append([ parse_job_info_method(job), get_description(cron_expression, options=options), ]) # sort list by module and reformat to a module.method format (instead of library.module.method) formatted_list = sorted(table_lines, key=itemgetter(0)) for entry in formatted_list: args_idx = entry[0].index("(") path = entry[0][:args_idx] rest = entry[0][args_idx:] path = ".".join(path.split(".")[-2:]) entry[0] = f"{path}{rest}" # convert jobs list into HTML table table_contents = tabulate( formatted_list, headers=["Aufgerufene Methode", "Zeitschema"], tablefmt="html", ) return str(html_top + table_contents + html_bottom)
class CronExpression(Resource): options = Options() options.locale_code = 'zh_CN' def post(self): try: cron_expression = request.form.get('expression', None) if cron_expression: expression = get_description(cron_expression, options=self.options) return {'description': str(expression)}, 200 else: return make_response(('', 200)) except Exception as e: return {'err': 'not valid %s' % e}, 500
def get_pretty(line_nbr, expression): """Get a human readable string for the cron expression""" import sys import subprocess import pyotherside # By default the module is installed in the 2.7 branch, pyotherside uses python 3 # We use a custom location sys.path.append("/usr/share/harbour-sailcron/python/") # https://github.com/Salamek/cron-descriptor from cron_descriptor import Options, CasingTypeEnum, DescriptionTypeEnum, ExpressionDescriptor # get proper 24/12 hour notation and strip output output = subprocess.check_output( "/usr/bin/dconf read /sailfish/i18n/lc_timeformat24h", shell=True) output = str(output).replace("'", "").replace('b"', "").replace('\\n"', "").strip() is24h = bool(output == "24") SPECIALS = { "reboot": '@reboot', "hourly": '0 * * * *', "daily": '0 0 * * *', "weekly": '0 0 * * 0', "monthly": '0 0 1 * *', "yearly": '0 0 1 1 *', "annually": '0 0 1 1 *', "midnight": '0 0 * * *' } key = expression.lstrip('@').rstrip(' ').lower() if key in SPECIALS.keys(): expression = SPECIALS[key] # set options options = Options() options.throw_exception_on_parse_error = False options.casing_type = CasingTypeEnum.Sentence options.use_24hour_time_format = is24h if expression == "@reboot": pyotherside.send('result', line_nbr, expression) human_format = "reboot" else: descripter = ExpressionDescriptor(expression, options) human_format = descripter.get_description(DescriptionTypeEnum.FULL) pyotherside.send('result', line_nbr, human_format) return human_format
def __init__(self, cronfile): """Initialize CrontabReader Args: cronfile: Path to cronfile Returns: None """ options = Options() options.day_of_week_start_index_zero = False options.use_24hour_time_format = True with open(cronfile) as f: for line in f.readlines(): parsed_line = self.parse_cron_line(line) if parsed_line: print("{} -> {}".format( parsed_line, ExpressionDescriptor(parsed_line, options)))
def test_lower_casing(self): options = Options() options.casing_type = CasingTypeEnum.LowerCase ceh = ExpressionDescriptor("* * * * *", options) self.assertEqual("every minute", ceh.get_description(DescriptionTypeEnum.FULL))
async def _list_reminders(self): """Format and show known reminders for the current room Sends a message listing them in the following format, using the alarm clock emoji ⏰ to indicate an alarm: 1️⃣ One-time Reminders * [⏰] <start time>: <reminder text> 📅 Cron Reminders * [⏰] m h d M wd (`m h d M wd`); next run in <rounded next time>; <reminder text> 🔁 Repeating Reminders * [⏰] every <recurring time>; next run in <rounded next time>; <reminder text> or if there are no reminders set: There are no reminders for this room. """ output = "" cron_reminder_lines = [] one_shot_reminder_lines = [] interval_reminder_lines = [] # Sort the reminder types for reminder in REMINDERS.values(): # Filter out reminders that don't belong to this room if reminder.room_id != self.room.room_id: continue # Organise alarms into markdown lists line = "- " if reminder.alarm: # Note that an alarm exists if available alarm_clock_emoji = "⏰" line += alarm_clock_emoji + " " # Print the duration before (next) execution next_execution = reminder.job.next_run_time next_execution = arrow.get(next_execution) # Cron-based reminders if isinstance(reminder.job.trigger, CronTrigger): # A human-readable cron tab, in addition to the actual tab o = Options() o.use_24hour_time_format = True line += f"{get_description(reminder.cron_tab, options=o)} (`{reminder.cron_tab}`); next run {next_execution.humanize()}" # One-time reminders elif isinstance(reminder.job.trigger, DateTrigger): # Just print when the reminder will go off line += f"{next_execution.humanize()}" # Repeat reminders elif isinstance(reminder.job.trigger, IntervalTrigger): # Print the interval, and when it will next go off line += f"every {readabledelta(reminder.recurse_timedelta)}; next run {next_execution.humanize()}" # Add the reminder's text line += f'; *"{reminder.reminder_text}"*' # Output the status of each reminder. We divide up the reminders by type in order # to show them in separate sections, and display them differently if isinstance(reminder.job.trigger, CronTrigger): cron_reminder_lines.append(line) elif isinstance(reminder.job.trigger, DateTrigger): one_shot_reminder_lines.append(line) elif isinstance(reminder.job.trigger, IntervalTrigger): interval_reminder_lines.append(line) if (not one_shot_reminder_lines and not cron_reminder_lines and not interval_reminder_lines): await send_text_to_room( self.client, self.room.room_id, "*There are no reminders for this room.*", ) return if one_shot_reminder_lines: output += "\n\n" + "**1️⃣ One-time Reminders**" + "\n\n" output += "\n".join(one_shot_reminder_lines) if cron_reminder_lines: output += "\n\n" + "**📅 Cron Reminders**" + "\n\n" output += "\n".join(cron_reminder_lines) if interval_reminder_lines: output += "\n\n" + "**🔁 Repeating Reminders**" + "\n\n" output += "\n".join(interval_reminder_lines) await send_text_to_room(self.client, self.room.room_id, output)
from domonic.terminal import crontab, date, uptime from domonic.javascript import Global from domonic.html import * from domonic import domonic from cron_descriptor import Options, ExpressionDescriptor from croniter import croniter from app import * _dark_mode = False # THIS IS GLOBAL. APPLIES TO EVERY USER! in every browser. fight for control! # this gets populated with parsed lines on page refresh _crons = {} # settings for cron_descriptor _options = Options() _options.day_of_week_start_index_zero = False _options.use_24hour_time_format = True class CrontabRenderer(object): rex = re.compile(r"^(\S{1,3}\s+\S{1,3}\s+\S{1,3}\s+\S{1,3}\s+\S{1,3}).+$") def __init__(self, ctab_data): self.ctab_data = ctab_data self.count = 0 _crons = {} self.__call__() # just to force the count def __call__(self):
def test_invalid_syntax_exception(self): options = Options() options.throw_exception_on_parse_error = True ceh = ExpressionDescriptor("* $ * * *", options) self.assertRaises(FormatException, ceh.get_description, DescriptionTypeEnum.FULL)
def test_title_casing(self): options = Options() options.casing_type = CasingTypeEnum.Title ceh = ExpressionDescriptor("* * * * *", options) self.assertEqual("Every Minute", ceh.get_description(DescriptionTypeEnum.FULL))
def test_none_cron_expression_error(self): options = Options() options.throw_exception_on_parse_error = False ceh = ExpressionDescriptor(None, options) self.assertEqual("Field 'ExpressionDescriptor.expression' not found.", ceh.get_description(DescriptionTypeEnum.FULL))
def register_job(self, workspace, job_class, log_in_db=False): jobkey = "" workspace_name = None if workspace is not None: if type(workspace) is str: jobkey += workspace + '/' workspace_name = workspace.name else: jobkey += workspace.name + '/' workspace_name = workspace.name jobInstance = job_class() jobkey += jobInstance.name jobInstance.job_key = jobkey if workspace is not None: jobInstance.workspace = workspace.name job = { 'job_class': job_class, 'name': jobInstance.name, 'workspace': workspace_name, 'description': jobInstance.description, 'parameters': jobInstance.parameters, 'trigger': 'Internal', 'log_in_db': log_in_db, 'cron': jobInstance.cron, 'day': jobInstance.day, 'week': jobInstance.week, 'day_of_week': jobInstance.day_of_week, 'hour': jobInstance.hour, 'minute': jobInstance.minute, 'second': jobInstance.second } if jobInstance.cron is True: cron_list = [] if job_class.minute is None: cron_list.append("*") else: cron_list.append(job_class.minute) if job_class.hour is None: cron_list.append("*") else: cron_list.append(job_class.hour) if job_class.day is None: cron_list.append("*") else: cron_list.append(job_class.day) cron_list.append("*") if job_class.day_of_week is None: cron_list.append("*") else: cron_list.append(job_class.day_of_week) cron_string = " ".join(cron_list) options = Options() options.throw_exception_on_parse_error = False options.day_of_week_start_index_zero = True options.use_24hour_time_format = True options.casing_type = CasingTypeEnum.LowerCase descripter = ExpressionDescriptor(cron_string, options) logManager.info("Register repetitive job '{}' triggered {}".format( jobkey, descripter.get_description())) self.scheduler.add_job(jobInstance.start_job, kwargs=({ "job_id": str(jobkey) }), id=(str(jobkey)), trigger='cron', replace_existing=True, day=job_class.day, day_of_week=job_class.day_of_week, week=job_class.week, hour=job_class.hour, minute=job_class.minute, second=job_class.second) job['trigger'] = descripter.get_description() self.jobs[str(jobkey)] = ObjDict(job.copy())
def __init__(self): self.options = Options() self.options.locale_code = 'pt_PT'
def setUp(self): """Set up en_US locale """ # all tests are written in en_US self.options = Options() self.options.locale_code = 'en_US'
def test_empty_cron_expression_exception(self): options = Options() options.throw_exception_on_parse_error = True ceh = ExpressionDescriptor('', options) self.assertRaises(MissingFieldException, ceh.get_description, DescriptionTypeEnum.FULL)
def get_cron_description(self, expression): options = Options() options.locale_code = 'zh_CN' return get_description(expression, options).__str__()