diff --git a/src/julia/options.py b/src/julia/options.py index 52d93647..00ba9801 100644 --- a/src/julia/options.py +++ b/src/julia/options.py @@ -41,6 +41,35 @@ def _domain(self): # used in test return str +class IntEtc(OptionDescriptor): + def __init__(self, name, *, etc={}): + self.name = name + self.default = etc + + def __set__(self, instance, value): + if instance is None: + raise AttributeError(self.name) + elif value in {None, *self.default} or isinstance(value, int): + setattr(instance, self.dataname, value) + else: + if self.default: + part = " or " + " ".join(map(str, self.default)) + else: + part = "" + raise ValueError( + f"Option {self.name} only accepts integers{part}. Got: {value}" + ) + + def _domain(self): + return {int, *self.default} + + def cli_argument_spec(self): + return dict( + super(IntEtc, self).cli_argument_spec(), + choices=list(self.default) + ["1", "2", "3", "..."], + ) + + class Choices(OptionDescriptor): def __init__(self, name, choicemap, default=None): self.name = name @@ -110,6 +139,12 @@ def yes_no_etc(*etc): warn_overwrite: {True, False, 'yes', 'no'} Enable or disable method overwrite warnings. + +min_optlevel: {0, 1, 2, 3} + Lower bound on the optimization level. + +threads: {int, 'auto'} + How many threads to use. """ @@ -134,9 +169,11 @@ class JuliaOptions(object): compile = Choices("compile", yes_no_etc("all", "min")) depwarn = Choices("depwarn", yes_no_etc("error")) warn_overwrite = Choices("warn_overwrite", yes_no_etc()) + min_optlevel = Choices("min_optlevel", dict(zip(range(4), map(str, range(4))))) optimize = Choices("optimize", dict(zip(range(4), map(str, range(4))))) inline = Choices("inline", yes_no_etc()) check_bounds = Choices("check_bounds", yes_no_etc()) + threads = IntEtc("threads", etc={"auto"}) def __init__(self, **kwargs): unsupported = [] @@ -168,8 +205,12 @@ def specified(self): def as_args(self): args = [] for (desc, value) in self.specified(): - args.append(desc.cli_argument_name()) - args.append(value) + if value is None: + ... + elif len(desc.cli_argument_name()) == 1: + args.append(desc.cli_argument_name() + str(value)) + else: + args.append(desc.cli_argument_name() + "=" + str(value)) return args @classmethod diff --git a/src/julia/tests/test_compatible_exe.py b/src/julia/tests/test_compatible_exe.py index afa78cf9..13a61c1f 100644 --- a/src/julia/tests/test_compatible_exe.py +++ b/src/julia/tests/test_compatible_exe.py @@ -23,7 +23,7 @@ def discover_other_pythons(): [sys.executable, "--version"], universal_newlines=True, stderr=subprocess.STDOUT ) - candidate_names = ["python", "python2", "python2.7", "python3"] + [ + candidate_names = ["python", "python3"] + [ "python3.{}".format(i) for i in range(20) ] found = {} diff --git a/src/julia/tests/test_juliaoptions.py b/src/julia/tests/test_juliaoptions.py index b793e730..cb82953a 100644 --- a/src/julia/tests/test_juliaoptions.py +++ b/src/julia/tests/test_juliaoptions.py @@ -7,12 +7,17 @@ @pytest.mark.parametrize("kwargs, args", [ ({}, []), (dict(compiled_modules=None), []), - (dict(compiled_modules=False), ["--compiled-modules", "no"]), - (dict(compiled_modules="no"), ["--compiled-modules", "no"]), - (dict(depwarn="error"), ["--depwarn", "error"]), - (dict(sysimage="PATH"), ["--sysimage", "PATH"]), - (dict(bindir="PATH"), ["--home", "PATH"]), - (dict(optimize=3), ["--optimize", "3"]), + (dict(compiled_modules=False), ["--compiled-modules=no"]), + (dict(compiled_modules="no"), ["--compiled-modules=no"]), + (dict(depwarn="error"), ["--depwarn=error"]), + (dict(sysimage="PATH"), ["--sysimage=PATH"]), + (dict(bindir="PATH"), ["--home=PATH"]), + (dict(optimize=3), ["--optimize=3"]), + (dict(threads=4), ["--threads=4"]), + (dict(min_optlevel=2), ["--min-optlevel=2"]), + (dict(threads="auto", optimize=3), ["--optimize=3", '--threads=auto']), + (dict(optimize=3, threads="auto"), ["--optimize=3", '--threads=auto']), # passed order doesn't matter + (dict(compiled_modules=None, depwarn="yes"), ["--depwarn=yes"]), ]) # fmt: on def test_as_args(kwargs, args):