forked from tableau/document-api-python
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfilter.py
More file actions
120 lines (100 loc) · 4.04 KB
/
Copy pathfilter.py
File metadata and controls
120 lines (100 loc) · 4.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import re
from tableaudocumentapi.utils import _clean_aggregated_column_names
class Filter(object):
"""A class representing a Filter in a worksheet or datasource"""
def __init__(self, filter_xml):
"""Initialize Filter from XML Element
Args:
filter_xml: XML element representing the filter
"""
self._xml = filter_xml
self._filter_class = filter_xml.get('class')
self._column = _clean_aggregated_column_names(filter_xml.get('column'))[1]
self._datasource = _clean_aggregated_column_names(filter_xml.get('column'))[0]
self._groupfilters = self._parse_groupfilters()
self._included_values = filter_xml.get('included-values')
self._min_value = None
self._max_value = None
min_el = filter_xml.find('min')
max_el = filter_xml.find('max')
if min_el is not None:
self._min_value = min_el.text
if max_el is not None:
self._max_value = max_el.text
@property
def xml(self):
"""Return xml of the filter """
return self._xml
@property
def groupfilters(self):
"""Return groupfilters of the filter"""
return self._groupfilters
@property
def filter_class(self):
"""Return class attribute of the filter"""
return self._filter_class
@property
def column(self):
"""Return columns of the filter """
return self._column
@property
def datasource(self):
"""Return datasource of the columns of the filter """
return self._datasource
@property
def min_value(self):
"""Return <min> text for quantitative range filters, or None."""
return self._min_value
@property
def max_value(self):
"""Return <max> text for quantitative range filters, or None."""
return self._max_value
@property
def included_values(self):
"""Return the included-values attribute (e.g. 'in-range', 'all'), or None."""
return self._included_values
@property
def members(self):
"""Flat list of member values extracted from groupfilters (categorical filters)."""
values = []
def _extract(gf_list):
for gf in gf_list:
if gf.get('function') == 'member' and gf.get('member'):
values.append(gf['member'].strip('"'))
_extract(gf.get('children', []))
_extract(self._groupfilters)
return values
def _parse_groupfilters(self):
"""Function that will parse the groupfilters under the filter"""
groupfilters = []
groupfilter_elements = self._xml.findall('groupfilter')
for groupfilter in groupfilter_elements:
parsed_groupfilter = self._parse_single_groupfilter(groupfilter)
if parsed_groupfilter:
groupfilters.append(parsed_groupfilter)
return groupfilters
def _parse_single_groupfilter(self, groupfilter_xml):
"""Parse a single groupfilter element recursively"""
if groupfilter_xml is None:
return None
groupfilter_data = {
'function': groupfilter_xml.get('function'),
'level': groupfilter_xml.get('level'),
'member': groupfilter_xml.get('member'),
'attributes': dict(groupfilter_xml.attrib),
'children': []
}
# Parse nested groupfilters recursively
child_groupfilters = groupfilter_xml.findall('groupfilter')
for child in child_groupfilters:
child_data = self._parse_single_groupfilter(child)
if child_data:
groupfilter_data['children'].append(child_data)
return groupfilter_data
def _parse_filters(root_node, path):
"""Function that will parse the filters under the worksheet or datasource"""
filters = []
filter_elements = root_node.findall(path)
for filter_element in filter_elements:
filters.append(Filter(filter_element))
return filters