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