Skip to content
This repository has been archived by the owner on Aug 26, 2024. It is now read-only.

Add scripts/shell, update to Python 3.8 #75

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ services:
cache: pip

python:
- "3.7"
- "3.8"

install:
- scripts/install
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ The service is deployed to http://hostedapi.herokuapp.com/

Requirements:

* [Python 3.7](https://www.python.org/downloads/)
* [Python 3.8](https://www.python.org/downloads/)
* [Postgres](https://www.postgresql.org/download/) (For Mac, I'd recommend [Postgres.app](https://postgresapp.com/))

To install and run the application:
Expand Down
2 changes: 1 addition & 1 deletion runtime.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
python-3.7.5
python-3.8.0
2 changes: 1 addition & 1 deletion scripts/install
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ if [ "${CONTINUOUS_INTEGRATION}" = "true" ]; then
BIN_PATH=""
else
rm -rf venv
virtualenv venv --python=python3.7
virtualenv venv --python=python3.8
BIN_PATH="venv/bin/"
fi

Expand Down
136 changes: 136 additions & 0 deletions scripts/shell
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#!venv/bin/python

import ast
import asyncio
import code
import concurrent.futures
import inspect
import os
import sys
import threading
import types
import warnings

from asyncio import futures


sys.path.append(os.getcwd())

class AsyncIOInteractiveConsole(code.InteractiveConsole):

def __init__(self, locals, loop):
super().__init__(locals)
self.compile.compiler.flags |= ast.PyCF_ALLOW_TOP_LEVEL_AWAIT

self.loop = loop

def runcode(self, code):
future = concurrent.futures.Future()

def callback():
global repl_future
global repl_future_interrupted

repl_future = None
repl_future_interrupted = False

func = types.FunctionType(code, self.locals)
try:
coro = func()
except SystemExit:
raise
except KeyboardInterrupt as ex:
repl_future_interrupted = True
future.set_exception(ex)
return
except BaseException as ex:
future.set_exception(ex)
return

if not inspect.iscoroutine(coro):
future.set_result(coro)
return

try:
repl_future = self.loop.create_task(coro)
futures._chain_future(repl_future, future)
except BaseException as exc:
future.set_exception(exc)

loop.call_soon_threadsafe(callback)

try:
return future.result()
except SystemExit:
raise
except BaseException:
if repl_future_interrupted:
self.write("\nKeyboardInterrupt\n")
else:
self.showtraceback()


class REPLThread(threading.Thread):

def run(self):
try:
banner = (
f'asyncio REPL {sys.version} on {sys.platform}\n'
f'Use "await" directly instead of "asyncio.run()".\n'
f'Type "help", "copyright", "credits" or "license" '
f'for more information.\n'
)

console.interact(
banner=banner,
exitmsg='exiting asyncio REPL...')
finally:
warnings.filterwarnings(
'ignore',
message=r'^coroutine .* was never awaited$',
category=RuntimeWarning)

loop.call_soon_threadsafe(loop.stop)


if __name__ == '__main__':
from dotenv import load_dotenv
load_dotenv()

from source.resources import database
from source import tables

loop = asyncio.new_event_loop()
loop.run_until_complete(database.connect())
asyncio.set_event_loop(loop)

repl_locals = {'database': database, 'tables': tables}
for key in {'__name__', '__package__',
'__loader__', '__spec__',
'__builtins__', '__file__'}:
repl_locals[key] = locals()[key]

console = AsyncIOInteractiveConsole(repl_locals, loop)

repl_future = None
repl_future_interrupted = False

try:
import readline # NoQA
except ImportError:
pass

repl_thread = REPLThread()
repl_thread.daemon = True
repl_thread.start()

while True:
try:
loop.run_forever()
except KeyboardInterrupt:
if repl_future and not repl_future.done():
repl_future.cancel()
repl_future_interrupted = True
continue
else:
break