mkosi fails to build with Python 3.11.0a4. =================================== FAILURES =================================== _______________________ test_def[MkosiConfigManyParams] ________________________ cls = <enum 'ManifestFormat'>, name = 'ManifestFormat.json' @classmethod def from_string(cls: Any, name: str) -> Any: """A convenience method to be used with argparse""" try: > return cls[name] mkosi/backend.py:97: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ cls = <enum 'ManifestFormat'>, name = 'ManifestFormat.json' def __getitem__(cls, name): """ Return the member matching `name`. """ > return cls._member_map_[name] E KeyError: 'ManifestFormat.json' /usr/lib64/python3.11/enum.py:818: KeyError During handling of the above exception, another exception occurred: self = ArgumentParserMkosi(prog='mkosi', usage=None, description='Build Bespoke OS Images', formatter_class=<class 'mkosi.CustomHelpFormatter'>, conflict_handler='error', add_help=False) action = CommaDelimitedListAction(option_strings=['--manifest-format'], dest='manifest_format', nargs=None, const=None, default...ype=<bound method Parseable.parse_list of <enum 'ManifestFormat'>>, choices=None, help='Manifest Format', metavar=None) arg_string = 'ManifestFormat.json' def _get_value(self, action, arg_string): type_func = self._registry_get('type', action.type, action.type) if not callable(type_func): msg = _('%r is not callable') raise ArgumentError(action, msg % type_func) # convert the value to the appropriate type try: > result = type_func(arg_string) /usr/lib64/python3.11/argparse.py:2500: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ cls = <enum 'ManifestFormat'>, string = 'ManifestFormat.json' @classmethod def parse_list(cls: Any, string: str) -> List[Any]: > return [cls.from_string(p) for p in string.split(",") if p] mkosi/backend.py:103: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ .0 = <list_iterator object at 0x7f11704a1030> > return [cls.from_string(p) for p in string.split(",") if p] mkosi/backend.py:103: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ cls = <enum 'ManifestFormat'>, name = 'ManifestFormat.json' @classmethod def from_string(cls: Any, name: str) -> Any: """A convenience method to be used with argparse""" try: return cls[name] except KeyError: > raise argparse.ArgumentTypeError(f"unknown Format: {name!r}") E argparse.ArgumentTypeError: unknown Format: 'ManifestFormat.json' mkosi/backend.py:99: ArgumentTypeError During handling of the above exception, another exception occurred: self = ArgumentParserMkosi(prog='mkosi', usage=None, description='Build Bespoke OS Images', formatter_class=<class 'mkosi.CustomHelpFormatter'>, conflict_handler='error', add_help=False) args = ['@/tmp/pytest-of-mockbuild/pytest-0/test_def_MkosiConfigManyParams0/mkosi.default', '--', 'build'] namespace = <[AttributeError("'int' object has no attribute 'name'") raised in repr()] Namespace object at 0x7f116fe03950> def parse_known_args(self, args=None, namespace=None): if args is None: # args default to the system args args = _sys.argv[1:] else: # make sure that args are mutable args = list(args) # default Namespace built from parser defaults if namespace is None: namespace = Namespace() # add any action defaults that aren't present for action in self._actions: if action.dest is not SUPPRESS: if not hasattr(namespace, action.dest): if action.default is not SUPPRESS: setattr(namespace, action.dest, action.default) # add any parser defaults that aren't present for dest in self._defaults: if not hasattr(namespace, dest): setattr(namespace, dest, self._defaults[dest]) # parse the arguments and exit if there are any errors if self.exit_on_error: try: > namespace, args = self._parse_known_args(args, namespace) /usr/lib64/python3.11/argparse.py:1877: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = ArgumentParserMkosi(prog='mkosi', usage=None, description='Build Bespoke OS Images', formatter_class=<class 'mkosi.CustomHelpFormatter'>, conflict_handler='error', add_help=False) arg_strings = ['--distribution', 'fedora', '--release', '28', '--repositories', 'http://fedora/repos', ...] namespace = <[AttributeError("'int' object has no attribute 'name'") raised in repr()] Namespace object at 0x7f116fe03950> def _parse_known_args(self, arg_strings, namespace): # replace arg strings that are file references if self.fromfile_prefix_chars is not None: arg_strings = self._read_args_from_files(arg_strings) # map all mutually exclusive arguments to the other arguments # they can't occur with action_conflicts = {} for mutex_group in self._mutually_exclusive_groups: group_actions = mutex_group._group_actions for i, mutex_action in enumerate(mutex_group._group_actions): conflicts = action_conflicts.setdefault(mutex_action, []) conflicts.extend(group_actions[:i]) conflicts.extend(group_actions[i + 1:]) # find all option indices, and determine the arg_string_pattern # which has an 'O' if there is an option at an index, # an 'A' if there is an argument, or a '-' if there is a '--' option_string_indices = {} arg_string_pattern_parts = [] arg_strings_iter = iter(arg_strings) for i, arg_string in enumerate(arg_strings_iter): # all args after -- are non-options if arg_string == '--': arg_string_pattern_parts.append('-') for arg_string in arg_strings_iter: arg_string_pattern_parts.append('A') # otherwise, add the arg to the arg strings # and note the index if it was an option else: option_tuple = self._parse_optional(arg_string) if option_tuple is None: pattern = 'A' else: option_string_indices[i] = option_tuple pattern = 'O' arg_string_pattern_parts.append(pattern) # join the pieces together to form the pattern arg_strings_pattern = ''.join(arg_string_pattern_parts) # converts arg strings to the appropriate and then takes the action seen_actions = set() seen_non_default_actions = set() def take_action(action, argument_strings, option_string=None): seen_actions.add(action) argument_values = self._get_values(action, argument_strings) # error if this argument is not allowed with other previously # seen arguments, assuming that actions that use the default # value don't really count as "present" if argument_values is not action.default: seen_non_default_actions.add(action) for conflict_action in action_conflicts.get(action, []): if conflict_action in seen_non_default_actions: msg = _('not allowed with argument %s') action_name = _get_action_name(conflict_action) raise ArgumentError(action, msg % action_name) # take the action if we didn't receive a SUPPRESS value # (e.g. from a default) if argument_values is not SUPPRESS: action(self, namespace, argument_values, option_string) # function to convert arg_strings into an optional action def consume_optional(start_index): # get the optional identified at this index option_tuple = option_string_indices[start_index] action, option_string, explicit_arg = option_tuple # identify additional optionals in the same arg string # (e.g. -xyz is the same as -x -y -z if no args are required) match_argument = self._match_argument action_tuples = [] while True: # if we found no optional action, skip it if action is None: extras.append(arg_strings[start_index]) return start_index + 1 # if there is an explicit argument, try to match the # optional's string arguments to only this if explicit_arg is not None: arg_count = match_argument(action, 'A') # if the action is a single-dash option and takes no # arguments, try to parse more single-dash options out # of the tail of the option string chars = self.prefix_chars if arg_count == 0 and option_string[1] not in chars: action_tuples.append((action, [], option_string)) char = option_string[0] option_string = char + explicit_arg[0] new_explicit_arg = explicit_arg[1:] or None optionals_map = self._option_string_actions if option_string in optionals_map: action = optionals_map[option_string] explicit_arg = new_explicit_arg else: msg = _('ignored explicit argument %r') raise ArgumentError(action, msg % explicit_arg) # if the action expect exactly one argument, we've # successfully matched the option; exit the loop elif arg_count == 1: stop = start_index + 1 args = [explicit_arg] action_tuples.append((action, args, option_string)) break # error if a double-dash option did not use the # explicit argument else: msg = _('ignored explicit argument %r') raise ArgumentError(action, msg % explicit_arg) # if there is no explicit argument, try to match the # optional's string arguments with the following strings # if successful, exit the loop else: start = start_index + 1 selected_patterns = arg_strings_pattern[start:] arg_count = match_argument(action, selected_patterns) stop = start + arg_count args = arg_strings[start:stop] action_tuples.append((action, args, option_string)) break # add the Optional to the list and return the index at which # the Optional's string args stopped assert action_tuples for action, args, option_string in action_tuples: take_action(action, args, option_string) return stop # the list of Positionals left to be parsed; this is modified # by consume_positionals() positionals = self._get_positional_actions() # function to convert arg_strings into positional actions def consume_positionals(start_index): # match as many Positionals as possible match_partial = self._match_arguments_partial selected_pattern = arg_strings_pattern[start_index:] arg_counts = match_partial(positionals, selected_pattern) # slice off the appropriate arg strings for each Positional # and add the Positional and its args to the list for action, arg_count in zip(positionals, arg_counts): args = arg_strings[start_index: start_index + arg_count] start_index += arg_count take_action(action, args) # slice off the Positionals that we just parsed and return the # index at which the Positionals' string args stopped positionals[:] = positionals[len(arg_counts):] return start_index # consume Positionals and Optionals alternately, until we have # passed the last option string extras = [] start_index = 0 if option_string_indices: max_option_string_index = max(option_string_indices) else: max_option_string_index = -1 while start_index <= max_option_string_index: # consume any Positionals preceding the next option next_option_string_index = min([ index for index in option_string_indices if index >= start_index]) if start_index != next_option_string_index: positionals_end_index = consume_positionals(start_index) # only try to parse the next optional if we didn't consume # the option string during the positionals parsing if positionals_end_index > start_index: start_index = positionals_end_index continue else: start_index = positionals_end_index # if we consumed all the positionals we could and we're not # at the index of an option string, there were extra arguments if start_index not in option_string_indices: strings = arg_strings[start_index:next_option_string_index] extras.extend(strings) start_index = next_option_string_index # consume the next optional and any arguments for it > start_index = consume_optional(start_index) /usr/lib64/python3.11/argparse.py:2085: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ start_index = 16 def consume_optional(start_index): # get the optional identified at this index option_tuple = option_string_indices[start_index] action, option_string, explicit_arg = option_tuple # identify additional optionals in the same arg string # (e.g. -xyz is the same as -x -y -z if no args are required) match_argument = self._match_argument action_tuples = [] while True: # if we found no optional action, skip it if action is None: extras.append(arg_strings[start_index]) return start_index + 1 # if there is an explicit argument, try to match the # optional's string arguments to only this if explicit_arg is not None: arg_count = match_argument(action, 'A') # if the action is a single-dash option and takes no # arguments, try to parse more single-dash options out # of the tail of the option string chars = self.prefix_chars if arg_count == 0 and option_string[1] not in chars: action_tuples.append((action, [], option_string)) char = option_string[0] option_string = char + explicit_arg[0] new_explicit_arg = explicit_arg[1:] or None optionals_map = self._option_string_actions if option_string in optionals_map: action = optionals_map[option_string] explicit_arg = new_explicit_arg else: msg = _('ignored explicit argument %r') raise ArgumentError(action, msg % explicit_arg) # if the action expect exactly one argument, we've # successfully matched the option; exit the loop elif arg_count == 1: stop = start_index + 1 args = [explicit_arg] action_tuples.append((action, args, option_string)) break # error if a double-dash option did not use the # explicit argument else: msg = _('ignored explicit argument %r') raise ArgumentError(action, msg % explicit_arg) # if there is no explicit argument, try to match the # optional's string arguments with the following strings # if successful, exit the loop else: start = start_index + 1 selected_patterns = arg_strings_pattern[start:] arg_count = match_argument(action, selected_patterns) stop = start + arg_count args = arg_strings[start:stop] action_tuples.append((action, args, option_string)) break # add the Optional to the list and return the index at which # the Optional's string args stopped assert action_tuples for action, args, option_string in action_tuples: > take_action(action, args, option_string) /usr/lib64/python3.11/argparse.py:2025: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ action = CommaDelimitedListAction(option_strings=['--manifest-format'], dest='manifest_format', nargs=None, const=None, default...ype=<bound method Parseable.parse_list of <enum 'ManifestFormat'>>, choices=None, help='Manifest Format', metavar=None) argument_strings = ['ManifestFormat.json'], option_string = '--manifest-format' def take_action(action, argument_strings, option_string=None): seen_actions.add(action) > argument_values = self._get_values(action, argument_strings) /usr/lib64/python3.11/argparse.py:1937: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = ArgumentParserMkosi(prog='mkosi', usage=None, description='Build Bespoke OS Images', formatter_class=<class 'mkosi.CustomHelpFormatter'>, conflict_handler='error', add_help=False) action = CommaDelimitedListAction(option_strings=['--manifest-format'], dest='manifest_format', nargs=None, const=None, default...ype=<bound method Parseable.parse_list of <enum 'ManifestFormat'>>, choices=None, help='Manifest Format', metavar=None) arg_strings = ['ManifestFormat.json'] def _get_values(self, action, arg_strings): # for everything but PARSER, REMAINDER args, strip out first '--' if action.nargs not in [PARSER, REMAINDER]: try: arg_strings.remove('--') except ValueError: pass # optional argument produces a default when not present if not arg_strings and action.nargs == OPTIONAL: if action.option_strings: value = action.const else: value = action.default if isinstance(value, str): value = self._get_value(action, value) self._check_value(action, value) # when nargs='*' on a positional, if there were no command-line # args, use the default if it is anything other than None elif (not arg_strings and action.nargs == ZERO_OR_MORE and not action.option_strings): if action.default is not None: value = action.default else: value = arg_strings self._check_value(action, value) # single argument or optional argument produces a single value elif len(arg_strings) == 1 and action.nargs in [None, OPTIONAL]: arg_string, = arg_strings > value = self._get_value(action, arg_string) /usr/lib64/python3.11/argparse.py:2467: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = ArgumentParserMkosi(prog='mkosi', usage=None, description='Build Bespoke OS Images', formatter_class=<class 'mkosi.CustomHelpFormatter'>, conflict_handler='error', add_help=False) action = CommaDelimitedListAction(option_strings=['--manifest-format'], dest='manifest_format', nargs=None, const=None, default...ype=<bound method Parseable.parse_list of <enum 'ManifestFormat'>>, choices=None, help='Manifest Format', metavar=None) arg_string = 'ManifestFormat.json' def _get_value(self, action, arg_string): type_func = self._registry_get('type', action.type, action.type) if not callable(type_func): msg = _('%r is not callable') raise ArgumentError(action, msg % type_func) # convert the value to the appropriate type try: result = type_func(arg_string) # ArgumentTypeErrors indicate errors except ArgumentTypeError as err: name = getattr(action.type, '__name__', repr(action.type)) msg = str(err) > raise ArgumentError(action, msg) E argparse.ArgumentError: argument --manifest-format: unknown Format: 'ManifestFormat.json' /usr/lib64/python3.11/argparse.py:2506: ArgumentError During handling of the above exception, another exception occurred: tested_config = <tests.test_config_parser.MkosiConfigManyParams object at 0x7f116fa76bd0> tmpdir = local('/tmp/pytest-of-mockbuild/pytest-0/test_def_MkosiConfigManyParams0') def test_def(tested_config, tmpdir): """Generate the mkosi.default file only""" with change_cwd(tmpdir.strpath): tested_config.prepare_mkosi_default(tmpdir.strpath) > args = mkosi.parse_args(tested_config.cli_arguments) tests/test_config_parser.py:914: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ mkosi/__init__.py:5689: in parse_args args = parse_args_file_group(argv, os.fspath(default_path)) mkosi/__init__.py:5743: in parse_args_file_group return create_parser().parse_args(defaults_files + argv) /usr/lib64/python3.11/argparse.py:1844: in parse_args args, argv = self.parse_known_args(args, namespace) /usr/lib64/python3.11/argparse.py:1879: in parse_known_args self.error(str(err)) /usr/lib64/python3.11/argparse.py:2599: in error self.exit(2, _('%(prog)s: error: %(message)s\n') % args) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = ArgumentParserMkosi(prog='mkosi', usage=None, description='Build Bespoke OS Images', formatter_class=<class 'mkosi.CustomHelpFormatter'>, conflict_handler='error', add_help=False) status = 2 message = "mkosi: error: argument --manifest-format: unknown Format: 'ManifestFormat.json'\n" def exit(self, status=0, message=None): if message: self._print_message(message, _sys.stderr) > _sys.exit(status) E SystemExit: 2 /usr/lib64/python3.11/argparse.py:2586: SystemExit ----------------------------- Captured stderr call ----------------------------- usage: mkosi [-h] [--version] [-d {fedora,debian,ubuntu,arch,opensuse,mageia,centos,centos_epel,clear,photon,openmandriva,rocky,rocky_epel,alma,alma_epel,gentoo}] [-r RELEASE] [-m MIRROR] [--repositories REPOS] [--use-host-repositories [USE_HOST_REPOSITORIES]] [--architecture ARCHITECTURE] [-t {OutputFormat.directory,OutputFormat.subvolume,OutputFormat.tar,OutputFormat.cpio,OutputFormat.gpt_ext4,OutputFormat.gpt_xfs,OutputFormat.gpt_btrfs,OutputFormat.gpt_squashfs,OutputFormat.plain_squashfs}] [--manifest-format MANIFEST_FORMAT] [-o PATH] [--output-split-root PATH] [--output-split-verity PATH] [--output-split-verity-sig PATH] [--output-split-kernel PATH] [-O DIR] [--workspace-dir DIR] [-f] [-b [BOOTABLE]] [--boot-protocols PROTOCOLS] [--kernel-command-line KERNEL_COMMAND_LINE] [--secure-boot [SECURE_BOOT]] [--secure-boot-key PATH] [--secure-boot-certificate PATH] [--secure-boot-valid-days DAYS] [--secure-boot-common-name CN] [--read-only [READ_ONLY]] [--encrypt {all,data}] [--verity [VERITY]] [--compress [ALG]] [--compress-fs [ALG]] [--compress-output [ALG]] [--mksquashfs MKSQUASHFS_TOOL] [--qcow2 [QCOW2]] [--hostname HOSTNAME] [--image-version IMAGE_VERSION] [--image-id IMAGE_ID] [--no-chown [NO_CHOWN]] [--tar-strip-selinux-context [TAR_STRIP_SELINUX_CONTEXT]] [-i [INCREMENTAL]] [-M [MINIMIZE]] [--without-unified-kernel-images [WITH_UNIFIED_KERNEL_IMAGES]] [--gpt-first-lba FIRSTLBA] [--hostonly-initrd [HOSTONLY_INITRD]] [--split-artifacts [SPLIT_ARTIFACTS]] [--base-packages OPTION] [-p PACKAGE] [--remove-package PACKAGE] [--with-docs [WITH_DOCS]] [-T [WITH_TESTS]] [--password PASSWORD] [--password-is-hashed [PASSWORD_IS_HASHED]] [--autologin [AUTOLOGIN]] [--cache PATH] [--extra-tree PATH] [--skeleton-tree PATH] [--clean-package-metadata [CLEAN_PACKAGE_METADATA]] [--remove-files GLOB] [--environment NAME[=VALUE]] [--build-sources PATH] [--build-directory PATH] [--include-directory PATH] [--install-directory PATH] [--build-package PACKAGE] [--skip-final-phase [SKIP_FINAL_PHASE]] [--build-script PATH] [--prepare-script PATH] [--postinst-script PATH] [--finalize-script PATH] [--source-file-transfer {copy-all,copy-git-cached,copy-git-others,copy-git-more,mount,None}] [--source-file-transfer-final {copy-all,copy-git-cached,copy-git-others,copy-git-more,mount,None}] [--source-resolve-symlinks [SOURCE_RESOLVE_SYMLINKS]] [--source-resolve-symlinks-final [SOURCE_RESOLVE_SYMLINKS_FINAL]] [--with-network [WITH_NETWORK]] [--settings PATH] [--base-image IMAGE] [--root-size BYTES] [--esp-size BYTES] [--xbootldr-size BYTES] [--swap-size BYTES] [--home-size BYTES] [--srv-size BYTES] [--var-size BYTES] [--tmp-size BYTES] [--usr-only [USR_ONLY]] [--checksum [CHECKSUM]] [--sign [SIGN]] [--key KEY] [--bmap [BMAP]] [--extra-search-path EXTRA_SEARCH_PATHS] [--qemu-headless [QEMU_HEADLESS]] [--qemu-smp SMP] [--qemu-mem MEM] [--network-veth [NETWORK_VETH]] [--ephemeral [EPHEMERAL]] [--ssh [SSH]] [--ssh-key PATH] [--ssh-timeout SECONDS] [--ssh-agent PATH] [--ssh-port PORT] [-C PATH] [--default PATH] [-a] [--all-directory PATH] [-B [AUTO_BUMP]] [--debug {run,build-script,workspace-command,disk}] {build,clean,help,summary,genkey,bump,serve,build,shell,boot,qemu,ssh} ... mkosi: error: argument --manifest-format: unknown Format: 'ManifestFormat.json' ______________________ test_def_1[MkosiConfigManyParams] _______________________ cls = <enum 'ManifestFormat'>, name = 'ManifestFormat.json' @classmethod def from_string(cls: Any, name: str) -> Any: """A convenience method to be used with argparse""" try: > return cls[name] mkosi/backend.py:97: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ cls = <enum 'ManifestFormat'>, name = 'ManifestFormat.json' def __getitem__(cls, name): """ Return the member matching `name`. """ > return cls._member_map_[name] E KeyError: 'ManifestFormat.json' /usr/lib64/python3.11/enum.py:818: KeyError During handling of the above exception, another exception occurred: self = ArgumentParserMkosi(prog='mkosi', usage=None, description='Build Bespoke OS Images', formatter_class=<class 'mkosi.CustomHelpFormatter'>, conflict_handler='error', add_help=False) action = CommaDelimitedListAction(option_strings=['--manifest-format'], dest='manifest_format', nargs=None, const=None, default...ype=<bound method Parseable.parse_list of <enum 'ManifestFormat'>>, choices=None, help='Manifest Format', metavar=None) arg_string = 'ManifestFormat.json' def _get_value(self, action, arg_string): type_func = self._registry_get('type', action.type, action.type) if not callable(type_func): msg = _('%r is not callable') raise ArgumentError(action, msg % type_func) # convert the value to the appropriate type try: > result = type_func(arg_string) /usr/lib64/python3.11/argparse.py:2500: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ cls = <enum 'ManifestFormat'>, string = 'ManifestFormat.json' @classmethod def parse_list(cls: Any, string: str) -> List[Any]: > return [cls.from_string(p) for p in string.split(",") if p] mkosi/backend.py:103: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ .0 = <list_iterator object at 0x7f116f4774c0> > return [cls.from_string(p) for p in string.split(",") if p] mkosi/backend.py:103: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ cls = <enum 'ManifestFormat'>, name = 'ManifestFormat.json' @classmethod def from_string(cls: Any, name: str) -> Any: """A convenience method to be used with argparse""" try: return cls[name] except KeyError: > raise argparse.ArgumentTypeError(f"unknown Format: {name!r}") E argparse.ArgumentTypeError: unknown Format: 'ManifestFormat.json' mkosi/backend.py:99: ArgumentTypeError During handling of the above exception, another exception occurred: self = ArgumentParserMkosi(prog='mkosi', usage=None, description='Build Bespoke OS Images', formatter_class=<class 'mkosi.CustomHelpFormatter'>, conflict_handler='error', add_help=False) args = ['@/tmp/pytest-of-mockbuild/pytest-0/test_def_1_MkosiConfigManyPara0/mkosi.default', '@mkosi.default.d/001_mkosi.conf', '--', 'build'] namespace = <[AttributeError("'int' object has no attribute 'name'") raised in repr()] Namespace object at 0x7f116fde5190> def parse_known_args(self, args=None, namespace=None): if args is None: # args default to the system args args = _sys.argv[1:] else: # make sure that args are mutable args = list(args) # default Namespace built from parser defaults if namespace is None: namespace = Namespace() # add any action defaults that aren't present for action in self._actions: if action.dest is not SUPPRESS: if not hasattr(namespace, action.dest): if action.default is not SUPPRESS: setattr(namespace, action.dest, action.default) # add any parser defaults that aren't present for dest in self._defaults: if not hasattr(namespace, dest): setattr(namespace, dest, self._defaults[dest]) # parse the arguments and exit if there are any errors if self.exit_on_error: try: > namespace, args = self._parse_known_args(args, namespace) /usr/lib64/python3.11/argparse.py:1877: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = ArgumentParserMkosi(prog='mkosi', usage=None, description='Build Bespoke OS Images', formatter_class=<class 'mkosi.CustomHelpFormatter'>, conflict_handler='error', add_help=False) arg_strings = ['--distribution', 'fedora', '--release', '28', '--repositories', 'http://fedora/repos', ...] namespace = <[AttributeError("'int' object has no attribute 'name'") raised in repr()] Namespace object at 0x7f116fde5190> def _parse_known_args(self, arg_strings, namespace): # replace arg strings that are file references if self.fromfile_prefix_chars is not None: arg_strings = self._read_args_from_files(arg_strings) # map all mutually exclusive arguments to the other arguments # they can't occur with action_conflicts = {} for mutex_group in self._mutually_exclusive_groups: group_actions = mutex_group._group_actions for i, mutex_action in enumerate(mutex_group._group_actions): conflicts = action_conflicts.setdefault(mutex_action, []) conflicts.extend(group_actions[:i]) conflicts.extend(group_actions[i + 1:]) # find all option indices, and determine the arg_string_pattern # which has an 'O' if there is an option at an index, # an 'A' if there is an argument, or a '-' if there is a '--' option_string_indices = {} arg_string_pattern_parts = [] arg_strings_iter = iter(arg_strings) for i, arg_string in enumerate(arg_strings_iter): # all args after -- are non-options if arg_string == '--': arg_string_pattern_parts.append('-') for arg_string in arg_strings_iter: arg_string_pattern_parts.append('A') # otherwise, add the arg to the arg strings # and note the index if it was an option else: option_tuple = self._parse_optional(arg_string) if option_tuple is None: pattern = 'A' else: option_string_indices[i] = option_tuple pattern = 'O' arg_string_pattern_parts.append(pattern) # join the pieces together to form the pattern arg_strings_pattern = ''.join(arg_string_pattern_parts) # converts arg strings to the appropriate and then takes the action seen_actions = set() seen_non_default_actions = set() def take_action(action, argument_strings, option_string=None): seen_actions.add(action) argument_values = self._get_values(action, argument_strings) # error if this argument is not allowed with other previously # seen arguments, assuming that actions that use the default # value don't really count as "present" if argument_values is not action.default: seen_non_default_actions.add(action) for conflict_action in action_conflicts.get(action, []): if conflict_action in seen_non_default_actions: msg = _('not allowed with argument %s') action_name = _get_action_name(conflict_action) raise ArgumentError(action, msg % action_name) # take the action if we didn't receive a SUPPRESS value # (e.g. from a default) if argument_values is not SUPPRESS: action(self, namespace, argument_values, option_string) # function to convert arg_strings into an optional action def consume_optional(start_index): # get the optional identified at this index option_tuple = option_string_indices[start_index] action, option_string, explicit_arg = option_tuple # identify additional optionals in the same arg string # (e.g. -xyz is the same as -x -y -z if no args are required) match_argument = self._match_argument action_tuples = [] while True: # if we found no optional action, skip it if action is None: extras.append(arg_strings[start_index]) return start_index + 1 # if there is an explicit argument, try to match the # optional's string arguments to only this if explicit_arg is not None: arg_count = match_argument(action, 'A') # if the action is a single-dash option and takes no # arguments, try to parse more single-dash options out # of the tail of the option string chars = self.prefix_chars if arg_count == 0 and option_string[1] not in chars: action_tuples.append((action, [], option_string)) char = option_string[0] option_string = char + explicit_arg[0] new_explicit_arg = explicit_arg[1:] or None optionals_map = self._option_string_actions if option_string in optionals_map: action = optionals_map[option_string] explicit_arg = new_explicit_arg else: msg = _('ignored explicit argument %r') raise ArgumentError(action, msg % explicit_arg) # if the action expect exactly one argument, we've # successfully matched the option; exit the loop elif arg_count == 1: stop = start_index + 1 args = [explicit_arg] action_tuples.append((action, args, option_string)) break # error if a double-dash option did not use the # explicit argument else: msg = _('ignored explicit argument %r') raise ArgumentError(action, msg % explicit_arg) # if there is no explicit argument, try to match the # optional's string arguments with the following strings # if successful, exit the loop else: start = start_index + 1 selected_patterns = arg_strings_pattern[start:] arg_count = match_argument(action, selected_patterns) stop = start + arg_count args = arg_strings[start:stop] action_tuples.append((action, args, option_string)) break # add the Optional to the list and return the index at which # the Optional's string args stopped assert action_tuples for action, args, option_string in action_tuples: take_action(action, args, option_string) return stop # the list of Positionals left to be parsed; this is modified # by consume_positionals() positionals = self._get_positional_actions() # function to convert arg_strings into positional actions def consume_positionals(start_index): # match as many Positionals as possible match_partial = self._match_arguments_partial selected_pattern = arg_strings_pattern[start_index:] arg_counts = match_partial(positionals, selected_pattern) # slice off the appropriate arg strings for each Positional # and add the Positional and its args to the list for action, arg_count in zip(positionals, arg_counts): args = arg_strings[start_index: start_index + arg_count] start_index += arg_count take_action(action, args) # slice off the Positionals that we just parsed and return the # index at which the Positionals' string args stopped positionals[:] = positionals[len(arg_counts):] return start_index # consume Positionals and Optionals alternately, until we have # passed the last option string extras = [] start_index = 0 if option_string_indices: max_option_string_index = max(option_string_indices) else: max_option_string_index = -1 while start_index <= max_option_string_index: # consume any Positionals preceding the next option next_option_string_index = min([ index for index in option_string_indices if index >= start_index]) if start_index != next_option_string_index: positionals_end_index = consume_positionals(start_index) # only try to parse the next optional if we didn't consume # the option string during the positionals parsing if positionals_end_index > start_index: start_index = positionals_end_index continue else: start_index = positionals_end_index # if we consumed all the positionals we could and we're not # at the index of an option string, there were extra arguments if start_index not in option_string_indices: strings = arg_strings[start_index:next_option_string_index] extras.extend(strings) start_index = next_option_string_index # consume the next optional and any arguments for it > start_index = consume_optional(start_index) /usr/lib64/python3.11/argparse.py:2085: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ start_index = 16 def consume_optional(start_index): # get the optional identified at this index option_tuple = option_string_indices[start_index] action, option_string, explicit_arg = option_tuple # identify additional optionals in the same arg string # (e.g. -xyz is the same as -x -y -z if no args are required) match_argument = self._match_argument action_tuples = [] while True: # if we found no optional action, skip it if action is None: extras.append(arg_strings[start_index]) return start_index + 1 # if there is an explicit argument, try to match the # optional's string arguments to only this if explicit_arg is not None: arg_count = match_argument(action, 'A') # if the action is a single-dash option and takes no # arguments, try to parse more single-dash options out # of the tail of the option string chars = self.prefix_chars if arg_count == 0 and option_string[1] not in chars: action_tuples.append((action, [], option_string)) char = option_string[0] option_string = char + explicit_arg[0] new_explicit_arg = explicit_arg[1:] or None optionals_map = self._option_string_actions if option_string in optionals_map: action = optionals_map[option_string] explicit_arg = new_explicit_arg else: msg = _('ignored explicit argument %r') raise ArgumentError(action, msg % explicit_arg) # if the action expect exactly one argument, we've # successfully matched the option; exit the loop elif arg_count == 1: stop = start_index + 1 args = [explicit_arg] action_tuples.append((action, args, option_string)) break # error if a double-dash option did not use the # explicit argument else: msg = _('ignored explicit argument %r') raise ArgumentError(action, msg % explicit_arg) # if there is no explicit argument, try to match the # optional's string arguments with the following strings # if successful, exit the loop else: start = start_index + 1 selected_patterns = arg_strings_pattern[start:] arg_count = match_argument(action, selected_patterns) stop = start + arg_count args = arg_strings[start:stop] action_tuples.append((action, args, option_string)) break # add the Optional to the list and return the index at which # the Optional's string args stopped assert action_tuples for action, args, option_string in action_tuples: > take_action(action, args, option_string) /usr/lib64/python3.11/argparse.py:2025: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ action = CommaDelimitedListAction(option_strings=['--manifest-format'], dest='manifest_format', nargs=None, const=None, default...ype=<bound method Parseable.parse_list of <enum 'ManifestFormat'>>, choices=None, help='Manifest Format', metavar=None) argument_strings = ['ManifestFormat.json'], option_string = '--manifest-format' def take_action(action, argument_strings, option_string=None): seen_actions.add(action) > argument_values = self._get_values(action, argument_strings) /usr/lib64/python3.11/argparse.py:1937: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = ArgumentParserMkosi(prog='mkosi', usage=None, description='Build Bespoke OS Images', formatter_class=<class 'mkosi.CustomHelpFormatter'>, conflict_handler='error', add_help=False) action = CommaDelimitedListAction(option_strings=['--manifest-format'], dest='manifest_format', nargs=None, const=None, default...ype=<bound method Parseable.parse_list of <enum 'ManifestFormat'>>, choices=None, help='Manifest Format', metavar=None) arg_strings = ['ManifestFormat.json'] def _get_values(self, action, arg_strings): # for everything but PARSER, REMAINDER args, strip out first '--' if action.nargs not in [PARSER, REMAINDER]: try: arg_strings.remove('--') except ValueError: pass # optional argument produces a default when not present if not arg_strings and action.nargs == OPTIONAL: if action.option_strings: value = action.const else: value = action.default if isinstance(value, str): value = self._get_value(action, value) self._check_value(action, value) # when nargs='*' on a positional, if there were no command-line # args, use the default if it is anything other than None elif (not arg_strings and action.nargs == ZERO_OR_MORE and not action.option_strings): if action.default is not None: value = action.default else: value = arg_strings self._check_value(action, value) # single argument or optional argument produces a single value elif len(arg_strings) == 1 and action.nargs in [None, OPTIONAL]: arg_string, = arg_strings > value = self._get_value(action, arg_string) /usr/lib64/python3.11/argparse.py:2467: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = ArgumentParserMkosi(prog='mkosi', usage=None, description='Build Bespoke OS Images', formatter_class=<class 'mkosi.CustomHelpFormatter'>, conflict_handler='error', add_help=False) action = CommaDelimitedListAction(option_strings=['--manifest-format'], dest='manifest_format', nargs=None, const=None, default...ype=<bound method Parseable.parse_list of <enum 'ManifestFormat'>>, choices=None, help='Manifest Format', metavar=None) arg_string = 'ManifestFormat.json' def _get_value(self, action, arg_string): type_func = self._registry_get('type', action.type, action.type) if not callable(type_func): msg = _('%r is not callable') raise ArgumentError(action, msg % type_func) # convert the value to the appropriate type try: result = type_func(arg_string) # ArgumentTypeErrors indicate errors except ArgumentTypeError as err: name = getattr(action.type, '__name__', repr(action.type)) msg = str(err) > raise ArgumentError(action, msg) E argparse.ArgumentError: argument --manifest-format: unknown Format: 'ManifestFormat.json' /usr/lib64/python3.11/argparse.py:2506: ArgumentError During handling of the above exception, another exception occurred: tested_config = <tests.test_config_parser.MkosiConfigManyParams object at 0x7f116f1eac10> tmpdir = local('/tmp/pytest-of-mockbuild/pytest-0/test_def_1_MkosiConfigManyPara0') def test_def_1(tested_config, tmpdir): """Generate the mkosi.default file plus one config file""" with change_cwd(tmpdir.strpath): tested_config.prepare_mkosi_default(tmpdir.strpath) tested_config.prepare_mkosi_default_d_1(tmpdir.strpath) > args = mkosi.parse_args(tested_config.cli_arguments) tests/test_config_parser.py:923: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ mkosi/__init__.py:5689: in parse_args args = parse_args_file_group(argv, os.fspath(default_path)) mkosi/__init__.py:5743: in parse_args_file_group return create_parser().parse_args(defaults_files + argv) /usr/lib64/python3.11/argparse.py:1844: in parse_args args, argv = self.parse_known_args(args, namespace) /usr/lib64/python3.11/argparse.py:1879: in parse_known_args self.error(str(err)) /usr/lib64/python3.11/argparse.py:2599: in error self.exit(2, _('%(prog)s: error: %(message)s\n') % args) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = ArgumentParserMkosi(prog='mkosi', usage=None, description='Build Bespoke OS Images', formatter_class=<class 'mkosi.CustomHelpFormatter'>, conflict_handler='error', add_help=False) status = 2 message = "mkosi: error: argument --manifest-format: unknown Format: 'ManifestFormat.json'\n" def exit(self, status=0, message=None): if message: self._print_message(message, _sys.stderr) > _sys.exit(status) E SystemExit: 2 /usr/lib64/python3.11/argparse.py:2586: SystemExit ----------------------------- Captured stderr call ----------------------------- usage: mkosi [-h] [--version] [-d {fedora,debian,ubuntu,arch,opensuse,mageia,centos,centos_epel,clear,photon,openmandriva,rocky,rocky_epel,alma,alma_epel,gentoo}] [-r RELEASE] [-m MIRROR] [--repositories REPOS] [--use-host-repositories [USE_HOST_REPOSITORIES]] [--architecture ARCHITECTURE] [-t {OutputFormat.directory,OutputFormat.subvolume,OutputFormat.tar,OutputFormat.cpio,OutputFormat.gpt_ext4,OutputFormat.gpt_xfs,OutputFormat.gpt_btrfs,OutputFormat.gpt_squashfs,OutputFormat.plain_squashfs}] [--manifest-format MANIFEST_FORMAT] [-o PATH] [--output-split-root PATH] [--output-split-verity PATH] [--output-split-verity-sig PATH] [--output-split-kernel PATH] [-O DIR] [--workspace-dir DIR] [-f] [-b [BOOTABLE]] [--boot-protocols PROTOCOLS] [--kernel-command-line KERNEL_COMMAND_LINE] [--secure-boot [SECURE_BOOT]] [--secure-boot-key PATH] [--secure-boot-certificate PATH] [--secure-boot-valid-days DAYS] [--secure-boot-common-name CN] [--read-only [READ_ONLY]] [--encrypt {all,data}] [--verity [VERITY]] [--compress [ALG]] [--compress-fs [ALG]] [--compress-output [ALG]] [--mksquashfs MKSQUASHFS_TOOL] [--qcow2 [QCOW2]] [--hostname HOSTNAME] [--image-version IMAGE_VERSION] [--image-id IMAGE_ID] [--no-chown [NO_CHOWN]] [--tar-strip-selinux-context [TAR_STRIP_SELINUX_CONTEXT]] [-i [INCREMENTAL]] [-M [MINIMIZE]] [--without-unified-kernel-images [WITH_UNIFIED_KERNEL_IMAGES]] [--gpt-first-lba FIRSTLBA] [--hostonly-initrd [HOSTONLY_INITRD]] [--split-artifacts [SPLIT_ARTIFACTS]] [--base-packages OPTION] [-p PACKAGE] [--remove-package PACKAGE] [--with-docs [WITH_DOCS]] [-T [WITH_TESTS]] [--password PASSWORD] [--password-is-hashed [PASSWORD_IS_HASHED]] [--autologin [AUTOLOGIN]] [--cache PATH] [--extra-tree PATH] [--skeleton-tree PATH] [--clean-package-metadata [CLEAN_PACKAGE_METADATA]] [--remove-files GLOB] [--environment NAME[=VALUE]] [--build-sources PATH] [--build-directory PATH] [--include-directory PATH] [--install-directory PATH] [--build-package PACKAGE] [--skip-final-phase [SKIP_FINAL_PHASE]] [--build-script PATH] [--prepare-script PATH] [--postinst-script PATH] [--finalize-script PATH] [--source-file-transfer {copy-all,copy-git-cached,copy-git-others,copy-git-more,mount,None}] [--source-file-transfer-final {copy-all,copy-git-cached,copy-git-others,copy-git-more,mount,None}] [--source-resolve-symlinks [SOURCE_RESOLVE_SYMLINKS]] [--source-resolve-symlinks-final [SOURCE_RESOLVE_SYMLINKS_FINAL]] [--with-network [WITH_NETWORK]] [--settings PATH] [--base-image IMAGE] [--root-size BYTES] [--esp-size BYTES] [--xbootldr-size BYTES] [--swap-size BYTES] [--home-size BYTES] [--srv-size BYTES] [--var-size BYTES] [--tmp-size BYTES] [--usr-only [USR_ONLY]] [--checksum [CHECKSUM]] [--sign [SIGN]] [--key KEY] [--bmap [BMAP]] [--extra-search-path EXTRA_SEARCH_PATHS] [--qemu-headless [QEMU_HEADLESS]] [--qemu-smp SMP] [--qemu-mem MEM] [--network-veth [NETWORK_VETH]] [--ephemeral [EPHEMERAL]] [--ssh [SSH]] [--ssh-key PATH] [--ssh-timeout SECONDS] [--ssh-agent PATH] [--ssh-port PORT] [-C PATH] [--default PATH] [-a] [--all-directory PATH] [-B [AUTO_BUMP]] [--debug {run,build-script,workspace-command,disk}] {build,clean,help,summary,genkey,bump,serve,build,shell,boot,qemu,ssh} ... mkosi: error: argument --manifest-format: unknown Format: 'ManifestFormat.json' ______________________ test_def_2[MkosiConfigManyParams] _______________________ cls = <enum 'ManifestFormat'>, name = 'ManifestFormat.json' @classmethod def from_string(cls: Any, name: str) -> Any: """A convenience method to be used with argparse""" try: > return cls[name] mkosi/backend.py:97: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ cls = <enum 'ManifestFormat'>, name = 'ManifestFormat.json' def __getitem__(cls, name): """ Return the member matching `name`. """ > return cls._member_map_[name] E KeyError: 'ManifestFormat.json' /usr/lib64/python3.11/enum.py:818: KeyError During handling of the above exception, another exception occurred: self = ArgumentParserMkosi(prog='mkosi', usage=None, description='Build Bespoke OS Images', formatter_class=<class 'mkosi.CustomHelpFormatter'>, conflict_handler='error', add_help=False) action = CommaDelimitedListAction(option_strings=['--manifest-format'], dest='manifest_format', nargs=None, const=None, default...ype=<bound method Parseable.parse_list of <enum 'ManifestFormat'>>, choices=None, help='Manifest Format', metavar=None) arg_string = 'ManifestFormat.json' def _get_value(self, action, arg_string): type_func = self._registry_get('type', action.type, action.type) if not callable(type_func): msg = _('%r is not callable') raise ArgumentError(action, msg % type_func) # convert the value to the appropriate type try: > result = type_func(arg_string) /usr/lib64/python3.11/argparse.py:2500: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ cls = <enum 'ManifestFormat'>, string = 'ManifestFormat.json' @classmethod def parse_list(cls: Any, string: str) -> List[Any]: > return [cls.from_string(p) for p in string.split(",") if p] mkosi/backend.py:103: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ .0 = <list_iterator object at 0x7f116ff7fbe0> > return [cls.from_string(p) for p in string.split(",") if p] mkosi/backend.py:103: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ cls = <enum 'ManifestFormat'>, name = 'ManifestFormat.json' @classmethod def from_string(cls: Any, name: str) -> Any: """A convenience method to be used with argparse""" try: return cls[name] except KeyError: > raise argparse.ArgumentTypeError(f"unknown Format: {name!r}") E argparse.ArgumentTypeError: unknown Format: 'ManifestFormat.json' mkosi/backend.py:99: ArgumentTypeError During handling of the above exception, another exception occurred: self = ArgumentParserMkosi(prog='mkosi', usage=None, description='Build Bespoke OS Images', formatter_class=<class 'mkosi.CustomHelpFormatter'>, conflict_handler='error', add_help=False) args = ['@/tmp/pytest-of-mockbuild/pytest-0/test_def_2_MkosiConfigManyPara0/mkosi.default', '@mkosi.default.d/002_mkosi.conf', '--', 'build'] namespace = <[AttributeError("'int' object has no attribute 'name'") raised in repr()] Namespace object at 0x7f116fdf68d0> def parse_known_args(self, args=None, namespace=None): if args is None: # args default to the system args args = _sys.argv[1:] else: # make sure that args are mutable args = list(args) # default Namespace built from parser defaults if namespace is None: namespace = Namespace() # add any action defaults that aren't present for action in self._actions: if action.dest is not SUPPRESS: if not hasattr(namespace, action.dest): if action.default is not SUPPRESS: setattr(namespace, action.dest, action.default) # add any parser defaults that aren't present for dest in self._defaults: if not hasattr(namespace, dest): setattr(namespace, dest, self._defaults[dest]) # parse the arguments and exit if there are any errors if self.exit_on_error: try: > namespace, args = self._parse_known_args(args, namespace) /usr/lib64/python3.11/argparse.py:1877: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = ArgumentParserMkosi(prog='mkosi', usage=None, description='Build Bespoke OS Images', formatter_class=<class 'mkosi.CustomHelpFormatter'>, conflict_handler='error', add_help=False) arg_strings = ['--distribution', 'fedora', '--release', '28', '--repositories', 'http://fedora/repos', ...] namespace = <[AttributeError("'int' object has no attribute 'name'") raised in repr()] Namespace object at 0x7f116fdf68d0> def _parse_known_args(self, arg_strings, namespace): # replace arg strings that are file references if self.fromfile_prefix_chars is not None: arg_strings = self._read_args_from_files(arg_strings) # map all mutually exclusive arguments to the other arguments # they can't occur with action_conflicts = {} for mutex_group in self._mutually_exclusive_groups: group_actions = mutex_group._group_actions for i, mutex_action in enumerate(mutex_group._group_actions): conflicts = action_conflicts.setdefault(mutex_action, []) conflicts.extend(group_actions[:i]) conflicts.extend(group_actions[i + 1:]) # find all option indices, and determine the arg_string_pattern # which has an 'O' if there is an option at an index, # an 'A' if there is an argument, or a '-' if there is a '--' option_string_indices = {} arg_string_pattern_parts = [] arg_strings_iter = iter(arg_strings) for i, arg_string in enumerate(arg_strings_iter): # all args after -- are non-options if arg_string == '--': arg_string_pattern_parts.append('-') for arg_string in arg_strings_iter: arg_string_pattern_parts.append('A') # otherwise, add the arg to the arg strings # and note the index if it was an option else: option_tuple = self._parse_optional(arg_string) if option_tuple is None: pattern = 'A' else: option_string_indices[i] = option_tuple pattern = 'O' arg_string_pattern_parts.append(pattern) # join the pieces together to form the pattern arg_strings_pattern = ''.join(arg_string_pattern_parts) # converts arg strings to the appropriate and then takes the action seen_actions = set() seen_non_default_actions = set() def take_action(action, argument_strings, option_string=None): seen_actions.add(action) argument_values = self._get_values(action, argument_strings) # error if this argument is not allowed with other previously # seen arguments, assuming that actions that use the default # value don't really count as "present" if argument_values is not action.default: seen_non_default_actions.add(action) for conflict_action in action_conflicts.get(action, []): if conflict_action in seen_non_default_actions: msg = _('not allowed with argument %s') action_name = _get_action_name(conflict_action) raise ArgumentError(action, msg % action_name) # take the action if we didn't receive a SUPPRESS value # (e.g. from a default) if argument_values is not SUPPRESS: action(self, namespace, argument_values, option_string) # function to convert arg_strings into an optional action def consume_optional(start_index): # get the optional identified at this index option_tuple = option_string_indices[start_index] action, option_string, explicit_arg = option_tuple # identify additional optionals in the same arg string # (e.g. -xyz is the same as -x -y -z if no args are required) match_argument = self._match_argument action_tuples = [] while True: # if we found no optional action, skip it if action is None: extras.append(arg_strings[start_index]) return start_index + 1 # if there is an explicit argument, try to match the # optional's string arguments to only this if explicit_arg is not None: arg_count = match_argument(action, 'A') # if the action is a single-dash option and takes no # arguments, try to parse more single-dash options out # of the tail of the option string chars = self.prefix_chars if arg_count == 0 and option_string[1] not in chars: action_tuples.append((action, [], option_string)) https://docs.python.org/3.11/whatsnew/3.11.html For the build logs, see: https://copr-be.cloud.fedoraproject.org/results/@python/python3.11/fedora-rawhide-x86_64/03525480-mkosi/ For all our attempts to build mkosi with Python 3.11, see: https://copr.fedorainfracloud.org/coprs/g/python/python3.11/package/mkosi/ Testing and mass rebuild of packages is happening in copr. You can follow these instructions to test locally in mock if your package builds with Python 3.11: https://copr.fedorainfracloud.org/coprs/g/python/python3.11/ Let us know here if you have any questions. Python 3.11 is planned to be included in Fedora 37. To make that update smoother, we're building Fedora packages with all pre-releases of Python 3.11. A build failure prevents us from testing all dependent packages (transitive [Build]Requires), so if this package is required a lot, it's important for us to get it fixed soon. We'd appreciate help from the people who know this package best, but if you don't want to work on this now, let us know so we can try to work around it on our side.
I pushed a fix to rawhide, but didn't build. I hope it'll get picked up automatically in the copr.
It did. Thanks.