Skip to content

Commit 6c6ea7e

Browse files
committed
Adds, ping service
1 parent b1e2bd1 commit 6c6ea7e

File tree

11 files changed

+213
-0
lines changed

11 files changed

+213
-0
lines changed

app/__init__.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
"""
2+
Module to register our Blueprints
3+
"""
4+
from .src.controller.ping import api as ping_ns
5+
from flask import Blueprint
6+
from flask_restplus import Api
7+
8+
9+
blueprint = Blueprint("api", __name__)
10+
11+
api = Api(
12+
blueprint,
13+
title="Flask-RESTplus API server",
14+
version="1.0.0",
15+
description="REST server for py",
16+
)
17+
18+
api.add_namespace(ping_ns, path="/ping")

app/src/__init__.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
"""
2+
App factory for our server.
3+
"""
4+
from .config import config_map
5+
from dotenv import find_dotenv, load_dotenv
6+
from flask import Flask
7+
8+
import os
9+
import pathlib
10+
11+
12+
load_dotenv(dotenv_path=str(pathlib.Path.cwd() / ".env"), verbose=True)
13+
14+
15+
def create_app(cfg):
16+
app = Flask(__name__)
17+
app.config.from_object(config_map[cfg])
18+
19+
return app

app/src/config.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"""
2+
Configuration module for the app.
3+
"""
4+
import os
5+
import pathlib
6+
import uuid
7+
8+
9+
class BaseConfig:
10+
TESTING = False
11+
BASE_DIR = pathlib.Path.cwd()
12+
SECRET_KEY = uuid.uuid4().hex
13+
14+
15+
class DevelopmentConfig(BaseConfig):
16+
pass
17+
18+
19+
class TestingConfig(BaseConfig):
20+
TESTING = True
21+
JSONIFY_PRETTYPRINT_REGULAR = True
22+
23+
24+
class ProductionConfig(BaseConfig):
25+
JSONIFY_PRETTYPRINT_REGULAR = True
26+
27+
28+
config_map = {
29+
"development": "app.src.config.DevelopmentConfig",
30+
"testing": "app.src.config.TestingConfig",
31+
"production": "app.src.config.ProductionConfig",
32+
}
33+
34+
KEY = BaseConfig.SECRET_KEY

app/src/controller/ping.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
"""
2+
Module to provide ping controller functionality
3+
"""
4+
from flask_restplus import Resource
5+
6+
from ..service import ping as service
7+
from ..utils import decorators, dto
8+
9+
api = dto.PingDto.api
10+
11+
12+
@api.route("/")
13+
class Ping(Resource):
14+
@decorators.validate_headers
15+
@api.doc("ping")
16+
def get(self):
17+
"""Ping response to find if the server is up"""
18+
return service.ping()

app/src/service/ping.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
"""
2+
Module to provide ping service fundtionality
3+
"""
4+
5+
6+
def ping():
7+
response_object = {"status": "success", "message": "PONG"}
8+
return (response_object, 200, {"Connection": "close"})
File renamed without changes.

app/src/utils/decorators.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import functools
2+
from flask import request
3+
4+
from .dto import PingDto
5+
6+
api = PingDto.api
7+
8+
9+
def validate_headers(func):
10+
@functools.wraps(func)
11+
def check(*args, **kwargs):
12+
if request.headers.get("Content-Type") != "application/json":
13+
return api.abort(415)
14+
return func(*args, **kwargs)
15+
16+
return check

app/src/utils/dto.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
"Module to implement ping data objects"
2+
from flask_restplus import Namespace, fields
3+
4+
5+
class PingDto:
6+
api = Namespace("ping", description="ping related operations")

app/test/test_config.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
"""
2+
Tests the app.main.config module.
3+
"""
4+
from flask import current_app
5+
from flask_testing import TestCase
6+
from manage import app
7+
8+
import os
9+
import unittest
10+
11+
12+
class TestBaseConfig(TestCase):
13+
def create_app(self):
14+
app.config.from_object("app.src.config.BaseConfig")
15+
return app
16+
17+
def test_app_is_base_config(self):
18+
self.assertIsNotNone(app.config.get("BASE_DIR"))
19+
self.assertIsNotNone(app.config.get("SECRET_KEY"))
20+
self.assertIsNotNone(app.config.get("ENV"))
21+
self.assertIsNotNone(app.config.get("DEBUG"))
22+
23+
self.assertFalse(app.config.get("TESTING"))
24+
25+
26+
class TestDevelopmentConfig(TestCase):
27+
def create_app(self):
28+
app.config.from_object("app.src.config.DevelopmentConfig")
29+
return app
30+
31+
def test_app_is_development(self):
32+
self.assertIsNotNone(current_app)
33+
34+
35+
class TestTestingConfig(TestCase):
36+
def create_app(self):
37+
app.config.from_object("app.src.config.TestingConfig")
38+
return app
39+
40+
def test_app_is_testing(self):
41+
self.assertTrue(app.config.get("TESTING"))
42+
self.assertTrue(app.config.get("JSONIFY_PRETTYPRINT_REGULAR"))
43+
44+
45+
class TestProductionConfig(TestCase):
46+
def create_app(self):
47+
app.config.from_object("app.src.config.ProductionConfig")
48+
return app
49+
50+
def test_app_is_production(self):
51+
self.assertTrue(app.config.get("JSONIFY_PRETTYPRINT_REGULAR"))
52+
53+
54+
if __name__ == "__main__":
55+
unittest.main()

manage.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"""
2+
Application entry point
3+
"""
4+
from app import blueprint
5+
from app.src import create_app
6+
from flask_cors import CORS
7+
from flask_script import Manager
8+
9+
import os
10+
import unittest
11+
12+
13+
app = create_app(os.getenv("FLASK_ENV") or "development")
14+
app.register_blueprint(blueprint)
15+
CORS(app, resources={"/ping/*": {"origins": "*"}})
16+
app.app_context().push()
17+
18+
manager = Manager(app)
19+
20+
21+
@manager.command
22+
def run():
23+
app.run()
24+
25+
26+
@manager.command
27+
def test():
28+
"""Runs the unit tests."""
29+
tests = unittest.TestLoader().discover("app/test", pattern="test*.py")
30+
result = unittest.TextTestRunner(verbosity=2).run(tests)
31+
if result.wasSuccessful():
32+
return 0
33+
return 1
34+
35+
36+
if __name__ == "__main__":
37+
manager.run()

0 commit comments

Comments
 (0)