Skip to content

Commit

Permalink
Merge 9f829c1 into 6202224
Browse files Browse the repository at this point in the history
  • Loading branch information
TheFriendlyCoder committed Jul 25, 2020
2 parents 6202224 + 9f829c1 commit d28f81e
Show file tree
Hide file tree
Showing 20 changed files with 885 additions and 169 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,7 @@ venv*/

# project files
.vscode/
.idea/
.idea/

.report.json
key.txt
4 changes: 3 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ script:
# For CPython the TravisCI env var mapping should be: 3.8 -> py38
- '[ "$TRAVIS_PYTHON_VERSION" = "pypy3.5" ] && export PYVER=`echo $TRAVIS_PYTHON_VERSION | tr "." "\n" | head -n 1` || export PYVER=py`echo $TRAVIS_PYTHON_VERSION | sed "s/\.//" | sed "s/^py//"`'
- echo $PYVER
- tox -f $PYVER
- tox -e $PYVER-lint
- tox -e $PYVER-test -- --block-network
- tox -e $PYVER-docs
# Only publish coverage metrics for the latest supported Python version
- '[ "$TRAVIS_PYTHON_VERSION" = "3.8" ] && coveralls || echo Skipping Coveralls'

Expand Down
2 changes: 1 addition & 1 deletion docs/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ sphinxcontrib-htmlhelp==1.0.3
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.4
urllib3==1.25.9
urllib3==1.25.10
2 changes: 2 additions & 0 deletions project.prop
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
"DEV_DEPENDENCIES" : [
"pytest",
"pytest-cov",
"pytest-recording",
"pytest-json-report",
"mock",
"pylint",
"sphinx",
Expand Down
13 changes: 10 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ MarkupSafe==1.1.1
mccabe==0.6.1
mock==3.0.5
more-itertools==8.4.0
multidict==4.7.6
packaging==20.4
pathlib2==2.3.5
pbr==5.4.5
Expand All @@ -33,8 +34,12 @@ pylint==2.5.3
pyparsing==2.4.7
pytest==5.4.3
pytest-cov==2.10.0
pytest-json-report==1.2.1
pytest-metadata==1.8.0
pytest-recording==0.8.1
python-dateutil==2.8.1
pytz==2020.1
PyYAML==5.3.1
requests==2.24.0
six==1.15.0
snowballstemmer==2.0.0
Expand All @@ -48,13 +53,15 @@ sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.4
toml==0.10.1
tox==3.17.1
tox==3.18.0
tox-factor==0.1.2
tox-pyenv==1.1.0
tqdm==4.48.0
typed-ast==1.4.1
urllib3==1.25.9
virtualenv==20.0.27
urllib3==1.25.10
vcrpy==4.0.2
virtualenv==20.0.28
wcwidth==0.2.5
wrapt==1.12.1
yarl==1.3.0
zipp==1.2.0
27 changes: 26 additions & 1 deletion src/friendlypins/board.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
"""Primitives for interacting with Pinterest boards"""
from datetime import datetime
from dateutil import tz
from friendlypins.pin import Pin
from friendlypins.utils.base_object import BaseObject

Expand Down Expand Up @@ -56,7 +58,30 @@ def url(self):
@property
def num_pins(self):
"""int: The total number of pins linked to this board"""
return int(self._data['counts']['pins'])
return self._data['counts']['pins']

@property
def num_followers(self):
"""int: number of people following this board"""
return self._data["counts"]["followers"]

@property
def num_collaborators(self):
"""int: number of people with edit permissions to this board"""
return self._data["counts"]["collaborators"]

@property
def creation_date(self):
"""datetime.datetime: when this board was created"""
# sample datetime to parse: "2020-07-21T16:16:03" (in UTC)
retval = datetime.strptime(self._data["created_at"],
"%Y-%m-%dT%H:%M:%S")
return retval.replace(tzinfo=tz.tzutc())

@property
def privacy_setting(self):
"""str: description of the restriction / privacy level of the board"""
return self._data["privacy"]

@property
def pins(self):
Expand Down
2 changes: 1 addition & 1 deletion src/friendlypins/headers.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def time_to_refresh(self):
"""datetime.datetime: the time stamp of when the rate limiting
threshold is renewed"""
if "X-Ratelimit-Refresh" not in self._data:
return datetime.now(tz=tz.tzutc())
return datetime.now(tz=tz.tzlocal())

diff = timedelta(seconds=int(self._data['X-Ratelimit-Refresh']))
return self.date + diff
Expand Down
36 changes: 33 additions & 3 deletions src/friendlypins/user.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"""Interfaces for interacting with Pinterest users"""
import logging
import json
from datetime import datetime
from dateutil import tz
from friendlypins.board import Board


Expand Down Expand Up @@ -90,7 +92,12 @@ def name(self):
alias for first_name + last_name
"""
return "{0} {1}".format(self.first_name, self.last_name)
return "{0} {1}".format(self.first_name, self.last_name).strip()

@property
def username(self):
"""str: display name, used for logging in to Pinterest"""
return self._data["username"]

@property
def url(self):
Expand All @@ -100,12 +107,35 @@ def url(self):
@property
def num_pins(self):
"""int: the total number of pins owned by this user"""
return int(self._data['counts']['pins'])
return self._data['counts']['pins']

@property
def num_boards(self):
"""int: the total number of boards owned by this user"""
return int(self._data['counts']['boards'])
return self._data['counts']['boards']

@property
def num_followers(self):
"""int: number of people following this Pinterest user"""
return self._data["counts"]["followers"]

@property
def created(self):
"""datetime.datetime: when this user's profile was created"""
# sample datetime to parse: "2020-07-21T16:16:03" (in UTC)
raw_date = self._data["created_at"]
retval = datetime.strptime(raw_date, "%Y-%m-%dT%H:%M:%S")
return retval.replace(tzinfo=tz.tzutc())

@property
def account_type(self):
"""str: type of Pinterest account (ie: individual / business)"""
return self._data["account_type"]

@property
def bio(self):
"""str: description of who this user is"""
return self._data["bio"]

@property
def boards(self):
Expand Down
19 changes: 13 additions & 6 deletions src/friendlypins/utils/rest_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,22 @@ def token(self):
"""str: authentication token"""
return self._token

def refresh_headers(self):
"""Forces an update to the cached headers"""
self._latest_header = None

@property
def headers(self):
"""Headers: the HTTP headers from the most recent API operation"""
if not self._latest_header:
temp_url = "{0}/me".format(self._root_url)
properties = {"access_token": self._token}
response = requests.get(temp_url, params=properties)
self._latest_header = Headers(response.headers)
self._raise_for_status(response)
if self._latest_header:
return self._latest_header

temp_url = "{0}/me".format(self._root_url)
properties = {"access_token": self._token}

response = requests.get(temp_url, params=properties)
self._latest_header = Headers(response.headers)

return self._latest_header

@staticmethod
Expand Down
110 changes: 110 additions & 0 deletions tests/cassettes/test_board/test_board_properties.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
interactions:
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
User-Agent:
- python-requests/2.24.0
method: GET
uri: https://api.pinterest.com/v1/boards/485262997288961007?access_token=DUMMY&fields=id%2Cname%2Curl%2Cdescription%2Ccreated_at%2Ccounts%2Cimage%2Creason%2Cprivacy&limit=100
response:
body:
string: '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>Redirecting...</title>
<h1>Redirecting...</h1>
<p>You should be redirected automatically to target URL: <a href="https://api.pinterest.com/v1/boards/485262997288961007/?limit=100&amp;access_token=DUMMY&amp;fields=id%2Cname%2Curl%2Cdescription%2Ccreated_at%2Ccounts%2Cimage%2Creason%2Cprivacy">https://api.pinterest.com/v1/boards/485262997288961007/?limit=100&amp;access_token=DUMMY&amp;fields=id%2Cname%2Curl%2Cdescription%2Ccreated_at%2Ccounts%2Cimage%2Creason%2Cprivacy</a>. If
not click the link.'
headers:
Age:
- '0'
Cache-Control:
- private
Connection:
- keep-alive
Content-Length:
- '705'
Content-Type:
- text/html; charset=utf-8
Date:
- Sat, 25 Jul 2020 19:37:27 GMT
Location:
- https://api.pinterest.com/v1/boards/485262997288961007/?limit=100&access_token=DUMMY&fields=id%2Cname%2Curl%2Cdescription%2Ccreated_at%2Ccounts%2Cimage%2Creason%2Cprivacy
Set-Cookie:
- _ir=0; Max-Age=1800; HttpOnly; Path=/; Secure
X-CDN:
- akamai
pinterest-generated-by:
- coreapp-ngapi-prod-0a01885a
x-envoy-upstream-service-time:
- '10'
x-pinterest-rid:
- '5816201325039197'
status:
code: 308
message: Permanent Redirect
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
Cookie:
- _ir=0
User-Agent:
- python-requests/2.24.0
method: GET
uri: https://api.pinterest.com/v1/boards/485262997288961007/?access_token=DUMMY&fields=id%2Cname%2Curl%2Cdescription%2Ccreated_at%2Ccounts%2Cimage%2Creason%2Cprivacy&limit=100
response:
body:
string: '{"data":{"id":"485262997288961007","name":"testing","url":"https://www.pinterest.com/thefriendlycoder/testing/","description":"Board
used for unit testing","created_at":"2020-07-21T16:16:03","counts":{"pins":2,"followers":100,"collaborators":0},"image":{"60x60":{"url":"https://i.pinimg.com/60x60/e7/f5/50/e7f550c0e688fcc24b0568415fe83a72.jpg","width":60,"height":60}},"reason":null,"privacy":"public"}}'
headers:
Access-Control-Allow-Origin:
- '*'
Age:
- '0'
Cache-Control:
- private
Connection:
- keep-alive
Content-Length:
- '403'
Content-Type:
- application/json
Date:
- Sat, 25 Jul 2020 19:37:28 GMT
Set-Cookie:
- _ir=0; Max-Age=1800; HttpOnly; Path=/; Secure
X-CDN:
- akamai
X-RateLimit-Limit:
- '1'
X-RateLimit-Remaining:
- '0'
pinterest-generated-by:
- coreapp-ngapi-prod-0a01072e
pinterest-version:
- 71bea45
x-content-type-options:
- nosniff
x-envoy-upstream-service-time:
- '65'
x-frame-options:
- DENY
x-pinterest-rid:
- '1116874069926147'
status:
code: 200
message: OK
version: 1

0 comments on commit d28f81e

Please sign in to comment.