Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ dist
.tox
coverage.xml
.coverage*
*_cache
*_cache
venv/
72 changes: 72 additions & 0 deletions weatherrouting/polar.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,16 @@

# For detail about GNU see <http://www.gnu.org/licenses/>.
import math
import re
from io import TextIOWrapper
from typing import Dict, Optional, Tuple


class PolarError(Exception):
def __init__(self, message):
Copy link
Owner

@dakk dakk May 12, 2025

Choose a reason for hiding this comment

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

This is not necessery; Exception already receives a list of arguments which are stored in Exception().args; you can put a "pass" in the body of the class

Copy link
Owner

Choose a reason for hiding this comment

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

class PolarError(Exception):
  pass

is enough

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am sorry, I missed it in my last commit.

Copy link
Owner

@dakk dakk May 15, 2025

Choose a reason for hiding this comment

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

Still wrong:

class PolarError(Exception):
   pass

self.message = message


class Polar:
def __init__(self, polar_path: str, f: Optional[TextIOWrapper] = None):
"""
Expand All @@ -29,6 +35,7 @@
f : File
File object for passing an opened file
"""
self.validate_polar_file(polar_path)

self.tws = []
self.twa = []
Expand Down Expand Up @@ -189,3 +196,68 @@
if twa > twadown:
twa = twadown
return twa

@staticmethod
def validate_polar_file(filepath): # noqa: C901

Check notice on line 201 in weatherrouting/polar.py

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

weatherrouting/polar.py#L201

Polar.validate_polar_file is too complex (19) (MC0001)
try:
with open(filepath, "r") as f:
content = f.read()
lines = content.strip().split("\n")

if len(lines) == 0:
raise PolarError("EMPTY_FILE")

# Parse header to get wind speeds
header_parts = re.split(r"\s+", lines[0].strip())

# Try to parse wind speeds (should be numeric)
try:
tws = [float(ws) for ws in header_parts[1:]]
except ValueError:
raise PolarError("WIND_SPEED_NOT_NUMERIC")

# Check for increasing wind speeds
if not all(tws[i] <= tws[i + 1] for i in range(len(tws) - 1)):
raise PolarError("WIND_SPEEDS_NOT_INCREASING")

# Check data rows
expected_columns = len(header_parts)
for i, line in enumerate(lines[1:], start=1):
parts = re.split(r"\s+", line.strip())

# Skip empty lines
if not parts or (len(parts) == 1 and not parts[0]):
raise PolarError("EMPTY_LINE")

# Check number of columns
if len(parts) != expected_columns:
raise PolarError("COLUMN_COUNT_MISMATCH")

# Check if TWA is in valid range
try:
twa = float(parts[0])
if twa < 0 or twa > 180:
raise PolarError("TWA_OUT_OF_RANGE")
except ValueError:
raise PolarError("TWA_NOT_NUMERIC")

# Check if boat speeds are non-negative
for j, speed in enumerate(parts[1:], start=1):

Check warning on line 245 in weatherrouting/polar.py

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

weatherrouting/polar.py#L245

Unused variable 'j'
# Skip empty values or specific placeholders
if speed in ["", "-", "NaN", "NULL"]:
raise PolarError("EMPTY_VALUE")
try:
boat_speed = float(speed)
if boat_speed < 0:
raise PolarError("NEGATIVE_SPEED")
except ValueError:
raise PolarError("SPEED_NOT_NUMERIC")

# If we get here, the file is valid
return True
except PolarError:
# Re-raise PolarError exceptions
raise
except Exception as e:
# Wrap other exceptions in PolarError
raise PolarError("UNEXPECTED_ERROR", f"Error processing file: {str(e)}")

Check failure on line 263 in weatherrouting/polar.py

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

weatherrouting/polar.py#L263

Too many positional arguments for constructor call