Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
11 changes: 6 additions & 5 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@ repos:
- tomli
exclude: 'cassettes/'

- repo: https://github.com/psf/black
rev: 24.8.0
hooks:
- id: black
language_version: python3
# Removed black - using ruff-format instead to avoid formatting conflicts
# - repo: https://github.com/psf/black
# rev: 24.8.0
# hooks:
# - id: black
# language_version: python3

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.6.4
Expand Down
52 changes: 32 additions & 20 deletions demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,7 @@ def __init__(self):

# Activity settings
self.activitytype = "" # Possible values: cycling, running, swimming, multi_sport, fitness_equipment, hiking, walking, other
self.activityfile = (
"test_data/sample_activity.gpx" # Supported file types: .fit .gpx .tcx
)
self.activityfile = "test_data/*.gpx" # Supported file types: .fit .gpx .tcx
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

config.activityfile is no longer used in the upload flow.

The glob pattern is defined here but never referenced in upload_activity_file (lines 1287-1403), which now performs its own file discovery via glob.glob("test_data/*.gpx"). Additionally, the menu description at line 227 displays config.activityfile, which now shows a glob pattern instead of a single file path, potentially confusing users.

Consider either:

  1. Remove self.activityfile from Config if it's truly unused, or
  2. Use config.activityfile as the glob pattern in upload_activity_file for consistency:
-        gpx_files = glob.glob("test_data/*.gpx")
+        gpx_files = glob.glob(config.activityfile)

And update the menu description at line 227 to be more accurate:

-                "desc": f"Upload activity data from {config.activityfile}",
+                "desc": "Upload activity data (interactive file selection)",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
self.activityfile = "test_data/*.gpx" # Supported file types: .fit .gpx .tcx
# In upload_activity_file (replace hard-coded glob with config)
gpx_files = glob.glob(config.activityfile)
Suggested change
self.activityfile = "test_data/*.gpx" # Supported file types: .fit .gpx .tcx
# In the menu definition (make description generic)
"desc": "Upload activity data (interactive file selection)",

self.workoutfile = "test_data/sample_workout.json" # Sample workout JSON file

# Export settings
Expand Down Expand Up @@ -1288,37 +1286,52 @@ def get_solar_data(api: Garmin) -> None:

def upload_activity_file(api: Garmin) -> None:
"""Upload activity data from file."""
import glob
import os

try:
# Default activity file from config
print(f"📤 Uploading activity from file: {config.activityfile}")
# List all .gpx files in test_data
gpx_files = glob.glob("test_data/*.gpx")
if not gpx_files:
print("❌ No .gpx files found in test_data directory.")
print("ℹ️ Please add GPX files to test_data before uploading.")
return

# Check if file exists
import os
print("Select a GPX file to upload:")
for idx, fname in enumerate(gpx_files, 1):
print(f" {idx}. {fname}")

if not os.path.exists(config.activityfile):
print(f"❌ File not found: {config.activityfile}")
print(
"ℹ️ Please place your activity file (.fit, .gpx, or .tcx) under the 'test_data' directory or update config.activityfile"
)
print("ℹ️ Supported formats: FIT, GPX, TCX")
while True:
try:
choice = int(input(f"Enter number (1-{len(gpx_files)}): "))
if 1 <= choice <= len(gpx_files):
selected_file = gpx_files[choice - 1]
break
else:
print("Invalid selection. Try again.")
except ValueError:
print("Please enter a valid number.")

print(f"📤 Uploading activity from file: {selected_file}")
if not os.path.exists(selected_file):
print(f"❌ File not found: {selected_file}")
return

# Upload the activity
result = api.upload_activity(config.activityfile)
result = api.upload_activity(selected_file)

if result:
print("✅ Activity uploaded successfully!")
call_and_display(
api.upload_activity,
config.activityfile,
selected_file,
method_name="upload_activity",
api_call_desc=f"api.upload_activity({config.activityfile})",
api_call_desc=f"api.upload_activity({selected_file})",
)
else:
print(f"❌ Failed to upload activity from {config.activityfile}")
print(f"❌ Failed to upload activity from {selected_file}")

