#!/usr/bin/env python # -*- coding: utf-8 -*- import os import asyncio import platform import subprocess try: import uvloop asyncio.set_event_loop_policy(uvloop.EventLoopPolicy()) except ImportError: pass import ssl try: _create_unverified_https_context = ssl._create_unverified_context except AttributeError: # Legacy Python that doesn't verify HTTPS certificates by default pass else: # Handle target environment that doesn't support HTTPS verification ssl._create_default_https_context = _create_unverified_https_context from lxml import etree import ctypes from urllib import parse, request from aiofile import AIOFile import aiohttp import async_timeout
def set_event_loop_policy(): current_policy = asyncio.get_event_loop_policy() if not isinstance(current_policy, uvloop.EventLoopPolicy): asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
def use_uvloop(request): if request.param: import uvloop asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
thread_pool_ids = ( "aiomisc pool", "default pool", ) @pytest.fixture(params=thread_pool_implementation, ids=thread_pool_ids) def thread_pool_executor(request): return request.param policies = (asyncio.DefaultEventLoopPolicy(), ) policy_ids = ("asyncio", ) if uvloop: policies = (uvloop.EventLoopPolicy(), ) + policies policy_ids = ("uvloop", ) + policy_ids @pytest.fixture(params=policies, ids=policy_ids) def event_loop_policy(request): return request.param @pytest.fixture() def certs(): return Path(os.path.dirname(os.path.abspath(__file__))) / "certs" @pytest.fixture def ssl_client_context(certs):
def main(test, **kwargs): # check configuration and request missing information from user # dotenv config values os.environ['PROD'] = str(not test) if test: os.environ['PYTHONASYNCIODEBUG'] = '1' os.environ.update({ key: str(value) for key, value in kwargs.items() if value is not None }) # TODO custom prompt function based on click's that asks for config details that aren't given database_type = os.getenv('DB_TYPE') if database_type != 'sqlite' and not os.getenv('DB_HOST'): os.environ['DB_HOST'] = prompt("DB host", value_proc=str, default='localhost') os.environ['DB_PORT'] = prompt( "DB port", value_proc=str, default='5432' if database_type == 'postgres' else '3306' if database_type == 'mysql' else None) os.environ['DB_NAME'] = prompt("DB name", value_proc=str) os.environ['DB_USER'] = prompt("DB user", value_proc=str) os.environ['DB_PASSWORD'] = prompt("DB password", value_proc=str, hide_input=True) cache_type = os.getenv('CACHE_TYPE') if os.getenv('CACHE_TYPE') != 'simple' and not os.getenv('CACHE_HOST'): os.environ['CACHE_HOST'] = prompt("Cache host", value_proc=str, default='localhost') os.environ['CACHE_PORT'] = prompt( "Cache port", value_proc=str, default='6379' if cache_type == 'redis' else None) os.environ['CACHE_PASSWORD'] = input("Cache password: "******"Cache number", value_proc=str, default='0') if not os.getenv('BOT_TOKEN'): if sys.platform in ('win32', 'cygwin', 'darwin'): if confirm( "You need a bot token for your bot. Do you want to create a " "bot now? (This will open a browser window/tab.)"): launch("https://discordapp.com/developers/applications/") os.environ['BOT_TOKEN'] = input("Bot token: ") config = Config(test) config.save() # automatically initialize database if using SQLite for convenience if database_type == 'sqlite': if ((test and not os.path.isfile( os.path.join(hero.ROOT_DIR, "test_db.sqlite3"))) or (not test and not os.path.isfile(os.path.join(hero.ROOT_DIR, "db.sqlite3")))): print("Running `hero dbinit`") database_initialization(test, from_main=True, **kwargs) print("You can now use `hero` to run your Discord Hero instance.") return # load extensions with open(os.path.join(hero.ROOT_DIR, 'extensions.txt')) as extensions_file: extensions = extensions_file.read().splitlines() os.environ['EXTENSIONS'] = ';'.join(extensions) with open(os.path.join(hero.ROOT_DIR, 'local_extensions.txt')) as local_extensions_file: local_extensions = local_extensions_file.read().splitlines() os.environ['LOCAL_EXTENSIONS'] = ';'.join(local_extensions) configs = [] for extension in extensions: configs.append(get_extension_config(extension)) for local_extension in local_extensions: configs.append(get_extension_config(local_extension, local=True)) installed_apps = [] for _config in configs: installed_apps.append(f"{_config.__module__}.{_config.__name__}") os.environ['INSTALLED_APPS'] = ';'.join(installed_apps) hero.TEST = test # setup cache hero.cache.init() # setup django os.environ.setdefault("DJANGO_SETTINGS_MODULE", "hero.django_settings") django.setup(set_prefix=False) # setup asyncio loop try: # noinspection PyUnresolvedReferences import uvloop asyncio.set_event_loop_policy(uvloop.EventLoopPolicy()) except ImportError: pass if sys.platform == "win32": asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy()) loop = asyncio.get_event_loop() from hero.models import CoreSettings # db config values try: settings, created = CoreSettings.get_or_create( name=os.getenv('NAMESPACE')) except (OperationalError, ProgrammingError): if database_type != 'sqlite': print("Running `hero dbinit`") database_initialization(test, from_main=True, **kwargs) print("You can now use `hero` to run your Discord Hero instance.") return raise if created: settings.prefixes = [ prompt("Bot command prefix", value_proc=str, default='!') ] settings.description = prompt("Short description of your bot", value_proc=str, default='') settings.save() with hero.Core(config=config, settings=settings, name=os.getenv('NAMESPACE', 'default'), loop=loop) as core: core.run()