Skip to content

Commit

Permalink
Use of Final for "const-ish" values.
Browse files Browse the repository at this point in the history
  • Loading branch information
joce committed Nov 17, 2023
1 parent 60c4283 commit a61c409
Show file tree
Hide file tree
Showing 8 changed files with 48 additions and 43 deletions.
3 changes: 2 additions & 1 deletion src/appui/_formatting.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"""
Functions for formatting various data types into strings for the Stockyard application.
"""
from typing import Final

_NO_VALUE: str = "N/A" # TODO Maybe use "" instead?
_NO_VALUE: Final[str] = "N/A" # TODO Maybe use "" instead?


def as_percent(value: float | None) -> str:
Expand Down
4 changes: 2 additions & 2 deletions src/appui/_quote_column_definitions.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Definitions of the available columns for the quote table."""

from math import inf
from typing import Optional, TypeVar
from typing import Final, Optional, TypeVar

from ._enums import Justify
from ._formatting import as_float, as_percent, as_shrunk_int
Expand Down Expand Up @@ -42,7 +42,7 @@ def _sign(v: T) -> int:
return 1 if v > 0 else -1 if v < 0 else 0


ALL_QUOTE_COLUMNS: dict[str, QuoteColumn] = {
ALL_QUOTE_COLUMNS: Final[dict[str, QuoteColumn]] = {
"ticker": (
QuoteColumn(
"Ticker",
Expand Down
6 changes: 3 additions & 3 deletions src/appui/_quote_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
This module contains the QuoteTable class which is a DataTable for displaying quotes.
"""

from typing import Any, override
from typing import Any, Final, override

from rich.style import Style
from rich.text import Text
Expand All @@ -17,8 +17,8 @@
class QuoteTable(DataTable[Text]):
"""A DataTable for displaying quotes."""

_GAINING_COLOR: str = "#00DD00"
_LOSING_COLOR: str = "#DD0000"
_GAINING_COLOR: Final[str] = "#00DD00"
_LOSING_COLOR: Final[str] = "#DD0000"

def __init__(self, state: QuoteTableState) -> None:
super().__init__()
Expand Down
22 changes: 11 additions & 11 deletions src/appui/quote_table_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import logging
from threading import Lock, Thread
from time import monotonic, sleep
from typing import Any, Callable, Optional
from typing import Any, Callable, Final, Optional

from yfinance import YFinance, YQuote

Expand All @@ -15,16 +15,16 @@
class QuoteTableState:
"""The state of the quote table."""

_TICKER_COLUMN_KEY: str = "ticker"
_TICKER_COLUMN_KEY: Final[str] = "ticker"

