Update fetchItem to search all subitems as well

This commit is contained in:
Michael Shepanski 2017-02-09 16:29:23 -05:00
parent 08e61960e7
commit ebf18ba020
2 changed files with 73 additions and 44 deletions

View file

@ -169,40 +169,58 @@ class PlexObject(object):
return self
def _checkAttrs(self, elem, **kwargs):
for kwarg, query in kwargs.items():
# strip underscore from special cased attrs
if kwarg in ('_key', '_cls', '_tag'):
kwarg = kwarg[1:]
# extract the kwarg operator if present
op, operator = 'exact', OPERATORS['exact']
if '__' in kwarg:
kwarg, op = kwarg.rsplit('__', 1)
if op not in OPERATORS:
raise BadRequest('Invalid filter operator: __%s' % op)
operator = OPERATORS[op]
# get value from elem and check ismissing operator
value = elem.attrib.get(kwarg)
log.debug("Checking %s.%s__%s=%s (value=%s)", elem.tag, kwarg, op,
str(query)[:20], str(value)[:20])
logme = elem.attrib.get('ratingKey') == '746'
attrsFound = {}
for attr, query in kwargs.items():
attr, op, operator = self._getAttrOperator(attr)
values = self._getAttrValue(elem, attr)
if logme: log.debug('Check %s.%s__%s=%s (value=%s)', elem.tag, attr, op, str(query)[:20], str(values)[:20])
# special case ismissing operator
if op == 'ismissing':
if query not in (True, False):
raise BadRequest('Value when using __ismissing must be in (True, False).')
if (query is True and value) or (query is False and not value):
if (query is True and values) or (query is False and not values):
return False
# special case query=None,0,'' to include missing attr
if op == 'exact' and query in (None, 0, '') and value is None:
# special case query in (None,0,'') to include missing attr
if op == 'exact' and query in (None, 0, '') and not values:
return True
# return if attr were looking for is missing
if not value:
return False
# cast value to the same type as query
if isinstance(query, int): value = int(value)
if isinstance(query, float): value = float(value)
if isinstance(query, bool): value = bool(int(value))
# perform the comparison
if not operator(value, query):
return False
return True
attrsFound[attr] = False
for value in values:
if isinstance(query, int): value = int(value)
if isinstance(query, float): value = float(value)
if isinstance(query, bool): value = bool(int(value))
if logme: log.info('%s %s %s', value, op, query)
if operator(value, query):
attrsFound[attr] = True
break
if logme: log.info(attrsFound)
return all(attrsFound.values())
def _getAttrOperator(self, attr):
attr = attr.lstrip('_')
for op, operator in OPERATORS.items():
if attr.endswith('__%s' % op):
attr = attr.rsplit('__', 1)[0]
return attr, op, operator
# default to exact match
return attr, 'exact', OPERATORS['exact']
def _getAttrValue(self, elem, attrstr, results=None):
#log.debug('Fetching %s in %s', attrstr, elem.tag)
parts = attrstr.split('__', 1)
attr = parts[0]
attrstr = parts[1] if len(parts) == 2 else None
if attrstr:
results = [] if results is None else results
for child in [c for c in elem if c.tag.lower() == attr.lower()]:
results += self._getAttrValue(child, attrstr, results)
return [r for r in results if r is not None]
# loop through attrs so we can perform case-insensative match
for _attr, value in elem.attrib.items():
if attr.lower() == _attr.lower():
return [value]
return []
def _loadData(self, data):
raise NotImplementedError('Abstract method not implemented.')

View file

@ -173,7 +173,7 @@ class PlexAttributes():
self._load_attrs(playqueue, 'pq')
def _parse_sync(self):
# TODO: Get this working..
# TODO: Get plexattrs._parse_sync() working.
pass
def _load_attrs(self, obj, cat=None):
@ -229,29 +229,39 @@ class PlexAttributes():
def print_report(self):
total_attrs = 0
for clsname in sorted(self.attrs.keys()):
meta = self.attrs[clsname]
count = meta['total']
print(_('\n%s (%s)\n%s' % (clsname, count, '-'*30), 'yellow'))
attrs = sorted(set(list(meta['xml'].keys()) + list(meta['obj'].keys())))
for attr in attrs:
state = self._attr_state(clsname, attr, meta)
count = meta['xml'].get(attr, 0)
categories = ','.join(meta['categories'].get(attr, ['--']))
examples = '; '.join(list(meta['examples'].get(attr, ['--']))[:3])[:80]
print('%7s %3s %-30s %-20s %s' % (count, state, attr, categories, examples))
total_attrs += count
if self._clsname_match(clsname):
meta = self.attrs[clsname]
count = meta['total']
print(_('\n%s (%s)\n%s' % (clsname, count, '-'*30), 'yellow'))
attrs = sorted(set(list(meta['xml'].keys()) + list(meta['obj'].keys())))
for attr in attrs:
state = self._attr_state(clsname, attr, meta)
count = meta['xml'].get(attr, 0)
categories = ','.join(meta['categories'].get(attr, ['--']))
examples = '; '.join(list(meta['examples'].get(attr, ['--']))[:3])[:80]
print('%7s %3s %-30s %-20s %s' % (count, state, attr, categories, examples))
total_attrs += count
print(_('\nSUMMARY\n%s' % ('-'*30), 'yellow'))
print('%7s %3s %3s %-20s %s' % ('total', 'new', 'old', 'categories', 'clsname'))
for clsname in sorted(self.attrs.keys()):
print('%7s %12s %12s %s' % (self.attrs[clsname]['total'],
_(self.attrs[clsname]['new'] or '', 'cyan'),
_(self.attrs[clsname]['old'] or '', 'red'),
clsname))
if self._clsname_match(clsname):
print('%7s %12s %12s %s' % (self.attrs[clsname]['total'],
_(self.attrs[clsname]['new'] or '', 'cyan'),
_(self.attrs[clsname]['old'] or '', 'red'),
clsname))
print('\nPlex Version %s' % self.plex.version)
print('PlexAPI Version %s' % plexapi.VERSION)
print('Total Objects %s' % sum([x['total'] for x in self.attrs.values()]))
print('Runtime %s min\n' % self.runtime)
def _clsname_match(self, clsname):
if not self.clsnames:
return True
for cname in self.clsnames:
if cname.lower() in clsname.lower():
return True
return False
def _attr_state(self, clsname, attr, meta):
if attr in meta['xml'].keys() and attr not in meta['obj'].keys():
self.attrs[clsname]['new'] += 1
@ -280,6 +290,7 @@ if __name__ == '__main__':
if not opts.force and os.path.exists(CACHEPATH):
with open(CACHEPATH, 'rb') as handle:
plexattrs = pickle.load(handle)
plexattrs.clsnames = [c for c in opts.clsnames.split(',') if c]
if not plexattrs:
plexattrs = PlexAttributes(opts).run()
with open(CACHEPATH, 'wb') as handle: