|
6 | 6 |
|
7 | 7 | from .enhanced_data_table import EnhancedTableCell |
8 | 8 | from .enums import Justify |
9 | | -from .formatting import as_compact, as_float, as_percent |
| 9 | +from .formatting import ( |
| 10 | + as_bool, |
| 11 | + as_compact, |
| 12 | + as_date, |
| 13 | + as_datetime, |
| 14 | + as_enum, |
| 15 | + as_float, |
| 16 | + as_percent, |
| 17 | +) |
10 | 18 | from .quote_table import quote_column |
11 | 19 |
|
12 | 20 | if TYPE_CHECKING: |
| 21 | + from datetime import date, datetime |
| 22 | + from enum import Enum |
| 23 | + |
13 | 24 | from .quote_table import QuoteColumn |
14 | 25 |
|
15 | 26 |
|
@@ -63,13 +74,12 @@ def __init__( |
63 | 74 | """ |
64 | 75 |
|
65 | 76 | primary = value if case_sensitive else value.lower() |
66 | | - if secondary_key: |
67 | | - sort_key = ( |
68 | | - primary, |
69 | | - secondary_key if case_sensitive else secondary_key.lower(), |
70 | | - ) |
71 | | - else: |
72 | | - sort_key = (primary,) |
| 77 | + secondary = ( |
| 78 | + (secondary_key if case_sensitive else secondary_key.lower()) |
| 79 | + if secondary_key |
| 80 | + else None |
| 81 | + ) |
| 82 | + sort_key = (primary, secondary) if secondary else (primary,) |
73 | 83 | super().__init__(sort_key, value, justification, style) |
74 | 84 |
|
75 | 85 |
|
@@ -184,6 +194,127 @@ def __init__( |
184 | 194 | ) |
185 | 195 |
|
186 | 196 |
|
| 197 | +class DateCell(EnhancedTableCell): |
| 198 | + """Cell that renders date values.""" |
| 199 | + |
| 200 | + def __init__( |
| 201 | + self, |
| 202 | + value: date | None, |
| 203 | + *, |
| 204 | + date_format: str | None = None, |
| 205 | + justification: Justify = Justify.LEFT, |
| 206 | + style: str = "", |
| 207 | + secondary_key: str | None = None, |
| 208 | + ) -> None: |
| 209 | + """Initialize the date cell. |
| 210 | +
|
| 211 | + Args: |
| 212 | + value (date | None): The date value to display. |
| 213 | + date_format (str | None): Optional format override for display. |
| 214 | + justification (Justify): The text justification. |
| 215 | + style (str): The style string for the cell. |
| 216 | + secondary_key (str | None): An optional secondary string key to use for |
| 217 | + tie-breaking during sorting. |
| 218 | + """ |
| 219 | + |
| 220 | + safe_value = float("-inf") if value is None else value.toordinal() |
| 221 | + super().__init__( |
| 222 | + _with_secondary_key(safe_value, secondary_key), |
| 223 | + as_date(value, date_format), |
| 224 | + justification, |
| 225 | + style, |
| 226 | + ) |
| 227 | + |
| 228 | + |
| 229 | +class DateTimeCell(EnhancedTableCell): |
| 230 | + """Cell that renders datetime values.""" |
| 231 | + |
| 232 | + def __init__( |
| 233 | + self, |
| 234 | + value: datetime | None, |
| 235 | + *, |
| 236 | + datetime_format: str | None = None, |
| 237 | + justification: Justify = Justify.LEFT, |
| 238 | + style: str = "", |
| 239 | + secondary_key: str | None = None, |
| 240 | + ) -> None: |
| 241 | + """Initialize the datetime cell. |
| 242 | +
|
| 243 | + Args: |
| 244 | + value (datetime | None): The datetime value to display. |
| 245 | + datetime_format (str | None): Optional format override for display. |
| 246 | + justification (Justify): The text justification. |
| 247 | + style (str): The style string for the cell. |
| 248 | + secondary_key (str | None): An optional secondary string key to use for |
| 249 | + tie-breaking during sorting. |
| 250 | + """ |
| 251 | + |
| 252 | + safe_value = float("-inf") if value is None else value.timestamp() |
| 253 | + super().__init__( |
| 254 | + _with_secondary_key(safe_value, secondary_key), |
| 255 | + as_datetime(value, datetime_format), |
| 256 | + justification, |
| 257 | + style, |
| 258 | + ) |
| 259 | + |
| 260 | + |
| 261 | +class EnumCell(EnhancedTableCell): |
| 262 | + """Cell that renders enum values in title case.""" |
| 263 | + |
| 264 | + def __init__( |
| 265 | + self, |
| 266 | + value: Enum | None, |
| 267 | + *, |
| 268 | + justification: Justify = Justify.LEFT, |
| 269 | + style: str = "", |
| 270 | + secondary_key: str | None = None, |
| 271 | + ) -> None: |
| 272 | + """Initialize the enum cell. |
| 273 | +
|
| 274 | + Args: |
| 275 | + value (Enum | None): The enum value to display. |
| 276 | + justification (Justify): The text justification. |
| 277 | + style (str): The style string for the cell. |
| 278 | + secondary_key (str | None): An optional secondary string key to use for |
| 279 | + tie-breaking during sorting. |
| 280 | + """ |
| 281 | + |
| 282 | + display_value = as_enum(value) |
| 283 | + primary = display_value.lower() if value is not None else "" |
| 284 | + sort_key = (primary, secondary_key.lower()) if secondary_key else (primary,) |
| 285 | + super().__init__(sort_key, display_value, justification, style) |
| 286 | + |
| 287 | + |
| 288 | +class BooleanCell(EnhancedTableCell): |
| 289 | + """Cell that renders boolean values as checkboxes.""" |
| 290 | + |
| 291 | + def __init__( |
| 292 | + self, |
| 293 | + *, |
| 294 | + value: bool | None, |
| 295 | + justification: Justify = Justify.CENTER, |
| 296 | + style: str = "", |
| 297 | + secondary_key: str | None = None, |
| 298 | + ) -> None: |
| 299 | + """Initialize the boolean cell. |
| 300 | +
|
| 301 | + Args: |
| 302 | + value (bool | None): The boolean value to display. |
| 303 | + justification (Justify): The text justification. |
| 304 | + style (str): The style string for the cell. |
| 305 | + secondary_key (str | None): An optional secondary string key to use for |
| 306 | + tie-breaking during sorting. |
| 307 | + """ |
| 308 | + |
| 309 | + safe_value = float("-inf") if value is None else float(value) |
| 310 | + super().__init__( |
| 311 | + _with_secondary_key(safe_value, secondary_key), |
| 312 | + as_bool(value=value), |
| 313 | + justification, |
| 314 | + style, |
| 315 | + ) |
| 316 | + |
| 317 | + |
187 | 318 | def _get_style_for_value(value: float) -> str: |
188 | 319 | """Get the style string based on the sign of a value. |
189 | 320 |
|
@@ -391,6 +522,90 @@ def _get_style_for_value(value: float) -> str: |
391 | 522 | ), |
392 | 523 | ) |
393 | 524 | ), |
| 525 | + "dividend_date": ( |
| 526 | + quote_column( |
| 527 | + "Div Date", |
| 528 | + full_name="Dividend Date", |
| 529 | + width=10, |
| 530 | + key="dividend_date", |
| 531 | + justification=Justify.LEFT, |
| 532 | + cell_factory=lambda q: DateCell( |
| 533 | + q.dividend_date, |
| 534 | + justification=Justify.LEFT, |
| 535 | + secondary_key=q.symbol or "", |
| 536 | + ), |
| 537 | + ) |
| 538 | + ), |
| 539 | + "market_state": ( |
| 540 | + quote_column( |
| 541 | + "Mkt State", |
| 542 | + full_name="Market State", |
| 543 | + width=10, |
| 544 | + key="market_state", |
| 545 | + justification=Justify.LEFT, |
| 546 | + cell_factory=lambda q: EnumCell( |
| 547 | + q.market_state, |
| 548 | + justification=Justify.LEFT, |
| 549 | + secondary_key=q.symbol or "", |
| 550 | + ), |
| 551 | + ) |
| 552 | + ), |
| 553 | + "option_type": ( |
| 554 | + quote_column( |
| 555 | + "Opt Type", |
| 556 | + full_name="Option Type", |
| 557 | + width=8, |
| 558 | + key="option_type", |
| 559 | + justification=Justify.LEFT, |
| 560 | + cell_factory=lambda q: EnumCell( |
| 561 | + q.option_type, |
| 562 | + justification=Justify.LEFT, |
| 563 | + secondary_key=q.symbol or "", |
| 564 | + ), |
| 565 | + ) |
| 566 | + ), |
| 567 | + "quote_type": ( |
| 568 | + quote_column( |
| 569 | + "Type", |
| 570 | + full_name="Quote Type", |
| 571 | + width=15, |
| 572 | + key="quote_type", |
| 573 | + justification=Justify.LEFT, |
| 574 | + cell_factory=lambda q: EnumCell( |
| 575 | + q.quote_type, |
| 576 | + justification=Justify.LEFT, |
| 577 | + secondary_key=q.symbol or "", |
| 578 | + ), |
| 579 | + ) |
| 580 | + ), |
| 581 | + "tradeable": ( |
| 582 | + quote_column( |
| 583 | + "Tradeable", |
| 584 | + full_name="Tradeable", |
| 585 | + width=9, |
| 586 | + key="tradeable", |
| 587 | + justification=Justify.CENTER, |
| 588 | + cell_factory=lambda q: BooleanCell( |
| 589 | + value=q.tradeable, |
| 590 | + justification=Justify.CENTER, |
| 591 | + secondary_key=q.symbol or "", |
| 592 | + ), |
| 593 | + ) |
| 594 | + ), |
| 595 | + "post_market_datetime": ( |
| 596 | + quote_column( |
| 597 | + "Post Mkt", |
| 598 | + full_name="Post-Market Datetime", |
| 599 | + width=16, |
| 600 | + key="post_market_datetime", |
| 601 | + justification=Justify.LEFT, |
| 602 | + cell_factory=lambda q: DateTimeCell( |
| 603 | + q.post_market_datetime, |
| 604 | + justification=Justify.LEFT, |
| 605 | + secondary_key=q.symbol or "", |
| 606 | + ), |
| 607 | + ) |
| 608 | + ), |
394 | 609 | } |
395 | 610 | """ |
396 | 611 | A dictionary that contains QuoteColumns available for the quote table. |
|
0 commit comments