Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Codecleanup #3 #54

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions .idea/cli-surf.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/inspectionProfiles/profiles_settings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

196 changes: 105 additions & 91 deletions poetry.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "cli-surf"
version = "0.1.0"
description = ""
authors = ["ryansurf <your@email.com>"] # TODO: email
authors = ["tadi <tadiguks@gmail.com>"] # TODO: email
readme = "README.md"
packages = [{ include = "src" }]

Expand All @@ -15,7 +15,7 @@ g4f = "0.3.1.9"
geopy = "2.4.1"
openmeteo-requests = "1.2.0"
pandas = "2.2.2"
pydantic = "2.7.2"
pydantic = {extras = ["email"], version = "^2.8.2"}
pydantic-settings = "2.2.1"
python-dotenv = "1.0.1"
requests = "2.32.3"
Expand Down
4 changes: 2 additions & 2 deletions src/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ def run(lat=0, long=0):
"""
Main function
"""
# Seperates the cli args into a list
args = helper.seperate_args(sys.argv)
# Separates the cli args into a list
args = helper.separate_args(sys.argv)

# return coordinates, lat, long, city
location = api.seperate_args_and_get_location(args)
Expand Down
177 changes: 111 additions & 66 deletions src/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,48 +42,53 @@ def arguments_dictionary(lat, long, city, args):
return arguments


def set_output_values(args, arguments): # noqa
"""
Takes a list of command line arguments(args)
and sets the appropritate values
in the arguments dictionary(show_wave = 1, etc).
Returns the arguments dict with the updated CLI args
"""
if "hide_wave" in args or "hw" in args:
arguments["show_wave"] = 0
if "show_large_wave" in args or "slw" in args:
arguments["show_large_wave"] = 1
if "hide_uv" in args or "huv" in args:
arguments["show_uv"] = 0
if "hide_height" in args or "hh" in args:
arguments["show_height"] = 0
if "hide_direction" in args or "hdir" in args:
arguments["show_direction"] = 0
if "hide_period" in args or "hp" in args:
arguments["show_period"] = 0
if "hide_location" in args or "hl" in args:
arguments["show_city"] = 0
if "hide_date" in args or "hdate" in args:
arguments["show_date"] = 0
if "metric" in args or "m" in args:
arguments["unit"] = "metric"
if "json" in args or "j" in args:
arguments["json_output"] = 1
if "gpt" in args or "g" in args:
arguments["gpt"] = 1
if "show_air_temp" in args or "sat" in args:
arguments["show_air_temp"] = 1
if "show_wind_speed" in args or "sws" in args:
arguments["show_wind_speed"] = 1
if "show_wind_direction" in args or "swd" in args:
arguments["show_wind_direction"] = 1
def set_output_values(args, arguments):
"""
Takes a list of command line (show_wave = 1, etc).
Returns the arguments dict with the updated CLI args.
"""
actions = {
"hide_wave": ("show_wave", 0),
"hw": ("show_wave", 0),
"show_large_wave": ("show_large_wave", 1),
"slw": ("show_large_wave", 1),
"hide_uv": ("show_uv", 0),
"huv": ("show_uv", 0),
"hide_height": ("show_height", 0),
"hh": ("show_height", 0),
"hide_direction": ("show_direction", 0),
"hdir": ("show_direction", 0),
"hide_period": ("show_period", 0),
"hp": ("show_period", 0),
"hide_location": ("show_city", 0),
"hl": ("show_city", 0),
"hide_date": ("show_date", 0),
"hdate": ("show_date", 0),
"metric": ("unit", "metric"),
"m": ("unit", "metric"),
"json": ("json_output", 1),
"j": ("json_output", 1),
"gpt": ("gpt", 1),
"g": ("gpt", 1),
"show_air_temp": ("show_air_temp", 1),
"sat": ("show_air_temp", 1),
"show_wind_speed": ("show_wind_speed", 1),
"sws": ("show_wind_speed", 1),
"show_wind_direction": ("show_wind_direction", 1),
"swd": ("show_wind_direction", 1),
}

for arg in args:
if arg in actions:
key, value = actions[arg]
arguments[key] = value
Copy link
Collaborator

