Source code for tt.config
"""
TalkyTrader Settings, Scheduling and Logging,
🧐⏱️⚙️
"""
import logging
import os
import subprocess
import sys
import dotenv
from asyncz.schedulers.asyncio import AsyncIOScheduler
from dynaconf import Dynaconf
from loguru import logger as loguru_logger
dotenv.load_dotenv()
#######################################
### ㊙️ Secrets ###
#######################################
"""
If you use 1Password to store your settings,
you can use :file:`.secrets.toml` to retrieve and
store your settings from a notesPlain item.
more info: https://support.1password.com/command-line-getting-started/
You need the following to your :file:`.env` file:
- OP_SERVICE_ACCOUNT_TOKEN: your 1Password service account token
- OP_VAULT: your 1Password vault
- OP_ITEM: your 1Password item
- OP_PATH: your one 1Password path (optional and default value `/usr/bin/op`)
The :file:`.secrets.toml` will be located in :file:`/tt/.secrets.toml` and
be created by the OP client via `op read op://vault/item/notesPlain > .secrets.toml`
"""
if os.getenv("OP_SERVICE_ACCOUNT_TOKEN") and os.path.exists(os.getenv("OP_PATH")):
loguru_logger.debug("Using OnePassword")
command = [
os.getenv("OP_PATH"),
"read",
f"op://{os.getenv('OP_VAULT')}/{os.getenv('OP_ITEM')}/notesPlain",
]
filepath = "/app/tt/.op.toml"
with open(filepath, "w") as output_file:
subprocess.run(command, stdout=output_file)
else:
loguru_logger.debug("No OP service account found")
#######################################
### ⚙️ Settings ###
#######################################
"""
Settings are loaded via dynaconf
Dynaconf is a powerful and easy-to-use
management library for Python.
It supports TOML settings file, .env file or environment variable, and other types.
Refer to https://github.com/dynaconf/dynaconf for more information.
More than 100 settings customizable via settings.toml or .env.
Most of them are predefined and you only need to
update the credentials related to your exchange and chat platform
Config will load:
- talky default: talky_settings.toml
- default from library if the library support it: default_settings.toml
- user settings: settings.toml
- user secrets: .secrets.toml
Your settings should be setup in
settings.toml,
.secrets.toml,
.env or
environment variable.
Settings.toml or .env can be located in :file:`/app/settings.toml`
or :file:`/app/.env` for docker.
If deployed locally, place your file in :file:`/tt/` folder.
"""
ROOT = os.path.dirname(__file__)
settings = Dynaconf(
envvar_prefix="TT",
root_path=os.path.dirname(ROOT),
load_dotenv=True,
settings_files=[
# load talky default
os.path.join(ROOT, "talky_settings.toml"),
# load lib default
"default_settings.toml",
# load user default
"settings.toml",
# load user secret
".secrets.toml",
# load settings from one password vault
".op.toml",
],
environments=True,
merge_enabled=True,
default_env="default",
)
########################################
### ⏱️ Scheduling ###
########################################
"""
Scheduling is managed via asyncz lib
More info: https://github.com/tarsil/asyncz
It allows you to schedule tasks at plugin level.
Refer to the plugin documentation
:file:`tt.plugins.plugin_manager`
"""
scheduler = AsyncIOScheduler()
########################################
### 🧐 Logging ###
########################################
"""
Logging is managed via loguru
"""
[docs]
class InterceptHandler(logging.Handler):
"""
InterceptHandler is a loguru handler
that intercepts all log records.
It can be used as a replacement for logging.basicConfig()
"""
[docs]
def emit(self, record):
"""
Emit a log record.
Args:
record (logging.LogRecord): The log record to emit.
Returns:
None
"""
# Get corresponding Loguru level if it exists.
try:
level = logger.level(record.levelname).name
except ValueError:
level = record.levelno
# Find caller from where originated the logged message.
frame, depth = sys._getframe(6), 6
while frame and frame.f_code.co_filename == logging.__file__:
frame = frame.f_back
depth += 1
logger.opt(depth=depth, exception=record.exc_info).log(
level, record.getMessage()
)
[docs]
def loguru_setup():
"""
Set up the loguru logger with custom configurations.
Returns:
loguru.logger: The configured loguru logger instance.
"""
loguru_logger.remove()
log_filters = {
"discord": settings.thirdparty_lib_loglevel,
"telethon": settings.thirdparty_lib_loglevel,
"web3": settings.thirdparty_lib_loglevel,
"apprise": settings.thirdparty_lib_loglevel,
"urllib3": settings.thirdparty_lib_loglevel,
"asyncz": settings.thirdparty_lib_loglevel,
"rlp": settings.thirdparty_lib_loglevel,
"numexpr": settings.thirdparty_lib_loglevel,
}
logging.basicConfig(handlers=[InterceptHandler()], level=0, force=True)
loguru_logger.add(
sink=sys.stdout,
level=settings.loglevel,
filter=log_filters,
)
if settings.loglevel == "DEBUG":
loguru_logger.warning(
"""
DEBUG ENABLED,
You can disable it
loglevel='INFO' in settings.toml
TT_LOGLEVEL=INFO in your .env or vars.
"""
)
return loguru_logger
logger = loguru_setup()