Repository: TheFriendlyCoder/friendlypins

Issue:
Add support for basic connectivity
Implement basic init method for API class, allowing connections to be made to a Pinterest account by specifying a user's API token, and perform a simple query to get information about the user who's token we're authenticating with.

Discussion:

Patch:
diff --git a/setup.py b/setup.py
index c322c9e..7827c73 100755
--- a/setup.py
+++ b/setup.py
@@ -7,20 +7,18 @@ from setuptools import setup, find_packages
 # project specific parameters
 PROJECT_NAME = 'friendlypins'
 PROJECT_DEPENDENCIES = [
-    #'requests[security]>=2.0.1',
-    'requests',
-    'six',
-    'tqdm']
+    'requests<3.0.0,>=2.0.0',
+    'six<2.0.0,>=1.0.0',]
 PROJECT_DEV_DEPENDENCIES = [
-    'wheel',
-    'twine',
-    'pytest',
-    'pytest-cov',
-    'mock',
-    'radon',
-    'pylint',
-    'sphinx>=1.2.3',
-    'tox']
+    'wheel<1.0.0',
+    'twine<2.0.0',
+    'pytest>=3.5.0<4.0.0',
+    'pytest-cov>=2.5.0<3.0.0',
+    'mock>=2.0.0<3.0.0',
+    'radon>=2.2.0<3.0.0',
+    'pylint>=1.8.0<2.0.0',
+    'sphinx>=1.2.3<2.0.0',
+    'tox>=3.0.0<4.0.0']
 PROJECT_DESCRIPTION = 'Python wrapper around the Pinterest developer APIs'
 PROJECT_KEYWORDS = 'pinterest api wrapper library'
 # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
diff --git a/src/friendlypins/api.py b/src/friendlypins/api.py
index 8b28950..c9540e1 100644
--- a/src/friendlypins/api.py
+++ b/src/friendlypins/api.py
@@ -1,10 +1,25 @@
 """Primary entry point for the Friendly Pinterest library"""
 from __future__ import print_function
+import logging
+import requests
+from friendlypins.user import User
 
 class API(object):  # pylint: disable=too-few-public-methods
     """High level abstraction for the core Pinterest API"""
-    def __init__(self):
-        self.name = "hello"
+
+    # URL of the root namespace for the Pinterest API
+    _root_url = 'https://api.pinterest.com/v1'
+
+    def __init__(self, personal_access_token):
+        """Constructor
+
+        :param str personal_access_token:
+            API authentication token used for secure access to a users'
+            Pinterest data
+        """
+
+        self._log = logging.getLogger(__name__)
+        self._token = personal_access_token
 
     def get_user(self, username=None):
         """Gets all primitives associated with a particular Pinterst user
@@ -15,11 +30,18 @@ class API(object):  # pylint: disable=too-few-public-methods
         returns: Pinterest user with the given name
         rtype: :class:`friendly_pinterest.user.User`
         """
-        print(self.name)
         if username:
-            return None
-        return None
+            raise NotImplementedError(
+                "Querying arbitrary Pinerest users is not yet supported.")
+        else:
+            temp_url = "{0}/me".format(self._root_url)
+        temp_url += "?access_token={0}".format(self._token)
+        response = requests.get(temp_url)
+        response.raise_for_status()
+        assert 'data' in response.json()
+        return User(response.json()['data'])
 
 
+# pylint: disable-all
 if __name__ == "__main__":
     pass
diff --git a/src/friendlypins/user.py b/src/friendlypins/user.py
new file mode 100644
index 0000000..02dd4e7
--- /dev/null
+++ b/src/friendlypins/user.py
@@ -0,0 +1,44 @@
+"""Interfaces for interacting with Pinterest users"""
+import logging
+
+class User(object):
+    """Abstraction around a Pinterest user and their associated data"""
+
+    def __init__(self, data):
+        """Constructor
+
+        :param dict data: JSON data parsed from the API
+        """
+        self._log = logging.getLogger(__name__)
+        self._data = data
+
+    @property
+    def unique_id(self):
+        """Gets the internal unique ID associated with the user
+        :rtype: :class:`str`
+        """
+        return self._data['id']
+
+    @property
+    def first_name(self):
+        """Gets the first name of the user
+        :rtype: :class:`str`
+        """
+        return self._data['first_name']
+
+    @property
+    def last_name(self):
+        """Gets the last name of the user
+        :rtype: :class:`str`
+        """
+        return self._data['last_name']
+
+    @property
+    def url(self):
+        """Gets the URL of the users profile
+        :rtype: :class:`str`
+        """
+        return self._data['url']
+
+if __name__ == "__main__":
+    pass


Test patch:
diff --git a/unit_tests/test_api.py b/unit_tests/test_api.py
index 2526048..67ada2e 100644
--- a/unit_tests/test_api.py
+++ b/unit_tests/test_api.py
@@ -1,12 +1,32 @@
 import pytest
+import mock
 from friendlypins.api import API
 
-def test_constructor():
-    obj = API()
-
 def test_get_user():
-    obj = API()
-    obj.get_user()
+    obj = API('abcd1234')
+    expected_url = 'https://www.pinterest.com/MyUserName/'
+    expected_firstname = "John"
+    expected_lastname = "Doe"
+    expected_id = "12345678"
+    expected_data = {
+        'data': {
+            'url': expected_url,
+            'first_name': expected_firstname,
+            'last_name': expected_lastname,
+            'id': expected_id
+        }
+    }
+    with mock.patch("friendlypins.api.requests") as mock_requests:
+        mock_response = mock.MagicMock()
+        mock_response.json.return_value = expected_data
+        mock_requests.get.return_value = mock_response
+        result = obj.get_user()
+
+        assert expected_url == result.url
+        assert expected_firstname == result.first_name
+        assert expected_lastname == result.last_name
+        assert expected_id == result.unique_id
+
 
 if __name__ == "__main__":
     pytest.main([__file__, "-v", "-s"])