@K-dash K-dash Jul 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work!
IMO, there's one point I'd like to highlight. To ensure that the modifications you've made haven't caused any regressions (and that everything is functioning correctly), I recommend adding test cases to test_helper.py. This will help guarantee the integrity of the changes.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @ryansurf Thank you!

I only made changes to the helper.py function and cli.py function where I fixed a typo. I am not sure how files like idea/misc.xml were altered.
I will also try to figure out why the formatter is failing but if not, I will let you know

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! @K-dash

Yes I agree with you on that. I'm adding some tests to the test_helper.py file. Will push the changes for your review when I am done.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @ryansurf Thank you!

I only made changes to the helper.py function and cli.py function where I fixed a typo. I am not sure how files like idea/misc.xml were altered. I will also try to figure out why the formatter is failing but if not, I will let you know

When you do git add <file>, make sure you're only adding helper.py and cli.py!

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @GUKWAT, hows it going? Feel free to ping me if you need any help!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @ryansurf I am just working on the unit tests for helper.py. Still trying to figure out how to format the code using ruff having issues when it comes to the file path

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@GUKWAT great! What are the file path errors you are dealing with?


return arguments


def seperate_args(args):
def separate_args(args):
"""
Args are seperated by commas in input. Sereperat them and return list
Args are separated by commas in input. Separate them and return list
"""
if len(args) > 1:
new_args = args[1].split(",")
Expand All @@ -109,49 +114,89 @@ def get_forecast_days(args):

def print_location(city, show_city):
"""
Prints location
Prints the location only if `show_city` is equal to 1.
Prints "Location unknown" if the value is not 1.

Args:
city (str): The name of the city to be printed.
show_city (int): An integer that determines whether the city
should be printed (1) or not (any other value).

Returns:
None
"""
if int(show_city) == 1:
print("Location: ", city)
print("\n")
print("Location:", city)
else:
print("Not Available")


def print_ocean_data(arguments_dict, ocean_data_dict):
def print_ocean_data(arguments_dict, ocean_data):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Improve handling of None values in print_ocean_data

Instead of printing 'None' for missing values, consider using a more user-friendly message like 'Not available' or 'N/A'.

Suggested change
def print_ocean_data(arguments_dict, ocean_data):
def print_ocean_data(arguments_dict, ocean_data):
for key, value in ocean_data.items():
if value is None:
print(f"{key}: N/A")
else:
print(f"{key}: {value}")

"""
Prints ocean data(height, wave direction, period, etc)
Prints ocean data (height, wave direction, period, etc.)

Args:
arguments_dict (dict): Dictionary with keys such as "show_uv", "show_height",
"show_direction", "show_period", "show_air_temp",
"show_wind_speed", and "show_wind_direction". Values
should be 1 to display the corresponding data; If the value
is not equal to 1 data will not be displayed.

ocean_data (dict): Dictionary containing ocean data. Keys include
"UV Index", "Height", "Swell Direction", "Period",
"Air Temperature", "Wind Speed", and "Wind Direction".

Returns:
None
"""
if int(arguments_dict["show_uv"]) == 1:
print("UV index: ", ocean_data_dict["UV Index"])
if int(arguments_dict["show_height"]) == 1:
print("Wave Height: ", ocean_data_dict["Height"])
if int(arguments_dict["show_direction"]) == 1:
print("Wave Direction: ", ocean_data_dict["Swell Direction"])
if int(arguments_dict["show_period"]) == 1:
print("Wave Period: ", ocean_data_dict["Period"])
if int(arguments_dict["show_air_temp"]) == 1:
print("Air Temp: ", ocean_data_dict["Air Temperature"])
if int(arguments_dict["show_wind_speed"]) == 1:
print("Wind Speed: ", ocean_data_dict["Wind Speed"])
if int(arguments_dict["show_wind_direction"]) == 1:
print("Wind Direction: ", ocean_data_dict["Wind Direction"])
display_mapping = {
"show_uv": ("UV Index", "UV index: "),
"show_height": ("Height", "Wave Height: "),
"show_direction": ("Swell Direction", "Wave Direction: "),
"show_period": ("Period", "Wave Period: "),
"show_air_temp": ("Air Temperature", "Air Temp: "),
"show_wind_speed": ("Wind Speed", "Wind Speed: "),
"show_wind_direction": ("Wind Direction", "Wind Direction: "),
}

