def test_optional_mapping_template_valid(self): config = _root({'foo': {'bar': 5, 'baz': 'bak'}}) template = {'bar': confuse.Integer(), 'baz': confuse.String()} valid = config.get({'foo': confuse.Optional(template)}) self.assertEqual(valid['foo']['bar'], 5) self.assertEqual(valid['foo']['baz'], 'bak')
def test_optional_string_missing_not_allowed(self): config = _root({}) with self.assertRaises(confuse.NotFoundError): config['foo'].get( confuse.Optional(confuse.String(), allow_missing=False))
def test_optional_string_null_missing_not_allowed(self): config = _root({'foo': None}) valid = config['foo'].get( confuse.Optional(confuse.String(), allow_missing=False)) self.assertIsNone(valid)
"wobjs": { "pick": str, "place": str }, "tools": { "pick_place": { "name": str, "io_pin_needles": str, "extend_signal": int, "retract_signal": int, "needles_pause": float, "compress_at_pick": float, }, "dist_sensor": { "name": str, "serial_port": confuse.String(default=None), "serial_baudrate": int, "max_z_adjustment": float, "adjust_loc_frames": bool, }, }, "robot_movement": { "global_speed_accel": { "speed_override": float, "speed_max_tcp": float, "accel": float, "accel_ramp": float, }, "speed": { "precise": float, "travel": float
template = { "version": optional(confuse.OneOf([str, int]), __version__), "host": str, "port": optional(int), "path": optional(confuse.Filename()), "mongo": { "url": str, "name": str, "username": optional(str), "password": optional(str), }, "interface": { "port": confuse.OneOf([confuse.String(pattern="COM\d+$"), confuse.Filename()]), "baudrate": int, "encoding": optional(str, "utf-8"), }, "manufacturer_code": confuse.String(pattern="^[a-fA-F0-9]{2}$"), "secret_key": optional(str), "max_session_age": confuse.OneOf([int, None]), "https": optional(bool, False), "sentry_dsn": optional(str), "sentry_csp_url": optional(str), "log_level": optional(str), }
def test_optional_mapping_template_allow_missing_default_value(self): config = _root({}) template = {'bar': confuse.Integer(), 'baz': confuse.String()} valid = config.get({'foo': confuse.Optional(template, {})}) self.assertIsInstance(valid['foo'], dict)
def test_optional_mapping_template_null_missing_not_allowed(self): config = _root({'foo': None}) template = {'bar': confuse.Integer(), 'baz': confuse.String()} valid = config.get( {'foo': confuse.Optional(template, allow_missing=False)}) self.assertIsNone(valid['foo'])
def test_optional_string_invalid_type(self): config = _root({'foo': 5}) with self.assertRaises(confuse.ConfigTypeError): config['foo'].get(confuse.Optional(confuse.String()))
def test_optional_string_null(self): config = _root({'foo': None}) valid = config['foo'].get(confuse.Optional(confuse.String())) self.assertIsNone(valid)
import confuse _config = confuse.Configuration('traktor_ice', __name__) _template = { 'icecast': { 'source': { 'user': confuse.String(default='source'), 'password': confuse.String(default='hackme'), }, 'admin': { 'user': confuse.String(default='admin'), 'password': confuse.String(default='hackme'), }, 'port': confuse.Integer(default=8000), 'server': confuse.String(default='localhost'), }, 'stream': { 'title': confuse.String(default='Stream Title'), 'description': confuse.String(default='Stream description'), 'genre': confuse.String(default='Stream Genre'), 'url': confuse.String(default='http://localhost'), }, 'traktor': { 'recordings-path': confuse.Path(), 'recordings-extension': confuse.String(default='wav') }, 'nowplaying': { 'port': confuse.Integer(default=8001) } }
def test_optional_string_valid_type(self): config = _root({'foo': 'bar'}) valid = config['foo'].get(confuse.Optional(confuse.String())) self.assertEqual(valid, 'bar')
class Config: template = { 'twitter': { 'consumer_key': confuse.String(), 'consumer_secret': confuse.String(), 'access_token_key': confuse.String(), 'access_token_secret': confuse.String(), 'min_ratelimit_percent': confuse.Integer(), 'search': { 'queries': confuse.TypeTemplate(list), 'max_queue': confuse.Integer(), 'max_quote_depth': confuse.Integer(), 'min_quote_similarity': confuse.Number(), 'skip_retweeted': confuse.TypeTemplate(bool), 'filter': { 'min_retweets': { 'enabled': confuse.TypeTemplate(bool), 'number': confuse.Integer() } }, 'sort': { 'by_keywords': { 'enabled': confuse.TypeTemplate(bool), 'keywords': confuse.StrSeq() }, 'by_age': { 'enabled': confuse.TypeTemplate(bool), }, 'by_retweets_count': { 'enabled': confuse.TypeTemplate(bool), } } }, 'actions': { 'follow': { 'enabled': confuse.TypeTemplate(bool), 'keywords': confuse.StrSeq(), 'max_following': confuse.Integer(), 'multiple': confuse.TypeTemplate(bool) }, 'favorite': { 'enabled': confuse.TypeTemplate(bool), 'keywords': confuse.StrSeq() }, 'tag_friend': { 'enabled': confuse.TypeTemplate(bool), 'friends': confuse.StrSeq(), } }, 'scheduler': { 'search_interval': confuse.Integer(), 'retweet_interval': confuse.Integer(), 'retweet_random_margin': confuse.Integer(), 'blocked_users_update_interval': confuse.Integer(), 'clear_queue_interval': confuse.Integer(), 'rate_limit_update_interval': confuse.Integer(), 'check_mentions_interval': confuse.Integer(), }, }, 'notifiers': { 'mail': { 'enabled': confuse.TypeTemplate(bool), 'host': confuse.String(), 'port': confuse.Integer(), 'tls': confuse.TypeTemplate(bool), 'username': confuse.String(), 'password': confuse.String(), 'recipient': confuse.String() }, 'pushbullet': { 'enabled': confuse.TypeTemplate(bool), 'token': confuse.String() } } } _valid = None @staticmethod def get(): """ Gets the static config object :return: """ if Config._valid is None: raise ValueError("Configuration not loaded") return Config._valid @staticmethod def load(filename=None): """ Loads a file and imports the settings :param filename: the file to import """ config = confuse.LazyConfig('Yatcobot', __name__) # Add default config when in egg (using this way because egg is breaking the default way) if len(config.sources) == 0: default_config_text = pkg_resources.resource_string("yatcobot", "config_default.yaml") default_config = confuse.ConfigSource(yaml.load(default_config_text, Loader=confuse.Loader), 'pkg/config_default.yaml', True) config.add(default_config) # Add user specified config if filename is not None and os.path.isfile(filename): config.set_file(filename) logger.info('Loading config files (From highest priority to lowest):') for i, config_source in enumerate(config.sources): logger.info('{}: Path: {}'.format(i, config_source.filename)) Config._valid = config.get(Config.template)
import os import sys from pathlib import Path import confuse from ncrt.utils import wsl from ncrt.utils.platform import Platform _template = { 'sessions_path': confuse.String(default=( Platform.get() == Platform.POSIX and f"{Path.home()}/.vandyke/SecureCRT/Config/Sessions" or Platform.get() == Platform.WSL and f"{wsl.win_env('APPDATA', wsl_path=True)}\\VanDyke\\Config\\Sessions" or Platform.get() == Platform.WIN and f"{os.environ['APPDATA']}\\VanDyke\\Config\\Sessions" or confuse.REQUIRED )) } _config = confuse.LazyConfig('ncrt', __name__) def config(template=None): if template is None: template = _template return _config.get(template) def ensure_valid(template=None): try: config(template) except confuse.ConfigError as err:
template = { "version": optional(confuse.OneOf([str, int]), __version__), "host": str, "port": optional(int), "path": optional(confuse.Filename()), "mongo": { "url": str, "name": str, "username": optional(str), "password": optional(str), }, "interface": { "port": confuse.OneOf([confuse.String(pattern="COM\\d+$"), confuse.Filename()]), "baudrate": int, "encoding": optional(str, "utf-8"), }, "manufacturer_code": confuse.StrSeq(), "secret_key": optional(str), "max_session_age": confuse.OneOf([int, None]), "https": optional(bool, False), "sentry_dsn": optional(str), "sentry_csp_url": optional(str), "log_level": optional(str), }
def test_optional_mapping_template_invalid(self): config = _root({'foo': {'bar': 5, 'baz': 10}}) template = {'bar': confuse.Integer(), 'baz': confuse.String()} with self.assertRaises(confuse.ConfigTypeError): config.get({'foo': confuse.Optional(template)})
def test_optional_string_null_string_provides_default(self): config = _root({'foo': None}) valid = config['foo'].get(confuse.Optional(confuse.String('baz'))) self.assertEqual(valid, 'baz')
def test_optional_mapping_template_allow_missing_no_explicit_default(self): config = _root({}) template = {'bar': confuse.Integer(), 'baz': confuse.String()} valid = config.get({'foo': confuse.Optional(template)}) self.assertIsNone(valid['foo'])
def test_optional_string_null_string_default_override(self): config = _root({'foo': None}) valid = config['foo'].get( confuse.Optional(confuse.String('baz'), default='bar')) self.assertEqual(valid, 'bar')
def test_optional_mapping_template_missing_not_allowed(self): config = _root({}) template = {'bar': confuse.Integer(), 'baz': confuse.String()} with self.assertRaises(confuse.NotFoundError): config.get( {'foo': confuse.Optional(template, allow_missing=False)})
def test_optional_string_allow_missing_no_explicit_default(self): config = _root({}) valid = config['foo'].get(confuse.Optional(confuse.String())) self.assertIsNone(valid)
class PlexMon(WebInterfaceMon): name = "plex" exclude_import = False URL = "http://{ip}:{port}" STATES = {"stopped": 0, "paused": 1, "buffering": 1, "playing": 2} CONFIG_TEMPLATE = { "ip": confuse.String(default="localhost"), "port": confuse.String(default="32400"), "poll_interval": confuse.Number(default=10), "scrobble_user": confuse.String(default="") } def __init__(self, scrobble_queue): try: self.token = get_token() self.URL = self.URL.format(**self.config) except KeyError: logger.exception("Check config for correct Plex params.") return if not self.token: logger.error("Unable to retrieve plex token.") return super().__init__(scrobble_queue) self.sess.headers["Accept"] = "application/json" self.sess.headers["X-Plex-Token"] = self.token self.session_url = self.URL + "/status/sessions" self.media_info_cache = {} def get_data(self, url): resp = self.sess.get(url) # TODO: If we get a 401, clear token and restart plex auth flow resp.raise_for_status() data = resp.json()["MediaContainer"] if data["size"] <= 0: return None # no user filter if not self.config["scrobble_user"] or "User" not in data["Metadata"][ 0]: return data["Metadata"][0] for metadata in data["Metadata"]: if metadata["User"]["title"] == self.config["scrobble_user"]: return metadata def update_status(self): status_data = self.get_data(self.session_url) if not status_data: self.status = {} return self.status["duration"] = int(status_data["duration"]) / 1000 self.status["position"] = int(status_data["viewOffset"]) / 1000 self.status["state"] = self.STATES.get(status_data["Player"]["state"], 0) self.status["media_info"] = self.get_media_info(status_data) def get_media_info(self, status_data): media_info = self.media_info_cache.get(status_data["ratingKey"]) if not media_info: if status_data["type"] == "episode": # get the show's data show_key = status_data["grandparentKey"] show_data = self.media_info_cache.get(show_key) if not show_data: show_data = self.get_data(self.URL + show_key) self.media_info_cache[show_key] = show_data else: show_data = None media_info = self._get_media_info(status_data, show_data) self.media_info_cache[status_data["ratingKey"]] = media_info return media_info @staticmethod def _get_media_info(status_data, show_data=None): if status_data["type"] == "movie": info = { "type": "movie", "title": status_data["title"], "year": status_data.get("year"), } elif status_data["type"] == "episode": info = { "type": "episode", "title": status_data["grandparentTitle"], "season": status_data["parentIndex"], "episode": status_data["index"], "year": show_data and show_data.get("year"), } else: logger.warning(f"Unknown media type {status_data['type']}") return None if info["year"] is not None: info["year"] = year = int(info["year"]) # if year is at the end of the title, like "The Boys (2019)", remove it # otherwise it might not show up on Trakt search suffix = f" ({year})" if info["title"].endswith(suffix): info["title"] = info["title"].replace(suffix, "") return cleanup_guess(info)
def test_optional_string_allow_missing_default_value(self): config = _root({}) valid = config['foo'].get(confuse.Optional(confuse.String(), 'baz')) self.assertEqual(valid, 'baz')
class PlexMon(WebInterfaceMon): name = "plex" exclude_import = False URL = "http://{ip}:{port}" STATES = {"stopped": 0, "paused": 1, "buffering": 1, "playing": 2} CONFIG_TEMPLATE = { "ip": confuse.String(default="localhost"), "port": confuse.String(default="32400"), "poll_interval": confuse.Number(default=10), } def __init__(self, scrobble_queue): try: self.token = get_token() self.URL = self.URL.format(**self.config) except KeyError: logger.exception("Check config for correct Plex params.") return if not self.token: logger.error("Unable to retrieve plex token.") return super().__init__(scrobble_queue) self.sess.headers["Accept"] = "application/json" self.sess.headers["X-Plex-Token"] = self.token self.session_url = self.URL + "/status/sessions" self.media_info_cache = {} def get_data(self, url): data = self.sess.get(url).json()["MediaContainer"] if data["size"] > 0: return data["Metadata"][0] def update_status(self): status_data = self.get_data(self.session_url) if not status_data: self.status = {} return self.status["duration"] = int(status_data["duration"]) / 1000 self.status["position"] = int(status_data["viewOffset"]) / 1000 self.status["state"] = self.STATES.get(status_data["Player"]["state"], 0) self.status["media_info"] = self.get_media_info(status_data) def get_media_info(self, status_data): media_info = self.media_info_cache.get(status_data["ratingKey"]) if not media_info: media_info = self._get_media_info(status_data) self.media_info_cache[status_data["ratingKey"]] = media_info return media_info @staticmethod def _get_media_info(status_data): if status_data["type"] == "movie": return {"type": "movie", "title": status_data["title"]} elif status_data["type"] == "episode": return { "type": "episode", "title": status_data["grandparentTitle"], "season": status_data["parentIndex"], "episode": status_data["index"], }
import logging import os import shutil import urllib.parse import confuse import git APP_NAME = 'forksync' CONFIG_TEMPLATE = { 'ssh_key': confuse.Filename(), 'cache_dir': confuse.Filename(default='/cache'), 'log_level': confuse.String(default='INFO'), 'repositories': confuse.Sequence({ 'origin': confuse.String(), 'upstream': confuse.String() }) } logging.basicConfig( level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') logger = logging.getLogger(APP_NAME) def fix_https_url(url): scheme, netloc, path, query, fragment = urllib.parse.urlsplit(url) scheme = 'ssh'