Skip to content

Commit

Permalink
Fix loading from file not allowing reload
Browse files Browse the repository at this point in the history
  • Loading branch information
brandonscript committed Apr 8, 2024
1 parent 4d7678c commit 0fe1172
Show file tree
Hide file tree
Showing 10 changed files with 56 additions and 22 deletions.
6 changes: 3 additions & 3 deletions README.md
Expand Up @@ -4,7 +4,7 @@

Tinta is a magical console output tool with support for printing in beautiful colors and with rich formatting, like bold and underline, using static, chain-able methods. It's so pretty, it's almost like a unicorn!

![version](https://img.shields.io/badge/version-0.1.7b5-green.svg) [_![GitHub Actions Badge](https://img.shields.io/github/actions/workflow/status/brandonscript/tinta/run-tests.yml)_](https://github.com/brandonscript/tinta/actions) [_![Codacy Badge](https://app.codacy.com/project/badge/Grade/32bf3e3172cf434b914647f06569a836)_](https://www.codacy.com/gh/brandonscript/tinta/dashboard?utm_source=github.com&utm_medium=referral&utm_content=brandonscript/tinta&utm_campaign=Badge_Grade) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/tinta) ![MIT License](https://img.shields.io/github/license/brandonscript/tinta) [_![](https://img.shields.io/badge/ethical-source-%23bb8c3c?labelColor=393162)_](https://img.shields.io/badge/ethical-source-%23bb8c3c?labelColor=393162) [_![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.0-4baaaa.svg)_](code_of_conduct.md)
![version](https://img.shields.io/badge/version-0.1.7b5-post0-green.svg) [_![GitHub Actions Badge](https://img.shields.io/github/actions/workflow/status/brandonscript/tinta/run-tests.yml)_](https://github.com/brandonscript/tinta/actions) [_![Codacy Badge](https://app.codacy.com/project/badge/Grade/32bf3e3172cf434b914647f06569a836)_](https://www.codacy.com/gh/brandonscript/tinta/dashboard?utm_source=github.com&utm_medium=referral&utm_content=brandonscript/tinta&utm_campaign=Badge_Grade) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/tinta) ![MIT License](https://img.shields.io/github/license/brandonscript/tinta) [_![](https://img.shields.io/badge/ethical-source-%23bb8c3c?labelColor=393162)_](https://img.shields.io/badge/ethical-source-%23bb8c3c?labelColor=393162) [_![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.0-4baaaa.svg)_](code_of_conduct.md)

## Features and Tinta Basics

Expand Down Expand Up @@ -193,7 +193,7 @@ All "add" methods (each color and style method, `Tinta()`, `push()`, and `tint`)

- `s (str)` – A sequence of one or more text strings, to be joined together.
- `sep (str)` – Used to join segment strings. Defaults to `' '`.
> _Note: `sep` behavior has been changed in v0.1.7b5 - if passing a `sep` argument in `print()`, it will overwrite any segment's individual `sep` argument._
> _Note: `sep` behavior has been changed in v0.1.7b5-post0 - if passing a `sep` argument in `print()`, it will overwrite any segment's individual `sep` argument._
For example:

Expand Down Expand Up @@ -228,7 +228,7 @@ All `Tinta` and dynamic color methods will make available the following attribut

_See below for detailed usage and arguments._

> (Note: breaking changes in v0.1.7b5 - several methods have been renamed for better semantics).
> (Note: breaking changes in v0.1.7b5-post0 - several methods have been renamed for better semantics).
- `print()` – Prints to the console.
- `to_str() -> str` – Returns a joined text string.
Expand Down
Binary file removed dist/tinta-0.1.7b5-py2.py3-none-any.whl
Binary file not shown.
Binary file added dist/tinta-0.1.7b5.post0-py2.py3-none-any.whl
Binary file not shown.
2 changes: 1 addition & 1 deletion pyproject.toml
Expand Up @@ -21,7 +21,7 @@

[project]
name = "tinta"
version = "0.1.7b5"
version = "0.1.7b5-post0"
description = "Tinta, a magical console output tool."
authors = [{ name = "Brandon Shelley", email = "brandon@pacificaviator.co" }]
license = "MIT"
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Expand Up @@ -30,7 +30,7 @@

setup(
name="tinta",
version="0.1.7b5",
version="0.1.7b5-post0",
description="Tinta, a magical console output tool.",
long_description=long_description,
long_description_content_type="text/markdown",
Expand Down
15 changes: 15 additions & 0 deletions tests/conftest.py
Expand Up @@ -44,3 +44,18 @@ def perf(request):

if request.config.option.perf is True:
C.PERF_MEASURE = True


@pytest.fixture(scope="function", autouse=False)
def alt_colors_ini(tmp_path):

from tinta import Tinta

colors_ini = tmp_path / "colors.ini"
colors_ini.write_text("""[colors]\nsparkle = 195\ndragons_breath = 202\n""")

orig_colors_ini = Tinta._colors._colors_ini_path

Tinta.load_colors(colors_ini)
yield colors_ini
Tinta.load_colors(orig_colors_ini)
16 changes: 16 additions & 0 deletions tests/test_tinta.py
Expand Up @@ -81,6 +81,22 @@ def test_init(self):
def test_accepts_string_on_init(self):
assert Tinta("initialized").to_str() == "initialized"

def test_load_colors(self, alt_colors_ini):
# create a test colors.ini

# load the colors
Tinta.load_colors(alt_colors_ini)

assert Tinta._colors.color_dict == {"sparkle": 195, "dragons_breath": 202}
assert Tinta()._colors.color_list == ["sparkle", "dragons_breath"]

# check the colors
assert Tinta().sparkle("sparkle").to_str() == f"\x1b[38;5;195msparkle{O}"
assert (
Tinta().dragons_breath("dragon's breath").to_str()
== f"\x1b[38;5;202mdragon's breath{O}"
)


class TestBasicColorizing:

Expand Down
2 changes: 1 addition & 1 deletion tinta/__init__.py
Expand Up @@ -21,7 +21,7 @@

from logging import getLogger

__version__ = "0.1.7b5"
__version__ = "0.1.7b5-post0"

logger = getLogger(__name__)

Expand Down
30 changes: 16 additions & 14 deletions tinta/ansi.py
Expand Up @@ -31,9 +31,9 @@ def _alias_keys(colors: "Union[AnsiColors, Type[AnsiColors]]", search: str, repl
alias_key = k.replace(search.lower(), repl.lower())
if (
alias_key not in colors_ini["colors"]
and alias_key not in colors._dict_colors
and alias_key not in colors._color_dict
):
colors._dict_colors[alias_key] = int(colors_ini["colors"][k])
colors._color_dict[alias_key] = int(colors_ini["colors"][k])
colors_ini["colors"][alias_key] = colors_ini["colors"][k]


Expand Down Expand Up @@ -79,8 +79,7 @@ class AnsiColors:

_initialized = False
_colors_ini_path = None
_dict_colors: Dict[str, int] = {}
_list_colors: List[str] = []
_color_dict: Dict[str, int] = {}

def __init__(self, path: Optional[Union[str, Path]] = None):

Expand All @@ -94,8 +93,9 @@ def __init__(self, path: Optional[Union[str, Path]] = None):
def load_colors(cls, path: Union[str, Path]):
"""Loads colors from a file."""

colors_ini["colors"] = {}
colors_ini.read(path)
cls._dict_colors = {k: int(v) for (k, v) in colors_ini["colors"].items()}
cls._color_dict = {k: int(v) for (k, v) in colors_ini["colors"].items()}
# Check if any of the color names loaded match the built-in methods. If so, raise an error.
# for col in loaded_colors.keys():
# if hasattr(cls, col):
Expand Down Expand Up @@ -130,10 +130,10 @@ def get(self, color: str) -> int:
if is_ansi_str(color):
return ansi_color_to_int(color)

if color not in self._dict_colors:
if color not in self._color_dict:
raise MissingColorError(f"Color '{color}' not found in colors.ini.")

return self._dict_colors[color]
return self._color_dict[color]

def reverse_get(self, code: int, ignore_errors: bool = False) -> str:
"""Returns the color name for an ANSI code.
Expand All @@ -149,7 +149,7 @@ def reverse_get(self, code: int, ignore_errors: bool = False) -> str:
if code == 0:
return "default"

for k, v in self._dict_colors.items():
for k, v in self._color_dict.items():
if v == code:
return k

Expand All @@ -160,12 +160,14 @@ def reverse_get(self, code: int, ignore_errors: bool = False) -> str:

return "[undefined color]"

def list_colors(self) -> List[str]:
@property
def color_list(self) -> List[str]:
"""Returns a list of all colors in the colors.ini file."""
return list(self._dict_colors.keys())
return list(self.color_dict.keys())

def dict_colors(self) -> Dict[str, int]:
@property
def color_dict(self) -> Dict[str, int]:
"""Returns a dictionary of all colors in the colors.ini file."""
if not self._dict_colors:
self._dict_colors = {k: int(v) for (k, v) in colors_ini["colors"].items()}
return self._dict_colors
if not self._color_dict:
self._color_dict = {k: int(v) for (k, v) in colors_ini["colors"].items()}
return self._color_dict
5 changes: 3 additions & 2 deletions tinta/tinta.py
Expand Up @@ -56,6 +56,7 @@ def __init__(cls, name, bases, dct):

def load_colors(cls, path: Union[str, Path]):
cls._initialized = False
AnsiColors._initialized = False
cls._colors = AnsiColors(path)


Expand Down Expand Up @@ -117,7 +118,7 @@ def __init__(
"""

# Inject ANSI helper functions
for c in Tinta._colors.dict_colors():
for c in Tinta._colors.color_dict:
if hasattr(self, c) and not str(getattr(self, c)).startswith(
"functools.partial(<bound method Tinta.tint"
):
Expand Down Expand Up @@ -642,7 +643,7 @@ def __getattr__(self, name: str) -> "Tinta":
try:
return self.__getattribute__(name) # type: ignore
except AttributeError as e:
known_colors = "\n - ".join(self._colors.list_colors())
known_colors = "\n - ".join(self._colors.color_list)
known_colors = f" - {known_colors}"
raise AttributeError(
f"'{name}' not found.\nDid you try and access a color that doesn't exist? Available colors:\n{known_colors}\n"
Expand Down

0 comments on commit 0fe1172

Please sign in to comment.