for key, (data_key, label) in display_mapping.items():
if int(arguments_dict.get(key, 0)) == 1:
value = ocean_data.get(data_key)
if value is not None:
print(f"{label}{value}")
else:
print(f"{label} Not available")


def print_forecast(ocean, forecast):
"""
Takes in list of forecast data and prints
Prints forecast data based on flags in the ocean dictionary.

Args:
ocean: Dictionary with keys like "show_date", "show_height",
"show_direction", and "show_period" indicating which data
to display (1 to show, otherwise hide).

forecast: List of tuples where each tuple contains
(date, wave height, wave direction, wave period).

Returns:
None
"""
transposed = list(zip(*forecast))

for day in transposed:
if ocean["show_date"] == 1:
print("Date: ", day[3])
if int(ocean["show_height"]) == 1:
print("Wave Height: ", day[0])
if int(ocean["show_direction"]) == 1:
print("Wave Direction: ", day[1])
if int(ocean["show_period"]) == 1:
print("Wave Period: ", day[2])
print("\n")
actions = {
"show_date": (3, "Date: "),
"show_height": (0, "Wave Height: "),
"show_direction": (1, "Wave Direction: "),
"show_period": (2, "Wave Period: "),
}

for key, (index, forecast_data) in actions.items():
if int(ocean.get(key, 0)) == 1:
print(forecast_data, day[index])
print("\n")

def extract_decimal(args):
"""
Expand Down
89 changes: 88 additions & 1 deletion tests/test_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,16 @@
"""

import io
import sys
from io import StringIO
from unittest.mock import patch

from src.helper import extract_decimal
from src.helper import (
extract_decimal,
print_location,
print_ocean_data,
set_output_values,
)


def test_invalid_input():
Expand All @@ -27,3 +34,83 @@ def test_default_input():
"""
decimal = extract_decimal([])
assert 1 == decimal


def test_print_location():
"""
Test the print_location function to check if the city name is printed
when the show_city parameter is 1
"""

city = "Perth"
show_city = 1
captured_output = io.StringIO()
sys.stdout = captured_output
print_location(city, show_city)
sys.stdout = sys.__stdout__
expected_output = "Location: Perth"
assert captured_output.getvalue().strip() == expected_output.strip()

def test_print_location_show_city_0():
"""
Test the print_location function to check if the city name prints
location not available when the show_city parameter is 0
"""
city = "Perth"
show_city = 0
captured_output = io.StringIO()
sys.stdout = captured_output
print_location(city, show_city)
sys.stdout = sys.__stdout__
expected_output = "Not Available"
assert captured_output.getvalue().strip() == expected_output.strip()


def test_set_output_values():
"""
Tests the set_output_values function to verify that it correctly
sets values in the output dictionary based on the provided list of
input arguments (args)
"""
args = ["hw", "show_large_wave", "huv"]
arguments = {}
expected = {"show_wave": 0, "show_large_wave": 1, "show_uv": 0}
assert set_output_values(args, arguments) == expected


def test_print_ocean_data():
"""
Test that checks if the print_ocean_data function prints all
the ocean data
"""
arguments_dict = {
"show_uv": "1",
"show_height": "1",
"show_direction": "1",
"show_period": "0",
"show_air_temp": "1",
"show_wind_speed": "1",
"show_wind_direction": "0",
}

ocean_data = {
"UV Index": 5,
"Height": 2.5,
"Swell Direction": "NE",
"Air Temperature": 25,
"Wind Speed": 15,
}

expected_output = (
"UV index: 5\n"
"Wave Height: 2.5\n"
"Wave Direction: NE\n"
"Air Temp: 25\n"
"Wind Speed: 15\n"
)

captured_output = StringIO()
sys.stdout = captured_output
print_ocean_data(arguments_dict, ocean_data)
sys.stdout = sys.__stdout__
assert captured_output.getvalue() == expected_output