wuenlp_tools.keys.lazykeys

 1import json
 2import os
 3from collections import UserString
 4
 5from wuenlp_tools.utils import _UserPath
 6
 7KEYS_PATH = _UserPath.home() / ".local/share/wuenlp-tools" / "keys.json"
 8
 9
10def read_keys():
11    """Read keys from the JSON file. Returns an empty dict if the file doesn't exist or is corrupted."""
12    if os.path.isfile(KEYS_PATH):
13        try:
14            with open(KEYS_PATH, "r") as f:
15                return json.load(f)
16        except json.JSONDecodeError:
17            return {}
18    return {}
19
20
21def write_keys(keys):
22    """Write the keys dictionary to the JSON file."""
23    os.makedirs(os.path.dirname(KEYS_PATH), exist_ok=True)
24    with open(KEYS_PATH, "w") as f:
25        json.dump(keys, f, indent=2)
26
27
28def get_api_key(key_name):
29    """
30    Get an API key by name from the file.
31    If not present, prompt the user and store it.
32    """
33    keys = read_keys()
34    if key_name in keys:
35        return keys[key_name]
36    else:
37        key_value = input(f"Please enter the API key for {key_name}: ").strip()
38        keys[key_name] = key_value
39        write_keys(keys)
40        return key_value
41
42
43class LazyKey(UserString):
44    """
45    A lazy-loading key that behaves like a string using UserString.
46
47    The actual API key is only requested (and cached) when the underlying data is accessed.
48    """
49
50    def __init__(self, key_name):
51        self.key_name = key_name
52        self._loaded = False
53        self._data = None  # _data will hold the actual key value
54        # We intentionally initialize the UserString with an empty string.
55        super().__init__("")
56
57    @property
58    def data(self):
59        """Load and cache the data on first access."""
60        if not self._loaded:
61            self._data = get_api_key(self.key_name)
62            self._loaded = True
63        return self._data
64
65    @data.setter
66    def data(self, value):
67        self._data = value
68
69    def __str__(self):
70        return self.data
71
72    def __repr__(self):
73        # Never include the secret in repr (pdoc and logs would leak it).
74        return f"LazyKey({self.key_name!r})"
75
76    # UserString uses self.data for many of its operations, so we simply return the loaded data.
77    def __add__(self, other):
78        return self.data + other
79
80    def __radd__(self, other):
81        return other + self.data
KEYS_PATH = PosixPath('~/.local/share/wuenlp-tools/keys.json')

Path whose repr uses ~ instead of the expanded home directory.

def read_keys():
11def read_keys():
12    """Read keys from the JSON file. Returns an empty dict if the file doesn't exist or is corrupted."""
13    if os.path.isfile(KEYS_PATH):
14        try:
15            with open(KEYS_PATH, "r") as f:
16                return json.load(f)
17        except json.JSONDecodeError:
18            return {}
19    return {}

Read keys from the JSON file. Returns an empty dict if the file doesn't exist or is corrupted.

def write_keys(keys):
22def write_keys(keys):
23    """Write the keys dictionary to the JSON file."""
24    os.makedirs(os.path.dirname(KEYS_PATH), exist_ok=True)
25    with open(KEYS_PATH, "w") as f:
26        json.dump(keys, f, indent=2)

Write the keys dictionary to the JSON file.

def get_api_key(key_name):
29def get_api_key(key_name):
30    """
31    Get an API key by name from the file.
32    If not present, prompt the user and store it.
33    """
34    keys = read_keys()
35    if key_name in keys:
36        return keys[key_name]
37    else:
38        key_value = input(f"Please enter the API key for {key_name}: ").strip()
39        keys[key_name] = key_value
40        write_keys(keys)
41        return key_value

Get an API key by name from the file. If not present, prompt the user and store it.

class LazyKey(collections.UserString):
44class LazyKey(UserString):
45    """
46    A lazy-loading key that behaves like a string using UserString.
47
48    The actual API key is only requested (and cached) when the underlying data is accessed.
49    """
50
51    def __init__(self, key_name):
52        self.key_name = key_name
53        self._loaded = False
54        self._data = None  # _data will hold the actual key value
55        # We intentionally initialize the UserString with an empty string.
56        super().__init__("")
57
58    @property
59    def data(self):
60        """Load and cache the data on first access."""
61        if not self._loaded:
62            self._data = get_api_key(self.key_name)
63            self._loaded = True
64        return self._data
65
66    @data.setter
67    def data(self, value):
68        self._data = value
69
70    def __str__(self):
71        return self.data
72
73    def __repr__(self):
74        # Never include the secret in repr (pdoc and logs would leak it).
75        return f"LazyKey({self.key_name!r})"
76
77    # UserString uses self.data for many of its operations, so we simply return the loaded data.
78    def __add__(self, other):
79        return self.data + other
80
81    def __radd__(self, other):
82        return other + self.data

A lazy-loading key that behaves like a string using UserString.

The actual API key is only requested (and cached) when the underlying data is accessed.

LazyKey(key_name)
51    def __init__(self, key_name):
52        self.key_name = key_name
53        self._loaded = False
54        self._data = None  # _data will hold the actual key value
55        # We intentionally initialize the UserString with an empty string.
56        super().__init__("")
key_name
data
58    @property
59    def data(self):
60        """Load and cache the data on first access."""
61        if not self._loaded:
62            self._data = get_api_key(self.key_name)
63            self._loaded = True
64        return self._data

Load and cache the data on first access.