Source code for flexget.components.variables.variables
import os
from datetime import datetime
import yaml
from jinja2 import TemplateError
from jinja2.nativetypes import NativeEnvironment
from loguru import logger
from sqlalchemy import Column
from sqlalchemy.sql.sqltypes import DateTime, Integer, Unicode
from flexget import db_schema
from flexget.config_schema import register_config_key
from flexget.event import event
from flexget.manager import Session
from flexget.plugin import PluginError
from flexget.utils.database import json_synonym
from flexget.utils.template import get_filters
logger = logger.bind(name='variables')
DB_VERSION = 0
Base = db_schema.versioned_base('variables', DB_VERSION)
[docs]
class Variables(Base):
__tablename__ = 'variables'
id = Column(Integer, primary_key=True)
_variables = Column('variables', Unicode)
variables = json_synonym('_variables')
added = Column(DateTime, default=datetime.now)
[docs]
def variables_from_file(config_base, filename):
variables_file = os.path.join(config_base, filename)
if not os.path.exists(variables_file):
raise PluginError(f'File {variables_file} does not exist!')
try:
with open(variables_file, 'rb') as f:
variables_dict = yaml.safe_load(f.read())
except yaml.YAMLError as e:
raise PluginError(f'Invalid variables file: {e}')
return variables_dict or {}
[docs]
def variables_from_db():
with Session() as session:
variables = session.query(Variables).first()
if variables:
return variables.variables
return {}
[docs]
def variables_to_db(variables_dict):
with Session() as session:
variables = session.query(Variables).first()
if not variables:
variables = Variables()
variables.variables = variables_dict
session.merge(variables)
[docs]
@event('manager.before_config_validate')
def process_variables(config, manager):
"""Render all string elements of the config against defined variables."""
env_params = {
'block_start_string': '^^disabled^^',
'block_end_string': '^^disabled^^',
'variable_start_string': '{?',
'variable_end_string': '?}',
}
if 'variables' not in config or config.get('variables') is False:
return None
env = NativeEnvironment(**env_params)
env.filters.update(get_filters())
if isinstance(config['variables'], bool):
logger.debug('trying to load variables from DB')
variables = variables_from_db()
elif isinstance(config['variables'], dict):
logger.debug('loading variables from config')
variables = config['variables']
else:
logger.debug('trying to load variables from file')
variables = variables_from_file(manager.config_base, config['variables'])
logger.debug('updating DB with variable file contents')
variables_to_db(variables)
env.globals = variables
_process(config, env)
return config
[docs]
def _process(element, environment):
if isinstance(element, dict):
for k, v in list(element.items()):
new_key = _process(k, environment)
if new_key:
element[new_key] = element.pop(k)
k = new_key
val = _process(v, environment)
if val:
element[k] = val
return None
if isinstance(element, list):
for i, v in enumerate(element):
val = _process(v, environment)
if val:
element[i] = val
return None
if isinstance(element, str) and '{?' in element:
try:
template = environment.from_string(element)
return template.render()
except (TemplateError, TypeError):
return None
return None
variables_config_schema = {'type': ['string', 'boolean', 'object']}
[docs]
@event('config.register')
def register_config():
register_config_key('variables', variables_config_schema)