API Reference - Sydefix/habit-tracker GitHub Wiki

API Documentation

This document provides a detailed reference for the functions available in the Habit Tracker application's modules.

analysis.py

This module contains all business logic related to analyzing habit data.

_is_completed_in_current_period(habit: Habit, current_time: datetime) -> bool

A single, consistent function to check if a habit was completed in its current period (today for daily, this week for weekly, etc.).

  • Parameters:
    • habit (Habit): The habit object to check.
    • current_time (datetime): The reference time, typically datetime.now().
  • Returns:
    • (bool): True if the habit was completed within its current period, False otherwise.

_calculate_current_deadline(habit: Habit, current_time: datetime) -> datetime

Calculates the upcoming deadline for a habit based on its periodicity.

  • Daily: End of the current day.
  • Weekly: End of the current week (Sunday).
  • Monthly: End of the current month.
  • Parameters:
    • habit (Habit): The habit object.
    • current_time (datetime): The reference time, typically datetime.now().
  • Returns:
    • (datetime): The calculated deadline for the habit's current period.

_periodicity(session: Session, periodicity: str) -> List[Habit]

Filters habits by a specific periodicity.

  • Parameters:
    • session (Session): The database session.
    • periodicity (str): The period to filter by (e.g., 'daily', 'weekly').
  • Returns:
    • (List[Habit]): A list of matching Habit objects.

generate_table(session: Session, periodicity: Optional[str] = None, habits: Optional[List[Habit]] = None) -> str

Generates a formatted string table of habits. Can be filtered by periodicity or a pre-supplied list of habits.

  • Parameters:
    • session (Session): The database session.
    • periodicity (Optional[str]): An optional periodicity to filter by.
    • habits (Optional[List[Habit]]): An optional pre-supplied list of habits.
  • Returns:
    • (str): A multi-line string representing the formatted table.

generate_list(session: Session, periodicity: Optional[str] = None, habits: Optional[List[Habit]] = None) -> List[str]

Generates a list of formatted strings for habits. Can be filtered by periodicity or a pre-supplied list of habits.

  • Parameters:
    • session (Session): The database session.
    • periodicity (Optional[str]): An optional periodicity to filter by.
    • habits (Optional[List[Habit]]): An optional pre-supplied list of habits.
  • Returns:
    • (List[str]): A list of human-readable strings, one for each habit.

longest_streak(session: Session, identifier: Optional[int | str] = None) -> int

Finds the longest streak from all habits or for a specific habit.

  • Parameters:
    • session (Session): The database session.
    • identifier (Optional[int | str]): The ID or name of a specific habit. If None, checks all habits to find the overall longest streak.
  • Returns:
    • (int): The highest number of consecutive days a habit was completed.

_break_count(habit: Habit) -> int

Calculates the number of times a habit's streak was broken.

  • Parameters:
    • habit (Habit): The habit to analyze.
  • Returns:
    • (int): The total number of times a streak was broken.

_gap_count(habit: Habit) -> int

Calculates the total number of missed days between streaks.

  • Parameters:
    • habit (Habit): The habit to analyze.
  • Returns:
    • (int): The sum of all gap days between broken streaks.

_gap_days(habit: Habit) -> Dict[str, List[date]]

Identifies the dates when streaks were broken and when they resumed.

  • Parameters:
    • habit (Habit): The habit to analyze.
  • Returns:
    • (Dict[str, List[date]]): A dictionary with 'break_dates' (last day of a streak) and 'resume_dates' (first day of the next).

struggled_habits(session: Session) -> List[Dict[str, Any]]

Analyzes all habits to find the most "struggled" ones based on a score: Struggle Score = (Number of Breaks) + (Total Gap Days).

  • Parameters:
    • session (Session): The database session.
  • Returns:
    • (List[Dict[str, Any]]): A list of dictionaries, one for each habit, sorted by the struggle score in descending order. Each dictionary contains the habit object, score, breaks, and gaps.

generate_summary(session: Session) -> str

Generates a high-level string summary of the overall habit landscape.

  • Parameters:
    • session (Session): The database session.
  • Returns:
    • (str): A formatted, multi-line string with the summary statistics.

cli.py

This module defines the public-facing Command-Line Interface (CLI) for the application. The functions within are decorated with @click and are not intended to be called directly from other modules; their API is the command line itself, as documented below.

Main Command: habit

The root command for the application. All other commands are subcommands of this.

  • Syntax:
    habit [OPTIONS] COMMAND [ARGS]...
    
  • Options:
    • -h, --help: Show the main help message and exit.

Command Group: demo

A playground to test habits using a separate demo database. This command group acts as a prefix for all other commands to run them against the demo environment.

  • Syntax:
    habit demo COMMAND [ARGS]...
    

demo start

Creates and seeds the demo database if it doesn't exist.

  • Syntax:
    habit demo start
    

demo reset

Deletes the existing demo database.

  • Syntax:
    habit demo reset
    

Core Commands

These commands can be run directly (e.g., habit add ...) to affect the production database, or prefixed with demo (e.g., habit demo add ...) to affect the demo database.

add

Adds a new habit to the database.

  • Syntax: habit add NAME [OPTIONS]
  • Arguments:
    • NAME: (Required) The name of the new habit.
  • Options:
    • -d, --description TEXT: A short description of the habit.
    • -p, --periodicity [daily|weekly|monthly]: The habit's period (default: daily).

update

Updates an existing habit's attributes.

  • Syntax: habit update IDENTIFIER [OPTIONS]
  • Arguments:
    • IDENTIFIER: (Required) The name or ID of the habit to update.
  • Options:
    • -n, --new-name TEXT: A new name for the habit.
    • -d, --description TEXT: A new description for the habit.
    • -p, --periodicity [daily|weekly|monthly]: A new periodicity for the habit.

