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

Aggregated Logbook #41

Closed
wants to merge 6 commits into from
Closed
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
87 changes: 18 additions & 69 deletions src/boardlib/__main__.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import argparse
Copy link
Owner

@lemeryfertitta lemeryfertitta Aug 20, 2024

Choose a reason for hiding this comment

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

There are a lot of changes in this file, but it seems to me like at most this should just be a one-line change to add aggregate=False, but really there shouldn't be any changes at all because aggregate is already defaulting to False. Can we revert this file please? There are multiple regressions, e.g. to the command output prints, the imports, and the styling.

import csv
import getpass
import os
import pathlib
import sys

import pandas as pd
import getpass
import boardlib.api.aurora
import boardlib.api.moon
import boardlib.db.aurora


LOGBOOK_FIELDS = ("board", "angle", "climb_name", "date", "logged_grade", "displayed_grade", "difficulty", "tries", "is_mirror", "sessions_count", "tries_total", "is_repeat", "is_ascent", "comment")

LOGBOOK_FIELDS = ("board", "angle", "climb_name", "date", "logged_grade", "displayed_grade", "difficulty", "tries", "is_mirror", "is_ascent", "comment", "sessions_count", "tries_total", "is_repeat")

def logbook_entries(board, username, password, grade_type="font", database=None):
api = (
Expand All @@ -20,103 +19,55 @@ def logbook_entries(board, username, password, grade_type="font", database=None)
else boardlib.api.aurora
if board in boardlib.api.aurora.HOST_BASES
else None
)
)
if api:
yield from api.logbook_entries(board, username, password, grade_type, database)

entries = api.logbook_entries(board, username, password, grade_type, db_path=database, aggregate=False)
for entry in entries:
if isinstance(entry, dict):
Copy link
Owner

Choose a reason for hiding this comment

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

Why do we need to add this check for these changes? When is entry not a dict?

yield entry
else:
raise ValueError(f"Unknown board {board}")



def write_entries(output_file, entries, no_headers=False, fields=LOGBOOK_FIELDS):
writer = csv.DictWriter(output_file, fieldnames=fields)
if not no_headers:
writer.writeheader()
writer.writerows(entries)


def handle_database_command(args):
if not args.database_path.exists():
args.database_path.parent.mkdir(parents=True, exist_ok=True)
print(f"Downloading database to {args.database_path}")
boardlib.db.aurora.download_database(args.board, args.database_path)

print(f"Synchronizing database at {args.database_path}")
row_counts = boardlib.db.aurora.sync_shared_tables(args.board, args.database_path)
for table_name, row_count in row_counts.items():
print(f"Synchronized {row_count} rows in {table_name}")

boardlib.db.aurora.sync_shared_tables(args.board, args.database_path)

def handle_logbook_command(args):
env_var = f"{args.board.upper()}_PASSWORD"
password = os.environ.get(env_var)
if not password:
password = getpass.getpass("Password: ")
entries = boardlib.api.aurora.logbook_entries(args.board, args.username, password, args.grade_type, args.database)

entries = boardlib.api.aurora.logbook_entries(args.board, args.username, password, args.grade_type, db_path=args.database)
if args.output:
with open(args.output, "w", encoding="utf-8") as output_file:
write_entries(output_file, entries.to_dict(orient="records"), args.no_headers, fields=LOGBOOK_FIELDS)
else:
sys.stdout.reconfigure(encoding="utf-8")
write_entries(sys.stdout, entries.to_dict(orient="records"), args.no_headers, fields=LOGBOOK_FIELDS)


def add_database_parser(subparsers):
database_parser = subparsers.add_parser(
"database", help="Download and sync the database"
)
database_parser.add_argument(
"board",
help="Board name",
choices=sorted(boardlib.api.aurora.HOST_BASES.keys()),
)
database_parser.add_argument(
"database_path",
help=(
"Path for the database file. "
"If the file does not exist, the database will be downloaded to the given path and synchronized. "
"If it does exist, the database will just be synchronized",
),
type=pathlib.Path,
)
database_parser = subparsers.add_parser("database", help="Download and sync the database")
database_parser.add_argument("board", help="Board name", choices=sorted(boardlib.api.aurora.HOST_BASES.keys()))
database_parser.add_argument("database_path", help="Path for the database file.", type=pathlib.Path)
database_parser.set_defaults(func=handle_database_command)


def add_logbook_parser(subparsers):
logbook_parser = subparsers.add_parser(
"logbook", help="Download full logbook entries (ascents and bids) to CSV"
)
logbook_parser.add_argument(
"board",
help="Board name",
choices=sorted(
boardlib.api.moon.BOARD_IDS.keys() | boardlib.api.aurora.HOST_BASES.keys()
),
)
logbook_parser = subparsers.add_parser("logbook", help="Download full logbook entries (ascents and bids) to CSV")
logbook_parser.add_argument("board", help="Board name", choices=sorted(boardlib.api.moon.BOARD_IDS.keys() | boardlib.api.aurora.HOST_BASES.keys()))
logbook_parser.add_argument("-u", "--username", help="Username", required=True)
logbook_parser.add_argument("-o", "--output", help="Output file", required=False)
logbook_parser.add_argument(
"--no-headers", help="Don't write headers", action="store_true", required=False
)
logbook_parser.add_argument(
"-g",
"--grade-type",
help="Grade type",
choices=("font", "hueco"),
default="font",
required=False,
)
logbook_parser.add_argument(
"-d",
"--database",
help="Path to the local database (optional). Using a local database will significantly speed up the logbook generation and is required to retrieve 'displayed_grade' and 'difficulty'. Create a local database with the 'database' command.",
type=pathlib.Path,
required=False,
)
logbook_parser.add_argument("--no-headers", help="Don't write headers", action="store_true", required=False)
logbook_parser.add_argument("-g", "--grade-type", help="Grade type", choices=("font", "hueco"), default="font", required=False)
logbook_parser.add_argument("-d", "--database", help="Path to the local database (optional).", type=pathlib.Path, required=False)
logbook_parser.set_defaults(func=handle_logbook_command)


def main():
parser = argparse.ArgumentParser()
Expand All @@ -126,7 +77,5 @@ def main():
args = parser.parse_args()
args.func(args)



if __name__ == "__main__":
main()
Loading