# Default values
_DEFAULT_COLUMN_KEYS: list[str] = [
_DEFAULT_COLUMN_KEYS: Final[list[str]] = [
"last",
"change_percent",
"volume",
"market_cap",
]
_DEFAULT_QUOTES: list[str] = [
_DEFAULT_QUOTES: Final[list[str]] = [
"AAPL",
"F",
"VT",
Expand All @@ -34,15 +34,15 @@ class QuoteTableState:
"EURUSD=X",
"BTC-USD",
]
_DEFAULT_SORT_DIRECTION: SortDirection = SortDirection.ASCENDING
_DEFAULT_QUERY_FREQUENCY: int = 60
_DEFAULT_SORT_DIRECTION: Final[SortDirection] = SortDirection.ASCENDING
_DEFAULT_QUERY_FREQUENCY: Final[int] = 60

# Config file keys
_COLUMNS: str = "columns"
_SORT_COLUMN: str = "sort_column"
_SORT_DIRECTION: str = "sort_direction"
_QUOTES: str = "quotes"
_QUERY_FREQUENCY: str = "query_frequency"
_COLUMNS: Final[str] = "columns"
_SORT_COLUMN: Final[str] = "sort_column"
_SORT_DIRECTION: Final[str] = "sort_direction"
_QUOTES: Final[str] = "quotes"
_QUERY_FREQUENCY: Final[str] = "query_frequency"

def __init__(self, yfin: YFinance) -> None:
self._yfin: YFinance = yfin
Expand Down
14 changes: 7 additions & 7 deletions src/appui/stockyardapp_state.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""The state of the whole stockyard application."""

import logging
from typing import Any, Optional
from typing import Any, Final, Optional

from yfinance import YFinance

Expand All @@ -13,7 +13,7 @@ class StockyardAppState:
"""The state of the Stockyard app."""

# Human readable logging levels
_LOGGING_LEVELS: dict[int, str] = {
_LOGGING_LEVELS: Final[dict[int, str]] = {
logging.NOTSET: "NOTSET",
logging.DEBUG: "DEBUG",
logging.INFO: "INFO",
Expand All @@ -23,13 +23,13 @@ class StockyardAppState:
}

# Default values
_DEFAULT_LOG_LEVEL: int = logging.INFO
_DEFAULT_TIME_FORMAT: TimeFormat = TimeFormat.TWENTY_FOUR_HOUR
_DEFAULT_LOG_LEVEL: Final[int] = logging.INFO
_DEFAULT_TIME_FORMAT: Final[TimeFormat] = TimeFormat.TWENTY_FOUR_HOUR

# Config file keys
_QUOTE_TABLE: str = "quote_table"
_LOG_LEVEL: str = "log_level"
_TIME_FORMAT: str = "time_format"
_QUOTE_TABLE: Final[str] = "quote_table"
_LOG_LEVEL: Final[str] = "log_level"
_TIME_FORMAT: Final[str] = "time_format"

def __init__(self, yfin: YFinance, *, title: str = "Stockyard") -> None:
# Transient members
Expand Down
26 changes: 14 additions & 12 deletions src/yfinance/_yclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import logging
from datetime import datetime, timedelta
from http.cookiejar import Cookie
from typing import Any
from typing import Any, Final
from urllib.parse import parse_qs, urlencode, urlparse

import requests
Expand All @@ -16,17 +16,19 @@
class YClient:
"""Yahoo! Finance API client."""

_DEFAULT_HTTP_TIMEOUT: int = 80
_YAHOO_FINANCE_URL: str = "https://finance.yahoo.com"
_YAHOO_FINANCE_QUERY_URL: str = "https://query1.finance.yahoo.com"
_CRUMB_URL: str = _YAHOO_FINANCE_QUERY_URL + "/v1/test/getcrumb"
_USER_AGENT: str = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36" # noqa: E501
_USER_AGENT_CLIENT_HINT_BRANDING_AND_VERSION: str = (
'"Google Chrome";v="113", "Chromium";v="113", "Not-A.Brand";v="24"'
)
_USER_AGENT_CLIENT_HINT_PLATFORM: str = '"Windows"'

_COOKIE_HEADERS: dict[str, str] = {
_DEFAULT_HTTP_TIMEOUT: Final[int] = 80
_YAHOO_FINANCE_URL: Final[str] = "https://finance.yahoo.com"
_YAHOO_FINANCE_QUERY_URL: Final[str] = "https://query1.finance.yahoo.com"
_CRUMB_URL: Final[str] = _YAHOO_FINANCE_QUERY_URL + "/v1/test/getcrumb"
_USER_AGENT: Final[
str
] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36" # noqa: E501
_USER_AGENT_CLIENT_HINT_BRANDING_AND_VERSION: Final[
str
] = '"Google Chrome";v="113", "Chromium";v="113", "Not-A.Brand";v="24"'
_USER_AGENT_CLIENT_HINT_PLATFORM: Final[str] = '"Windows"'

_COOKIE_HEADERS: Final[dict[str, str]] = {
"authority": "finance.yahoo.com",
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", # noqa: E501
"accept-language": "en-US,en;q=0.9",
Expand Down
4 changes: 2 additions & 2 deletions src/yfinance/yfinance.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""A Python interface to the Yahoo! Finance API."""

import logging
from typing import Any
from typing import Any, Final

from ._yclient import YClient
from .yquote import YQuote
Expand All @@ -10,7 +10,7 @@
class YFinance:
"""A Python interface to the Yahoo! Finance API."""

_QUOTE_API: str = "/v7/finance/quote"
_QUOTE_API: Final[str] = "/v7/finance/quote"

def __init__(self) -> None:
self._yclient = YClient()
Expand Down
12 changes: 7 additions & 5 deletions tests/appui/test_quote_table_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import sys
from contextlib import contextmanager
from time import sleep
from typing import Any
from typing import Any, Final

import pytest

Expand All @@ -21,13 +21,15 @@
from .helpers import compare_shrunken_ints

# A number with 2 decimal values
NUMBER_RE: re.Pattern[str] = re.compile(r"^(?:-?\d+\.\d{2}|N/A)$", re.M)
NUMBER_RE: Final[re.Pattern[str]] = re.compile(r"^(?:-?\d+\.\d{2}|N/A)$", re.M)

# A percentage with 2 decimal values
PERCENT_RE: re.Pattern[str] = re.compile(r"^(?:-?\d+\.\d{2}%|N/A)$", re.M)
PERCENT_RE: Final[re.Pattern[str]] = re.compile(r"^(?:-?\d+\.\d{2}%|N/A)$", re.M)

# A shrunken int
SHRUNK_RE: re.Pattern[str] = re.compile(r"^(?:\d{1,3}(?:\.\d{2}[KMBT])?|N/A)$", re.M)
SHRUNKEN_INT_RE: Final[re.Pattern[str]] = re.compile(
r"^(?:\d{1,3}(?:\.\d{2}[KMBT])?|N/A)$", re.M
)


@pytest.fixture(name="quote_table_state")
Expand Down Expand Up @@ -342,7 +344,7 @@ def test_default_get_quotes_rows(quote_table_state: QuoteTableState):
assert row.values[0].value == quotes[i]
assert NUMBER_RE.match(row.values[1].value) # last
assert PERCENT_RE.match(row.values[2].value) # change_percent
assert SHRUNK_RE.match(row.values[3].value) # market_cap
assert SHRUNKEN_INT_RE.match(row.values[3].value) # market_cap


##############################################################################
Expand Down

0 comments on commit a61c409

Please sign in to comment.