diff --git a/API_METHODS.md b/API_METHODS.md index 9ee463c..5ee8702 100644 --- a/API_METHODS.md +++ b/API_METHODS.md @@ -1,5 +1,5 @@ # MEETUP API Methods -[Source](http://www.meetup.com/meetup_api/docs/) +[Source](https://www.meetup.com/meetup_api/docs/) ##v3 abuse diff --git a/README.rst b/README.rst index 04c2ea0..de319b7 100644 --- a/README.rst +++ b/README.rst @@ -27,7 +27,7 @@ Initialize Client and Execute API Call .. code-block:: python >>> import meetup.api - >>> client = meetup.api.Client('my_special_api_key_value') + >>> client = meetup.api.Client('my_special_token_value') >>> >>> type(client) @@ -49,7 +49,7 @@ Initialize Client and Execute API Call 'Meetup API Testing Sandbox' >>> >>> group_info.link - 'http://www.meetup.com/Meetup-API-Testing/' + 'https://www.meetup.com/Meetup-API-Testing/' For a full listing of implemented API methods, take a look at the `API Client Details`_. @@ -78,11 +78,11 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -.. _Meetup: http://www.meetup.com/ -.. _Meetup REST API documentation: http://www.meetup.com/meetup_api/ +.. _Meetup: https://www.meetup.com/ +.. _Meetup REST API documentation: https://www.meetup.com/meetup_api/ .. _Python: https://www.python.org/ -.. _API Client Details: http://meetup-api.readthedocs.org/en/latest/meetup_api.html#api-client-details -.. _Getting Started: http://meetup-api.readthedocs.org/en/latest/getting_started.html +.. _API Client Details: https://meetup-api.readthedocs.org/en/latest/meetup_api.html#api-client-details +.. _Getting Started: https://meetup-api.readthedocs.org/en/latest/getting_started.html .. |build-status| image:: https://img.shields.io/travis/pferate/meetup-api.svg?style=flat :alt: Build Status diff --git a/docs/getting_started.rst b/docs/getting_started.rst index 271ac9c..d295643 100644 --- a/docs/getting_started.rst +++ b/docs/getting_started.rst @@ -23,9 +23,9 @@ Usage Initialize Client ~~~~~~~~~~~~~~~~~ -To initialize your Meetup API Client, you will need to import the Client class and create a Client object. Before making and API requests, you will need to assign your API key to the object. +To initialize your Meetup API Client, you will need to import the Client class and create a Client object. Before making and API requests, you will need to assign your OAuth token value to the object. -Three ways to assign your API key (in order of precedence): +Three ways to assign your OAuth token (in order of precedence): 1. Assign to attribute: @@ -33,20 +33,20 @@ Three ways to assign your API key (in order of precedence): >>> import meetup.api >>> client = meetup.api.Client() - >>> client.api_key = 'my_special_api_key_value' + >>> client.token = 'my_special_token_value' 2. Assign at initialization: .. code-block:: python >>> import meetup.api - >>> client = meetup.api.Client('my_special_api_key_value') + >>> client = meetup.api.Client('my_special_token_value') 3. Retrieved from environment variable: .. code-block:: bash - $ export MEETUP_API_KEY=my_special_api_key_value + $ export MEETUP_OAUTH_TOKEN=my_special_token_value .. code-block:: python @@ -59,7 +59,7 @@ Execute API Calls .. code-block:: python >>> import meetup.api - >>> client = meetup.api.Client('my_special_api_key_value') + >>> client = meetup.api.Client('my_special_token_value') >>> group_info = client.GetGroup({'urlname': 'Meetup-API-Testing'}) >>> >>> type(client) @@ -80,7 +80,7 @@ Execute API Calls 'Meetup API Testing Sandbox' >>> >>> group_info.link - 'http://www.meetup.com/Meetup-API-Testing/' + 'https://www.meetup.com/Meetup-API-Testing/' A full listing of implemented API methods can be found at :ref:`meetup_api`. diff --git a/docs/index.rst b/docs/index.rst index 043e767..d3715e0 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,12 +1,12 @@ Welcome to Meetup API's documentation! ====================================== -.. _Meetup: http://www.meetup.com/ -.. _API: http://www.meetup.com/meetup_api/ +.. _Meetup: https://www.meetup.com/ +.. _API: https://www.meetup.com/meetup_api/ .. Inline linking was needed here due to the apostrophe. -meetup-api is a Python client for `Meetup's `_ RESTful `API`_. It is compatible with both Python 2 and Python 3. Currently only API Key authentication is available (OAuth is planned for a future release). +meetup-api is a Python client for `Meetup's `_ RESTful `API`_. It is compatible with both Python 2 and Python 3. Currently only OAuth token authentication is available, as Meetup is removing API Keys support on 15 August 2019. The Python Requests-OAuthlib can be used to get OAuth tokens for this. .. _user-docs: diff --git a/docs/meetup_api.rst b/docs/meetup_api.rst index 7891814..b39a65c 100644 --- a/docs/meetup_api.rst +++ b/docs/meetup_api.rst @@ -1158,9 +1158,9 @@ API Client Methods This method does not require authentication. It requires only a url parameter and responds according to the [OEmbed specification](http://www.oembed.com/). Any of the following base URLs may refer to embeddable content: - * http://www.meetup.com/ - * http://meetup.com/ - * http://meetu.ps/ + * https://www.meetup.com/ + * https://meetup.com/ + * https://meetu.ps/ An optional __maxwidth__ parameter may be provided. diff --git a/meetup/api.py b/meetup/api.py index 65d7fe9..270bc4a 100644 --- a/meetup/api.py +++ b/meetup/api.py @@ -9,8 +9,8 @@ from meetup import exceptions -API_DEFAULT_URL = 'http://api.meetup.com/' -API_KEY_ENV_NAME = 'MEETUP_API_KEY' +API_DEFAULT_URL = 'https://api.meetup.com/' +TOKEN_ENV_NAME = 'MEETUP_OAUTH_TOKEN' API_SPEC_DIR = os.path.join(os.path.dirname(__file__), 'api_specification') API_SERVICE_FILES = [ ('v1', os.path.join(API_SPEC_DIR, 'meetup_v1_services.json')), @@ -100,20 +100,20 @@ class Client(object): """ Meetup API Client. - There are 3 options for defining the API key prior to making API calls: + There are 3 options for defining the oauth token prior to making API calls: - 1. Pass it as a parameter (api_key) - 2. Stored as an environment variable, if parameter is not defined. (Default: MEETUP_API_KEY) - 3. Define it after the object is created. (client.api_key = 'my_secret_api_key') + 1. Pass it as a parameter (api_token) + 2. Stored as an environment variable, if parameter is not defined. (Default: MEETUP_OAUTH_TOKEN) + 3. Define it after the object is created. (client.api_token = 'my_secret_oauth_token') - :param api_key: Meetup API Key, from https://secure.meetup.com/meetup_api/key/ + :param api_token: Meetup oauth token, from https://www.meetup.com/meetup_api/auth/ :param api_url: Meetup API URL, Keeping it flexible so that it can be generalized in the future. :param overlimit_wait: Whether or not to wait and retry if over API request limit. (Default: True) """ - def __init__(self, api_key=None, api_url=API_DEFAULT_URL, overlimit_wait=True): + def __init__(self, token=None, api_url=API_DEFAULT_URL, overlimit_wait=True): self._api_url = api_url - self.api_key = api_key or os.environ.get(API_KEY_ENV_NAME) + self.token = token or os.environ.get(TOKEN_ENV_NAME) self.overlimit_wait = overlimit_wait self.session = requests.Session() self.rate_limit = RateLimit() @@ -131,13 +131,13 @@ def __init__(self, api_key=None, api_url=API_DEFAULT_URL, overlimit_wait=True): self.services[service_name] = service_details def _call(self, service_name, parameters=None, **kwargs): - if not self.api_key: - raise exceptions.ApiKeyError('Meetup API key not set') + if not self.token: + raise exceptions.TokenError('Meetup oauth2 token not set') if not parameters: parameters = {} if not isinstance(parameters, dict): raise exceptions.ApiParameterError('Parameters must be dict') - parameters['key'] = self.api_key + parameters['access_token'] = self.token for key, value in six.iteritems(kwargs): parameters[key] = value diff --git a/meetup/api_specification/meetup_v1_services.json b/meetup/api_specification/meetup_v1_services.json index 92a81b2..7a171e0 100644 --- a/meetup/api_specification/meetup_v1_services.json +++ b/meetup/api_specification/meetup_v1_services.json @@ -166,7 +166,7 @@ }, "summary": "oEmbed implementation", "uri": "/oembed", - "notes": "\nThis method does not require authentication. It requires only a url parameter and responds according to the [OEmbed specification](http://www.oembed.com/). Any of the following base URLs may refer to embeddable content:\n\n* http://www.meetup.com/\n* http://meetup.com/\n* http://meetu.ps/\n\nAn optional __maxwidth__ parameter may be provided.\n" + "notes": "\nThis method does not require authentication. It requires only a url parameter and responds according to the [OEmbed specification](http://www.oembed.com/). Any of the following base URLs may refer to embeddable content:\n\n* https://www.meetup.com/\n* https://meetup.com/\n* https://meetu.ps/\n\nAn optional __maxwidth__ parameter may be provided.\n" }, "GetTopics": { "version": "1", @@ -257,4 +257,4 @@ "notes": null } } -} \ No newline at end of file +} diff --git a/meetup/exceptions.py b/meetup/exceptions.py index d084aa5..9dc59f3 100644 --- a/meetup/exceptions.py +++ b/meetup/exceptions.py @@ -10,9 +10,9 @@ class ClientException(MeetupBaseException): """ -class ApiKeyError(ClientException): +class TokenError(ClientException): """ - There is a problem with the client API key. + There is a problem with the client OAuth token. """ @@ -48,7 +48,7 @@ class HttpClientError(MeetupHttpBaseException): class HttpUnauthorized(HttpClientError): """ - Called when the server sends a 401 error (when you don't provide a valid key) + Called when the server sends a 401 error (when you don't provide a valid OAuth token) """ diff --git a/tests/test_client.py b/tests/test_client.py index dfdfc88..14a817c 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -2,7 +2,7 @@ import pytest from meetup import exceptions -from meetup.api import API_KEY_ENV_NAME, Client, MeetupObject +from meetup.api import TOKEN_ENV_NAME, Client, MeetupObject @pytest.fixture @@ -11,20 +11,20 @@ def api_client(): @pytest.mark.incremental -class TestApiKey: +class TestToken: def test_environment_key(self, api_client): - # Compare object API key with environment variable - assert api_client.api_key == os.environ.get(API_KEY_ENV_NAME) + # Compare object OAuth token with environment variable + assert api_client.token == os.environ.get(TOKEN_ENV_NAME) def test_empty_key(self, api_client): - # Undefined API Key should fail - api_client.api_key = None - with pytest.raises(exceptions.ApiKeyError): + # Undefined OAuth token should fail + api_client.token = None + with pytest.raises(exceptions.TokenError): api_client.GetDashboard() def test_invalid_key(self, api_client): # Same with invalid API Key - api_client.api_key = 'foobarbaz' + api_client.token = 'foobarbaz' with pytest.raises(exceptions.HttpUnauthorized): api_client.GetDashboard() diff --git a/tox.ini b/tox.ini index 9910458..d46cbc6 100644 --- a/tox.ini +++ b/tox.ini @@ -3,7 +3,7 @@ envlist=py27,py34,py35,coverage,flake8,docs [testenv] usedevelop=True -passenv=MEETUP_API_KEY +passenv=MEETUP_OAUTH_TOKEN deps= -rrequirements-dev.txt pytest-cov @@ -33,3 +33,7 @@ changedir=docs deps=sphinx commands= make clean html + +[pytest] +markers = + incremental: custom marker