def run_server(): app: ModuleType = import_app() # Starts the server or runs the main function if the app isn't using routes, meaning it's just a script. try: if not cfg.is_repl and not cfg.is_module_transpile: printing.style_print('Running the app...', styles=['bold'], end=' ') print('(Press Ctrl+C to stop)') if not cfg.uses_routes: # The app is just a script. Ask is used like a general purpose language. app.main() # The app uses routes, so it's an API, the app needs to run in a web server. elif askfile.get(['server', 'production'], True) is True and cfg.is_dev is False: # Run in the production server. print('\033[91m\t- ', end='') waitress.serve( TransLogger( app.app, logger_name='Ask Application', format=' '.join([ f'\033[37m\t- {datetime.datetime.now().strftime("[%d/%b/%Y %H:%M:%S]")}\033[0m', '\033[1m%(REQUEST_METHOD)s\033[0m ' '"\033[32m%(REMOTE_ADDR)s%(REQUEST_URI)s\033[0m"', '→', '\033[94m%(status)s\033[0m', ])), host=askfile.get(['server', 'host'], '127.0.0.1'), port=askfile.get(['server', 'port'], '5000'), ident='Ask Application', ) else: # Run in the development server. os.environ['FLASK_APP'] = files.output_file_path() if cfg.is_dev: os.environ['FLASK_ENV'] = 'development' app.app.run() except Exception as e: # Exception is used here to capture all exception types. errors.error_while_running(e, cfg.transpilation_result['source_lines'], cfg.transpilation_result['time_result']) if cfg.is_repl: # Tries to remove the line the error was on. if len(cfg.repl_previous_transpiled.split('\n')) > 2: cfg.repl_previous_transpiled = '\n'.join( cfg.repl_previous_transpiled.split('\n')[:-2]) return exit(1)
def main(): cfg.set_defaults() if len(sys.argv) > 1: param_file_name, no_valid_flags = parse_sys_args(sys.argv) cfg.source_file_name = param_file_name # Load the config if it hasn't been set. # This will only be false when running in module transpile mode. if not cfg.ask_config: askfile.load() if not param_file_name and True in [ x in sys.argv for x in ['-d', '--dev', '-xd', '--extra-dev'] ]: repl(True) if not cfg.is_module_transpile: printing.initial_print() if os.path.isfile(f'{os.getcwd()}/{cfg.source_file_name}'): transpiler.transpile_from_file() if askfile.get(['system', 'server'], True): # Starts server serve_run.run_server() elif not cfg.is_module_transpile: printing.style_print('\nAuto start server is turned OFF.', styles=['bold']) print('\t - The transpiled code can be found in:', end=' ') printing.style_print(askfile.get(['system', 'output_path'], 'app.py'), color='blue', end='') print('.') else: if no_valid_flags: if param_file_name[0] == '-': style_print(f'- Invalid flag "{param_file_name}".', color='yellow') exit(1) printing.style_print('- The file could not be found!', color='red') exit(1) # Deletes the output file if configured to. files.maybe_delete_app() else: repl(True)
def db_path_with_prefix() -> str: prefix = 'sqlite:///' if askfile.get(['db', 'custom'], False): prefix = '' return f'{prefix}{get_db_file_path()}'
def maybe_delete_app(force: bool = False): if not askfile.get(['system', 'keep_app'], True) or force: try: os.remove(output_file_path()) for module in cfg.imported_ask_modules_to_delete: os.remove(f'{get_root_from_file_path(output_file_path())}/{module}.py') except FileNotFoundError: return
def generic_construct_output_file_path(file_name_or_path): prefix = f'{os.getcwd()}/' if askfile.get(['db', 'custom'], False): prefix = '' if '/' in cfg.source_file_name: prefix += f'{get_root_from_file_path(cfg.source_file_name)}/' if file_name_or_path[0] == '/': file_name_or_path = file_name_or_path[1:] return prefix + file_name_or_path
def build_db(file_name: str): if not cfg.is_include_transpile: printing.style_print('Database:', styles=['bold']) if not askfile.get(['db', 'custom'], False) and not os.path.exists( files.get_db_file_path()): if not cfg.is_include_transpile: print('\t- Building database...', end='') db_root = files.get_root_from_file_path(files.get_db_file_path()) if not cfg.is_include_transpile: print('\t✅') if db_root and db_root != file_name and not os.path.exists(db_root): if not cfg.is_include_transpile: print('\t- Building Folder Structure...', end='') os.makedirs(db_root) if not cfg.is_include_transpile: print('\t✅')
def generic_transpile_symbol(word: str, words: dict, default: str = None) -> str: if askfile.get(['rules', 'underscores'], True): words = translator_utils.add_underscores_to_dict_keys(words) return defaultdict(lambda: default if default is not None else word, words)[word]
def lex(raw: List[str]) -> List[List[str]]: tmp = '' is_collector = False is_str = False might_be_special_str = False collector_ends = [] include_collector_end = False is_dict = [] tokens = [] for line in raw: line = lexer_utils.reformat_line(line) for char_index, char in enumerate(line): # Ignores comments if char == '#': break if is_str: if char not in collector_ends: tmp += char if char in collector_ends: tmp += char tokens.append(['STR', tmp]) is_str = False collector_ends = [] tmp = '' continue # Detects raw & f-strings. if char in ['r', 'f']: might_be_special_str = char if is_collector: if char not in collector_ends: tmp += char else: tokens[-1][1] = tmp if include_collector_end: tokens.append([ 'OP' if char not in ['\n', '\t'] else 'FORMAT', char ]) is_collector = False include_collector_end = False tmp = '' # Function call. elif char == '(': if tmp: tokens.append(['FUNC', tmp.replace(' ', '')]) tmp = '' # Variable assignment. elif char == '=': if tmp: tokens.append(['WORD', tmp]) tokens.append(['OP', char]) if tmp not in cfg.variables: cfg.variables.append(tmp) tmp = '' else: tokens.append(['OP', char]) # String. elif char in ['"', '\'']: is_str = True collector_ends = [char] tmp = '' if might_be_special_str == 'r': tmp = r'' elif might_be_special_str == 'f': tmp = f'' tmp += char might_be_special_str = '' # Dict open. elif char == '{': is_dict.append(True) tokens.append(['OP', char]) # Dict close. elif char == '}': tokens, tmp, is_collector, collector_ends, include_collector_end = lexer_utils.word_or_special( tokens, tmp) is_dict.pop(0) tokens.append(['OP', char]) # Number (on its own). elif char.isdigit() and not tmp: if tokens and tokens[-1][0] == 'NUM': tokens[-1][1] += char continue tokens.append(['NUM', char]) # Decorator. elif char == '&': is_collector = True collector_ends = ['\n'] include_collector_end = True tmp = '' tokens.append(['DEC', '']) # Operator (special character). elif char in cfg.operators: if char == ':' and is_dict and tmp: tokens.append(['KEY', tmp]) tmp = '' tokens, tmp, is_collector, collector_ends, include_collector_end = lexer_utils.word_or_special( tokens, tmp) tokens.append(['OP', char]) # Formatting. elif char in ['\n', '\t']: tokens, tmp, is_collector, collector_ends, include_collector_end = lexer_utils.word_or_special( tokens, tmp) tokens.append(['FORMAT', char]) # Character isn't anything specific, meaning it's e.g. a letter. These get collected for later use. elif char not in ['\n', '\t', ' ']: tmp += char else: # There might be a word or keyword in tmp. tokens, tmp, is_collector, collector_ends, include_collector_end = lexer_utils.word_or_special( tokens, tmp) if len(tokens) > 2 and transpiler_utils.token_check( tokens[-2], 'WORD', transpiler_utils.add_underscores_to_elems(['db']) if askfile.get(['rules', 'underscores'], True) else 'db'): # Removes the WORD 'db'/'_db' and the OP '.'. tokens.pop(-1) tokens.pop(-1) is_collector = True collector_ends = ['(', ',', ')'] include_collector_end = True tmp = '' tokens.append(['DB_ACTION', '']) cfg.uses_db = True return tokens
def output_file_path() -> str: return generic_construct_output_file_path(askfile.get(['system', 'output_path'], 'app.py'))
def get_db_file_path() -> str: return generic_construct_output_file_path(askfile.get(['db', 'path'], 'db.db'))
def test_multiple_missing(self): cfg.ask_config = {} self.assertEqual( 'missing', askfile.get(['missing_group', 'missing_key'], 'missing'))
def test_multiple(self): cfg.ask_config = {'group': {'key': 'value'}} self.assertEqual('value', askfile.get(['group', 'key'], 'missing'))
def test_single(self): cfg.ask_config = {'key': 'value'} self.assertEqual('value', askfile.get(['key'], 'missing'))