Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
efa144e
Updated ReadMe.md
cdvx Aug 18, 2018
5961055
update READMe.md
cdvx Aug 18, 2018
5f85ed4
Add links to challenge out puts to github
cdvx Aug 20, 2018
b339401
Update README with challenge information
cdvx Aug 20, 2018
8cb4d4f
Add .gitignore to master
Aug 21, 2018
5f6da1c
Create endpoint to fecth all questions
Aug 21, 2018
4098ce6
Set up challenge 2 output [finishes #159935259]
Aug 21, 2018
881fc2c
Add get question endpoint [finishes #159936149]
Aug 21, 2018
4c2eb4e
Add post question endpoint [finishes #159936800]
Aug 21, 2018
f67df19
Add post answer endpoint [finishes #159937299]
Aug 21, 2018
4160f4e
Add update question endpoint [finishes #159937715]
Aug 21, 2018
6edc2e2
Add delete question endpoint [finishes #159937808]
Aug 21, 2018
e2236eb
Merge branch 'Challenge-2' into ft-Get-all-questions
cdvx Aug 22, 2018
0ce2f45
Merge pull request #16 from cdvx/ft-Get-all-questions
cdvx Aug 22, 2018
2fcaa6c
Merge pull request #17 from cdvx/ft-Get-one-question
cdvx Aug 22, 2018
3cce9ee
Merge branch 'Challenge-2' into ft-Post-a-question
cdvx Aug 22, 2018
507bfe6
Merge pull request #19 from cdvx/ft-Post-a-question
cdvx Aug 22, 2018
b8cf79a
Merge pull request #21 from cdvx/ft-Post-answer
cdvx Aug 22, 2018
5787f83
Merge pull request #22 from cdvx/ft-Update-question
cdvx Aug 22, 2018
733fc34
Remove dummy data from API [finishes #159949876]
Aug 22, 2018
c30a4e1
Merge pull request #23 from cdvx/ft-Delete-question
cdvx Aug 22, 2018
7ea2bae
Add root route for app [finishes #159951595]
Aug 22, 2018
89e5c81
Merge pull request #24 from cdvx/ft-Delete-question
cdvx Aug 22, 2018
abff8b9
Add .travis.yml and .coveral.yml
Aug 22, 2018
c9a3b6d
Add buildpack intergration for Heroku
Aug 22, 2018
84911cc
Remove Static and Templates folder, and forms.py
Aug 22, 2018
fd4c670
Modify requirements.txt
Aug 22, 2018
0486072
Remove port from run.py
Aug 22, 2018
483dc90
Modify procfile
Aug 22, 2018
0374632
Add badge to README.md
Aug 22, 2018
1b35043
Modify README.md
Aug 22, 2018
eda4601
Modify .travis.yml
Aug 23, 2018
c276a70
Modify travis.yml
Aug 23, 2018
bacbd60
Remove py.test --cov command from travis
Aug 23, 2018
e0e5199
Rename .coverall.yml to .coveralls.yml
Aug 23, 2018
72141eb
Remove dummy data entiresly from models [finishes #159985152]
Aug 23, 2018
2838450
Modify README.md to leave working badges
cdvx Aug 23, 2018
a8f6406
Update README
cdvx Aug 23, 2018
4c0ab43
Update README
cdvx Aug 23, 2018
ffa5c77
Update README
cdvx Aug 23, 2018
063674c
Update README badges
cdvx Aug 23, 2018
5a25e24
Modify test [finishes #159986807]
Aug 23, 2018
fc2ed53
Merge branch 'master' into Challenge-2
cdvx Aug 23, 2018
f09d5b2
Update README
cdvx Aug 23, 2018
9834f03
Remove unused import from test_route
Aug 23, 2018
68e8f76
Merge branch 'Challenge-2' of https://github.com/cdvx/StackOverflow-l…
Aug 23, 2018
b9488ca
Merge branch 'develop' into Challenge-2
cdvx Aug 23, 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!{"lines": {"/home/benx/Desktop/Andela/StackOverflow-lite/tests/__init__.py": [1, 2, 4], "/home/benx/Desktop/Andela/StackOverflow-lite/tests/test_models.py": [1, 3, 4, 6, 9, 11, 16, 23, 30, 35, 12, 13, 14, 17, 18, 19, 20, 21, 31, 32, 33, 24, 25, 26, 27, 28, 36, 37, 38, 39], "/home/benx/Desktop/Andela/StackOverflow-lite/tests/base.py": [1, 3, 4, 6, 7, 8, 11, 12, 16, 19, 22, 13, 14, 20, 17], "/home/benx/Desktop/Andela/StackOverflow-lite/tests/test_route.py": [1, 3, 4, 6, 9, 11, 15, 20, 24, 33, 42, 55, 12, 13, 56, 57, 58, 21, 22, 16, 17, 18, 26, 27, 28, 30, 31, 45, 46, 48, 49, 50, 51, 35, 36, 37, 39, 40]}}
2 changes: 2 additions & 0 deletions .coveralls.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
service_name: travis-ci
repo_token: P3qLJJitpWmAjv0rQfP6wVj0kHuqxZpgx
9 changes: 6 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
.pytest_cache/
__pycache__/
venv/
.vscode/
__pycache__/
app/__pycache__/
app/routes/__pycache__
.vscode/
.vscode/settings.json
.pytest_cache/
13 changes: 13 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
language: python
python:
- "3.6"

install:
- pip install -r requirements.txt

script:
- pytest

after_success:
- coveralls

1 change: 1 addition & 0 deletions Procfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
web: gunicorn --workers=1 run:app
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,22 @@
# StackOverflow-lite
# StackOverflow-lite

[![Test Coverage](https://api.codeclimate.com/v1/badges/a99a88d28ad37a79dbf6/test_coverage)](https://codeclimate.com/github/codeclimate/codeclimate/test_coverage)



[![Coverage Status](https://coveralls.io/repos/github/cdvx/StackOverflow-lite/badge.svg?branch=Challenge-2)](https://coveralls.io/github/cdvx/StackOverflow-lite?branch=Challenge-2)



git hub pages(challenge one) output:
https://cdvx.github.io/StackOverflow-lite/UI/user.html
chalenge one setup:
Challenge one output is set up in the gh-pages branch, and hosted on github pages
the pages are: user.html, question.html, other links are accessible through the links on the pages


pivotal tracker output:
https://www.pivotaltracker.com/n/projects/2189643



6 changes: 6 additions & 0 deletions app/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from flask import Flask
from config import Config

app = Flask(__name__)

app.config.from_object(Config)
30 changes: 30 additions & 0 deletions app/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
class Question:
def __init__(self, questionId=0, topic='', body=''):
self.id = questionId
self.topic = topic
self.body = body
self.answers = []

def __repr__(self):
return {
'questionId': self.id,
'topic': self.topic,
'body': self.body
}


class Answer:
def __init__(self, answerId=0, body='', Qn_Id=0):
self.answerId = answerId
self.body = body
self.Qn_Id = Qn_Id

def __repr__(self):
return {
'answerId': self.answerId,
'Qn_Id': self.Qn_Id,
'body': self.body
}

questionsList = []
answersList = []
145 changes: 145 additions & 0 deletions app/routes/routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
from flask import (Flask, Response, flash, json, jsonify,
request, session, url_for)

from app import app
from app.models import Answer, Question, answersList, questionsList

@app.route('/')
def show_api_works():
return jsonify({'Welcome to my app': [{'message': "endpoints work"}]})


@app.route('/api/v1/questions', methods=['GET'])
def get_questions():
if questionsList:
return jsonify({'questions': questionsList})
return jsonify({'messgae': 'No Questions added yet'})

@app.route('/api/v1/questions/<int:questionId>', methods=['GET'])
def get_question(questionId):
if questionsList:
for question in questionsList:
if question['questionId'] == questionId:
temp = {
'questionId': question['questionId'],
'topic': question['topic'],
'body': question['body']
}
return jsonify(temp)
return Response(json.dumps(['Question not Found']),
status=404, mimetype='application/json')
return jsonify({f'Question {questionId}': 'Has not been added yet'})

@app.route('/api/v1/questions', methods=['POST'])
def add_question():

request_data = request.get_json()
if (valid_question(request_data)):
temp = {
'questionId': request_data['questionId'],
'topic': request_data['topic'],
'body': request_data['body']
}
questionsList.append(temp)
response = Response('', 201, mimetype='application/json')
response.headers['location'] = ('questions/' +
str(request_data['questionId']))

return response
else:
bad_object = {
"error": "Invalid question object",
"hint": '''Request format should be,{'questionId':1, 'topic': 'python',
'body': 'what is python in programming' }'''
}
response = Response(json.dumps([bad_object]),
status=400, mimetype='application/json')
return response

@app.route('/api/v1/questions/<int:questionId>/answers', methods=['POST'])
def add_answer(questionId):
request_data = request.get_json()
if questionsList:
if (valid_answer(request_data)):
temp = {
'answerId': request_data['answerId'],
'Qn_Id': request_data['Qn_Id'],
'body': request_data['body']
}
answersList.append(temp)
for question in questionsList:
if question['questionId'] == request_data['Qn_Id']:
question = Question(question['questionId'],
question['topic'], question['body'])
question.answers.append(temp)

response = Response('', status=201, mimetype='application/json')
response.headers['location'] = ('answers/' +
str(request_data['answerId']))
return response

else:
bad_object = {
"error": "Invalid answer object",
"hint": '''Request format should be {'answerId':1,
'body': 'this is the body',
'Qn_Id': 2}'''
}
response = Response(json.dumps([bad_object]),
status=400, mimetype='application/json')
return response
return jsonify({f'Attempt to answer Question {questionId}':
f'Question {questionId} does not exit.'})


@app.route('/api/v1/questions/<int:questionId>', methods=['PATCH'])
def update_question(questionId):
request_data = request.get_json()
if questionsList:
updated_question = dict()
ids = [question['questionId'] for question in questionsList]

if questionId in ids:
if "topic" in request_data:
updated_question["topic"] = request_data["topic"]
if "body" in request_data:
updated_question["body"] = request_data["topic"]

for question in questionsList:
if question["questionId"] == questionId:
question.update(updated_question)

response = Response('', status=204)
response.headers['Location'] = "/questions" + str(questionId)
return response
response = Response(json.dumps(['Question not found']), status=404)
return response


@app.route('/api/v1/questions/<int:questionId>', methods=['DELETE'])
def delete_question(questionId):
if questionsList:
ids = [question['questionId'] for question in questionsList]
if questionId in ids:
for question in questionsList:
if questionId == question['questionId']:
questionsList.remove(question)
response = Response('', status=200, mimetype='application/json')
return response
response = Response(json.dumps(['Question not found']),
status=404, mimetype='application/json')
return response


def valid_question(questionObject):
if 'topic' in questionObject and 'body' in questionObject:
return True
else:
return False

def valid_answer(answerObject):
if 'Qn_Id' in answerObject and 'answerId' in answerObject and 'body' in answerObject :
return True
else:
return False

6 changes: 6 additions & 0 deletions config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import os
basedir = os.path.abspath(os.path.dirname(__file__))


class Config(object):
SECRET_KEY = os.environ.get('SECRET_KEY') or 'tesxting'
14 changes: 14 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
nose==1.3.7
certifi==0.0.8
chardet==1.0.1
coverage==4.0.3
coveralls==1.3.0
Flask==1.0.2
Flask-Testing==0.7.1
gunicorn==19.9.0
pep8==1.7.1
pylint==2.1.1
pytest==3.7.1
python-coveralls==2.9.1
requests==2.19.1
Werkzeug==0.14.1
5 changes: 5 additions & 0 deletions run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from app import app
from app.routes import routes

if __name__ == '__main__':
app.run()
4 changes: 4 additions & 0 deletions tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from app import app
from config import Config

app.config.from_object(Config)
85 changes: 85 additions & 0 deletions tests/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import unittest

from flask import current_app
from flask_testing import TestCase

from app import app
from app.routes import routes
from app.models import Answer, Question
from config import Config


class APITestCase(TestCase):
def create_app(self):
app.config['DEBUG'] = True
return app

def setUp(self):
self.app = app.test_client()

def tearDown(self):
pass

def post_question(self):
pass





ans_List = [

{
'answerId': 1,
'Qn_Id': 1,
'body': ""},
{'answerId': 2,
'Qn_Id': 2,
'body': ""},
{'answerId': 3,
'Qn_Id': 3,
'body': ""},
{'answerId': 4,
'Qn_Id': 4,
'body': ""}
]


def createQnsList():
'''Generates a List of five questions with different topics
and links answers to them'''

QnsList = []
body = ""

topics = [0, '', '', '', '', '']

for i in range(1, 6):
Qn = Question(i, topics[i], body)

for answer in ans_List:
if answer['Qn_Id'] == Qn.id:
Qn.answers.append(answer)

QnsList.append(Qn.__repr__())
return QnsList

questionsList = createQnsList()


def createAnsList():
'''Generates list of five answers'''
AnsList = []
body = ""

l = [question['questionId'] for question in questionsList]
qnIds = [id for id in l]
qnIds[:0] = [0]

for i in range(1, 6):
Ans = Answer(i, body, qnIds[i])
AnsList.append(Ans.__repr__())
return AnsList

answersList = createAnsList()

Loading