delete

Deletes a habit by its name or ID.

  • Syntax: habit delete IDENTIFIER
  • Arguments:
    • IDENTIFIER: (Required) The name or ID of the habit to delete.

checkoff

Marks a habit as completed for the current time.

  • Syntax: habit checkoff IDENTIFIER
  • Arguments:
    • IDENTIFIER: (Required) The name or ID of the habit to complete.

list

A shortcut to display habits in a list format.

  • Syntax: habit list [OPTIONS]
  • Options:
    • -p, --periodicity [daily|weekly|monthly]: Filter habits by a specific periodicity.

analyze

Analyzes and displays habit data.

  • Syntax: habit analyze [OPTIONS]
  • Options:
    • -p, --periodicity [daily|weekly|monthly]: Filter analysis by a specific periodicity.
    • --show [table|list|summary|streak|struggle]: The type of analysis to show (default: table).
    • --habit TEXT: Specify a habit name or ID for streak analysis.

habit_manager.py

This module defines the HabitManager class, which acts as a business logic layer, providing a clean interface for all CRUD (Create, Read, Update, Delete) and other specific operations related to habits.

class HabitManager

A class to manage CRUD operations for Habit objects.

__init__(self, session: Session)

Initializes the HabitManager with a database session.

  • Parameters:
    • session (Session): The SQLAlchemy session object to be used for all database operations.

find_by_name(self, name: str) -> Habit | None

Finds a single habit by its unique name.

  • Parameters:
    • name (str): The exact name of the habit to find.
  • Returns:
    • (Habit | None): The Habit object if exactly one is found, otherwise None.
  • Raises:
    • MultipleResultsFound: If more than one habit with the same name exists.

find_by_id(self, habit_id: int) -> Habit | None

Finds a single habit by its primary key (ID).

  • Parameters:
    • habit_id (int): The ID of the habit to find.
  • Returns:
    • (Habit | None): The Habit object if found, otherwise None.

find_habit(self, identifier: int | str) -> Habit | None

Finds a habit by its ID or name. A wrapper for find_by_id and find_by_name.

  • Parameters:
    • identifier (int | str): The ID (int) or name (str) of the habit.
  • Returns:
    • (Habit | None): The Habit object if found, otherwise None.
  • Raises:
    • TypeError: If the identifier is not an integer or a string.
    • MultipleResultsFound: If the identifier is a string and multiple habits match that name.

get_all_habits(self) -> list[Habit]

Retrieves all habits from the database.

  • Returns:
    • (list[Habit]): A list of all Habit objects.

insert(self, habit_to_insert: Habit) -> Habit

Inserts a new Habit object into the database.

  • Parameters:
    • habit_to_insert (Habit): The Habit instance to be saved.
  • Returns:
    • (Habit): The saved Habit instance, refreshed with its new ID.
  • Raises:
    • ValueError: If the habit's periodicity is not one of the allowed values.
    • SQLAlchemyError: If a database error occurs during the transaction.

update(self, identifier: int | str, new_name: str = None, ...) -> Habit | None

Updates an existing habit's attributes.

  • Parameters:
    • identifier (int | str): The ID or name of the habit to update.
    • new_name (str, optional): The new name for the habit.
    • new_description (str, optional): The new description for the habit.
    • new_periodicity (str, optional): The new periodicity for the habit.
  • Returns:
    • (Habit | None): The updated Habit object if found and changed, otherwise None if the habit was not found.
  • Raises:
    • ValueError: If new_periodicity is not one of the allowed values.
    • MultipleResultsFound: If identifier is a string and multiple habits match.
    • SQLAlchemyError: If a database error occurs during the transaction.

delete(self, identifier: int | str) -> bool

Deletes a habit from the database by its name or ID.

  • Parameters:
    • identifier (int | str): The name or ID of the habit to delete.
  • Returns:
    • (bool): True if the habit was found and deleted, False otherwise.
  • Raises:
    • MultipleResultsFound: If identifier is a string and multiple habits match.
    • SQLAlchemyError: If a database error occurs during the transaction.

checkoff(self, identifier: int | str) -> Habit | None

Marks a habit as completed for the current time by creating a new Completion record.

  • Parameters:
    • identifier (int | str): The name or ID of the habit to check off.
  • Returns:
    • (Habit | None): The Habit object, refreshed with the new completion, or None if the habit was not found.
  • Raises:
    • MultipleResultsFound: If identifier is a string and multiple habits match.
    • SQLAlchemyError: If a database error occurs during the transaction.

models.py

This module defines the database schema for the Habit Tracker application using SQLAlchemy's ORM.

class Habit

Represents a single habit tracked by a user.

  • Attributes:
    • id (Integer): Unique identifier for the habit.
    • name (String): The name of the habit (e.g., 'Drink Water').
    • description (String): A short description of the habit.
    • periodicity (String): The frequency of the habit ('daily', 'weekly', 'monthly').
    • creation_date (DateTime): The timestamp when the habit was created.
    • completions (relationship): A one-to-many relationship to all associated Completion records.

class Completion

Represents a single completion event for a specific habit.

  • Attributes:
    • id (Integer): Unique identifier for the completion event.
    • completion_date (DateTime): The timestamp when the habit was marked as complete.
    • habit_id (Integer): A foreign key linking this completion to a specific habit.
    • habit (relationship): A many-to-one relationship back to the parent Habit object.

Further Information

The models in this file are defined using the SQLAlchemy Declarative Mapping system. For more in-depth information on how models, columns, and relationships work, please refer to the official SQLAlchemy ORM Documentation.