| Conditions | 18 | 
| Total Lines | 195 | 
| Lines | 0 | 
| Ratio | 0 % | 
| Changes | 9 | ||
| Bugs | 0 | Features | 0 | 
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like parsecli() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
| 1 | # | ||
| 48 | def parsecli(cliargs=None, error_on_config=False): | ||
| 49 | """Parse command line arguments | ||
| 50 | |||
| 51 | :param list cliargs: Arguments to parse or None (=use sys.argv) | ||
| 52 | :return: parsed arguments | ||
| 53 | :rtype: argparse.Namespace | ||
| 54 | """ | ||
| 55 | |||
| 56 | # parse just --config and --verbose | ||
| 57 | confparser = argparse.ArgumentParser(add_help=False) | ||
| 58 |     confparser.add_argument('--config', dest='configfile', metavar='CONFIGFILE', | ||
| 59 | help='user config file location, uses also ' | ||
| 60 | 'XDG_CONFIG_HOME env variable if set') | ||
| 61 |     confparser.add_argument('-v', '--verbose', action='count', | ||
| 62 | help="Increase verbosity level") | ||
| 63 | args, remaining_argv = confparser.parse_known_args(cliargs) | ||
| 64 | |||
| 65 | # Store configuration filename for further usage: | ||
| 66 | configfile = args.configfile | ||
| 67 | config = None | ||
| 68 | |||
| 69 | # init log module | ||
| 70 | setloglevel(args.verbose) | ||
| 71 | |||
| 72 | # init config module | ||
| 73 | # Exception handled in __init__.py | ||
| 74 | config = docmanagerconfig(args.configfile) | ||
| 75 | |||
| 76 | # Read the log level from the config files | ||
| 77 | try: | ||
| 78 | verbosity_level = int(config["general"]["verbosity_level"]) | ||
| 79 | |||
| 80 | if args.verbose is not None: | ||
| 81 | if verbosity_level > args.verbose: | ||
| 82 | args.verbose = verbosity_level | ||
| 83 | else: | ||
| 84 | args.verbose = verbosity_level | ||
| 85 | |||
| 86 | # set log level | ||
| 87 | setloglevel(args.verbose) | ||
| 88 | except KeyError: | ||
| 89 | pass | ||
| 90 | |||
| 91 | if remaining_argv: | ||
| 92 | alias = remaining_argv[0] | ||
| 93 | |||
| 94 | # parse aliases | ||
| 95 |         if is_alias(alias) and not alias.startswith('-'): | ||
| 96 | remaining_argv = remaining_argv[1:] | ||
| 97 | |||
| 98 | try: | ||
| 99 |                 value = parse_alias_value("{alias} {args}".format(alias=config.get("alias", alias), | ||
| 100 | args=" ".join(remaining_argv))) | ||
| 101 | cliargs = shlex.split(value) | ||
| 102 | except (NoSectionError, NoOptionError) as err: | ||
| 103 | pass | ||
| 104 | |||
| 105 | # parse cli parameters | ||
| 106 | filesargs = dict(nargs='+', | ||
| 107 | metavar="FILE", | ||
| 108 | help='One or more DocBook XML or DC files.' | ||
| 109 | ) | ||
| 110 | propargs = dict(action='append', | ||
| 111 | # metavar="PROP[[=VALUE],PROP[=VALUE]...] | ||
| 112 | help='One or more properties to get, set, delete, or get-attr. ' | ||
| 113 | 'Syntax of PROPERTIES: PROP[[=VALUE],PROP[=VALUE]...]' | ||
| 114 | ' Example (get/del): -p foo or -p foo,bar or ' | ||
| 115 | '-p foo -p bar ' | ||
| 116 | 'Example (set): -p foo=a or -p foo=a,bar=b or ' | ||
| 117 | '-p foo=a -p bar=b' | ||
| 118 | ) | ||
| 119 | stop_on_error = dict(action='store_true', | ||
| 120 | default=False, | ||
| 121 | help='Stop if an (XML) error is found ' | ||
| 122 | 'in a XML file (default: %(default)s)' | ||
| 123 | ) | ||
| 124 | queryformat = dict(action='store', | ||
| 125 | help='The output query format. For more information, have a look into the manual page.' | ||
| 126 | ) | ||
| 127 | sort = dict(action='store', | ||
| 128 | help='Sorts the output by XML properties.' | ||
| 129 | ) | ||
| 130 | filters = dict(action='append', | ||
| 131 | help='Filters the analyzed data. For more information, have a look into the manual page.' | ||
| 132 | ) | ||
| 133 | default_output = dict(action='store', | ||
| 134 | help='Sets the default output for properties which are not available in a file. By default, DocManager prints nothing.' | ||
| 135 | ) | ||
| 136 | quiet = dict(action='store_true', | ||
| 137 | help='DocManager will print nothing or in some cases only the relevant output.' | ||
| 138 | ) | ||
| 139 | prop = dict(action='store', help='The property which gets modified.') | ||
| 140 | attributes = dict(action='append', help='One or more attributes to get, set, or delete.' | ||
| 141 | 'Syntax of ATTRIBUTES: ATTR[[=VALUE],ATTR[=VALUE]...]' | ||
| 142 | ' Example (attr-get/attr-del): -a foo or -a foo,bar or ' | ||
| 143 | '-a foo -a bar ' | ||
| 144 | 'Example (attr-set): -a foo=a or -a foo=a,bar=b or ' | ||
| 145 | '-a foo=a -a bar=b') | ||
| 146 |     mainprops = tuple(("-{}".format(i.upper()[0]), "--{}".format(i)) | ||
| 147 | for i in DEFAULT_DM_PROPERTIES) | ||
| 148 | |||
| 149 | parser = argparse.ArgumentParser( | ||
| 150 | prog="docmanager", | ||
| 151 | parents=[confparser], | ||
| 152 | # usage="%(prog)s COMMAND [OPTIONS] FILE [FILE ...]\n", | ||
| 153 | description="Docmanager sets, gets, deletes, or queries " | ||
| 154 | "meta-information for DocBook5 XML files.") | ||
| 155 |     parser.add_argument('--version', | ||
| 156 | action='version', | ||
| 157 | version='%(prog)s ' + __version__ | ||
| 158 | ) | ||
| 159 |     parser.add_argument('--langlist', | ||
| 160 | action='store_true' | ||
| 161 | ) | ||
| 162 |     parser.add_argument('-j', '--jobs', | ||
| 163 | type=int, | ||
| 164 | default=DEFAULT_PROCESSES, | ||
| 165 | action='store', | ||
| 166 | help='The amount of jobs for parsing all XML files.' | ||
| 167 | ) | ||
| 168 | |||
| 169 | # Create a subparser for all of our subcommands, | ||
| 170 | # save the subcommand in 'dest' | ||
| 171 | subparsers = parser.add_subparsers( | ||
| 172 | dest='action', | ||
| 173 | title="Available subcommands", | ||
| 174 | # metavar="COMMAND" | ||
| 175 | ) | ||
| 176 | |||
| 177 | init_subcmd(subparsers, stop_on_error, propargs, mainprops, filesargs) | ||
| 178 | get_subcmd(subparsers, quiet, propargs, filesargs) | ||
| 179 | set_subcmd(subparsers, stop_on_error, propargs, mainprops, filesargs) | ||
| 180 | del_subcmd(subparsers, propargs, filesargs) | ||
| 181 | setattr_subcmd(subparsers, stop_on_error, prop, attributes, filesargs) | ||
| 182 | delattr_subcmd(subparsers, stop_on_error, prop, attributes, filesargs) | ||
| 183 | getattr_subcmd(subparsers, stop_on_error, propargs, attributes, filesargs) | ||
| 184 | analyze_subcmd(subparsers, queryformat, filters, sort, quiet, stop_on_error, default_output, filesargs) | ||
| 185 | config_subcmd(subparsers) | ||
| 186 | alias_subcmd(subparsers) | ||
| 187 | |||
| 188 | # ----- | ||
| 189 | args = parser.parse_args(args=cliargs) | ||
| 190 | |||
| 191 | if args.configfile is None: | ||
| 192 | args.configfile = configfile | ||
| 193 | |||
| 194 | args.config = config | ||
| 195 | |||
| 196 | ## | ||
| 197 | rewrite_alias(args) | ||
| 198 | |||
| 199 | # Display language list | ||
| 200 | if args.langlist is True: | ||
| 201 | show_langlist() | ||
| 202 | |||
| 203 | # If docmanager is called without anything, print the help and exit | ||
| 204 | if args.action is None: | ||
| 205 | parser.print_help() | ||
| 206 | sys.exit(ReturnCodes.E_CALL_WITHOUT_PARAMS) | ||
| 207 | |||
| 208 | if not hasattr(args, 'properties'): | ||
| 209 | args.properties = None | ||
| 210 | |||
| 211 | if not hasattr(args, 'stop_on_error'): | ||
| 212 | args.stop_on_error = False | ||
| 213 | |||
| 214 | # Clean file list | ||
| 215 | if hasattr(args, 'files'): | ||
| 216 | clean_filelist(args) | ||
| 217 | else: | ||
| 218 | args.files = None | ||
| 219 | |||
| 220 | # set default value for --quiet | ||
| 221 | if not hasattr(args, 'quiet'): | ||
| 222 | args.quiet = False | ||
| 223 | |||
| 224 | # Fix file list - this is needed for aliases - issue#67 | ||
| 225 | # This functions kills the process if a file was not found | ||
| 226 | fix_filelist(args.files) | ||
| 227 | |||
| 228 | # Fix properties | ||
| 229 | fix_properties(args) | ||
| 230 | |||
| 231 | # Fix attributes (-a/--attribute) | ||
| 232 | fix_attributes(args) | ||
| 233 | |||
| 234 | # check for input format | ||
| 235 | input_format_check(args) | ||
| 236 | |||
| 237 | # check jobs argument | ||
| 238 | if args.jobs < 1 or args.jobs > 64: | ||
| 239 |         log.error("Invalid argument in '-j/--jobs'. Please choose something between 1-64!") | ||
| 240 | sys.exit(ReturnCodes.E_INVALID_ARGUMENTS) | ||
| 241 | |||
| 242 | return args | ||
| 243 |