Add basic ipython-based repl via --repl

This commit is contained in:
caryoscelus 2023-11-26 18:09:56 +00:00
parent 28440346b1
commit ba60f5dc0e
4 changed files with 31 additions and 4 deletions

View file

@ -1,4 +1,5 @@
### zeronet-conservancy 0.7.10+
- ipython-based repl via --repl for debug/interactive development (@caryoscelus)
### zeronet-conservancy 0.7.10 (2023-07-26) (18d35d3bed4f0683e99)
prepared by @caryoscelus

View file

@ -15,3 +15,4 @@ rich
defusedxml>=0.7
pyaes
requests
ipython>=8

View file

@ -15,7 +15,7 @@ class Config(object):
self.version = "0.7.10+"
self.user_agent = "conservancy"
# DEPRECATED ; replace with git-generated commit
self.rev = 5121
self.rev = 5130
self.user_agent_rev = 8192
self.argv = argv
self.action = None
@ -304,6 +304,7 @@ class Config(object):
self.parser.add_argument('--tor_hs_limit', help='Maximum number of hidden services in Tor always mode', metavar='limit', type=int, default=10)
self.parser.add_argument('--tor_hs_port', help='Hidden service port in Tor always mode', metavar='limit', type=int, default=15441)
self.parser.add_argument('--repl', help='Instead of printing logs in console, drop into REPL after initialization', action='store_true')
self.parser.add_argument('--version', action='version', version=f'zeronet-conservancy {self.version} r{self.rev}')
self.parser.add_argument('--end', help='Stop multi value argument parsing', action='store_true')
@ -583,7 +584,7 @@ class Config(object):
format = '%(name)s %(message)s'
if self.console_log_level == "default":
if self.silent:
if self.silent or self.repl:
level = logging.ERROR
elif self.debug:
level = logging.DEBUG

View file

@ -157,6 +157,7 @@ if config.msgpack_purepython:
os.environ["MSGPACK_PUREPYTHON"] = "True"
# Fix console encoding on Windows
# TODO: check if this is still required
if sys.platform.startswith("win"):
import subprocess
try:
@ -193,7 +194,7 @@ elif config.bind:
@PluginManager.acceptPlugins
class Actions(object):
class Actions:
def call(self, function_name, kwargs):
logging.info("Version: %s r%s, Python %s, Gevent: %s" % (config.version, config.rev, sys.version, gevent.__version__))
@ -202,6 +203,11 @@ class Actions(object):
if back:
print(back)
def ipythonThread(self):
import IPython
IPython.embed()
self.gevent_quit.set()
# Default action: Start serving UiServer and FileServer
def main(self):
global ui_server, file_server
@ -221,7 +227,25 @@ class Actions(object):
CryptConnection.manager.removeCerts()
logging.info("Starting servers....")
gevent.joinall([gevent.spawn(ui_server.start), gevent.spawn(file_server.start)])
import threading
self.gevent_quit = threading.Event()
launched_greenlets = [gevent.spawn(ui_server.start), gevent.spawn(file_server.start)]
# if --repl, start ipython thread
# FIXME: Unfortunately this leads to exceptions on exit so use with care
if config.repl:
threading.Thread(target=self.ipythonThread).start()
stopped = 0
# Process all greenlets in main thread
while not self.gevent_quit.is_set() and stopped < len(launched_greenlets):
stopped += len(gevent.joinall(launched_greenlets, timeout=1))
# Exited due to repl, so must kill greenlets
if stopped < len(launched_greenlets):
gevent.killall(launched_greenlets, exception=KeyboardInterrupt)
logging.info("All server stopped")
# Site commands