Commit 72f4531d authored by Eckhart Arnold's avatar Eckhart Arnold

test_server.py: fix spwaning test

parent 020af6fb
...@@ -42,7 +42,7 @@ from DHParser.syntaxtree import Node, RootNode, ZOMBIE_TAG, StrictResultType ...@@ -42,7 +42,7 @@ from DHParser.syntaxtree import Node, RootNode, ZOMBIE_TAG, StrictResultType
from DHParser.transform import TransformationFunc from DHParser.transform import TransformationFunc
from DHParser.parse import Grammar from DHParser.parse import Grammar
from DHParser.error import adjust_error_locations, is_error, is_fatal, Error from DHParser.error import adjust_error_locations, is_error, is_fatal, Error
from DHParser.log import log_parsing_history, log_ST, is_logging, logfile_basename from DHParser.log import log_parsing_history, log_ST, is_logging
from DHParser.toolkit import load_if_file, get_config_value from DHParser.toolkit import load_if_file, get_config_value
...@@ -126,7 +126,7 @@ class Compiler: ...@@ -126,7 +126,7 @@ class Compiler:
self.context = [] # type: List[Node] self.context = [] # type: List[Node]
self._None_check = True # type: bool self._None_check = True # type: bool
self._dirty_flag = False self._dirty_flag = False
self._debug = get_config_value('debug') # type: bool self._debug = get_config_value('debug_compiler') # type: bool
self._debug_already_compiled = set() # type: Set[Node] self._debug_already_compiled = set() # type: Set[Node]
self.finalizers = [] # type: List[Callable, Tuple] self.finalizers = [] # type: List[Callable, Tuple]
...@@ -221,6 +221,21 @@ class Compiler: ...@@ -221,6 +221,21 @@ class Compiler:
return result return result
def logfile_basename(filename_or_text, function_or_class_or_instance) -> str:
"""Generates a reasonable logfile-name (without extension) based on
the given information.
"""
if is_filename(filename_or_text):
return os.path.basename(os.path.splitext(filename_or_text)[0])
else:
try:
name = function_or_class_or_instance.__qualname.__
except AttributeError:
name = function_or_class_or_instance.__class__.__name__
i = name.find('.')
return name[:i] + '_out' if i >= 0 else name
def compile_source(source: str, def compile_source(source: str,
preprocessor: Optional[PreprocessorFunc], # str -> str preprocessor: Optional[PreprocessorFunc], # str -> str
parser: Grammar, # str -> Node (concrete syntax tree (CST)) parser: Grammar, # str -> Node (concrete syntax tree (CST))
...@@ -261,7 +276,7 @@ def compile_source(source: str, ...@@ -261,7 +276,7 @@ def compile_source(source: str,
""" """
ast = None # type: Optional[Node] ast = None # type: Optional[Node]
original_text = load_if_file(source) # type: str original_text = load_if_file(source) # type: str
log_file_name = logfile_basename(source, compiler) # type: str log_file_name = logfile_basename(source, compiler) if is_logging() else '' # type: str
# preprocessing # preprocessing
......
...@@ -173,9 +173,10 @@ CONFIG_PRESET['server_default_port'] = 8888 ...@@ -173,9 +173,10 @@ CONFIG_PRESET['server_default_port'] = 8888
# #
######################################################################## ########################################################################
# Turn on (costly) debugging functionality. # Turn on (costly) debugging functionality for any of the respective
# Default value: False # modules or subsystems.
CONFIG_PRESET['debug'] = False # Default value: always False
CONFIG_PRESET['debug_compiler'] = False
######################################################################## ########################################################################
......
...@@ -62,7 +62,7 @@ from DHParser.toolkit import is_filename, escape_control_characters, GLOBALS ...@@ -62,7 +62,7 @@ from DHParser.toolkit import is_filename, escape_control_characters, GLOBALS
__all__ = ('log_dir', __all__ = ('log_dir',
'logging', 'logging',
'is_logging', 'is_logging',
'logfile_basename', 'append_log',
'clear_logs', 'clear_logs',
'HistoryRecord', 'HistoryRecord',
'log_ST', 'log_ST',
...@@ -151,19 +151,13 @@ def is_logging() -> bool: ...@@ -151,19 +151,13 @@ def is_logging() -> bool:
return False return False
def logfile_basename(filename_or_text, function_or_class_or_instance) -> str: def append_log(log_name: str, text: str) -> None:
"""Generates a reasonable logfile-name (without extension) based on """Appends text to the log-file with the name 'log_name' if logging is on.
the given information.
""" """
if is_filename(filename_or_text): ldir = log_dir()
return os.path.basename(os.path.splitext(filename_or_text)[0]) if ldir:
else: with open(os.path.join(ldir, log_name), 'a') as f:
try: f.write(text)
name = function_or_class_or_instance.__qualname.__
except AttributeError:
name = function_or_class_or_instance.__class__.__name__
i = name.find('.')
return name[:i] + '_out' if i >= 0 else name
def clear_logs(logfile_types=frozenset(['.cst', '.ast', '.log'])): def clear_logs(logfile_types=frozenset(['.cst', '.ast', '.log'])):
......
...@@ -54,7 +54,8 @@ from typing import Callable, Coroutine, Optional, Union, Dict, List, Tuple, Sequ ...@@ -54,7 +54,8 @@ from typing import Callable, Coroutine, Optional, Union, Dict, List, Tuple, Sequ
cast cast
from DHParser.syntaxtree import DHParser_JSONEncoder from DHParser.syntaxtree import DHParser_JSONEncoder
from DHParser.toolkit import get_config_value, re from DHParser.log import is_logging
from DHParser.toolkit import get_config_value, GLOBALS, re
from DHParser.versionnumber import __version__ from DHParser.versionnumber import __version__
...@@ -146,15 +147,10 @@ def asyncio_run(coroutine: Coroutine, loop=None) -> Any: ...@@ -146,15 +147,10 @@ def asyncio_run(coroutine: Coroutine, loop=None) -> Any:
return asyncio.run(coroutine) return asyncio.run(coroutine)
else: else:
if loop is None: if loop is None:
myloop = asyncio.new_event_loop() loop = asyncio.get_event_loop()
asyncio.set_event_loop(myloop)
else: else:
myloop = loop myloop = loop
result = myloop.run_until_complete(coroutine) result = loop.run_until_complete(coroutine)
if loop is None:
asyncio.set_event_loop(None)
myloop.run_until_complete(myloop.shutdown_asyncgens())
myloop.close()
return result return result
...@@ -212,6 +208,8 @@ class Server: ...@@ -212,6 +208,8 @@ class Server:
self.pp_executor = None # type: Optional[ProcessPoolExecutor] self.pp_executor = None # type: Optional[ProcessPoolExecutor]
self.tp_executor = None # type: Optional[ThreadPoolExecutor] self.tp_executor = None # type: Optional[ThreadPoolExecutor]
self.log_file = (self.__class__.__name__ + '.log') if is_logging() else '' # type: str
self.loop = None # just for python 3.5 compatibility... self.loop = None # just for python 3.5 compatibility...
async def handle_request(self, async def handle_request(self,
......
...@@ -178,6 +178,14 @@ class TestServer: ...@@ -178,6 +178,14 @@ class TestServer:
RUN_SERVER_SCRIPT = """ RUN_SERVER_SCRIPT = """
import os
import sys
path = '.'
while not 'DHParser' in os.listdir(path) and len(path) < 20:
path = os.path.join('..', path)
sys.path.append(path)
def dummy(s: str) -> str: def dummy(s: str) -> str:
return s return s
...@@ -191,22 +199,28 @@ if __name__ == '__main__': ...@@ -191,22 +199,28 @@ if __name__ == '__main__':
run_server('127.0.0.1', 8888) run_server('127.0.0.1', 8888)
""" """
def asyncio_run(coroutine):
"""Backward compatible version of Pyhon 3.7's `asyncio.run()`"""
if sys.version_info >= (3, 7):
return asyncio.run(coroutine)
else:
loop = asyncio.get_event_loop()
return loop.run_until_complete(coroutine)
class TestSpawning: class TestSpawning:
"""Tests spawning a server by starting a script via subprocess.Popen.""" """Tests spawning a server by starting a script via subprocess.Popen."""
def stop_server(self):
async def send_stop_server():
try:
reader, writer = await asyncio.open_connection('127.0.0.1', 8888)
writer.write(STOP_SERVER_REQUEST)
_ = await reader.read(1024)
writer.close()
except ConnectionRefusedError:
pass
asyncio.run(send_stop_server())
def setup(self): def setup(self):
self.tmpdir = 'tmp_' + concurrent_ident() self.tmpdir = 'tmp_' + concurrent_ident()
os.mkdir(self.tmpdir) os.mkdir(self.tmpdir)
self.stop_server()
def teardown(self): def teardown(self):
self.stop_server()
for fname in os.listdir(self.tmpdir): for fname in os.listdir(self.tmpdir):
os.remove(os.path.join(self.tmpdir, fname)) os.remove(os.path.join(self.tmpdir, fname))
os.rmdir(self.tmpdir) os.rmdir(self.tmpdir)
...@@ -215,26 +229,32 @@ class TestSpawning: ...@@ -215,26 +229,32 @@ class TestSpawning:
scriptname = os.path.join(self.tmpdir, 'spawn_server.py') scriptname = os.path.join(self.tmpdir, 'spawn_server.py')
with open(scriptname, 'w') as f: with open(scriptname, 'w') as f:
f.write(RUN_SERVER_SCRIPT) f.write(RUN_SERVER_SCRIPT)
subprocess.Popen(['python', scriptname]) subprocess.Popen(['python3', scriptname])
countdown = 20
delay = 0.05 async def identify():
connected = False countdown = 20
reader, writer = None, None delay = 0.05
while countdown > 0: connected = False
try: reader, writer = None, None
reader, writer = asyncio_run(asyncio.open_connection('127.0.0.1', 8888)) while countdown > 0:
countdown = 0 try:
connected = True reader, writer = await asyncio.open_connection('127.0.0.1', 8888)
except ConnectionRefusedError: print(countdown)
time.sleep(delay) countdown = 0
delay += 0.0 connected = True
countdown -= 1 except ConnectionRefusedError:
if connected: time.sleep(delay)
writer.write(IDENTIFY_REQUEST.encode()) delay += 0.0
data = asyncio_run(reader.read(500)) countdown -= 1
writer.close() if connected:
print(data.decode()) writer.write(IDENTIFY_REQUEST.encode())
data = await reader.read(500)
writer.close()
return data.decode()
return ''
result = asyncio.run(identify())
print(result)
if __name__ == "__main__": if __name__ == "__main__":
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment