def latest_partition(cls, table_name: str, schema: Optional[str], database, show_first: bool = False): """Returns col name and the latest (max) partition value for a table :param table_name: the name of the table :param schema: schema / database / namespace :param database: database query will be run against :type database: models.Database :param show_first: displays the value for the first partitioning key if there are many partitioning keys :type show_first: bool >>> latest_partition('foo_table') (['ds'], ('2018-01-01',)) """ indexes = database.get_indexes(table_name, schema) if len(indexes[0]["column_names"]) < 1: raise SupersetTemplateException( "The table should have one partitioned field") elif not show_first and len(indexes[0]["column_names"]) > 1: raise SupersetTemplateException( "The table should have a single partitioned field " "to use this function. You may want to use " "`presto.latest_sub_partition`") column_names = indexes[0]["column_names"] part_fields = [(column_name, True) for column_name in column_names] sql = cls._partition_query(table_name, database, 1, part_fields) df = database.get_df(sql, schema) return column_names, cls._latest_partition_from_df(df)
def latest_partition(cls, table_name, schema, database, show_first=False): """Returns col name and the latest (max) partition value for a table :param table_name: the name of the table :type table_name: str :param schema: schema / database / namespace :type schema: str :param database: database query will be run against :type database: models.Database :param show_first: displays the value for the first partitioning key if there are many partitioning keys :type show_first: bool >>> latest_partition('foo_table') '2018-01-01' """ indexes = database.get_indexes(table_name, schema) if len(indexes[0]['column_names']) < 1: raise SupersetTemplateException( 'The table should have one partitioned field') elif not show_first and len(indexes[0]['column_names']) > 1: raise SupersetTemplateException( 'The table should have a single partitioned field ' 'to use this function. You may want to use ' '`presto.latest_sub_partition`') part_field = indexes[0]['column_names'][0] sql = cls._partition_query(table_name, 1, [(part_field, True)]) df = database.get_df(sql, schema) return part_field, cls._latest_partition_from_df(df)
def latest_sub_partition( cls, table_name: str, schema: Optional[str], database: "Database", **kwargs: Any ) -> Any: """Returns the latest (max) partition value for a table A filtering criteria should be passed for all fields that are partitioned except for the field to be returned. For example, if a table is partitioned by (``ds``, ``event_type`` and ``event_category``) and you want the latest ``ds``, you'll want to provide a filter as keyword arguments for both ``event_type`` and ``event_category`` as in ``latest_sub_partition('my_table', event_category='page', event_type='click')`` :param table_name: the name of the table, can be just the table name or a fully qualified table name as ``schema_name.table_name`` :type table_name: str :param schema: schema / database / namespace :type schema: str :param database: database query will be run against :type database: models.Database :param kwargs: keyword arguments define the filtering criteria on the partition list. There can be many of these. :type kwargs: str >>> latest_sub_partition('sub_partition_table', event_type='click') '2018-01-01' """ indexes = database.get_indexes(table_name, schema) part_fields = indexes[0]["column_names"] for k in kwargs.keys(): # pylint: disable=consider-iterating-dictionary if k not in k in part_fields: # pylint: disable=comparison-with-itself msg = "Field [{k}] is not part of the portioning key" raise SupersetTemplateException(msg) if len(kwargs.keys()) != len(part_fields) - 1: msg = ( "A filter needs to be specified for {} out of the " "{} fields." ).format(len(part_fields) - 1, len(part_fields)) raise SupersetTemplateException(msg) for field in part_fields: if field not in kwargs.keys(): field_to_return = field sql = cls._partition_query( table_name, database, 1, [(field_to_return, True)], kwargs ) df = database.get_df(sql, schema) if df.empty: return "" return df.to_dict()[field_to_return][0]
def safe_proxy(func: Callable[..., Any], *args: Any, **kwargs: Any) -> Any: return_value = func(*args, **kwargs) value_type = type(return_value).__name__ if value_type not in ALLOWED_TYPES: raise SupersetTemplateException( _( "Unsafe return type for function %(func)s: %(value_type)s", func=func.__name__, value_type=value_type, ) ) if value_type in COLLECTION_TYPES: try: return_value = json.loads(json.dumps(return_value)) except TypeError as ex: raise SupersetTemplateException( _("Unsupported return value for method %(name)s", name=func.__name__,) ) from ex return return_value
def validate_context_types(context: Dict[str, Any]) -> Dict[str, Any]: for key in context: arg_type = type(context[key]).__name__ if arg_type not in ALLOWED_TYPES and key not in context_addons(): if arg_type == "partial" and context[ key].func.__name__ == "safe_proxy": continue raise SupersetTemplateException( _( "Unsafe template value for key %(key)s: %(value_type)s", key=key, value_type=arg_type, )) if arg_type in COLLECTION_TYPES: try: context[key] = json.loads(json.dumps(context[key])) except TypeError: raise SupersetTemplateException( _("Unsupported template value for key %(key)s", key=key)) return context