Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions plexapi/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,7 @@ def query(self, path, method=None, headers=None, timeout=None, **kwargs):
raise NotFound(message)
else:
raise BadRequest(message)
data = utils.cleanXMLString(response.text).encode('utf8')
return ElementTree.fromstring(data) if data.strip() else None
return utils.parseXMLString(response.text)

def sendCommand(self, command, proxy=None, **params):
""" Convenience wrapper around :func:`~plexapi.client.PlexClient.query` to more easily
Expand Down
7 changes: 2 additions & 5 deletions plexapi/myplex.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import threading
import time
from urllib.parse import parse_qsl, urlencode, urlsplit, urlunsplit
from xml.etree import ElementTree

import requests

Expand Down Expand Up @@ -250,8 +249,7 @@ def query(self, url, method=None, headers=None, timeout=None, **kwargs):
return response.json()
elif 'text/plain' in response.headers.get('Content-Type', ''):
return response.text.strip()
data = utils.cleanXMLString(response.text).encode('utf8')
return ElementTree.fromstring(data) if data.strip() else None
return utils.parseXMLString(response.text)

def ping(self):
""" Ping the Plex.tv API.
Expand Down Expand Up @@ -1879,8 +1877,7 @@ def _query(self, url, method=None, headers=None, **kwargs):
codename = codes.get(response.status_code)[0]
errtext = response.text.replace('\n', ' ')
raise BadRequest(f'({response.status_code}) {codename} {response.url}; {errtext}')
data = response.text.encode('utf8')
return ElementTree.fromstring(data) if data.strip() else None
return utils.parseXMLString(response.text)


def _connect(cls, url, token, session, timeout, results, i, job_is_done_event=None):
Expand Down
4 changes: 1 addition & 3 deletions plexapi/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import os
from functools import cached_property
from urllib.parse import urlencode
from xml.etree import ElementTree

import requests

Expand Down Expand Up @@ -768,8 +767,7 @@ def query(self, key, method=None, headers=None, params=None, timeout=None, **kwa
raise NotFound(message)
else:
raise BadRequest(message)
data = utils.cleanXMLString(response.text).encode('utf8')
return ElementTree.fromstring(data) if data.strip() else None
return utils.parseXMLString(response.text)

def search(self, query, mediatype=None, limit=None, sectionId=None):
""" Returns a list of media items or filter categories from the resulting
Expand Down
13 changes: 13 additions & 0 deletions plexapi/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@

from plexapi.exceptions import BadRequest, NotFound, Unauthorized

from xml.etree import ElementTree
Comment thread
eliasbenb marked this conversation as resolved.
Outdated

try:
from tqdm import tqdm
except ImportError:
Expand Down Expand Up @@ -718,3 +720,14 @@ def sha1hash(guid):

def cleanXMLString(s):
return _illegal_XML_re.sub('', s)


def parseXMLString(s: str):
""" Parse an XML string and return an ElementTree object. """
if not s.strip():
return None
encoded_s = s.encode('utf-8')
try: # Attempt to parse the string as-is without cleaning (which is expensive)
return ElementTree.fromstring(encoded_s)
except ElementTree.ParseError: # If it fails, clean the string and try again
return ElementTree.fromstring(cleanXMLString(encoded_s))
Comment thread
JonnyWong16 marked this conversation as resolved.
Outdated
Loading