Skip to content

Commit

Permalink
Bug and test fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
amitt001 committed Jul 8, 2018
1 parent 114bd00 commit 87a19bc
Show file tree
Hide file tree
Showing 11 changed files with 202 additions and 76 deletions.
22 changes: 21 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,26 @@ I would like to thank DigitalOcean for providing initial hosting to Pygmy projec
License
=======

The MIT license (MIT)
MIT License

Copyright (c) 2017 Amit Tripathi(https://twitter.com/amitt019)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
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.

[Read License Terms](https://github.com/amitt001/pygmy/blob/master/LICENSE)
1 change: 1 addition & 0 deletions pygmy/model/link.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ def add(self, db, long_url, **kwargs):
try:
db.commit()
except IntegrityError:
db.rollback()
raise ShortURLUnavailable('Short URL already taken or unavailable')
return self.link

Expand Down
7 changes: 7 additions & 0 deletions pygmy/rest/shorturl.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from pygmy.model import LinkManager, UserManager
from pygmy.validator import LinkSchema
from pygmy.utilities.urls import validate_url
from pygmy.core.logger import log


class LongUrlApi(MethodView):
Expand Down Expand Up @@ -41,8 +42,13 @@ def post(self):
return jsonify(dict(error='Invalid user')), 400
data['owner'] = user.id
if errors:
log.error('Error in the request payload %s', errors)
if errors.get('long_url'):
errors.update({'error': errors.get('long_url')})
return jsonify(errors), 400

long_url = data.pop('long_url')
log.info('Shortening url %s', long_url)
link = self.manager.get(long_url)
if link is None or (
data.get('is_custom') or
Expand All @@ -53,6 +59,7 @@ def post(self):
except ShortURLUnavailable as e:
return jsonify(dict(error=str(e))), 400
result = self.schema.dump(link)
log.info('Url: %s shortened, response: %s', long_url, result.data.get('short_code'))
return jsonify(result.data), 201


Expand Down
7 changes: 0 additions & 7 deletions pygmyui/pygmy/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,6 @@ def link_shortener(request):
'unauthorized.html',
context=API_ERROR(e.args[0]),
status=401)
except InvalidInput as e:
context.update(dict(input_error=e.args[0]))
_ = [form.add_error(str(key), err)
for key, err in e.args[0].items()]
# return render(request, 'pygmy/short_url.html', context=context)
return render(
request, "invalid_form.html", context=context, status=400)
except (ObjectNotFound, InvalidInput) as e:
return render(request, '400.html',
context=API_ERROR(e.args[0]), status=400)
Expand Down
1 change: 0 additions & 1 deletion pygmyui/restclient/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
from restclient.pygmy import PygmyApiClient
55 changes: 36 additions & 19 deletions pygmyui/restclient/base.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import os
import sys
import requests

from functools import wraps

sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
from restclient.errors import (
RestAPIConnectionError, RestClientException, ObjectNotFound,
LinkExpired, UnAuthorized, InvalidInput)
Expand Down Expand Up @@ -32,17 +36,22 @@ def _wrapped(*args, **kwargs):
class Client:
"""This is an Abstract Base Class"""

def __init__(self, rest_url, username, password):
def __init__(
self, base_url, basic_auth=False, username=None, password=None,
request_data_type='json', return_for_status=[]):
"""Pass username and password as None when basic auth is disabled"""
self.rest_url = rest_url
self.rest_url = base_url
self.basic_auth = None
if password is None:
raise RestClientException(
'`username` is required when `password` is given')
if username is None:
raise RestClientException(
'`password` is required when `username` is given')
if not (username is None and password is None):
self.request_data_type = request_data_type
if return_for_status and not isinstance(return_for_status, list):
return_for_status = [return_for_status]
self.return_for_status = return_for_status

if basic_auth is True:
if password is None or username is None:
raise RestClientException(
'`username` and `password` are required when `basic_auth` is True'
)
self.basic_auth = requests.auth.HTTPBasicAuth(username, password)

@property
Expand All @@ -54,7 +63,7 @@ def makeurl(base_url, path):
return urljoin(base_url, path)

def call(self, path, data=None, method=None,
return_for_status=[], header_param=None):
return_for_status=[], headers=None):
"""
The wrapper over `requests` library.
:param path: url_path
Expand All @@ -66,29 +75,37 @@ def call(self, path, data=None, method=None,
being handled here, so that calling method can handle it in it's
own custom way.
:type return_for_status: str/list
:param header_param: Add parameters to header
:type header_param: dict
:param headers: Add parameters to header
:type headers: dict
:return:
"""
headers = self.header
headers.update({'User-Agent': 'Pygmy API REST client'})
if header_param:
headers.update(header_param)
header_params = self.header
header_params.update({'User-Agent': 'Pygmy API REST client'})
if headers:
header_params.update(headers)

request_param = dict(
url=self.makeurl(self.rest_url, path),
auth=self.basic_auth, headers=headers)
url=self.makeurl(self.rest_url, path), auth=self.basic_auth, headers=header_params
)

