def configure_tasktable_crud(self, task=None, function=None, args=[], vars={}, period = 3600, # seconds, so 1 hour ): """ Configure the task table for interactive CRUD, setting defaults, widgets and hiding unnecessary fields @param task: the task name (will use a UUID if omitted) @param function: the function name (won't hide if omitted) @param args: the function position arguments @param vars: the function named arguments """ T = current.T NONE = current.messages["NONE"] UNLIMITED = T("unlimited") tablename = self.TASK_TABLENAME table = current.db[tablename] table.uuid.readable = table.uuid.writable = False table.sync_output.readable = table.sync_output.writable = False table.times_failed.readable = False field = table.start_time field.represent = lambda dt: S3DateTime.datetime_represent(dt, utc=True) field.widget = S3DateTimeWidget(past=0) field.requires = IS_UTC_DATETIME( format=current.deployment_settings.get_L10n_datetime_format() ) field = table.stop_time field.represent = lambda dt: S3DateTime.datetime_represent(dt, utc=True) field.widget = S3DateTimeWidget(past=0) field.requires = IS_EMPTY_OR( IS_UTC_DATETIME( format=current.deployment_settings.get_L10n_datetime_format() )) if not task: import uuid task = str(uuid.uuid4()) field = table.task_name field.default = task field.readable = False field.writable = False if function: field = table.function_name field.default = function field.readable = False field.writable = False field = table.args field.default = json.dumps(args) field.readable = False field.writable = False field = table.repeats field.label = T("Repeat") field.comment = T("times (0 = unlimited)") field.default = 0 field.represent = lambda opt: \ opt and "%s %s" % (opt, T("times")) or \ opt == 0 and UNLIMITED or \ NONE field = table.period field.label = T("Run every") field.default = period field.widget = S3TimeIntervalWidget.widget field.requires = IS_TIME_INTERVAL_WIDGET(table.period) field.represent = S3TimeIntervalWidget.represent field.comment = None table.timeout.default = 600 table.timeout.represent = lambda opt: \ opt and "%s %s" % (opt, T("seconds")) or \ opt == 0 and UNLIMITED or \ NONE field = table.vars field.default = json.dumps(vars) field.readable = field.writable = False # Always use "default" controller (web2py uses current controller), # otherwise the anonymous worker does not pass the controller # permission check and gets redirected to login before it reaches # the task function which does the s3_impersonate field = table.application_name field.default = "%s/default" % current.request.application field.readable = field.writable = False table.group_name.readable = table.group_name.writable = False table.status.readable = table.status.writable = False table.next_run_time.readable = table.next_run_time.writable = False table.times_run.readable = table.times_run.writable = False table.assigned_worker_name.readable = table.assigned_worker_name.writable = False current.s3db.configure(tablename, list_fields=["id", "enabled", "start_time", "repeats", "period", (T("Last run"), "last_run_time"), (T("Last status"), "status"), (T("Next run"), "next_run_time"), "stop_time" ]) response = current.response if response: response.s3.crud_strings[tablename] = Storage( title_create = T("Add Job"), title_display = T("Scheduled Jobs"), title_list = T("Job Schedule"), title_update = T("Edit Job"), #title_search = T("Search for Job"), subtitle_create = T("Add Job"), label_list_button = T("List Jobs"), label_create_button = T("Add Job"), msg_record_created = T("Job added"), msg_record_modified = T("Job updated"), msg_record_deleted = T("Job deleted"), msg_list_empty = T("No jobs configured yet"), msg_no_match = T("No jobs configured")) return
def s3_datetime(name="date", **attr): """ Return a standard Datetime field Additional options to normal S3ResuableField: default = "now" (in addition to usual meanings) represent = "date" (in addition to usual meanings) widget = "date" (in addition to usual meanings) past = x hours future = x hours """ if "past" in attr: past = attr["past"] del attr["past"] else: past = None if "future" in attr: future = attr["future"] del attr["future"] else: future = None if "default" in attr and attr["default"] == "now": attr["default"] = current.request.utcnow if "label" not in attr: attr["label"] = current.T("Date") if "represent" not in attr: attr["represent"] = lambda dt: S3DateTime.datetime_represent(dt, utc=True) elif attr["represent"] == "date": attr["represent"] = lambda dt: S3DateTime.date_represent(dt, utc=True) if "widget" not in attr: if past is None and future is None: attr["widget"] = S3DateTimeWidget() elif past is None: attr["widget"] = S3DateTimeWidget(future=future) elif future is None: attr["widget"] = S3DateTimeWidget(past=past) else: attr["widget"] = S3DateTimeWidget(past=past, future=future) elif attr["widget"] == "date": if past is None and future is None: attr["widget"] = S3DateWidget() requires = IS_DATE( format=current.deployment_settings.get_L10n_date_format()) else: now = current.request.utcnow.date() current_month = now.month if past is None: future = int(round(future / 744.0, 0)) attr["widget"] = S3DateWidget(future=future) future_month = now.month + future if future_month <= 12: max = now.replace(month=future_month) else: current_year = now.year years = int(future_month / 12) future_year = current_year + years future_month = future_month - (years * 12) max = now.replace(year=future_year, month=future_month) requires = IS_DATE_IN_RANGE( format=current.deployment_settings.get_L10n_date_format(), maximum=max, error_message=current.T( "Date must be %(max)s or earlier!")) elif future is None: past = int(round(past / 744.0, 0)) attr["widget"] = S3DateWidget(past=past) if past < current_month: min = now.replace(month=current_month - past) else: current_year = now.year past_years = int(past / 12) past_months = past - (past_years * 12) min = now.replace(year=current_year - past_years, month=current_month - past_months) requires = IS_DATE_IN_RANGE( format=current.deployment_settings.get_L10n_date_format(), minimum=min, error_message=current.T("Date must be %(min)s or later!")) else: future = int(round(future / 744.0, 0)) past = int(round(past / 744.0, 0)) attr["widget"] = S3DateWidget(past=past, future=future) future_month = now.month + future if future_month < 13: max = now.replace(month=future_month) else: current_year = now.year years = int(future_month / 12) future_year = now.year + years future_month = future_month - (years * 12) max = now.replace(year=future_year, month=future_month) if past < current_month: min = now.replace(month=current_month - past) else: current_year = now.year past_years = int(past / 12) past_months = past - (past_years * 12) min = now.replace(year=current_year - past_years, month=current_month - past_months) requires = IS_DATE_IN_RANGE( format=current.deployment_settings.get_L10n_date_format(), maximum=max, minimum=min, error_message=current.T( "Date must be between %(min)s and %(max)s!")) if "empty" in attr: if attr["empty"] is False: attr["requires"] = requires else: attr["requires"] = IS_EMPTY_OR(requires) del attr["empty"] else: # Default attr["requires"] = IS_EMPTY_OR(requires) if "requires" not in attr: if past is None and future is None: requires = IS_UTC_DATETIME( format=current.deployment_settings.get_L10n_datetime_format()) else: now = current.request.utcnow if past is None: max = now + datetime.timedelta(hours=future) requires = IS_UTC_DATETIME( format=current.deployment_settings. get_L10n_datetime_format(), maximum=max, error_message=current.T( "Date must be %(max)s or earlier!")) elif future is None: min = now - datetime.timedelta(hours=past) requires = IS_UTC_DATETIME( format=current.deployment_settings. get_L10n_datetime_format(), minimum=min, error_message=current.T("Date must be %(min)s or later!")) else: min = now - datetime.timedelta(hours=past) max = now + datetime.timedelta(hours=future) requires = IS_UTC_DATETIME( format=current.deployment_settings. get_L10n_datetime_format(), maximum=max, minimum=min, error_message=current.T( "Date must be between %(min)s and %(max)s!")) if "empty" in attr: if attr["empty"] is False: attr["requires"] = requires else: attr["requires"] = IS_EMPTY_OR(requires) del attr["empty"] else: # Default attr["requires"] = IS_EMPTY_OR(requires) f = S3ReusableField(name, "datetime", **attr) return f()