Pablo Solar VilariƱo
2020-03-16 cc49820afe95233e9c3a87e35541f9233fb89faa
Adding service which provides a simple news feed (#2)

* Adding service which provides a simple news feed

* Added inital README

* Renaming const to express what it does

* Removed LICENSE
6 files added
185 ■■■■■ changed files
python-flask-gossip/.gitignore 11 ●●●●● patch | view | raw | blame | history
python-flask-gossip/Dockerfile 14 ●●●●● patch | view | raw | blame | history
python-flask-gossip/README.md 73 ●●●●● patch | view | raw | blame | history
python-flask-gossip/requirements.txt 2 ●●●●● patch | view | raw | blame | history
python-flask-gossip/src/data/finance.json 49 ●●●●● patch | view | raw | blame | history
python-flask-gossip/src/gossip.py 36 ●●●●● patch | view | raw | blame | history
python-flask-gossip/.gitignore
New file
@@ -0,0 +1,11 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# IDEs
.idea
# dependencies
/venv
__pycache__
# misc
.DS_Store
python-flask-gossip/Dockerfile
New file
@@ -0,0 +1,14 @@
FROM ubi8/python-36
ENV FLASK_APP="gossip.py"
COPY src /app
COPY requirements.txt /app
WORKDIR /app
RUN pip install -r requirements.txt
EXPOSE 5000
CMD [ "flask", "run", "--host=0.0.0.0"]
python-flask-gossip/README.md
New file
@@ -0,0 +1,73 @@
# Gossip Service
The Gossip Service is a small application written in [Python](https://www.python.org/) + [Flask](https://flask.palletsprojects.com)
which exposes a variable endpoint in order to retrieve news from a specific topic. It Comes with CORS enabled so it can
be used from browsers.
## How it works
The application exposes a `GET` endpoint `/news/<topic>` on port `5000` by default. Once a GET request hits the service,
the application uses the `<topic>` part of the endpoint to find a json file with that name.
In the case of not being able to locate a file with the `<topic>` name, the application throws a 404 error. In any other
case, the application loads the list of news from the json file, picks 3 randomly and returns the list sorted by their
timestamp.
Template of the json used to store the news:
```json
{
  "data": [
    {
      "anyFieldKey": "anyFieldValue",
      "timestamp": 1578454302
    }
  ]
}
```
The only requirements for the json files are:
- Be a well formed JSON file
- The `data` field should exists and stores the list of news objects
- Each news element should have a `timestamp` field
## Installation
The Gossip Service is a Python application with Flask so, in order to run in your local machine you need Python + some
libraries.
A simple approach is to have different Python virtual environments per project. Execute the following command in the
root of this project ot install a virtual environment:
```
$ python3 -m virtualenv venv
```
Once the virtual environment is installed in the project, you need to activate this new virtual environment. Execute the
following command to activate it:
```
. venv/bin/activate
```
After the activation of the virtual environment you need to install all the requirements for the service (unless you did
this step before). Execute the following command to install all the required libraries:
```
pip install -r requirements.txt
```
## Running Gossip in local
To run the Gossip Service in local, execute the following commands:
```
$ cd src
$ export FLASK_APP=gossip.py
$ flask run
```
 ## Running Gossip in a containers environment
In order to run the Gossip Service in a containers environment you need a container image. A prebuilt image is
available in [quay.io](https://quay.io/repository/psolarvi/python-flask-gossip)
python-flask-gossip/requirements.txt
New file
@@ -0,0 +1,2 @@
Flask
flask-cors
python-flask-gossip/src/data/finance.json
New file
@@ -0,0 +1,49 @@
{
  "data": [
    {
      "id": "8f9f00d0-acce-4eda-9b31-2251ab393846",
      "title": "Energy Sector +0.20%",
      "timestamp": 1578454302
    },
    {
      "id": "26fabd5b-d21e-405e-a624-e03a21b8d5ef",
      "title": "Financials Sector -0.77%",
      "timestamp": 1579263010
    },
    {
      "id": "451bf2da-9af4-417b-bc5f-bb14bcdbdfc8",
      "title": "Basic Materials Sector -0.48%",
      "timestamp": 1579724882
    },
    {
      "id": "a20e3370-52df-4631-8028-b1ba2ede2257",
      "title": "Healthcare Sector +0.92%",
      "timestamp": 1580165061
    },
    {
      "id": "c8b770ed-997d-45ba-89a2-d10e9951e0d2",
      "title": "Industrials Sector -1.02%",
      "timestamp": 1580240625
    },
    {
      "id": "35b7d3a9-0e47-40ab-aeed-b223ad6a8afa",
      "title": "Technology Sector +0.11%",
      "timestamp": 1581686667
    },
    {
      "id": "e3ffea9c-5025-4d48-a451-e78cbbb37f79",
      "title": "Cyclical Goods & Services Sector +0.07%",
      "timestamp": 1581921237
    },
    {
      "id": "52048c22-d270-4224-9f01-dc70d32c4fb1",
      "title": "Non-Cyclical Goods & Services Sector +0.33%",
      "timestamp": 1582278201
    },
    {
      "id": "b7fc7f33-b777-4ec2-89ef-2339cbf662b5",
      "title": "Utilities Sector +0.46%",
      "timestamp": 1583351796
    }
  ]
}
python-flask-gossip/src/gossip.py
New file
@@ -0,0 +1,36 @@
import json
import random
from flask import abort, Flask, jsonify
from flask_cors import CORS
from markupsafe import escape
app = Flask(__name__)
CORS(app)
NUM_OF_NEWS = 3
def sortByTimestamp(element):
  return element['timestamp']
@app.errorhandler(404)
def topicNotFound(error):
    return "Unable to find the specific topic", 404
@app.route('/news/<string:topic>')
def getNewsForTopic(topic):
    try:
        # Loading the file which has the topic news
        with open('./data/%s.json' % escape(topic)) as topicFile:
            news = json.load(topicFile)
        # Picking only a few elements from the list of news
        randomSelection = random.sample(news['data'], NUM_OF_NEWS)
        # Sorting the resulting list by the timestamp
        randomSelection.sort(key=sortByTimestamp)
        return jsonify(randomSelection)
    # If we can not find a file for the topic, we throw a 404 error
    except IOError:
        abort(404)