Esempio n. 1
0
    def configure_tasktable_crud(
            self,
            task=None,
            function=None,
            args=None,
            vars=None,
            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
        """

        if args is None:
            args = []
        if vars is None:
            vars = {}

        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.prevent_drift.readable = table.prevent_drift.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(
                label_create=T("Create Job"),
                title_display=T("Scheduled Jobs"),
                title_list=T("Job Schedule"),
                title_update=T("Edit Job"),
                label_list_button=T("List Jobs"),
                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
Esempio n. 2
0
    def configure_tasktable_crud(self,
                                 task=None,
                                 function=None,
                                 args=None,
                                 vars=None,
                                 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
        """

        if args is None:
            args = []
        if vars is None:
            vars = {}

        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.prevent_drift.readable = table.prevent_drift.writable = False

        table.sync_output.readable = table.sync_output.writable = False

        table.times_failed.readable = False

        # Configure start/stop time fields
        for fn in ("start_time", "stop_time"):
            field = table[fn]
            field.represent = lambda dt: \
                            S3DateTime.datetime_represent(dt, utc=True)
            field.requires = IS_UTC_DATETIME()
            set_min = set_max = None
            if fn == "start_time":
                set_min = "#scheduler_task_stop_time"
            elif fn == "stop_time":
                set_max = "#scheduler_task_start_time"
            field.widget = S3CalendarWidget(past = 0,
                                            set_min = set_min,
                                            set_max = set_max,
                                            timepicker = True,
                                            )

        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 = T("seconds")

        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(
                label_create = T("Create Job"),
                title_display = T("Scheduled Jobs"),
                title_list = T("Job Schedule"),
                title_update = T("Edit Job"),
                label_list_button = T("List Jobs"),
                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
Esempio n. 3
0
def s3_datetime(name="date", **attr):
    """
        Return a standard datetime field

        @param name: the field name

        @keyword default: the field default, use "now" for current datetime
        @keyword represent: the field representation method, use "date" for
                            S3DateTime.date_represent (default is
                            S3DateTime.datetime_represent)
        @keyword widget: the form widget, can use "date" to configure an
                         S3DateWidget (default is S3DateTimeWidget)
        @keyword past: limit selection to x hours before now
        @keyword future: limit selection to x hours after now
        @keyword min: earliest selectable datetime.datetime (overrides past)
        @keyword max: latest selectable datetime.datetime (overrides future)

        @ToDo: Different default field name in case we need to start supporting
               Oracle, where 'date' is a reserved word
    """

    now = current.request.utcnow

    limits = {}
    for keyword in ("past", "future", "min", "max"):
        if keyword in attr:
            limits[keyword] = attr[keyword]
            del attr[keyword]

    # Default and label
    if "default" in attr and attr["default"] == "now":
        attr["default"] = now
    if "label" not in attr:
        attr["label"] = current.T("Date")

    # Representation option
    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)

    # Helper functions to convert min/max dates into past/future hours
    def past_hours(earliest):
        diff = now - earliest
        return divmod(diff.days * 86400 + diff.seconds, 3600)[0]

    def future_hours(latest):
        diff = latest - now
        return divmod(diff.days * 86400 + diff.seconds, 3600)[0]

    requires = None
    widget = attr.get("widget")

    if widget == "date":

        # Helper function to convert past/future hours into
        # earliest/latest datetime, retaining day of month and
        # time of day
        def limit(delta):
            current_month = now.month
            years, hours = divmod(-delta, 8760)
            months = divmod(hours, 744)[0]
            if months > current_month:
                years += 1
            month = divmod((current_month - months) + 12, 12)[1]
            year = now.year - years
            return now.replace(month=month, year=year)

        # Compute limits
        earliest = limits.get("min")
        if not earliest:
            past = limits.get("past")
            if past is not None:
                earliest = limit(-past)
        else:
            past = past_hours(earliest)
        latest = attr.get("max")
        if not latest:
            future = attr.get("future")
            if future is not None:
                latest = limit(future)
        else:
            future = future_hours(latest)

        # Widget
        widget_opts = {}
        if past is not None:
            widget_opts["past"] = int(round(past / 744.0, 0))
        if future is not None:
            widget_opts["future"] = int(round(future / 744.0, 0))
        attr["widget"] = S3DateWidget(**widget_opts)

        # Validator
        if "requires" not in attr:
            dateformat = current.deployment_settings.get_L10n_date_format()
            if past is None and future is None:
                requires = IS_UTC_DATE()
            elif past is None:
                requires = IS_UTC_DATE(maximum=latest.date())
            elif future is None:
                requires = IS_UTC_DATE(minimum=earliest.date())
            else:
                attr["widget"] = S3DateWidget(past=past, future=future)
                requires = IS_UTC_DATE(maximum=latest.date(), minimum=earliest.date())

    elif widget is None or widget == "datetime":

        # Widget
        attr["widget"] = S3DateTimeWidget(**limits)

        # Validator
        if "requires" not in attr:
            earliest = limits.get("min")
            if not earliest:
                past = limits.get("past")
                if past is not None:
                    earliest = now - datetime.timedelta(hours=past)
            latest = limits.get("max")
            if not latest:
                future = limits.get("future")
                if future is not None:
                    latest = now + datetime.timedelta(hours=future)
            if earliest and latest:
                requires = IS_UTC_DATETIME(minimum=earliest, maximum=latest)
            elif earliest:
                requires = IS_UTC_DATETIME(minimum=earliest)
            elif latest:
                requires = IS_UTC_DATETIME(maximum=latest)
            else:
                requires = IS_UTC_DATETIME()

    if "requires" not in attr and requires is not None:
        empty = attr.pop("empty", None)
        if empty is False:
            attr["requires"] = requires
        else:
            attr["requires"] = IS_EMPTY_OR(requires)

    return S3ReusableField(name, "datetime", **attr)()