blob: 4959711adc23d12f1f7a961bcdb161445c113c59 [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import sys
def get_file_text(path):
""" Returns file text by path"""
file_io = open(path, "r")
text = file_io.read()
file_io.close()
return text
def get_file_output(encoding="utf-8", path=sys.argv[-1], arg_string=""):
"""
Returns answer file output
:param encoding: to decode output in python3
:param path: path of file to execute
:return: list of strings
"""
import subprocess
proc = subprocess.Popen([sys.executable, path], stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
if arg_string:
for arg in arg_string.split("\n"):
proc.stdin.write(bytearray(str(arg) + "\n", encoding))
proc.stdin.flush()
return list(map(lambda x: str(x.decode(encoding)), proc.communicate()[0].splitlines()))
def test_file_importable():
""" Tests there is no obvious syntax errors"""
path = sys.argv[-1]
if not path.endswith(".py"):
import os
parent = os.path.abspath(os.path.join(path, os.pardir))
python_files = [f for f in os.listdir(parent) if os.path.isfile(os.path.join(parent, f)) and f.endswith(".py")]
for python_file in python_files:
if python_file == "tests.py":
continue
check_importable_path(os.path.join(parent, python_file))
return
check_importable_path(path)
def check_importable_path(path):
""" Checks that file is importable.
Reports failure otherwise.
"""
saved_input = patch_input()
try:
import_file(path)
except:
failed("The file contains syntax errors", test_file_importable.__name__)
return
finally:
revert_input(saved_input)
passed(test_file_importable.__name__)
def patch_input():
def mock_fun(_m=""):
return "mock"
if sys.version_info[0] == 3:
import builtins
save_input = builtins.input
builtins.input = mock_fun
return save_input
elif sys.version_info[0] == 2:
import __builtin__
save_input = __builtin__.raw_input
__builtin__.raw_input = mock_fun
__builtin__.input = mock_fun
return save_input
def revert_input(saved_input):
if sys.version_info[0] == 3:
import builtins
builtins.input = saved_input
elif sys.version_info[0] == 2:
import __builtin__
__builtin__.raw_input = saved_input
__builtin__.input = saved_input
def import_file(path):
""" Returns imported file """
if sys.version_info[0] == 2 or sys.version_info[1] < 3:
import imp
return imp.load_source("tmp", path)
elif sys.version_info[0] == 3:
import importlib.machinery
return importlib.machinery.SourceFileLoader("tmp", path).load_module("tmp")
def import_task_file():
""" Returns imported file.
Imports file from which check action was run
"""
path = sys.argv[-1]
return import_file(path)
def test_is_not_empty():
"""
Checks that file is not empty
"""
path = sys.argv[-1]
file_text = get_file_text(path)
if len(file_text) > 0:
passed()
else:
failed("The file is empty. Please, reload the task and try again.")
def test_text_equals(text, error_text):
"""
Checks that answer equals text.
"""
path = sys.argv[-1]
file_text = get_file_text(path)
if file_text.strip() == text:
passed()
else:
failed(error_text)
def test_answer_placeholders_text_deleted(error_text="Don't just delete task text"):
"""
Checks that all answer placeholders are not empty
"""
windows = get_answer_placeholders()
for window in windows:
if len(window) == 0:
failed(error_text)
return
passed()
def set_congratulation_message(message):
""" Overrides default 'Congratulations!' message """
print("#educational_plugin CONGRATS_MESSAGE " + message)
def failed(message="Please, reload the task and try again.", name=None):
""" Reports failure """
if not name:
name = sys._getframe().f_back.f_code.co_name
print("#educational_plugin " + name + " FAILED + " + message)
def passed(name=None):
""" Reports success """
if not name:
name = sys._getframe().f_back.f_code.co_name
print("#educational_plugin " + name + " test OK")
def get_answer_placeholders():
"""
Returns all answer placeholders text
"""
prefix = "#educational_plugin_window = "
path = sys.argv[-1]
import os
file_name_without_extension = os.path.splitext(path)[0]
windows_path = file_name_without_extension + "_windows"
windows = []
f = open(windows_path, "r")
window_text = ""
first = True
for line in f.readlines():
if line.startswith(prefix):
if not first:
windows.append(window_text.strip())
else:
first = False
window_text = line[len(prefix):]
else:
window_text += line
if window_text:
windows.append(window_text.strip())
f.close()
return windows
def check_samples(samples=()):
"""
Check script output for all samples. Sample is a two element list, where the first is input and
the second is output.
"""
for sample in samples:
if len(sample) == 2:
output = get_file_output(arg_string=str(sample[0]))
if "\n".join(output) != sample[1]:
failed(
"Test from samples failed: \n \n"
"Input:\n{}"
"\n \n"
"Expected:\n{}"
"\n \n"
"Your result:\n{}".format(str.strip(sample[0]), str.strip(sample[1]), "\n".join(output)))
return
set_congratulation_message("All test from samples passed. Now we are checking your solution on Stepik server.")
passed()
def run_common_tests(error_text="Please, reload file and try again"):
test_is_not_empty()
test_answer_placeholders_text_deleted()
test_file_importable()