Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
ea6da11
[starts #161737782] build model and view for parcels POST api
ipaullly Nov 5, 2018
26d0031
[starts #161748253] Create GET delivery order list
ipaullly Nov 6, 2018
67006a9
[starts #161766269]Build API to retrieve single order
ipaullly Nov 6, 2018
37f0d14
[finishes #161766269] Add class and methods docstrings
ipaullly Nov 6, 2018
534a2b9
[starts #161773293] write passing test for POST new parcel order
ipaullly Nov 7, 2018
66c2c04
[starts #161773596] write test for GET list of delivery orders
ipaullly Nov 7, 2018
101cd2c
[finishes #161773596] add doctsrtings to test class
ipaullly Nov 7, 2018
7f1fd34
[starts #161774149] restructure v1 test folder and write test for sin…
ipaullly Nov 7, 2018
49471e2
[starts #161777597] Add status attribute and update status method
ipaullly Nov 7, 2018
7c66fd9
Create PUT method to cancel order by id
ipaullly Nov 7, 2018
d011417
[finishes #161777597] write test for PUT cancel order endpoint
ipaullly Nov 7, 2018
e22c523
[starts #161796710] Create authentication blueprint in project directory
ipaullly Nov 7, 2018
1abc184
create user registration model and registration api
ipaullly Nov 7, 2018
5520d68
[finishes #161796710] add a test for registration endpoint
ipaullly Nov 8, 2018
0d6055e
write test for registration endpoint and additional logic in its view
ipaullly Nov 8, 2018
0a4cd75
[starts #161820120] Add methods to decode/encode tokens and instance …
ipaullly Nov 8, 2018
dcf6e3e
Add enpoint to login and generate token
ipaullly Nov 8, 2018
9e33084
[finishes #161820120] write minimal tests for sign in endpoint
ipaullly Nov 8, 2018
71d794e
[starts #161834170]enable continuous integration
ipaullly Nov 9, 2018
df4bf08
add system site package
ipaullly Nov 9, 2018
7ca8944
corrects the install script
ipaullly Nov 9, 2018
2be30ed
update .travis.yml file
ipaullly Nov 9, 2018
4014b58
travis configuration
ipaullly Nov 9, 2018
f6c7725
travis build correction
ipaullly Nov 9, 2018
490ff5d
travis build trials
ipaullly Nov 9, 2018
3197171
travis build trials
ipaullly Nov 9, 2018
10742fd
travis build trial
ipaullly Nov 9, 2018
2d3bf80
travis build trial
ipaullly Nov 9, 2018
d383adb
[starts #161850180] setup heroku Procfile
ipaullly Nov 9, 2018
284ee50
add runtime.txt
ipaullly Nov 9, 2018
cb77807
Edit Profile
ipaullly Nov 9, 2018
8894c8d
Add port to Procfile
ipaullly Nov 9, 2018
2d98861
Add covergae script in travis.yml
ipaullly Nov 10, 2018
ea32f02
[starts #161858618] create GET orders from a single user
ipaullly Nov 10, 2018
7e53285
[finishes #161858618] add test for retrieving orders by a specific user
ipaullly Nov 10, 2018
fbce096
update README.md
ipaullly Nov 10, 2018
db77b9a
add code climate badges
ipaullly Nov 11, 2018
7583551
Add nosetest command to .travis.yml
ipaullly Nov 11, 2018
c3258f0
delete pkg-resources from requirements.txt
ipaullly Nov 11, 2018
effae76
add update pip command to .travis.yml
ipaullly Nov 11, 2018
52965be
Travis trial 27
ipaullly Nov 11, 2018
30b353c
travis integration trial 29
ipaullly Nov 11, 2018
e55316a
update README.md
ipaullly Nov 11, 2018
32c468c
add codecov to .travis.yml
ipaullly Nov 12, 2018
81177dc
remove pkg-resources==0.0.0
ipaullly Nov 12, 2018
8834aad
add codecov token
ipaullly Nov 12, 2018
7571ed0
[starts #161911823] add assert statement to check signup endpoint
ipaullly Nov 13, 2018
290fa14
edit assertIn args for login/register api tests
ipaullly Nov 13, 2018
fe13c7e
[finishes #161911823] add test for empty strings and finish checking …
ipaullly Nov 13, 2018
31b405a
[starts #161920708] create utilities and move decode token function i…
ipaullly Nov 13, 2018
70898e0
[starts #161921842] add scripts for code climate integration
ipaullly Nov 13, 2018
fd2a662
Try codecov integration
ipaullly Nov 13, 2018
42e74bc
add coverage xml
ipaullly Nov 13, 2018
d9239ca
add codecov badge
ipaullly Nov 13, 2018
b11f21e
[starts #161951629] update README.md with commands to run app locally
ipaullly Nov 14, 2018
f65d1c5
[finishes #161951629] make testing instructions more clear
ipaullly Nov 14, 2018
64d72d4
[starts #161954076] Add created order to response of POST request
ipaullly Nov 14, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .coverage
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
!coverage.py: This is a private format, don't read it directly!{"arcs":{"/home/ipaullly/dev/parcels/sendIT/app/__init__.py":[[-1,1],[1,2],[2,3],[3,6],[6,-1],[-6,7],[7,9],[9,10],[10,11],[11,13],[13,-6]],"/home/ipaullly/dev/parcels/sendIT/app/api/__init__.py":[[-1,1],[1,-1]],"/home/ipaullly/dev/parcels/sendIT/app/api/v1/__init__.py":[[-1,1],[1,2],[2,3],[3,5],[5,7],[7,9],[9,10],[10,11],[11,12],[12,-1]],"/home/ipaullly/dev/parcels/sendIT/app/api/v1/views.py":[[-1,1],[1,2],[2,3],[3,5],[5,7],[-7,7],[7,10],[10,11],[11,37],[37,-7],[7,47],[-47,47],[47,50],[50,51],[51,-47],[47,61],[-61,61],[61,64],[64,65],[65,-61],[61,72],[-72,72],[72,75],[75,76],[76,-72],[72,-1],[-11,15],[15,16],[16,17],[17,18],[18,19],[19,20],[20,22],[22,23],[23,24],[24,32],[32,33],[33,34],[34,35],[35,-11],[23,25],[25,28],[28,29],[29,30],[30,31],[31,-11],[-37,41],[41,42],[42,43],[43,44],[44,45],[45,-37],[-65,66],[66,67],[67,68],[68,69],[69,70],[70,-65],[-51,55],[55,56],[56,57],[57,58],[58,59],[59,-51],[-76,80],[80,81],[81,82],[82,83],[83,84],[84,-76]],"/home/ipaullly/dev/parcels/sendIT/app/api/v1/models.py":[[-2,2],[2,4],[-4,4],[4,7],[7,8],[8,12],[12,27],[27,33],[33,40],[40,48],[48,-4],[4,-2],[-8,9],[9,10],[10,-8],[-12,17],[17,18],[18,19],[19,20],[20,21],[21,22],[22,23],[23,25],[25,-12],[-27,31],[31,-27],[-48,52],[-52,52],[52,52],[52,-52],[52,53],[53,-48],[-33,37],[-37,37],[37,37],[37,-37],[37,38],[38,-33],[-40,44],[-44,44],[44,44],[44,-44],[44,45],[45,46],[46,-40]],"/home/ipaullly/dev/parcels/sendIT/app/auth/__init__.py":[[-1,1],[1,-1]],"/home/ipaullly/dev/parcels/sendIT/app/auth/v1/__init__.py":[[-1,1],[1,2],[2,3],[3,5],[5,7],[7,9],[9,10],[10,-1]],"/home/ipaullly/dev/parcels/sendIT/app/auth/v1/views.py":[[-1,1],[1,2],[2,3],[3,5],[-5,5],[5,8],[8,9],[9,-5],[5,28],[-28,28],[28,31],[31,32],[32,-28],[28,-1],[-32,33],[33,34],[34,35],[35,37],[37,38],[38,39],[39,52],[52,54],[54,56],[56,-32],[-9,10],[10,11],[11,12],[12,14],[14,15],[15,16],[16,18],[18,19],[19,20],[20,-9],[39,40],[40,41],[41,42],[42,44],[44,46],[46,-32],[14,23],[23,26],[26,-9]],"/home/ipaullly/dev/parcels/sendIT/app/auth/v1/models.py":[[-1,1],[1,2],[2,3],[3,4],[4,6],[-6,6],[6,9],[9,10],[10,15],[15,-6],[6,18],[-10,11],[11,12],[12,13],[13,14],[14,-10],[18,20],[-20,20],[20,23],[23,24],[24,-20],[20,31],[-31,31],[31,34],[34,35],[35,42],[42,52],[52,60],[60,67],[67,86],[86,-31],[31,-1],[-86,91],[91,95],[95,-86],[-35,36],[36,37],[37,38],[38,39],[39,40],[40,-35],[-42,46],[46,47],[47,48],[48,49],[49,50],[-60,64],[64,65],[-65,65],[65,65],[65,-65],[65,-60],[50,-42],[91,92],[92,93],[93,94],[94,-86],[-52,56],[56,57],[57,-52],[-67,71],[71,73],[73,74],[74,75],[75,77],[77,78],[78,79],[79,80],[80,83],[83,84],[84,-67],[93,91]],"/home/ipaullly/dev/parcels/sendIT/app/tests/__init__.py":[[-1,1],[1,-1]],"/home/ipaullly/dev/parcels/sendIT/app/tests/v1/__init__.py":[[-1,1],[1,-1]],"/home/ipaullly/dev/parcels/sendIT/app/tests/v1/test_edgecases.py":[[-1,1],[1,2],[2,3],[3,5],[-5,5],[5,8],[8,9],[9,23],[23,-5],[5,32],[32,-1],[-9,13],[13,14],[14,16],[16,17],[17,18],[18,19],[19,20],[20,-9],[-23,27],[27,28],[28,29],[29,30],[30,-23]],"/home/ipaullly/dev/parcels/sendIT/app/tests/v1/test_login.py":[[-1,1],[1,2],[2,3],[3,5],[-5,5],[5,8],[8,9],[9,21],[21,31],[31,-5],[5,39],[39,-1],[-9,10],[10,11],[11,13],[13,14],[14,17],[17,18],[18,-9],[-31,33],[33,34],[34,35],[35,36],[36,-31],[-21,23],[23,24],[24,25],[25,26],[26,27],[27,28],[28,29],[29,-21]],"/home/ipaullly/dev/parcels/sendIT/app/tests/v1/test_parcels.py":[[-1,1],[1,2],[2,3],[3,5],[-5,5],[5,8],[8,9],[9,23],[23,32],[32,43],[43,53],[53,63],[63,-5],[5,75],[75,-1],[-9,13],[13,14],[14,16],[16,17],[17,18],[18,19],[19,20],[20,-9],[-32,36],[36,37],[37,38],[38,39],[39,40],[40,41],[41,-32],[-53,57],[57,58],[58,59],[59,60],[60,61],[61,-53],[-43,47],[47,48],[48,49],[49,50],[50,51],[51,-43],[-23,27],[27,28],[28,29],[29,30],[30,-23],[-63,67],[67,68],[68,69],[69,70],[70,71],[71,-63]],"/home/ipaullly/dev/parcels/sendIT/app/tests/v1/test_register.py":[[-1,1],[1,2],[2,3],[3,5],[-5,5],[5,8],[8,9],[9,22],[22,28],[28,-5],[5,36],[36,-1],[-9,10],[10,11],[11,13],[13,14],[14,17],[17,18],[18,-9],[-28,29],[29,30],[30,31],[31,32],[32,33],[33,34],[34,-28],[-22,23],[23,24],[24,25],[25,-22]],"/home/ipaullly/dev/parcels/sendIT/app/utilities/__init__.py":[],"/home/ipaullly/dev/parcels/sendIT/app/utilities/JWT_token.py":[]}}
13 changes: 13 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[run]
branch = True
source = app

[report]
exclude_lines =
if self.debug:
pragma: no cover
raise NotImplementedError
if __name__ == .__main__.:
ignore_errors = True
omit =
tests/*
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
*__pycache__
venv
.vscode
*.pytest_cache
db_config.py
23 changes: 23 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
env:
global:
- CC_TEST_REPORTER_ID=e6fc31601f7b6906c6ff9c0bfc5afb08d679e93ea89c315aaf6758c20bcdc274
language: python
python:
- "3.6.5"
install:
- pip install --upgrade pip && pip install -r requirements.txt
- pip install coveralls
- pip install codecov
- pip install pytest
before_script:
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
- chmod +x ./cc-test-reporter
- ./cc-test-reporter before-build
script:
- pytest
after_script:
- ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
- coveralls
after_success:
- codecov -t b1bc8af2-07e9-45e9-8824-c733282c6cea

1 change: 1 addition & 0 deletions Procfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
web: gunicorn 'app:create_app()'
97 changes: 97 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,98 @@
# sendIT
[![Maintainability](https://api.codeclimate.com/v1/badges/db4df351dbe833d147b0/maintainability)](https://codeclimate.com/github/ipaullly/sendIT/maintainability)
[![Build Status](https://travis-ci.com/ipaullly/sendIT.svg?branch=ft-GET-user-orders-161858618)](https://travis-ci.com/ipaullly/sendIT) [![codecov](https://codecov.io/gh/ipaullly/sendIT/branch/ch-code-climates-161921842/graph/badge.svg)](https://codecov.io/gh/ipaullly/sendIT)

The sendIT app is built using flask to make RESTful APIs to achieve basic functionalities for the app

## RESTful API Endpoints for sendIT


| Method | Endpoint | Description |
| ------------- | ------------- | ------------- |
| `POST` | `/api/v1/parcels` | Create a new parcel order |
| `GET` | `/api/v1/parcels` | Get a all parcel delivery orders |
| `GET` | `/api/v1/parcels/<int:id>` | Get a single delivery order by id |
| `POST` | `/auth/v1/register` | Register a new user |
| `POST` | `/auth/v1/login` | log a user into account |
| `PUT` | `/api/v1/parcels/<parcelId>/cancel` | Cancel a specific parcel delivery order |


# Development Configuration

Ensure that you have python 3.6.5, pip and virtualenv running

# Initial Setup

Create a project directory in your local machine

```
mkdir sendIT
```

Move into your directory:

```
cd sendIT
```

## Initialize a virtual python Environment to House all your Dependencies

create the virtual environment

```
python3 -p virtualenv venv
```
activate the environment before cloning the project from github

```
source venv/bin/activate
```

## Clone and Configure a the sendIT flask Project

Provided you have a github account, login before entering the command to create a local copy of the repo

```
git clone https://github.com/ipaullly/sendIT.git
```

Next, install the requirements by typing:

```
pip install -r requirements.txt
```
## Running the sendIT flask app locally

Once you are in a virtual environment with all the dependencies installed, set the environmental variables:
```
export FLASK_APP=run.py
export FLASK_ENV=development
```
initialize the server with the command:
```
flask run
```

## Testing
To test the endpointsensure that the following tools are available the follow steps below

### Tool:
Postman

with the flask server running power up POSTMAN to test your endpoints. set the localhost:
```
http://127.0.0.1:5000/
```
append the localhost with urls for the various endpoints, for example:
```
http://127.0.0.1:5000/api/v1/parcels
```
ensure to set the correct HTTP method before sending the request

### Commands
The application was tested using `pytest` and code cov.
run the command
```
pytest --cov app
```
this generates a detailed log of the tests in your app directory
7 changes: 6 additions & 1 deletion app/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
from flask import Flask, Blueprint
from .api.v1 import version1
from .auth.v1 import auth
#from db_config import create_tables, destroy_tables

def create_app():
app = Flask(__name__)
app = Flask(__name__, instance_relative_config=True)
#create_tables()
app.config.from_pyfile('config.py')
app.register_blueprint(version1)
app.register_blueprint(auth)

return app
Binary file added app/__init__.pyc
Binary file not shown.
7 changes: 6 additions & 1 deletion app/api/v1/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
from flask import Blueprint
from flask_restful import Api

from .views import ParcelList, IndividualParcel, CancelParcel, UserOrders

version1 = Blueprint('v1', __name__, url_prefix="/api/v1")

api = Api(version1)

api.add_resource(ParcelList, '/parcels')
api.add_resource(IndividualParcel, '/parcels/<int:id>')
api.add_resource(UserOrders, '/user/<string:id>/parcels')
api.add_resource(CancelParcel, '/parcels/<int:id>/cancel')
55 changes: 55 additions & 0 deletions app/api/v1/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@

parcels = []

class Parcels:
"""
Class with CRUD functionalities on the Parcels resource
"""
def __init__(self):
self.db = parcels
self.parcel_status = 'pending'

def create_order(self, item, pickup, dest, pricing, username):
"""
instance method to generate new entry into delivery orders list
"""
payload = {
"id" : len(self.db) + 1,
"itemName" : item,
"pickupLocation" : pickup,
"destination" : dest,
"pricing" : pricing,
"authorId" : username,
"status" : self.parcel_status
}
self.db.append(payload)
return payload

def order_list(self):
"""
retrieves entire list of delivery orders
"""
return self.db

def retrieve_single_order(self, parcelID):
"""
retrieve a single order by id
"""
order_by_id = [parc for parc in self.db if parc['id'] == parcelID][0]
return order_by_id

def cancel_order(self, ParcelID):
"""
update parcel status to cancel
"""
parcel_to_cancel = [parc for parc in self.db if parc['id'] == ParcelID]
parcel_to_cancel[0]['status'] = 'cancelled'
return parcel_to_cancel

def get_orders_by_user(self, AuthorID):
"""
retrieve all orders by a specific user given her/his username
"""
user_orders = [parc for parc in self.db if parc['authorId'] == AuthorID][0]
return user_orders

77 changes: 72 additions & 5 deletions app/api/v1/views.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,86 @@
from flask_restful import Resource
from flask import make_response, jsonify, request
from .models import Parcels

order = Parcels()

class ParcelList(Resource):

"""
class for Create order and retrieve list of orders API endpoints
"""
def post(self):
pass
"""
post method to add new order to list of orders
"""
data = request.get_json()
item = data['item']
pickup = data['pickup']
dest = data['dest']
pricing = data['pricing']
author = data['user_id']

try:
if " " in item:
raise Exception
elif type(pricing) is not int:
raise Exception
else:
res = order.create_order(item, pickup, dest, pricing, author)
return make_response(jsonify({
"message" : "delivery order created successfully",
"new delivery order" : res
}), 201)
except Exception:
return make_response(jsonify({
"message" : "wrong input format"
}), 400)

def get(self):
pass
"""
get method to retrieve list of all orders
"""
resp = order.order_list()
return make_response(jsonify({
"message" : "ok",
"Delivery Orders" : resp
}), 200)

class IndividualParcel(Resource):
"""
class for API endpoints for retrieving single order and cancelling particular order
"""
def get(self, id):
"""
get method to retrieve order by id
"""
single = order.retrieve_single_order(id)
return make_response(jsonify({
"message" : "Ok",
"order" : single
}), 200)

class UserOrders(Resource):
"""
class for endpoint that restrieves all the orders made by a specific user
"""
def get(self, id):
pass
user_orders = order.get_orders_by_user(id)
return make_response(jsonify({
"message" : "Ok",
"orders by single user" : user_orders
}), 200)

class CancelParcel(Resource):
"""
class for endpoint to cancel parcel order
"""
def put(self, id):
pass
"""
PUT request to update parcel status to 'cancelled'
"""
cancel_parcel = order.cancel_order(id)
return make_response(jsonify({
"message" : "order is cancelled",
"cancelled order" : cancel_parcel
}), 201)

Empty file added app/auth/__init__.py
Empty file.
10 changes: 10 additions & 0 deletions app/auth/v1/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from flask import Blueprint
from flask_restful import Api
from .views import Registration, SignIn

auth = Blueprint('authV1', __name__, url_prefix="/auth/v1")

api = Api(auth)

api.add_resource(Registration, '/register')
api.add_resource(SignIn, '/login')
Loading