def get_config_object(self): if self.args.config is not None: return Config(os.path.abspath(self.args.config)) else: return Config( os.path.join('../../../../TestFramework/', Config.DEFAULT_CONFIG_FILE))
def handle_enabled(user): if request.method == 'GET': return format_return(Config.get_enabled()) elif request.method == 'PUT': return format_return(Config.put_enabled(request.get_json())) else: return 'access to that route not allowed', 204
def handle_helpers(user, helper): if request.method == 'GET': return format_return(Config.get_helper(helper)) elif request.method == 'PUT': return format_return(Config.put_helper(helper, request.get_json())) elif request.method == 'DELETE': return format_return(Config.delete_helper(helper)) else: return 'access to that service not allowed', 204
def handle_thing(user, thing): if request.method == 'GET': return format_return(Config.get_thing(thing)) elif request.method == 'PUT': return format_return(Config.put_thing(thing, request.get_json())) elif request.method == 'DELETE': return format_return(Config.delete_thing(thing)) else: return 'access to that service not allowed', 204
def __init__(self, host: str, port: int): self._root = dirname(__file__) self._app = Quart(__name__) self._debug = False self._host = host self._port = port self._domain = f"http://{host}:{port}" self._agent = Agent() self._config = Config() self._proxy = RequestProxy()
def __init__(self): # Anime self._config = Config() self._anime_searchers: Dict[str, AnimeSearcher] = {} self._anime_detail_parsers: Dict[str, AnimeDetailParser] = {} self._anime_url_parsers: Dict[str, AnimeUrlParser] = {} self._anime_proxy_cls: Dict[str, Type[StreamProxy]] = {} # Danmaku self._danmaku_searchers: Dict[str, DanmakuSearcher] = {} self._danmaku_detail_parsers: Dict[str, DanmakuDetailParser] = {} self._danmaku_data_parsers: Dict[str, DanmakuDataParser] = {} for module in self._config.get_enabled_modules(): self.load_full_module(module)
def test_connection(): """AWS Cognito Connection test.""" _config = Config() test_connection = boto3.client( _config.AWS_SERVICE, aws_access_key_id=_config.AWS_ACCESS_KEY_ID, aws_secret_access_key=_config.AWS_SECRET_ACCESS_KEY, region_name=_config.AWS_REGION_NAME)
def main() -> None: """Application entrypoint.""" config = Config.load_config() app = init_app(config) web.run_app(app)
def __init__(self, channel, message, config: Config): self.channel = channel channel_url = config.slack_channel(channel) if not channel_url: raise HTTPException( status_code=501, detail=f"No slack channel '{channel}' configured" ) self.channel_url = channel_url self.message = message
def __init__(self): self._scheduler = Scheduler() self._bangumi = Bangumi() self._config = Config() # Memory Database for cache self._anime_db = CacheDB() self._danmaku_db = CacheDB() self._proxy_db = CacheDB() self._others_db = CacheDB()
def main() -> None: """Start the API for controlling mitmproxy.""" if sys.version_info < (3, 6): sys.exit("Python >= 3.6 required") config = Config(parse_args()) flow = Flow(config) proxy = Proxy(flow) http = Server(proxy) http.start()
def test_builder(self) -> None: self.assertIsInstance(Config(_EXAMPLE_CONFIG), Config) self.temp_config.write_text(_NOT_A_CONFIG) self.assertRaises(config.exception.InvalidConfiguration, Config._build, self.temp_config) self.temp_config.write_text(_BAD_YAML) self.assertRaises(config.exception.InvalidConfiguration, Config._build, self.temp_config)
def test_validator(self) -> None: self.assertTrue(Config(_EXAMPLE_CONFIG)._is_valid) self.temp_config.write_text(_ADDED_INFO_CONFIG) self.assertTrue(Config(self.temp_config)._is_valid) self.temp_config.write_text(_SCALAR_LIST_CONFIG) self.assertRaises(config.exception.InvalidSemantics, Config, self.temp_config) self.temp_config.write_text(_INCORRECT_TYPE_CONFIG) self.assertRaises(config.exception.InvalidSemantics, Config, self.temp_config) self.temp_config.write_text(_MISSING_KEY_CONFIG) self.assertRaises(config.exception.InvalidSemantics, Config, self.temp_config) self.temp_config.write_text(_MISSING_OPTIONAL_CONFIG) self.assertTrue((c := Config(self.temp_config))._is_valid) self.assertEqual(c.email.smtp.port, 25) self.temp_config.write_text(_MISSING_DELETION_LIMBO)
def aws_config(providers: dict): test = config.TEST_CONFIG config.TEST_CONFIG = True cfg = Config( providers={ "aws": dict( access_key_id="access", secret_access_key="secret", region="region", **providers, ) }, topics=[], boto=MockBoto(), ) config.TEST_CONFIG = test return cfg
def app(): """ Set up global app for functional tests """ class Response(APIResponse): @cached_property def json(self): return json.loads(self.data) class APIClient(FlaskClient): def open(self, *args, **kwargs): if 'json' in kwargs: kwargs['data'] = json.dumps(kwargs.pop('json')) kwargs['content_type'] = 'application/json' return super(APIClient, self).open(*args, **kwargs) _config = Config() app = create_app(_config) app.response_class = Response app.test_client_class = APIClient app.testing = True return app
def test_example_config(self) -> None: # NOTE This is coupled to eg/.vaultrc # Any changes there must be reflected in these tests config = Config(_EXAMPLE_CONFIG) self.assertEqual(config.identity.ldap.host, "ldap.example.com") self.assertEqual(config.identity.ldap.port, 389) self.assertEqual(config.identity.users.dn, "ou=users,dc=example,dc=com") self.assertEqual(config.identity.users.attributes.uid, "uidNumber") self.assertEqual(config.identity.users.attributes.name, "cn") self.assertEqual(config.identity.users.attributes.email, "mail") self.assertEqual(config.identity.groups.dn, "ou=groups,dc=example,dc=com") self.assertEqual(config.identity.groups.attributes.gid, "gidNumber") self.assertEqual(config.identity.groups.attributes.owners, "owner") self.assertEqual(config.identity.groups.attributes.members, "member") self.assertEqual(config.persistence.postgres.host, "postgres.example.com") self.assertEqual(config.persistence.postgres.port, 5432) self.assertEqual(config.persistence.database, "sandman") self.assertEqual(config.persistence.user, "a_db_user") self.assertEqual(config.persistence.password, "abc123") self.assertEqual(config.email.smtp.host, "mail.example.com") self.assertEqual(config.email.smtp.port, 25) self.assertEqual(config.email.sender, "*****@*****.**") self.assertEqual(config.deletion.threshold, time.delta(days=90)) self.assertEqual(config.deletion.warnings, [time.delta( days=10), time.delta(days=3), time.delta(days=1)]) self.assertEqual(config.deletion.limbo, time.delta(days=14)) self.assertEqual(config.archive.threshold, 1000) self.assertEqual(config.archive.handler, T.Path("/path/to/executable"))
def app(): """ Set up global app for functional testing """ class Response(APIResponse): @cached_property def json(self): return json.loads(self.data) class APIClient(FlaskClient): def open(self, *args, **kwargs): if 'json' in kwargs: kwargs['data'] = json.dumps(kwargs.pop('json')) kwargs['content_type'] = 'application/json' return super(APIClient, self).open(*args, **kwargs) _config = Config() app = create_app(_config) app.response_class = Response app.test_client_class = APIClient app.testing = True disconnect() # Disconnets the previous connection with MongoDB connect('mockDB', host='mongomock://localhost') # MongoDB mock connection return app
def topic( topic_name: str, config: Config = Depends(get_config), message=Depends(message), ): topic = config.topic(topic_name) if not topic: raise HTTPException( status_code=501, detail=f"No topic '{topic_name}' configured" ) for provider, params in topic.params(message): if provider == Provider.SLACK: SlackMessage(**params, config=config).send() elif provider == Provider.DISCORD: DiscordMessage(**params, config=config).send() elif provider == Provider.TWILIO: TwilioMessage(**params, config=config).send() elif provider == Provider.SNS: SnsMessage(**params, config=config).send() else: raise HTTPException( status_code=400, detail=f"Unsupported provider '{provider}'" ) return f"Sent {message} to topic '{topic_name}'"
You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/ """ import unittest from unittest.mock import patch import core.idm from core import typing as T from api.config import Config from api.idm.idm import LDAPIdentityManager, LDAPUser, LDAPGroup from api.idm.ldap import NoResultsFound # NOTE This ties our tests to the example configuration _EXAMPLE_CONFIG = Config(T.Path("eg/.vaultrc")).identity def _DUMMY_PWUID(uid): # Dummy passwd interface, that acts as an identity function return T.SimpleNamespace(pw_uid=uid) def _DUMMY_GRGID(gid): # Dummy group interface, that acts as an identity function return T.SimpleNamespace(gr_name="foo", gr_gid=gid) def _DUMMY_PWNAM(username): # Dummy passwd-by-username interface: Take the bottom 10-bits from # the hash of the username string as the user ID
import pytest import requests from api.config import Config from api.providers import discord test_config = Config( providers={"discord": { "channels": { "alerts": "fake-webhook" } }}, topics=[]) def test_discord_message(): discord_message = discord.DiscordMessage(channel="alerts", message="test message", config=test_config) discord_message.send() assert True
class ModuleLoader(object): """ 模块加载器, 负责动态加载/卸载各个模块 """ def __init__(self): # Anime self._config = Config() self._anime_searchers: Dict[str, AnimeSearcher] = {} self._anime_detail_parsers: Dict[str, AnimeDetailParser] = {} self._anime_url_parsers: Dict[str, AnimeUrlParser] = {} self._anime_proxy_cls: Dict[str, Type[StreamProxy]] = {} # Danmaku self._danmaku_searchers: Dict[str, DanmakuSearcher] = {} self._danmaku_detail_parsers: Dict[str, DanmakuDetailParser] = {} self._danmaku_data_parsers: Dict[str, DanmakuDataParser] = {} for module in self._config.get_enabled_modules(): self.load_full_module(module) def load_full_module(self, module: str): """ 加载模块中所以的类 :param module: 引擎引擎模块名, api.xxx.xxx """ self.load_search_module(module) self.load_utils_module(module) def load_search_module(self, module: str): """ 只加载搜索引擎模块, 用于搜索资源 """ py_module = import_module(module) for name, cls in getmembers(py_module, isclass): if issubclass(cls, AnimeSearcher) and cls != AnimeSearcher \ and module not in self._anime_searchers: self._anime_searchers[module] = cls( ) # 创建 Searcher 对象, 程序执行期间一直使用 logger.info(f"Loading {name}: {cls}") if issubclass(cls, DanmakuSearcher) and cls != DanmakuSearcher \ and module not in self._danmaku_searchers: self._danmaku_searchers[module] = cls() logger.info(f"Loading {name}: {cls}") def load_utils_module(self, module: str): """ 只加载工具模块, 用于资源数据的解析 """ py_module = import_module(module) for name, cls in getmembers(py_module, isclass): if issubclass(cls, AnimeDetailParser) and cls != AnimeDetailParser \ and module not in self._anime_detail_parsers: self._anime_detail_parsers[module] = cls() logger.info(f"Loading {name}: {cls}") if issubclass(cls, AnimeUrlParser) and cls != AnimeUrlParser \ and module not in self._anime_url_parsers: self._anime_url_parsers[module] = cls() logger.info(f"Loading {name}: {cls}") if issubclass(cls, StreamProxy) and cls != StreamProxy \ and module not in self._anime_proxy_cls: self._anime_proxy_cls[module] = cls # 只加载 class, 动态创建 logger.info(f"Loading {name}: {cls}") if issubclass(cls, DanmakuDetailParser) and cls != DanmakuDetailParser \ and module not in self._danmaku_detail_parsers: self._danmaku_detail_parsers[module] = cls() logger.info(f"Loading {name}: {cls}") if issubclass(cls, DanmakuDataParser) and cls != DanmakuDataParser \ and module not in self._danmaku_data_parsers: self._danmaku_data_parsers[module] = cls() logger.info(f"Loading {name}: {cls}") def unload_full_module(self, module: str) -> None: """卸载模块名对应的引擎""" if module.startswith("api.anime"): self._anime_searchers.pop(module, None) self._anime_detail_parsers.pop(module, None) self._anime_url_parsers.pop(module, None) self._anime_proxy_cls.pop(module, None) if module.startswith("api.danmaku"): self._danmaku_searchers.pop(module, None) self._danmaku_detail_parsers.pop(module, None) self._danmaku_data_parsers.pop(module, None) logger.info(f"Unloaded <module {module}>") def change_module_state(self, module: str, enable: bool) -> bool: """动态加载/卸载引擎, 并更新配置文件""" if enable: # 加载引擎 self.load_full_module(module) return self._config.update_module_state(module, True) else: # 卸载引擎 self.unload_full_module(module) return self._config.update_module_state(module, False) def get_anime_searchers(self) -> List[AnimeSearcher]: return list(self._anime_searchers.values()) def get_anime_detail_parser(self, module: str) -> Optional[AnimeDetailParser]: return self._anime_detail_parsers.get(module) def get_anime_url_parser(self, module: str) -> AnimeUrlParser: return self._anime_url_parsers.get( module) or AnimeUrlParser() # 没有就有默认的 def get_anime_proxy_class(self, module: str) -> Type[StreamProxy]: return self._anime_proxy_cls.get(module) or StreamProxy def get_danmaku_searcher(self) -> List[DanmakuSearcher]: return list(self._danmaku_searchers.values()) def get_danmaku_detail_parser( self, module: str) -> Optional[DanmakuDetailParser]: return self._danmaku_detail_parsers.get(module) def get_danmaku_data_parser(self, module: str) -> Optional[DanmakuDataParser]: return self._danmaku_data_parsers.get(module)
class APIRouter: def __init__(self, host: str, port: int): self._root = dirname(__file__) self._app = Quart(__name__) self._debug = False self._host = host self._port = port self._domain = f"http://{host}:{port}" self._agent = Agent() self._config = Config() self._proxy = RequestProxy() self._stats = Statistics() def set_domain(self, domain: str): """ 设置 API 返回的资源链接的域名, 域名含协议头不含端口号 如: http://www.foo.bar """ self._domain = f"{domain}:{self._port}" if domain else self._domain def run(self): """启动 API 解析服务""" def exception_handler(_loop, context): logger.debug(context) self._init_routers() # 为了解决事件循环内部出现的异常 if os.name == "nt": asyncio.set_event_loop_policy( asyncio.WindowsSelectorEventLoopPolicy()) loop = asyncio.new_event_loop() loop.set_exception_handler(exception_handler) asyncio.set_event_loop(loop) self._app.run(host=self._host, port=self._port, debug=False, use_reloader=False, loop=loop) def _init_routers(self): """创建路由接口""" @self._app.after_request async def apply_caching(resp: Response): """设置响应的全局 headers, 允许跨域""" resp.headers["Server"] = "Anime-API" resp.headers["Access-Control-Allow-Origin"] = "*" resp.headers["Access-Control-Allow-Headers"] = "*" return resp @self._app.route("/") async def index(): """API 主页显示帮助信息""" file = f"{self._root}/templates/interface.txt" with open(file, encoding="utf-8") as f: text = f.read() return Response(text, mimetype="text/plain") @self._app.route("/statistics") async def statistics(): """百度统计转发, 用户体验计划""" return await self._stats.transmit(request) @self._app.route("/statistics/<hm_js>") async def get_statistics_js(hm_js): return await self._stats.get_hm_js(request) # ======================== Anime Interface =============================== @self._app.route("/anime/bangumi/updates") async def get_bangumi_updates(): """获取番剧更新时间表""" bangumi_list = await self._agent.get_bangumi_updates() data = [] for bangumi in bangumi_list: one_day = { "date": bangumi.date, "day_of_week": bangumi.day_of_week, "is_today": bangumi.is_today, "updates": [] } for info in bangumi: one_day["updates"].append({ "title": info.title, "cover_url": f"{info.cover_url}", # 图片一律走代理, 防止浏览器跨域拦截 "update_time": info.update_time, "update_to": info.update_to }) data.append(one_day) return jsonify(data) @self._app.route("/anime/search/<path:keyword>") async def search_anime(keyword): """番剧搜索, 该方法回阻塞直到所有引擎数据返回""" result: List[AnimeMeta] = [] await self._agent.get_anime_metas( keyword.strip(), callback=lambda m: result.append(m)) ret = [] for meta in result: ret.append({ "title": meta.title, "cover_url": f"{meta.cover_url}", "category": meta.category, "description": meta.desc, "score": 80, # TODO: 番剧质量评分机制 "module": meta.module, "url": f"{self._domain}/anime/{meta.token}" }) return jsonify(ret) @self._app.websocket("/anime/search") async def ws_search_anime(): async def push(meta: AnimeMeta): await websocket.send_json({ "title": meta.title, "cover_url": f"{meta.cover_url}", "category": meta.category, "description": meta.desc, "score": 80, "engine": meta.module, "url": f"{self._domain}/anime/{meta.token}" }) # route path 不能有中文, 客户端 send 关键字 keyword = await websocket.receive() await self._agent.get_anime_metas(keyword.strip(), co_callback=push) @self._app.route("/anime/<token>") async def get_anime_detail(token): """返回番剧详情页面信息""" detail = await self._agent.get_anime_detail(token) if not detail: return Response("Parse detail failed", status=404) ret = { "title": detail.title, "cover_url": f"{detail.cover_url}", "description": detail.desc, "category": detail.category, "module": detail.module, "play_lists": [] } for idx, playlist in enumerate(detail): lst = { "name": playlist.name, "num": playlist.num, "video_list": [] } # 一个播放列表 for episode, video in enumerate(playlist): video_path = f"{token}/{idx}/{episode}" lst["video_list"].append({ "name": video.name, "info": f"{self._domain}/anime/{video_path}", "player": f"{self._domain}/anime/{video_path}/player", }) ret["play_lists"].append(lst) return jsonify(ret) @self._app.route("/anime/<token>/<playlist>/<episode>") async def parse_anime_info(token: str, playlist: str, episode: str): """获取视频信息""" url = await self._agent.get_anime_real_url(token, int(playlist), int(episode)) info = { "raw_url": f"{self._domain}/anime/{token}/{playlist}/{episode}/url", "proxy_url": f"{self._domain}/proxy/anime/{token}/{playlist}/{episode}", "format": url.format, # "resolution": url.resolution, "size": url.size, "lifetime": url.left_lifetime } return jsonify(info) @self._app.route("/anime/<token>/<playlist>/<episode>/url") async def redirect_to_real_url(token: str, playlist: str, episode: str): """重定向到视频直链, 防止直链过期导致播放器无法播放""" proxy = await self._agent.get_anime_proxy(token, int(playlist), int(episode)) if not proxy or not proxy.is_available(): return Response("Resource not available", status=404) if proxy.is_enforce_proxy(): # 该资源启用了强制代理 return redirect(f"/proxy/anime/{token}/{playlist}/{episode}") return redirect(proxy.get_real_url()) @self._app.route("/anime/<token>/<playlist>/<episode>/player") async def player_without_proxy(token, playlist, episode): """视频直链播放测试""" url = f"{self._domain}/anime/{token}/{playlist}/{episode}" return await render_template("player.html", info_url=url) # ======================== Danmaku Interface =============================== @self._app.route("/danmaku/search/<path:keyword>") async def search_danmaku(keyword): """搜索番剧弹幕库""" result: List[DanmakuMeta] = [] await self._agent.get_danmaku_metas( keyword.strip(), callback=lambda m: result.append(m)) data = [] for meta in result: data.append({ "title": meta.title, "num": meta.num, "module": meta.module, "score": 80, # TODO: 弹幕质量评分机制 "url": f"{self._domain}/danmaku/{meta.token}" }) return jsonify(data) @self._app.websocket("/danmaku/search") async def ws_search_danmaku(): """搜索番剧弹幕库""" async def push(meta: DanmakuMeta): await websocket.send_json({ "title": meta.title, "num": meta.num, "module": meta.module, "score": 80, "url": f"{self._domain}/danmaku/{meta.token}" }) keyword = await websocket.receive() await self._agent.get_danmaku_metas(keyword.strip(), co_callback=push) @self._app.route("/danmaku/<token>") async def get_danmaku_detail(token): """获取番剧各集对应的弹幕库信息""" detail = await self._agent.get_danmaku_detail(token) if detail.is_empty(): return Response("Parse danmaku detail failed", status=404) data = [] for episode, danmaku in enumerate(detail): data.append({ "name": danmaku.name, "url": f"{self._domain}/danmaku/{token}/{episode}", # Dplayer 会自动添加 /v3/ "data": f"{self._domain}/danmaku/{token}/{episode}/v3/" # 调试用 }) return jsonify(data) @self._app.route("/danmaku/<token>/<episode>/v3/") async def get_danmaku_data(token, episode): """解析视频的弹幕库信息, 返回 DPlayer 支持的弹幕格式""" data = await self._agent.get_danmaku_data(token, int(episode)) ret = {"code": 0, "data": data.data, "num": data.num} return jsonify(ret) # ======================== IPTV Interface =============================== @self._app.route("/iptv/list") async def get_iptv_list(): """IPTV 直播源""" sources = self._agent.get_iptv_sources() data = [] for source in sources: data.append({"name": source.name, "url": source.url}) return jsonify(data) # ======================== Proxy Interface =============================== @self._app.route("/proxy/image/<path:raw_url>") async def image_proxy(raw_url): """对跨域图片进行代理访问, 返回数据""" return await self._proxy.make_response(raw_url) @self._app.route("/proxy/anime/<token>/<playlist>/<episode>") async def anime_stream_proxy(token, playlist, episode): """代理访问普通的视频数据流""" proxy = await self._agent.get_anime_proxy(token, int(playlist), int(episode)) if not proxy: return Response("proxy error", status=404) if proxy.get_stream_format() == "hls": # m3u8 代理 proxy.set_chunk_proxy_router( f"{self._domain}/proxy/hls/{token}/{playlist}/{episode}") return await proxy.make_response_for_m3u8() else: # mp4 代理 range_field = request.headers.get("range") return await proxy.make_response_with_range(range_field) @self._app.route("/proxy/hls/<token>/<playlist>/<episode>/<path:url>") async def m3u8_chunk_proxy(token, playlist, episode, url): """代理访问视频的某一块数据""" proxy = await self._agent.get_anime_proxy(token, int(playlist), int(episode)) if not proxy: return Response("m3u8 chunk proxy error", status=404) return await proxy.make_response_for_chunk(url) # ======================== System Interface =============================== @self._app.route("/system/logs") async def show_logs(): file = f"{self._root}/logs/api.log" with open(file, encoding="utf-8") as f: text = f.read() return Response(text, mimetype="text/plain") @self._app.route("/system/version") async def show_system_version(): return jsonify(self._config.get_version()) @self._app.route("/system/clear") async def clear_system_cache(): """清空 API 的临时缓存数据""" mem_free = self._agent.cache_clear() return jsonify({"clear": "success", "free": mem_free}) @self._app.route("/system/modules", methods=["GET", "POST", "OPTIONS"]) async def show_global_settings(): if request.method == "GET": return jsonify(self._config.get_modules_status()) if request.method == "POST": options = await request.json ret = {} for option in options: module = option.get("module") enable = option.get("enable") if not module: continue ok = self._agent.change_module_state(module, enable) ret[module] = "success" if ok else "failed" return jsonify(ret) if request.method == "OPTIONS": return Response("")
def setUpClass(cls): cls.config = Config(os.path.dirname(__file__))
class DatabaseTest(unittest.TestCase): db = WeatherTalkDatabase(Config()) app = app def setUp(self): self.db = WeatherTalkDatabase(Config()) def tearDown(self): self.db.session.remove() @staticmethod def generate_observation(): observation = Observation(humidity=float(random.randrange(0, 100)), temperature=float(random.randrange(0, 100)), pressure=float(random.randrange(0, 100)), wind=float(random.randrange(0, 100)), condition=WeatherTypes.Sunny, location="test, test") return observation @staticmethod def generate_device(): return Device(name=str(uuid.uuid1().hex)) @staticmethod def generate_user(): return User(name=str(uuid.uuid1().hex), email=str(uuid.uuid1().hex), password=str(uuid.uuid1().hex)) def test_create_user(self): test_content = ENTRIES.get("user") user = None try: user = self.generate_user() self.db.session.add(user) except Exception as e: self.fail(f"Error {e}, {e.__class__}") self.assertIsNotNone(user) for _ in range(0, random.randrange(1, 10)): try: device = self.generate_device() user.devices.append(device) self.db.session.add(device) except Exception as e: self.fail(f"Error {e}, {e.__class__}") self.db.session.commit() def test_delete_user(self): db_users = self.db.session.query(User).all() if not db_users: for _ in range(0, random.randrange(1, 10)): user = self.generate_user() self.db.session.add(user) self.db.session.commit() db_users = self.db.session.query(User).all() for user in db_users: try: self.db.session.delete(user) self.db.session.commit() except Exception as e: self.fail(f"Error {e}, {e.__class__}") def test_create_device(self): device = None try: device = self.generate_device() self.db.session.add(device) self.db.session.commit() except Exception as e: self.fail(f"Error {e}, {e.__class__}") self.assertIsNotNone(device) def test_delete_device(self): devices = self.db.session.query(Device).all() if not devices: for _ in range(0, random.randrange(1, 10)): device = self.generate_device() self.db.session.add(device) self.db.session.commit() devices = self.db.session.query(Device).all() for device in devices: try: self.db.session.delete(device) self.db.session.commit() except Exception as e: self.fail(f"Error {e}, {e.__class__}") def test_create_device_group(self): try: user = self.generate_user() group = DeviceGroup(name=str(uuid.uuid1().hex), user_id=user.id) for _ in range(0, random.randrange(1, 10)): device = self.generate_device() group.members.append(device) self.db.session.add(device) self.db.session.add(user) self.db.session.add(group) self.db.session.commit() except Exception as e: self.fail(f"Error {e}, {e.__class__}") def test_delete_device_group(self): groups = self.db.session.query(DeviceGroup).all() if not groups: user = self.generate_user() group = DeviceGroup(name=str(uuid.uuid1().hex), user_id=user.id) for _ in range(0, random.randrange(1, 10)): device = self.generate_device() group.members.append(device) self.db.session.add(device) self.db.session.add(user) self.db.session.add(group) self.db.session.commit() groups = self.db.session.query(DeviceGroup).all() for group in groups: try: self.db.session.delete(group) self.db.session.commit() except Exception as e: self.fail(f"Error {e}, {e.__class__}") def test_create_observation(self): try: observation = self.generate_observation() self.db.session.add(observation) self.db.session.commit() except Exception as e: self.fail(f"Error {e}, {e.__class__}") def test_delete_observation(self): observations = self.db.session.query(Observation).all() if not observations: for _ in range(0, random.randrange(1, 10)): observation = self.generate_observation() self.db.session.add(observation) self.db.session.commit() for observation in observations: try: self.db.session.delete(observation) self.db.session.commit() except Exception as e: self.fail(f"Error {e}, {e.__class__}")
# Copyright 2019 by Mihail Butnaru # All rights reserved. from api.app import create_app from api.config import Config _config = Config() app = create_app(_config)
def setUp(self): self.db = WeatherTalkDatabase(Config())
def create_app(): app = Flask(__name__) app.config.from_object(Config()) return app
def __init__(self): self.session: Optional[ClientSession] = None self._domain_mapping: Dict[str, str] = Config().get("domain_mapping") self._dns_server = []
parser.add_argument('--recorder_fs_ready', action='store_true', help='Recorder folders and files already created') parser.add_argument( '--preserve_player_fs', action='store_true', help='Do not remove player folders and files after test') parser.add_argument( '--preserve_recorder_fs', action='store_true', help='Do not remove recorder folders and files after test') args = parser.parse_args() if args.config is not None: config = Config(os.path.abspath(args.config)) else: config = Config(os.path.join('../../../', Config.DEFAULT_CONFIG_FILE)) # Create Device Manager dev_manager = DeviceManager(config) # Assign devices according to role player, recorder = dev_manager.get_devices_by_serials( args.player, args.recorder) # Create test runner instance tc_runner = AdnPlayerRecorderExampleTestTcRunner(config, player=player, recorder=recorder)
client.publish(f'{prefix}/rsp', json.dumps(payload), qos=0, retain=True) else: client.publish(f'{prefix}/data/{topic}', json.dumps(payload), qos=0, retain=True) if __name__ == '__main__': # TODO: error check print('m2ag.labs core service 0.2.0') print('copyright 2021 https://m2aglabs.com') config = Config.get_server_config() logging.basicConfig( level=config['log_level'], format="%(asctime)s %(filename)s:%(lineno)s %(levelname)s %(message)s") prefix = config.get('prefix') try: client = mqtt.Client(config.get('id'), protocol=mqtt.MQTTv311, transport="tcp") client.username_pw_set(username=secrets.get('mqtt_id'), password=secrets.get('mqtt_password')) if secrets.get('mqtt_tls'): client.tls_set(ca_certs=secrets.get('mqtt_ca')) if secrets.get('mqtt_insecure'): client.tls_insecure_set(True) client.connect(secrets.get('mqtt_broker'), secrets.get('mqtt_port'),