Skip to content

Commit

Permalink
Merge pull request #21 from K-dash/refactor/unify-directory-structure
Browse files Browse the repository at this point in the history
Refactor directory structure and unify frontend and backend
  • Loading branch information
ryansurf authored May 28, 2024
2 parents 2d100c1 + 60001d6 commit c60474c
Show file tree
Hide file tree
Showing 14 changed files with 59 additions and 55 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ jobs:
pip install pytest
- name: Test with pytest
run: |
cd src/tests
pytest
cd src
pytest
5 changes: 3 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ COPY . .
# USER app

# Set the working directory for running the application
WORKDIR /app/src/backend
WORKDIR /app/src
EXPOSE 8000

# Command to run the Flask application
CMD ["python3", "server.py"]
CMD ["python3", "server.py"]
15 changes: 5 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ To run locally on your machine, I recommend either:
4. `python3 -m venv venv`
5. `source venv/bin/activate`
6. `pip install -r requirements.txt`
7. `cd src/backend`
7. `cd src`
8. `python3 server.py`

**Or running Docker (install [Docker](https://docs.docker.com/engine/install/))**
Expand All @@ -102,20 +102,15 @@ Change `.env.example` to `.env`

| Variable | Description|
| -------- | ------- |
| `PORT` | The port you want to open to run the application. Default = `8000` |
| `IP_ADDRESS` | The ip your server is running on. Default = `localhost` |
| `SMTP_SERVER` | The email server you are using. Default = smtp.gmail.com |
| `EMAIL` | The email you will send the report from. |
| `EMAIL_PW` | The sending email's password |
| `EMAIL_RECEIVER` | The email that will receive the report (your personal email) |
| `COMMAND` | The command that will be ran and shown in the email. Default = `localhost:8000` |
| `SUBJECT` | The email's subject. Default = Surf Report |

**config.json**

| Variable | Description|
| -------- | ------- |
| `port` | The port you want to open to run the application. Default = `8000` |
| `ip_address` | The ip your server is running on. Default = `localhost` |


**Email Server**

Expand All @@ -135,7 +130,7 @@ Although this application was made with the cli in mind, there is a frontend.

`http://localhost:8000/home` **or** `<ip_of_host>:<port>/home` if the application is running on a different host or you have changed the default port.

You may need to change `ip_address` in `config.json` to match the ip of the host running the machine.
You may need to change `IP_ADDRESS` in `.env` to match the ip of the host running the machine.

Now, running `python3 server.py` will launch the website!

Expand All @@ -153,4 +148,4 @@ Questions? Comments?
* [GitHub](https://github.com/ryansurf)

## License
[![License](https://img.shields.io/:license-mit-blue.svg?style=flat-square)](https://badges.mit-license.org)
[![License](https://img.shields.io/:license-mit-blue.svg?style=flat-square)](https://badges.mit-license.org)
Empty file added src/__init__.py
Empty file.
14 changes: 8 additions & 6 deletions src/backend/api.py → src/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ def forecast(lat, long, decimal, days=0):
daily_data["date"],
]


def gather_data(lat, long, ocean):
"""
Calls APIs though python files
Expand All @@ -178,20 +179,21 @@ def gather_data(lat, long, ocean):
"Direction": ocean_data[1],
"Period": ocean_data[2],
"UV Index": uv_index,
"Forecast": json_forecast
"Forecast": json_forecast,
}
return ocean_data, uv_index, data_dict


def seperate_args_and_get_location(args):
"""
Gets user's coordinates from either the argument(location=) or, if none,
the default coordinates(default_location())
"""
coordinates = get_coordinates(args)
location_data = {
"coordinates" : coordinates,
"lat" : coordinates[0],
"long" : coordinates[1],
"city" : coordinates[2]
"coordinates": coordinates,
"lat": coordinates[0],
"long": coordinates[1],
"city": coordinates[2],
}
return location_data
return location_data
File renamed without changes.
27 changes: 14 additions & 13 deletions src/backend/main.py → src/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@
"""

import sys
import helper
import api
import art
import os
import subprocess
from dotenv import load_dotenv
from helper import arguments_dictionary

sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

def main(lat=0, long=0):
from src import helper
from src import api
from src import art


def run(lat=0, long=0):
"""
Main function
"""
#Seperates the cli args into a list
# Seperates the cli args into a list
args = helper.seperate_args(sys.argv)

# return coordinates, lat, long, city
Expand All @@ -29,9 +29,9 @@ def main(lat=0, long=0):
if lat == 0 and long == 0:
lat, long = set_location[2], set_location[3]

#Sets ocean = dictionary with
# Sets ocean = dictionary with
arguments = helper.arguments_dictionary(lat, long, city, args)
#Updates the ocean dict with the valeus from the arguments
# Updates the ocean dict with the valeus from the arguments
arguments = helper.set_output_values(args, arguments)

lat = float(lat)
Expand All @@ -42,14 +42,15 @@ def main(lat=0, long=0):
uv_index = data[1]
data_dict = data[2]

#Non-JSON output
# Non-JSON output
if arguments["json_output"] == 0:
helper.print_outputs(lat, long, coordinates, ocean_data, arguments)
return data_dict
#JSON Output
# JSON Output
else:
json_output = helper.json_output(data_dict)
return json_output


if __name__ == "__main__":
main()
run()
26 changes: 16 additions & 10 deletions src/backend/helper.py → src/helper.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
"""
General helper functions
"""
import subprocess

import json
import api
import art
import os
import pandas as pd
from http.server import SimpleHTTPRequestHandler, HTTPServer


def arguments_dictionary(lat, long, city, args):
"""
Expand All @@ -25,11 +24,11 @@ def arguments_dictionary(lat, long, city, args):
"show_period": 1,
"show_city": 1,
"show_date": 1,
"json_output" : 0,
"json_output": 0,
"unit": "imperial",
"decimal": extract_decimal(args),
"forecast_days": get_forecast_days(args),
"color": get_color(args)
"color": get_color(args),
}
return arguments

Expand Down Expand Up @@ -136,6 +135,7 @@ def round_decimal(round_list, decimal):
rounded_list.append(round(num, decimal))
return rounded_list


def set_output_values(args, ocean):
"""
Takes a list of command line arguments(args) and sets the appropritate values
Expand Down Expand Up @@ -163,14 +163,16 @@ def set_output_values(args, ocean):
ocean["json_output"] = 1
return ocean


def json_output(data_dict):
"""
If JSON=TRUE in .args, we print and return the JSON data
"""
"""
json_out = json.dumps(data_dict, indent=4)
print(json_out)
return data_dict


def print_outputs(lat, long, coordinates, ocean_data, arguments):
"""
Basically the main printing function, calls all the other printing functions
Expand All @@ -183,12 +185,15 @@ def print_outputs(lat, long, coordinates, ocean_data, arguments):
print("No ocean data at this location.")
else:
print_location(arguments["city"], arguments["show_city"])
art.print_wave(arguments["show_wave"], arguments["show_large_wave"], arguments["color"])
art.print_wave(
arguments["show_wave"], arguments["show_large_wave"], arguments["color"]
)
print_output(arguments)
print("\n")
forecast = api.forecast(lat, long, arguments["decimal"], arguments["forecast_days"])
print_forecast(arguments, forecast)


def set_location(location):
"""
Sets locations variables
Expand All @@ -197,21 +202,22 @@ def set_location(location):
lat, long = location["lat"], location["long"]
return coordinates, city, lat, long


def forecast_to_json(data, decimal):
"""
Takes forecast() as input and returns it in JSON format
"""
surf_height, swell_direction, swell_period, dates = data

# Formatting into JSON
forecasts = []
for i in range(len(dates)):
forecast = {
"date": str(dates[i].date()),
"surf height": round(float(surf_height[i]), decimal),
"swell direction": round(float(swell_direction[i]), decimal),
"swell period": round(float(swell_period[i]), decimal)
"swell period": round(float(swell_period[i]), decimal),
}
forecasts.append(forecast)

return forecasts
File renamed without changes.
9 changes: 4 additions & 5 deletions src/backend/server.py → src/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from dotenv import load_dotenv, dotenv_values
import os
import subprocess
import json
import asyncio
import urllib.parse

Expand All @@ -20,7 +19,7 @@

@app.route("/help")
def serve_help():
return send_from_directory("../../", "help.txt")
return send_from_directory("../", "help.txt")


@app.route("/home")
Expand All @@ -30,7 +29,7 @@ def serve_index():

@app.route("/script.js")
def serve_script():
return send_file("../frontend/script.js")
return send_file("static/script.js")


@app.route("/")
Expand All @@ -52,7 +51,7 @@ def default_route():
async def run_subprocess():
try:
result = subprocess.run(
["python3", "main.py", args],
["python3", "cli.py", args],
capture_output=True,
text=True,
check=True,
Expand All @@ -72,4 +71,4 @@ async def run_subprocess():


if __name__ == "__main__":
app.run(port=os.getenv("PORT"))
app.run(host="0.0.0.0", port=os.getenv("PORT"))
File renamed without changes.
File renamed without changes.
Empty file added src/tests/__init__.py
Empty file.
14 changes: 7 additions & 7 deletions src/tests/test_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@

import sys

sys.path.append("../backend")
sys.path.append("../src")

from unittest.mock import patch
import io
import time
from main import main
from helper import extract_decimal
from api import get_coordinates, get_uv, ocean_information
from src import cli
from src.helper import extract_decimal
from src.api import get_coordinates, get_uv, ocean_information


def test_invalid_input():
Expand Down Expand Up @@ -56,9 +56,9 @@ def test_main_output():
Main() returns a dictionary of: location, height, period, etc.
This functions checks if the dictionary is returned and is populated
"""
#Hardcode lat and long for location. If not, when test are ran in Github Actions
#We get an error(because server probably isn't near ocean)
data_dict = main(36.95, -121.97)
# Hardcode lat and long for location. If not, when test are ran in Github Actions
# We get an error(because server probably isn't near ocean)
data_dict = cli.run(36.95, -121.97)
print(data_dict)
time.sleep(5)
assert len(data_dict) >= 5

0 comments on commit c60474c

Please sign in to comment.