예제 #1
0
def create_bundle(config: DodonaConfig,
                  output: IO,
                  plan: testplan.Plan,
                  language: Optional[str] = None) -> Bundle:
    """
    Create a configuration bundle.

    :param config: The Dodona configuration.
    :param output: Where the output should go.
    :param plan: The testplan.
    :param language: Optional programming language. If None, the one from the Dodona
                     configuration will be used.

    :return: The configuration bundle.
    """
    import tested.languages as langs

    if language is None:
        language = _get_language(config)
    # noinspection PyDataclass
    adjusted_config = config.copy(update={"programming_language": language})
    lang_config = langs.get_language(language)
    return Bundle(
        config=adjusted_config,
        out=output,
        lang_config=lang_config,
        secret=utils.get_identifier(),
        context_separator_secret=utils.get_identifier(),
        plan=plan
    )
예제 #2
0
    def is_supported(language: str) -> bool:
        language: Language = get_language(language)

        from .languages.config import TypeSupport

        required = testplan.get_used_features()

        # Check constructs
        available_constructs = language.supported_constructs()
        if not (required.constructs <= available_constructs):
            return False

        mapping = language.type_support_map()
        for t in required.types:
            if mapping[t] == TypeSupport.UNSUPPORTED:
                return False

        # Check language specific evaluators
        for testcase in (testcase for tab in testplan.tabs
                         for run in tab.runs
                         for context in run.contexts
                         for testcase in context.all_testcases()):
            eval_langs = testcase.output.get_specific_eval_languages()
            if eval_langs is not None and language not in eval_langs:
                return False

        nested_types = filter(lambda x: x[0] in (
            BasicSequenceTypes.SET, BasicObjectTypes.MAP), required.nested_types)
        restricted = language.restriction_map()
        for key, value_types in nested_types:
            if not (value_types <= restricted[key]):
                return False

        return True
예제 #3
0
def configuration(config,
                  exercise: str,
                  language: str,
                  work_dir: Path,
                  plan: str = "plan.json",
                  solution: str = "solution",
                  options=None) -> DodonaConfig:
    """Create a config."""
    # Get the file extension for this language.
    ext = get_language(language).extension_file()
    if options is None:
        options = {}
    exercise_dir = Path(config.rootdir).parent / "exercise"
    ep = f'{exercise_dir}/{exercise}'
    return DodonaConfig(**merge(
        {
            "memory_limit": 536870912,
            "time_limit": threading.TIMEOUT_MAX,
            "programming_language": language,
            "natural_language": 'nl',
            "resources": Path(f'{ep}/evaluation'),
            "source": Path(f'{ep}/solution/{solution}.{ext}'),
            "judge": Path(f'{config.rootdir}/src'),
            "workdir": work_dir,
            "plan_name": plan,
        }, options))
예제 #4
0
def configuration(config, exercise: str, language: str, work_dir: Path,
                  plan: str = "plan.json", solution: str = "solution",
                  options=None, backward_compatibility_plan: bool = False) -> DodonaConfig:
    """Create a config."""
    # Get the file extension for this language.
    ext = get_language(language).extension_file()
    if options is None:
        options = {}
    exercise_dir = Path(config.rootdir) / "exercise"
    ep = f'{exercise_dir}/{exercise}'
    testplan = "plan_name" if backward_compatibility_plan else "testplan"
    return DodonaConfig(**merge({
        "memory_limit":         536870912,
        "time_limit":           3600,  # One hour
        "programming_language": language,
        "natural_language":     'nl',
        "resources":            Path(f'{ep}/evaluation'),
        "source":               Path(f'{ep}/solution/{solution}.{ext}'),
        "judge":                Path(f'{config.rootdir}'),
        "workdir":              work_dir,
        testplan:               plan,
        "options":              {
            "linter": False
        }
    }, options))
예제 #5
0
def _language_inheritance_tree(bundle: Bundle) -> List[str]:
    current = bundle.lang_config
    result = [bundle.config.programming_language]
    while lang := current.inherits_from():
        result.append(lang)
        current = get_language(lang)
예제 #6
0
def create_description_instance_from_template(
        template: Template,
        programming_language: str = "python",
        natural_language: str = "en",
        namespace: str = "submission",
        is_html: bool = True) -> str:
    from pathlib import Path
    judge_directory = Path(__file__).parent.parent
    language = get_language(programming_language)

    bundle = Bundle(config=DodonaConfig(
        resources="",
        source="",
        time_limit=0,
        memory_limit=0,
        natural_language=natural_language,
        programming_language=programming_language,
        workdir="",
        judge=str(judge_directory)),
                    out=open(os.devnull, 'w'),
                    lang_config=language,
                    context_separator_secret="",
                    secret="",
                    plan=Plan(namespace=namespace))

    description_generator = language.get_description_generator()

    # Partial function doesn't work because of bundle must be given,
    # but custom_type_map not
    def get_type_name(args: TYPE_ARG,
                      custom_type_map: TYPE_CONFIG_NAME = None) -> str:
        return description_generator.get_type_name(args,
                                                   bundle,
                                                   custom_type_map,
                                                   is_html=is_html)

    def get_natural_type_name(type_name: str, plural: bool = False):
        return description_generator.get_natural_type_name(
            type_name, bundle, plural, is_html)

    def get_variable(var_name: str, is_global: bool = True):
        if is_global:
            return description_generator.get_global_variable_name(
                var_name, is_html)
        return description_generator.get_variable_name(var_name, is_html)

    namespace = language.conventionalize_namespace(namespace)
    if is_html:
        namespace = html.escape(namespace)

    return template.render(
        function=partial(description_generator.get_function_name,
                         is_html=is_html),
        property=partial(description_generator.get_property_name,
                         is_html=is_html),
        variable=get_variable,
        datatype_common=get_natural_type_name,
        datatype=get_type_name,
        statement=partial(description_generator.get_code,
                          bundle=bundle,
                          is_html=is_html,
                          statement=True),
        expression=partial(description_generator.get_code,
                           bundle=bundle,
                           is_html=is_html,
                           statement=False),
        prompt=description_generator.get_prompt(is_html=is_html),
        programming_language=description_generator.get_prompt_language(
            is_html=is_html),
        programming_language_raw=description_generator.get_prompt_language(
            is_html=False),
        namespace=language.conventionalize_namespace(namespace),
        natural_language=natural_languages.get(natural_language,
                                               natural_language),
        natural_language_iso639=natural_language)