Exemplo n.º 1
0
def transpile_from_file():
    # Transpiles.
    with open(cfg.source_file_name) as f:
        source_lines = f.readlines()

    if not source_lines:
        printing.style_print('\t- The file is empty!', color='red')
        exit(1)

    transpile(source_lines)
Exemplo n.º 2
0
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)
Exemplo n.º 3
0
def transpile(source_lines: List[str]):
    # Transpilation time capture start.
    start_time = time.time()

    if not cfg.is_repl and not cfg.is_module_transpile:
        printing.style_print('Transpiling...', styles=['bold'], end='')

    # Lexing.
    tokens_list = lexer.lexer(source_lines)

    # Parsing.
    translated = translator.translator(tokens_list)

    # Saves the transpiled code to the build/output file
    with open(files.output_file_path(), 'w+') as f:
        f.write('')
        f.write(translated)

    # The transpilation is done.
    end_time = time.time()
    time_result = round(end_time - start_time, 3)

    if not cfg.is_repl and not cfg.is_module_transpile:
        # Checkmark for the 'Transpiling...' message at the start of this function.
        print('\t✅')
    if cfg.is_dev:
        pprint(tokens_list)

    if not cfg.is_repl and not cfg.is_module_transpile:
        printing.transpilation_result(source_lines, time_result)

    # Database setup & build.
    if cfg.uses_db:
        build_db(cfg.source_file_name)

    # Verify transpilation
    verify_and_load_db(source_lines, time_result)

    # Stores the result in the global store.
    cfg.transpilation_result = {
        'source_lines': source_lines,
        'time_result': time_result
    }

    if re.search(r'class[\s]+[\w]+\(db\.Model\):\n.+',
                 cfg.included_module_code):
        printing.style_print('IMPORTANT:', styles=['bold'], color='yellow')
        print('\t- Database models should not be declared in included files❗️')
Exemplo n.º 4
0
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✅')
Exemplo n.º 5
0
def repl(first_time: bool = False):
    cfg.is_repl = True

    if first_time:
        printing.initial_print()
        printing.style_print('Type "q" to quit.', color='gray')

    line = input('Ask >>> ')

    # Quit/Exit
    if line == 'q':
        files.maybe_delete_app(True)
        return

    transpiler.transpile([line])
    serve_run.run_server()

    repl()
Exemplo n.º 6
0
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)
Exemplo n.º 7
0
def error_while_running(e: Exception, source_lines: list, time_result: float):
    # Catches e.g. syntax errors.
    try:
        msg, data = e.args
        _, line, _, code = data
    except ValueError:
        msg = e.args[0]
        line = ''
        code = ''

    if not cfg.is_repl:
        # Prints out the error.
        # Clears the screen and re-prints the transpilation result.
        os.system('cls' if os.name == 'nt' else 'clear')

        printing.initial_print()
        printing.style_print('Transpiling...', styles=['bold'], end='')
        print('\t❌ ')
        printing.transpilation_result(source_lines, time_result, True)

    parse_and_print_error({'msg': msg, 'line': line, 'code': code})

    if cfg.is_repl:
        return
Exemplo n.º 8
0
def parse_and_print_error(err: dict):
    # This function tries to figure out on which line the error is coming from.
    # This is complicated since the error is coming from the transpiled code and not the source code.

    matches = []
    skip_to_printing = False

    message = ''
    code = ''
    line_nr = 0

    try:
        message = err['msg'].capitalize()
    except AttributeError:
        message = err['msg']

    if err['msg'] == 48:
        # Address already in use eror:
        message = 'Address already in use.'
        skip_to_printing = True
    if cfg.is_repl:
        printing.style_print('Error!', color='red', end=' ')
        print(message)

        return

    if not skip_to_printing:
        transpiled_line_nr = err['line']
        code = err['code'].replace('\t', '')

        line_nr = None

        # Looks for the most similar line in the Ask code.
        with open(cfg.source_file_name, 'r') as f:
            raw_lines = f.readlines()

        matches = list(difflib.get_close_matches(code, raw_lines))

        if cfg.is_dev:
            # Prints out the "real" line number.
            printing.style_print('\t- DEV: ', color='blue', end=' ')
            print(
                f'{message} on line: {transpiled_line_nr} in: {files.output_file_path()}'
            )

    # No matching line was found, this most likely means that it's not a syntax error.
    if skip_to_printing or not matches:
        printing.style_print('\t- Error!', color='red')
        if not message:
            print('Something went wrong!')
        else:
            print(f'\t\t- {message}')

        return

    # Gets the correct line number.
    for line_index, line in enumerate(raw_lines):
        if line == str(matches[0]):
            line_nr = line_index
            break

    # Prints out a customized error message based on the original.
    # Format: Error! ([file name]) [message] on line [nr] [\n] - in/at: [error line code].
    printing.style_print('\t- Error!', color='red', end=' ')
    printing.style_print(f'({cfg.source_file_name})', color='gray', end=' ')
    printing.style_print(message, styles=['bold'], end=' ')
    print('on line', end=' ')
    printing.style_print(f'{line_nr},', color='blue')
    print('\t\t- in/at: ', end='')
    printing.style_print(code, styles=['bold'])
Exemplo n.º 9
0
def parse_sys_args(sys_args: List[str], is_unittest=False) -> Tuple[str, bool]:
    flags = [
        '-d', '--dev', '-xd', '--extra-dev', '-v', '--version', '-h', '--help',
        '--module-transpile', '--include-transpile'
    ]

    file_name = ''
    no_valid_flags = True

    for param in sys_args[1:]:
        if param in flags:
            no_valid_flags = False

            if param in ['-d', '--dev']:
                cfg.is_dev = True
            if param in ['-xd', '--extra-d']:
                cfg.is_extra_dev = True

                if is_unittest:
                    continue
                printing.style_print('Extra Dev Mode Activated!', 'red',
                                     ['bold'])
            elif param in ['-v', '--version']:
                if is_unittest:
                    continue

                printing.style_print('- Version:', color='blue', end=' ')
                print(cfg.project_information["version"])
            elif param in ['-h', '--help']:
                if is_unittest:
                    continue

                print('Usage: ask_lang [OPTIONS] [FILE]...', end='\n\n')
                print(
                    tabulate([
                        ['-h', '--help', 'Show this message.'],
                        ['-v', '--version', 'Show version information.'],
                        ['-d', '--dev', 'Turn on development & debug mode.'],
                    ],
                             headers=['Option', 'Long Format', 'Description']))
                print()
                print(
                    'Other configurations can be added to a file called `Askfile.toml`.'
                )
                print('Go to: https://docs.ask-lang.org for more information',
                      end='\n\n')
            elif param == '--module-transpile':
                cfg.ask_config = {
                    'system': {
                        'output_path': '',
                        'server': False
                    }
                }

                cfg.is_module_transpile = True
            elif param == '--include-transpile':
                cfg.is_include_transpile = True
        else:
            file_name = param

    if cfg.is_dev and file_name == '':
        no_valid_flags = True

    if cfg.is_module_transpile:
        cfg.ask_config['system']['output_path'] = files.get_file_of_file_path(
            file_name.replace('.ask', '.py'))

    return file_name, no_valid_flags