def _task_filter_publishes(self, sg_publishes, environment, **kwargs):
        """
        """
        # time.sleep(5)
        filtered_publishes = []
        if (
            sg_publishes
            and environment
            and environment.publish_template
            and environment.context
        ):

            # convert created_at unix time stamp to shotgun std time stamp for all publishes
            for sg_publish in sg_publishes:
                created_at = sg_publish.get("created_at")
                if created_at:
                    created_at = datetime.fromtimestamp(
                        created_at, sg_timezone.LocalTimezone()
                    )
                    sg_publish["created_at"] = created_at

            filtered_publishes = self._filter_publishes(
                sg_publishes,
                environment.publish_template,
                environment.valid_file_extensions,
            )
        return {"sg_publishes": filtered_publishes}
    def get_datetime_bucket(dt):
        """
        This attempts to get the datetime bucket for the given datetime passed. Datetime buckets
        follow the same logic as the ShotGrid Web UI.

        NOTE should we move this to shotgun_globals.date_time module?

        :param dt: The datetime value to process
        :type dt: str | float | datetime.datetime

        :return: The datetime bucket that this datetime value falls into.
        :rtype: str
        """

        if dt is None:
            return "No Date"

        if isinstance(dt, six.string_types):
            if dt in FilterItem.DATETIME_BUCKETS:
                return dt

            dt = datetime.strptime(dt, "%Y-%m-%d")
            dt.replace(tzinfo=sg_timezone.LocalTimezone())

        if isinstance(dt, float):
            dt = datetime.fromtimestamp(dt, tz=sg_timezone.LocalTimezone())

        if not isinstance(dt, datetime):
            raise TypeError(
                "Cannot convert value type '{}' to datetime".format(type(dt)))

        # NOTE
        # Date comparisons - the ordering of the comparisons affect the result
        # The return value must be one of the values defined in DATETIME_BUCKETS
        #
        now = datetime.now(sg_timezone.LocalTimezone())
        today = now.date()
        date_value = dt.date()
        if date_value == today:
            return "Today"

        yesterday = now - timedelta(days=1)
        if date_value == yesterday.date():
            return "Yesterday"

        tomorrow = now + timedelta(days=1)
        if date_value == tomorrow.date():
            return "Tomorrow"

        # ShotGrid Web UI calculates Far Future as more than 120 days (30 days times 4, roughly 4 months)
        far_future = today + timedelta(days=30 * 4)
        if date_value > far_future:
            return "Far Future"

        # ShotGrid Web UI calculates Long Ago similarly to Far Future
        long_ago = today - timedelta(days=30 * 4)
        if date_value < long_ago:
            return "Long Ago"

        # ShotGrid Web UI calculates months ago as at least four weeks passed
        four_weeks_ago = today - timedelta(weeks=4)
        if date_value < four_weeks_ago:
            return "Last Few Months"
        # And similarly for next months ahead
        four_weeks_ahead = today + timedelta(weeks=4)
        if date_value > four_weeks_ahead:
            return "Next Few Months"

        # ShotGrid Web UI calculates week boundaries from Sunday; e.g. Last week will be any day from today
        # until (and including) last Sunday
        # Past weeks
        days_since_sunday = today.weekday() + 1
        last_last_sunday = today - timedelta(days=days_since_sunday, weeks=1)
        if date_value < last_last_sunday:
            return "Last Few Weeks"

        last_sunday = today - timedelta(days=days_since_sunday)
        if date_value < last_sunday:
            return "Last Week"

        next_sunday = today + timedelta(days=-days_since_sunday, weeks=1)
        if last_sunday <= date_value < next_sunday:
            return "This Week"

        next_next_sunday = today + timedelta(days=-days_since_sunday, weeks=2)
        if date_value < next_next_sunday:
            return "Next Week"

        if date_value <= four_weeks_ahead:
            return "Next Few Weeks"

        assert (
            False
        ), "Datetime value was not able to be converted to bucket, will default to plain datetime string"
        return dt.strftime("%x")
    def filter_value(self, value):
        """
        Validate the data to be set as the filter's value.
        """

        if isinstance(value, dict) and self.filter_type not in (
                self.FilterType.DICT,
                self.FilterType.LIST,
        ):
            # Try to extract the value from the dictionary object, for filter types that
            # are not expected a dictionary value.
            value = value.get("value")

        if value is None:
            # Just leave it as is
            pass

        elif self.filter_type == self.FilterType.GROUP:
            if value is None:
                value = []

            if not isinstance(value, list):
                raise TypeError(
                    "Attempting to set invalid value '{value}' for '{type}' filter type"
                    .format(value=value, type=self.filter_type))

            for filter_item in value:
                if not isinstance(filter_item, FilterItem):
                    raise TypeError(
                        "Attempting to set invalid value group filter '{item}'. Must be a FilterItem"
                        .format(item=filter_item))

        elif self.filter_type == self.FilterType.BOOL:
            # Allow 0 and 1 to be coerced to False and True. Do not allow any other non-bool data
            # types to go through, this could cause misleading filtering.
            if value == 0:
                value = False
            elif value == 1:
                value = True

            if not isinstance(value, bool):
                raise TypeError(
                    "Attempting to set invalid value '{value}' for '{type}' filter type"
                    .format(value=value, type=self.filter_type))

        elif self.filter_type == self.FilterType.STR:
            if not isinstance(value, six.string_types):
                # Just coerce it to string type.
                value = str(value)

        elif self.filter_type == self.FilterType.NUMBER:
            if isinstance(value, six.string_types):
                # For string values, first try to coerce to an int.
                try:
                    value = int(value)
                except ValueError:
                    pass

            if isinstance(value, six.string_types):
                # Still a string value, next try to coerce to a float.
                try:
                    value = float(value)
                except ValueError:
                    pass

            if not isinstance(value, numbers.Number):
                raise TypeError(
                    "Attempting to set invalid value '{value}' for '{type}' filter type"
                    .format(value=value, type=self.filter_type))

        elif self.filter_type == self.FilterType.DICT:
            if not isinstance(value, (dict, six.string_types)):
                raise TypeError(
                    "Attempting to set invalid value '{value}' for '{type}' filter type"
                    .format(value=value, type=self.filter_type))

        elif self.filter_type == self.FilterType.DATETIME:
            # Allow string values that are a valid "datetime" bucket or datetime objects
            valid = False
            if isinstance(value, six.string_types):
                valid = value in self.DATETIME_BUCKETS

            if not valid:
                if isinstance(value, six.string_types):
                    value = datetime.strptime(value, "%Y-%m-%d")
                    value.replace(tzinfo=sg_timezone.LocalTimezone())

                if isinstance(value, float):
                    value = datetime.fromtimestamp(
                        value, tz=sg_timezone.LocalTimezone())

                if not isinstance(value, datetime):
                    raise TypeError(
                        "Attempting to set invalid value '{value}' for '{type}' filter type"
                        .format(value=value, type=self.filter_type))

        self._filter_value = value