except FileNotFoundError:
print(f"❌ File not found: {config.activityfile}")
print(f"❌ File not found: {selected_file}")
Comment on lines +1303 to +1324
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Risk of UnboundLocalError if exception occurs before file selection.

The try block starts at line 1291, but selected_file is only assigned at line 1307 inside the while True loop. If an exception occurs before the user completes the selection (e.g., during glob.glob() or input()), the except FileNotFoundError handler at line 1323 will reference an undefined selected_file, causing an UnboundLocalError.

Initialize selected_file before the selection loop:

     try:
+        selected_file = None  # Initialize before potential exceptions
         # List all .gpx files in test_data
         gpx_files = glob.glob("test_data/*.gpx")

Then update the error message to handle the case where no file was selected:

     except FileNotFoundError:
-        print(f"❌ File not found: {selected_file}")
+        print(f"❌ File not found: {selected_file if selected_file else 'No file selected'}")
         print("ℹ️ Please ensure the activity file exists in the current directory")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
while True:
try:
choice = int(input(f"Enter number (1-{len(gpx_files)}): "))
if 1 <= choice <= len(gpx_files):
selected_file = gpx_files[choice - 1]
break
else:
print("Invalid selection. Try again.")
except ValueError:
print("Please enter a valid number.")
# Upload the activity
result = api.upload_activity(config.activityfile)
print(f"📤 Uploading activity from file: {selected_file}")
if result:
print("✅ Activity uploaded successfully!")
call_and_display(
api.upload_activity,
config.activityfile,
method_name="upload_activity",
api_call_desc=f"api.upload_activity({config.activityfile})",
)
else:
print(f"❌ Failed to upload activity from {config.activityfile}")
call_and_display(
api.upload_activity,
selected_file,
method_name="upload_activity",
api_call_desc=f"api.upload_activity({selected_file})",
)
except FileNotFoundError:
print(f"❌ File not found: {config.activityfile}")
print(f"❌ File not found: {selected_file}")
try:
selected_file = None # Initialize before potential exceptions
# List all .gpx files in test_data
gpx_files = glob.glob("test_data/*.gpx")
while True:
try:
choice = int(input(f"Enter number (1-{len(gpx_files)}): "))
if 1 <= choice <= len(gpx_files):
selected_file = gpx_files[choice - 1]
break
else:
print("Invalid selection. Try again.")
except ValueError:
print("Please enter a valid number.")
print(f"📤 Uploading activity from file: {selected_file}")
call_and_display(
api.upload_activity,
selected_file,
method_name="upload_activity",
api_call_desc=f"api.upload_activity({selected_file})",
)
except FileNotFoundError:
print(f"❌ File not found: {selected_file if selected_file else 'No file selected'}")
print("ℹ️ Please ensure the activity file exists in the current directory")
🤖 Prompt for AI Agents
In demo.py around lines 1303 to 1324, selected_file is only set inside the
user-selection loop which can lead to an UnboundLocalError in the
FileNotFoundError except block if an exception occurs earlier; initialize
selected_file to None before the selection loop (or at the start of the
enclosing try) and change the except FileNotFoundError handler to check if
selected_file is None and print a generic "❌ File not found or no file selected"
message, otherwise print the specific filename, ensuring the handler never
references an uninitialized variable.

print("ℹ️ Please ensure the activity file exists in the current directory")
except requests.exceptions.HTTPError as e:
if e.response.status_code == 409:
Expand Down Expand Up @@ -1363,7 +1376,6 @@ def upload_activity_file(api: Garmin) -> None:
print(f"❌ Too many requests: {e}")
print("💡 Please wait a few minutes before trying again")
except Exception as e:
# Check if this is a wrapped HTTP error from the Garmin library
error_str = str(e)
if "409 Client Error: Conflict" in error_str:
print(
Expand Down
Loading