From 97775387c53a0df2a54eb85147059cba25453c9b Mon Sep 17 00:00:00 2001 From: Jason Lawrence Date: Mon, 19 Jul 2021 15:19:13 -0500 Subject: [PATCH 1/3] Decouple resource address sorting from connection attempts --- plexapi/myplex.py | 54 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 13 deletions(-) diff --git a/plexapi/myplex.py b/plexapi/myplex.py index 925a189f8..511d47153 100644 --- a/plexapi/myplex.py +++ b/plexapi/myplex.py @@ -16,6 +16,10 @@ from plexapi.sync import SyncItem, SyncList from requests.status_codes import _codes as codes +# Default order to prioritize available resource connections +RESOURCE_LOCATION_ORDER = ['local', 'remote', 'relay'] +RESOURCE_SCHEME_ORDER = ['https', 'http'] + class MyPlexAccount(PlexObject): """ MyPlex account and profile information. This object represents the data found Account on @@ -947,38 +951,62 @@ def _loadData(self, data): self.ownerid = utils.cast(int, data.attrib.get('ownerId', 0)) self.sourceTitle = data.attrib.get('sourceTitle') # owners plex username. - def connect(self, ssl=None, timeout=None): - """ Returns a new :class:`~plexapi.server.PlexServer` or :class:`~plexapi.client.PlexClient` object. + def preferred_connections(self, + ssl=None, + timeout=None, + locations=RESOURCE_LOCATION_ORDER, + schemes=RESOURCE_SCHEME_ORDER, + ): + """ Returns a sorted list of the available connection addresses for this resource. Often times there is more than one address specified for a server or client. - This function will prioritize local connections before remote or relay and HTTPS before HTTP. - After trying to connect to all available addresses for this resource and - assuming at least one connection was successful, the PlexServer object is built and returned. + Default behavior will prioritize local connections before remote or relay and HTTPS before HTTP. Parameters: ssl (bool, optional): Set True to only connect to HTTPS connections. Set False to only connect to HTTP connections. Set None (default) to connect to any HTTP or HTTPS connection. timeout (int, optional): The timeout in seconds to attempt each connection. - - Raises: - :exc:`~plexapi.exceptions.NotFound`: When unable to connect to any addresses for this resource. """ - # Keys in the order we want the connections to be sorted - locations = ['local', 'remote', 'relay'] - schemes = ['https', 'http'] connections_dict = {location: {scheme: [] for scheme in schemes} for location in locations} for connection in self.connections: # Only check non-local connections unless we own the resource if self.owned or (not self.owned and not connection.local): location = 'relay' if connection.relay else ('local' if connection.local else 'remote') - connections_dict[location]['http'].append(connection.httpuri) - connections_dict[location]['https'].append(connection.uri) + if location not in locations: + continue + if 'http' in schemes: + connections_dict[location]['http'].append(connection.httpuri) + if 'https' in schemes: + connections_dict[location]['https'].append(connection.uri) if ssl is True: schemes.remove('http') elif ssl is False: schemes.remove('https') connections = [] for location in locations: for scheme in schemes: connections.extend(connections_dict[location][scheme]) + return connections + + def connect(self, + ssl=None, + timeout=None, + locations=RESOURCE_LOCATION_ORDER, + schemes=RESOURCE_SCHEME_ORDER, + ): + """ Returns a new :class:`~plexapi.server.PlexServer` or :class:`~plexapi.client.PlexClient` object. + Uses `MyPlexResource.preferred_connections()` to generate the priority order of connection addresses. + After trying to connect to all available addresses for this resource and + assuming at least one connection was successful, the PlexServer object is built and returned. + + Parameters: + ssl (bool, optional): Set True to only connect to HTTPS connections. Set False to + only connect to HTTP connections. Set None (default) to connect to any + HTTP or HTTPS connection. + timeout (int, optional): The timeout in seconds to attempt each connection. + + Raises: + :exc:`~plexapi.exceptions.NotFound`: When unable to connect to any addresses for this resource. + """ + connections = self.preferred_connections(ssl, timeout, locations, schemes) # Try connecting to all known resource connections in parellel, but # only return the first server (in order) that provides a response. cls = PlexServer if 'server' in self.provides else PlexClient From e0e2e39b040c4ce31aebb20f54bc7eef3eae799b Mon Sep 17 00:00:00 2001 From: Jason Lawrence Date: Mon, 19 Jul 2021 15:28:47 -0500 Subject: [PATCH 2/3] Fix lint --- plexapi/myplex.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plexapi/myplex.py b/plexapi/myplex.py index 511d47153..167efe838 100644 --- a/plexapi/myplex.py +++ b/plexapi/myplex.py @@ -951,7 +951,8 @@ def _loadData(self, data): self.ownerid = utils.cast(int, data.attrib.get('ownerId', 0)) self.sourceTitle = data.attrib.get('sourceTitle') # owners plex username. - def preferred_connections(self, + def preferred_connections( + self, ssl=None, timeout=None, locations=RESOURCE_LOCATION_ORDER, @@ -986,7 +987,8 @@ def preferred_connections(self, connections.extend(connections_dict[location][scheme]) return connections - def connect(self, + def connect( + self, ssl=None, timeout=None, locations=RESOURCE_LOCATION_ORDER, From ad7b9749f7d86a28d0b3acdffba855e3165d025e Mon Sep 17 00:00:00 2001 From: Jason Lawrence Date: Mon, 19 Jul 2021 16:56:10 -0500 Subject: [PATCH 3/3] Move defaults to class --- plexapi/myplex.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/plexapi/myplex.py b/plexapi/myplex.py index 167efe838..15da2115d 100644 --- a/plexapi/myplex.py +++ b/plexapi/myplex.py @@ -16,10 +16,6 @@ from plexapi.sync import SyncItem, SyncList from requests.status_codes import _codes as codes -# Default order to prioritize available resource connections -RESOURCE_LOCATION_ORDER = ['local', 'remote', 'relay'] -RESOURCE_SCHEME_ORDER = ['https', 'http'] - class MyPlexAccount(PlexObject): """ MyPlex account and profile information. This object represents the data found Account on @@ -927,6 +923,10 @@ class MyPlexResource(PlexObject): TAG = 'Device' key = 'https://plex.tv/api/resources?includeHttps=1&includeRelay=1' + # Default order to prioritize available resource connections + DEFAULT_LOCATION_ORDER = ['local', 'remote', 'relay'] + DEFAULT_SCHEME_ORDER = ['https', 'http'] + def _loadData(self, data): self._data = data self.name = data.attrib.get('name') @@ -955,8 +955,8 @@ def preferred_connections( self, ssl=None, timeout=None, - locations=RESOURCE_LOCATION_ORDER, - schemes=RESOURCE_SCHEME_ORDER, + locations=DEFAULT_LOCATION_ORDER, + schemes=DEFAULT_SCHEME_ORDER, ): """ Returns a sorted list of the available connection addresses for this resource. Often times there is more than one address specified for a server or client. @@ -991,8 +991,8 @@ def connect( self, ssl=None, timeout=None, - locations=RESOURCE_LOCATION_ORDER, - schemes=RESOURCE_SCHEME_ORDER, + locations=DEFAULT_LOCATION_ORDER, + schemes=DEFAULT_SCHEME_ORDER, ): """ Returns a new :class:`~plexapi.server.PlexServer` or :class:`~plexapi.client.PlexClient` object. Uses `MyPlexResource.preferred_connections()` to generate the priority order of connection addresses.