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

        # 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. 2
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)()
Esempio n. 3
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. 4
0
def s3_date(name="date", **attr):
    """
        Return a standard Date field

        Additional options to normal S3ReusableField:
            default == "now" (in addition to usual meanings)
            past = x months
            future = x months
            start_field = "selector" for start field
            default_interval = x months from start date
            default_explicit = Bool for explicit default

        start_field and default_interval should be given together

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

    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

    T = current.T
    now = current.request.utcnow.date()

    if "default" in attr and attr["default"] == "now":
        attr["default"] = now

    if "label" not in attr:
        attr["label"] = T("Date")

    if "represent" not in attr:
        attr["represent"] = lambda d: S3DateTime.date_represent(d, utc=True)

    if "requires" not in attr:

        if past is None and future is None:
            requires = IS_UTC_DATE()
        else:
            current_month = now.month
            if past is None:
                future_month = now.month + future
                if future_month <= 12:
                    maximum = 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)
                    if future_month:
                        maximum = now.replace(year=future_year, month=future_month)
                    else:
                        maximum = now.replace(year=future_year)
                requires = IS_UTC_DATE(maximum=maximum)
            elif future is None:
                if past < current_month:
                    minimum = now.replace(month=current_month - past)
                else:
                    current_year = now.year
                    past_years = int(past / 12)
                    past_months = past - (past_years * 12)
                    past_month = current_month - past_months
                    if past_month:
                        minimum = now.replace(year=current_year - past_years, month=past_month)
                    else:
                        minimum = now.replace(year=current_year - past_years)
                requires = IS_UTC_DATE(minimum=minimum)
            else:
                future_month = now.month + future
                if future_month <= 12:
                    maximum = 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)
                    if future_month:
                        maximum = now.replace(year=future_year, month=future_month)
                    else:
                        maximum = now.replace(year=future_year)
                if past < current_month:
                    minimum = now.replace(month=current_month - past)
                else:
                    current_year = now.year
                    past_years = int(past / 12)
                    past_months = past - (past_years * 12)
                    past_month = current_month - past_months
                    if past_month:
                        minimum = now.replace(year=current_year - past_years, month=past_month)
                    else:
                        minimum = now.replace(year=current_year - past_years)
                requires = IS_UTC_DATE(minimum=minimum, maximum=maximum)

        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 "widget" not in attr:
        # Widget Options
        widget_option = {}

        if "start_field" in attr:
            widget_option["start_field"] = attr["start_field"]
            del attr["start_field"]

        if "default_interval" in attr:
            widget_option["default_interval"] = attr["default_interval"]
            del attr["default_interval"]

        if "default_explicit" in attr:
            widget_option["default_explicit"] = attr["default_explicit"]
            del attr["default_explicit"]

        if future is not None:
            widget_option["future"] = future

        if past is not None:
            widget_option["past"] = past

        attr["widget"] = S3DateWidget(**widget_option)

    f = S3ReusableField(name, "date", **attr)
    return f()