From 966a6ce29e2a42c099c78e959d41d2a3eca70521 Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Sun, 1 Oct 2023 00:52:59 +0200 Subject: [PATCH] httplib2 should be an explicit dependency for Google integrations. Plus, some misc LINT/Black chores. --- platypush/plugins/db/__init__.py | 4 +- platypush/plugins/foursquare/__init__.py | 192 +++++++++++------- .../plugins/google/calendar/manifest.yaml | 5 + platypush/plugins/google/drive/manifest.yaml | 5 + platypush/plugins/google/fit/manifest.yaml | 5 + platypush/plugins/google/mail/manifest.yaml | 5 + platypush/plugins/google/maps/manifest.yaml | 5 + platypush/plugins/google/pubsub/manifest.yaml | 5 + .../plugins/google/translate/manifest.yaml | 5 + .../plugins/google/youtube/manifest.yaml | 5 + platypush/utils/reflection/_parser.py | 25 +-- setup.py | 12 +- 12 files changed, 184 insertions(+), 89 deletions(-) diff --git a/platypush/plugins/db/__init__.py b/platypush/plugins/db/__init__.py index 0b84900f99..5f32258c20 100644 --- a/platypush/plugins/db/__init__.py +++ b/platypush/plugins/db/__init__.py @@ -25,7 +25,7 @@ class DbPlugin(Plugin): _db_error_wait_interval = 5.0 _db_error_retries = 3 - def __init__(self, engine=None, **kwargs): + def __init__(self, engine=None, *args, **kwargs): """ :param engine: Default SQLAlchemy connection engine string (e.g. ``sqlite:///:memory:`` or ``mysql://user:pass@localhost/test``) @@ -42,7 +42,7 @@ class DbPlugin(Plugin): super().__init__() self.engine_url = engine - self.engine = self.get_engine(engine, **kwargs) + self.engine = self.get_engine(engine, *args, **kwargs) def get_engine( self, engine: Optional[Union[str, Engine]] = None, *args, **kwargs diff --git a/platypush/plugins/foursquare/__init__.py b/platypush/plugins/foursquare/__init__.py index 2a66cace8b..79d4b572f2 100644 --- a/platypush/plugins/foursquare/__init__.py +++ b/platypush/plugins/foursquare/__init__.py @@ -15,7 +15,8 @@ class FoursquarePlugin(Plugin): - Copy the ``client_id`` and ``client_secret``. - Add a redirect URL. It must point to a valid IP/hostname with a web server running, even if it runs locally. You can also use the local URL of the platypush web server - e.g. http://192.168.1.2:8008/. - - Open the following URL: ``https://foursquare.com/oauth2/authenticate?client_id=CLIENT_ID&response_type=token&redirect_uri=REDIRECT_URI``. + - Open the following URL: + ``https://foursquare.com/oauth2/authenticate?client_id=CLIENT_ID&response_type=token&redirect_uri=REDIRECT_URI``. Replace ``CLIENT_ID`` and ``REDIRECT_URI`` with the parameters from your app. - Allow the application. You will be redirected to the URL you provided. Copy the ``access_token`` provided in the URL. @@ -26,14 +27,16 @@ class FoursquarePlugin(Plugin): def __init__(self, access_token: str, **kwargs): """ - :param access_token: + :param access_token: The access token to use to authenticate to the Foursquare API. """ super().__init__(**kwargs) self.access_token = access_token def _get_url(self, endpoint): return '{url}/{endpoint}?oauth_token={token}&v={version}'.format( - url=self.api_base_url, endpoint=endpoint, token=self.access_token, + url=self.api_base_url, + endpoint=endpoint, + token=self.access_token, version=datetime.date.today().strftime('%Y%m%d'), ) @@ -44,24 +47,32 @@ class FoursquarePlugin(Plugin): :return: A list of checkins, as returned by the Foursquare API. """ url = self._get_url('users/self/checkins') - return requests.get(url).json().get('response', {}).get('checkins', {}).get('items', []) + return ( + requests.get(url) + .json() + .get('response', {}) + .get('checkins', {}) + .get('items', []) + ) # noinspection DuplicatedCode @action - def search(self, - latitude: Optional[float] = None, - longitude: Optional[float] = None, - altitude: Optional[float] = None, - latlng_accuracy: Optional[float] = None, - altitude_accuracy: Optional[float] = None, - near: Optional[str] = None, - query: Optional[str] = None, - limit: Optional[int] = None, - url: Optional[int] = None, - categories: Optional[List[str]] = None, - radius: Optional[int] = None, - sw: Optional[Union[Tuple[float], List[float]]] = None, - ne: Optional[Union[Tuple[float], List[float]]] = None,) -> List[Dict[str, Any]]: + def search( + self, + latitude: Optional[float] = None, + longitude: Optional[float] = None, + altitude: Optional[float] = None, + latlng_accuracy: Optional[float] = None, + altitude_accuracy: Optional[float] = None, + near: Optional[str] = None, + query: Optional[str] = None, + limit: Optional[int] = None, + url: Optional[int] = None, + categories: Optional[List[str]] = None, + radius: Optional[int] = None, + sw: Optional[Union[Tuple[float], List[float]]] = None, + ne: Optional[Union[Tuple[float], List[float]]] = None, + ) -> List[Dict[str, Any]]: """ Search for venues. @@ -82,7 +93,9 @@ class FoursquarePlugin(Plugin): :param ne: North/east boundary box as a ``[latitude, longitude]`` pair. :return: A list of venues, as returned by the Foursquare API. """ - assert (latitude and longitude) or near, 'Specify either latitude/longitude or near' + assert ( + latitude and longitude + ) or near, 'Specify either latitude/longitude or near' args = {} if latitude and longitude: @@ -111,27 +124,31 @@ class FoursquarePlugin(Plugin): args['ne'] = ne url = self._get_url('venues/search') - return requests.get(url, params=args).json().get('response', {}).get('venues', []) + return ( + requests.get(url, params=args).json().get('response', {}).get('venues', []) + ) # noinspection DuplicatedCode @action - def explore(self, - latitude: Optional[float] = None, - longitude: Optional[float] = None, - altitude: Optional[float] = None, - latlng_accuracy: Optional[float] = None, - altitude_accuracy: Optional[float] = None, - section: Optional[str] = None, - near: Optional[str] = None, - query: Optional[str] = None, - limit: Optional[int] = None, - categories: Optional[List[str]] = None, - radius: Optional[int] = None, - open_now: bool = True, - sort_by_distance: Optional[bool] = None, - sort_by_popularity: Optional[bool] = None, - price: Optional[List[int]] = None, - saved: Optional[bool] = None) -> List[Dict[str, Any]]: + def explore( + self, + latitude: Optional[float] = None, + longitude: Optional[float] = None, + altitude: Optional[float] = None, + latlng_accuracy: Optional[float] = None, + altitude_accuracy: Optional[float] = None, + section: Optional[str] = None, + near: Optional[str] = None, + query: Optional[str] = None, + limit: Optional[int] = None, + categories: Optional[List[str]] = None, + radius: Optional[int] = None, + open_now: bool = True, + sort_by_distance: Optional[bool] = None, + sort_by_popularity: Optional[bool] = None, + price: Optional[List[int]] = None, + saved: Optional[bool] = None, + ) -> List[Dict[str, Any]]: """ Explore venues around a location. @@ -168,7 +185,9 @@ class FoursquarePlugin(Plugin): :return: A list of venues, as returned by the Foursquare API. """ - assert (latitude and longitude) or near, 'Specify either latitude/longitude or near' + assert ( + latitude and longitude + ) or near, 'Specify either latitude/longitude or near' args = {} if latitude and longitude: @@ -203,15 +222,19 @@ class FoursquarePlugin(Plugin): args['price'] = ','.join([str(p) for p in price]) url = self._get_url('venues/explore') - return requests.get(url, params=args).json().get('response', {}).get('venues', []) + return ( + requests.get(url, params=args).json().get('response', {}).get('venues', []) + ) @action - def trending(self, - latitude: Optional[float] = None, - longitude: Optional[float] = None, - near: Optional[str] = None, - limit: Optional[int] = None, - radius: Optional[int] = None) -> List[Dict[str, Any]]: + def trending( + self, + latitude: Optional[float] = None, + longitude: Optional[float] = None, + near: Optional[str] = None, + limit: Optional[int] = None, + radius: Optional[int] = None, + ) -> List[Dict[str, Any]]: """ Get the trending venues around a location. @@ -224,7 +247,9 @@ class FoursquarePlugin(Plugin): :return: A list of venues, as returned by the Foursquare API. """ - assert (latitude and longitude) or near, 'Specify either latitude/longitude or near' + assert ( + latitude and longitude + ) or near, 'Specify either latitude/longitude or near' args = {} if latitude and longitude: @@ -237,24 +262,29 @@ class FoursquarePlugin(Plugin): args['radius'] = radius url = self._get_url('venues/trending') - return requests.get(url, params=args).json().get('response', {}).get('venues', []) + return ( + requests.get(url, params=args).json().get('response', {}).get('venues', []) + ) @staticmethod def _parse_time(t): - if isinstance(t, int) or isinstance(t, float): + if isinstance(t, (int, float)): return datetime.datetime.fromtimestamp(t) if isinstance(t, str): return datetime.datetime.fromisoformat(t) - assert isinstance(t, datetime.datetime), 'Cannot parse object of type {} into datetime: {}'.format( - type(t), t) + assert isinstance( + t, datetime.datetime + ), 'Cannot parse object of type {} into datetime: {}'.format(type(t), t) return t @action - def time_series(self, - venue_id: Union[str, List[str]], - start_at: Union[int, float, datetime.datetime, str], - end_at: Union[int, float, datetime.datetime, str]) -> List[Dict[str, Any]]: + def time_series( + self, + venue_id: Union[str, List[str]], + start_at: Union[int, float, datetime.datetime, str], + end_at: Union[int, float, datetime.datetime, str], + ) -> List[Dict[str, Any]]: """ Get the visitors stats about one or multiple venues over a time range. The user must be a manager of those venues. @@ -275,13 +305,17 @@ class FoursquarePlugin(Plugin): } url = self._get_url('venues/timeseries') - return requests.get(url, params=args).json().get('response', {}).get('venues', []) + return ( + requests.get(url, params=args).json().get('response', {}).get('venues', []) + ) @action - def stats(self, - venue_id: str, - start_at: Union[int, float, datetime.datetime, str], - end_at: Union[int, float, datetime.datetime, str]) -> List[Dict[str, Any]]: + def stats( + self, + venue_id: str, + start_at: Union[int, float, datetime.datetime, str], + end_at: Union[int, float, datetime.datetime, str], + ) -> List[Dict[str, Any]]: """ Get the stats about a venue over a time range. The user must be a manager of that venue. @@ -297,7 +331,9 @@ class FoursquarePlugin(Plugin): } url = self._get_url('venues/{}/stats'.format(venue_id)) - return requests.get(url, params=args).json().get('response', {}).get('venues', []) + return ( + requests.get(url, params=args).json().get('response', {}).get('venues', []) + ) @action def managed(self) -> List[Dict[str, Any]]: @@ -306,18 +342,26 @@ class FoursquarePlugin(Plugin): :return: A list of venues, as returned by the Foursquare API. """ url = self._get_url('venues/managed') - return requests.get(url).json().get('response', {}).get('venues', []).get('items', []) + return ( + requests.get(url) + .json() + .get('response', {}) + .get('venues', []) + .get('items', []) + ) @action - def checkin(self, - venue_id: str, - latitude: Optional[float] = None, - longitude: Optional[float] = None, - altitude: Optional[float] = None, - latlng_accuracy: Optional[float] = None, - altitude_accuracy: Optional[float] = None, - shout: Optional[str] = None, - broadcast: Optional[List[str]] = None) -> Dict[str, Any]: + def checkin( + self, + venue_id: str, + latitude: Optional[float] = None, + longitude: Optional[float] = None, + altitude: Optional[float] = None, + latlng_accuracy: Optional[float] = None, + altitude_accuracy: Optional[float] = None, + shout: Optional[str] = None, + broadcast: Optional[List[str]] = None, + ) -> Dict[str, Any]: """ Create a new check-in. @@ -350,10 +394,14 @@ class FoursquarePlugin(Plugin): if shout: args['shout'] = shout if broadcast: - args['broadcast'] = ','.join(broadcast) if isinstance(broadcast, list) else broadcast + args['broadcast'] = ( + ','.join(broadcast) if isinstance(broadcast, list) else broadcast + ) url = self._get_url('checkins/add') - return requests.post(url, data=args).json().get('response', {}).get('checkin', {}) + return ( + requests.post(url, data=args).json().get('response', {}).get('checkin', {}) + ) # vim:sw=4:ts=4:et: diff --git a/platypush/plugins/google/calendar/manifest.yaml b/platypush/plugins/google/calendar/manifest.yaml index 073f748034..be05715606 100644 --- a/platypush/plugins/google/calendar/manifest.yaml +++ b/platypush/plugins/google/calendar/manifest.yaml @@ -5,20 +5,25 @@ manifest: - py3-google-api-python-client - py3-google-auth - py3-oauth2client + - py3-httplib2 apt: - python3-google-auth - python3-oauth2client + - python3-httplib2 dnf: - python-google-api-client - python-google-auth - python-oauth2client + - python-httplib2 pacman: - python-google-api-python-client - python-google-auth - python-oauth2client + - python-httplib2 pip: - google-api-python-client - google-auth - oauth2client + - httplib2 package: platypush.plugins.google.calendar type: plugin diff --git a/platypush/plugins/google/drive/manifest.yaml b/platypush/plugins/google/drive/manifest.yaml index 6885a7fd27..43ae897370 100644 --- a/platypush/plugins/google/drive/manifest.yaml +++ b/platypush/plugins/google/drive/manifest.yaml @@ -5,20 +5,25 @@ manifest: - py3-google-api-python-client - py3-google-auth - py3-oauth2client + - py3-httplib2 apt: - python3-google-auth - python3-oauth2client + - python3-httplib2 dnf: - python-google-api-client - python-google-auth - python-oauth2client + - python-httplib2 pacman: - python-google-api-python-client - python-google-auth - python-oauth2client + - python-httplib2 pip: - google-api-python-client - google-auth - oauth2client + - httplib2 package: platypush.plugins.google.drive type: plugin diff --git a/platypush/plugins/google/fit/manifest.yaml b/platypush/plugins/google/fit/manifest.yaml index d90a7f8212..9d48ecb057 100644 --- a/platypush/plugins/google/fit/manifest.yaml +++ b/platypush/plugins/google/fit/manifest.yaml @@ -5,20 +5,25 @@ manifest: - py3-google-api-python-client - py3-google-auth - py3-oauth2client + - py3-httplib2 apt: - python3-google-auth - python3-oauth2client + - python3-httplib2 dnf: - python-google-api-client - python-google-auth - python-oauth2client + - python-httplib2 pacman: - python-google-api-python-client - python-google-auth - python-oauth2client + - python-httplib2 pip: - google-api-python-client - google-auth - oauth2client + - httplib2 package: platypush.plugins.google.fit type: plugin diff --git a/platypush/plugins/google/mail/manifest.yaml b/platypush/plugins/google/mail/manifest.yaml index 3a2bc1dac3..4bb62ac033 100644 --- a/platypush/plugins/google/mail/manifest.yaml +++ b/platypush/plugins/google/mail/manifest.yaml @@ -5,20 +5,25 @@ manifest: - py3-google-api-python-client - py3-google-auth - py3-oauth2client + - py3-httplib2 apt: - python3-google-auth - python3-oauth2client + - python3-httplib2 dnf: - python-google-api-client - python-google-auth - python-oauth2client + - python-httplib2 pacman: - python-google-api-python-client - python-google-auth - python-oauth2client + - python-httplib2 pip: - google-api-python-client - google-auth - oauth2client + - httplib2 package: platypush.plugins.google.mail type: plugin diff --git a/platypush/plugins/google/maps/manifest.yaml b/platypush/plugins/google/maps/manifest.yaml index 0c8b747c62..bdc63b1453 100644 --- a/platypush/plugins/google/maps/manifest.yaml +++ b/platypush/plugins/google/maps/manifest.yaml @@ -5,20 +5,25 @@ manifest: - py3-google-api-python-client - py3-google-auth - py3-oauth2client + - py3-httplib2 apt: - python3-google-auth - python3-oauth2client + - python3-httplib2 dnf: - python-google-api-client - python-google-auth - python-oauth2client + - python-httplib2 pacman: - python-google-api-python-client - python-google-auth - python-oauth2client + - python-httplib2 pip: - google-api-python-client - google-auth - oauth2client + - httplib2 package: platypush.plugins.google.maps type: plugin diff --git a/platypush/plugins/google/pubsub/manifest.yaml b/platypush/plugins/google/pubsub/manifest.yaml index 83c4fd77f5..360fba64e2 100644 --- a/platypush/plugins/google/pubsub/manifest.yaml +++ b/platypush/plugins/google/pubsub/manifest.yaml @@ -5,21 +5,26 @@ manifest: - py3-google-api-python-client - py3-google-auth - py3-oauth2client + - py3-httplib2 apt: - python3-google-auth - python3-oauth2client + - python3-httplib2 dnf: - python-google-api-client - python-google-auth - python-oauth2client + - python-httplib2 pacman: - python-google-api-python-client - python-google-auth - python-oauth2client + - python-httplib2 pip: - google-api-python-client - google-auth - oauth2client - google-cloud-pubsub + - httplib2 package: platypush.plugins.google.pubsub type: plugin diff --git a/platypush/plugins/google/translate/manifest.yaml b/platypush/plugins/google/translate/manifest.yaml index f7256f763d..1176000ecb 100644 --- a/platypush/plugins/google/translate/manifest.yaml +++ b/platypush/plugins/google/translate/manifest.yaml @@ -5,21 +5,26 @@ manifest: - py3-google-api-python-client - py3-google-auth - py3-oauth2client + - py3-httplib2 apt: - python3-google-auth - python3-oauth2client + - python3-httplib2 dnf: - python-google-api-client - python-google-auth - python-oauth2client + - python-httplib2 pacman: - python-google-api-python-client - python-google-auth - python-oauth2client + - python-httplib2 pip: - google-api-python-client - google-auth - oauth2client - google-cloud-translate + - httplib2 package: platypush.plugins.google.translate type: plugin diff --git a/platypush/plugins/google/youtube/manifest.yaml b/platypush/plugins/google/youtube/manifest.yaml index 3308ed0058..88d578463d 100644 --- a/platypush/plugins/google/youtube/manifest.yaml +++ b/platypush/plugins/google/youtube/manifest.yaml @@ -5,20 +5,25 @@ manifest: - py3-google-api-python-client - py3-google-auth - py3-oauth2client + - py3-httplib2 apt: - python3-google-auth - python3-oauth2client + - python3-httplib2 dnf: - python-google-api-client - python-google-auth - python-oauth2client + - python-httplib2 pacman: - python-google-api-python-client - python-google-auth - python-oauth2client + - python-httplib2 pip: - google-api-python-client - google-auth - oauth2client + - httplib2 package: platypush.plugins.google.youtube type: plugin diff --git a/platypush/utils/reflection/_parser.py b/platypush/utils/reflection/_parser.py index fcf5972204..db253c02de 100644 --- a/platypush/utils/reflection/_parser.py +++ b/platypush/utils/reflection/_parser.py @@ -134,7 +134,7 @@ class DocstringParser: return None lines = text.split("\n") - return (lines[0] + " " + tw.dedent("\n".join(lines[1:]) or "")).strip() + return (lines[0] + "\n" + tw.dedent("\n".join(lines[1:]) or "")).strip() ctx = ParseContext(obj) yield ctx @@ -203,17 +203,18 @@ class DocstringParser: return # Update the current parameter docstring if required - if ( - ctx.state == ParseState.PARAM - and cls._is_continuation_line(line) - and ctx.cur_param in ctx.parsed_params - ): - ctx.parsed_params[ctx.cur_param].doc = ( - ((ctx.parsed_params[ctx.cur_param].doc or "") + "\n" + line.rstrip()) - if ctx.parsed_params.get(ctx.cur_param) - and ctx.parsed_params[ctx.cur_param].doc - else "" - ) + if ctx.state == ParseState.PARAM and cls._is_continuation_line(line): + if ctx.cur_param in ctx.parsed_params: + ctx.parsed_params[ctx.cur_param].doc = ( + ( + (ctx.parsed_params[ctx.cur_param].doc or "") + + "\n" + + line.rstrip() + ) + if ctx.parsed_params.get(ctx.cur_param) + and ctx.parsed_params[ctx.cur_param].doc + else "" + ) return # Update the current docstring if required diff --git a/setup.py b/setup.py index 8919f97061..e9efd0cb14 100755 --- a/setup.py +++ b/setup.py @@ -110,6 +110,7 @@ setup( # Support for Google text2speech plugin 'google-tts': [ 'oauth2client', + 'httplib2', 'google-api-python-client', 'google-auth', 'google-cloud-texttospeech', @@ -130,7 +131,12 @@ setup( 'google-assistant-legacy': ['google-assistant-library', 'google-auth'], 'google-assistant': ['google-assistant-sdk[samples]', 'google-auth'], # Support for the Google APIs - 'google': ['oauth2client', 'google-auth', 'google-api-python-client'], + 'google': [ + 'oauth2client', + 'google-auth', + 'google-api-python-client', + 'httplib2', + ], # Support for Last.FM scrobbler plugin 'lastfm': ['pylast'], # Support for custom hotword detection @@ -213,9 +219,9 @@ setup( # Support for Trello integration 'trello': ['py-trello'], # Support for Google Pub/Sub - 'google-pubsub': ['google-cloud-pubsub', 'google-auth'], + 'google-pubsub': ['google-cloud-pubsub', 'google-auth', 'httplib2'], # Support for Google Translate - 'google-translate': ['google-cloud-translate', 'google-auth'], + 'google-translate': ['google-cloud-translate', 'google-auth', 'httplib2'], # Support for keyboard/mouse plugin 'inputs': ['pyuserinput'], # Support for Buienradar weather forecast