_call = requests.get
if method is None:
method = 'GET' if data is None else 'POST'
if method.upper() == 'POST':
_call = requests.post
request_param['json'] = data
if self.request_data_type == 'json':
request_param['json'] = data
else:
request_param['data'] = data
# Make rest call and handle the response
response = _call(**request_param)

if return_for_status and not isinstance(return_for_status, list):
return_for_status = [return_for_status]
return_for_status = self.return_for_status + return_for_status
if response.status_code in return_for_status:
return response

error_object = self.error_object_from_response(response)
if error_object is not None:
raise error_object
Expand Down
4 changes: 2 additions & 2 deletions pygmyui/restclient/pygmy.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def __init__(self, rest_url, username, password, hostname, request=None):
self.HOSTNAME = '{}{}'.format(scheme, hostname)
self.request = request
self.cookies = None if request is None else request.COOKIES
super().__init__(rest_url, username, password)
super().__init__(rest_url, basic_auth=True, username=username, password=password)

def __repr__(self):
return '<PygmyApiClient ({0.name}:{0.password}) {0.rest_url}>'.format(
Expand Down Expand Up @@ -129,7 +129,7 @@ def unshorten(self, short_url_code, secret=None):
"""
short_code = urlparse(short_url_code).path.strip('/')
url_path = '/api/unshorten?url=' + self.rest_url + '/' + short_code
r = self.call(url_path, header_param=dict(secret_key=secret))
r = self.call(url_path, headers=dict(secret_key=secret))
resp = r.json()
if resp.get('short_code'):
resp['short_url'] = self.makeurl(self.HOSTNAME, resp['short_code'])
Expand Down
7 changes: 6 additions & 1 deletion pygmyui/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,12 @@
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/" style="color: white; font-size: 30px">
<img style="background-color: white;" src="/static/logo/logov2.png" alt="Pygy.co (Pygmy) logo" srcset="/static/logo/logov2.svg" height="70" width="150">
<img style="background-color: white;"
src="/static/logo/logov2.svg"
onerror="this.src='/static/logo/logov2.png'"
alt="Pygy.co (Pygmy) logo"
height="70"
width="150">
</a>
</div>
<div id="navbar" class="collapse navbar-collapse">
Expand Down
2 changes: 1 addition & 1 deletion pygmyui/utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""A common util file to use methods across different django apps"""

from restclient import PygmyApiClient
from restclient.pygmy import PygmyApiClient
from urllib.parse import urlparse


Expand Down
9 changes: 7 additions & 2 deletions tests/fixture.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
'run_test_server',
]

_PYGMY_SUBPROCESS_LOG_FILE = 'pygmy/data/pygmy_subproc.log'
_PYGMYUI_SUBPROCESS_LOG_FILE = 'pygmy/data/pygmyui_subproc.log'


class PygmyApiTestServer:
pygmyapi_proc = None
Expand All @@ -17,8 +20,9 @@ class PygmyApiTestServer:
def start_pygmy_api_server(cls):
# os.chdir('src')
command = ['coverage', 'run', 'pygmy_api_run.py', 'test']
fobj = open(_PYGMY_SUBPROCESS_LOG_FILE, 'w')
cls.pygmyapi_proc = subprocess.Popen(
command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
command, stdout=fobj, stderr=fobj)
# Wait for server to start
time.sleep(1)
# os.chdir('..')
Expand All @@ -37,8 +41,9 @@ class PygmyUiTestServer:
@classmethod
def start_pygmy_ui_server(cls):
command = ['gunicorn','-b 127.0.0.1:8001', '--chdir', 'pygmyui', '-w 1', 'pygmyui.wsgi']
fobj = open(_PYGMY_SUBPROCESS_LOG_FILE, 'w')
cls.pygmyui_proc = subprocess.Popen(
command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
command, stdout=fobj, stderr=fobj)
# Wait for server to start
time.sleep(1)
return cls.pygmyui_proc
Expand Down
Loading

0 comments on commit 87a19bc

Please sign in to comment.