Browse Source

Fill in the docblock for the docopt function

master
J. King 2 years ago
parent
commit
bcaea92ac2
  1. 277
      lib/Docopt.php

277
lib/Docopt.php

@ -22,6 +22,134 @@ namespace MensBeam\Docopt;
class Docopt {
# __version__ = "0.7.2"
public const VERSION = "0.7.2";
# def docopt(
# docstring: Optional[str] = None,
# argv: Optional[Union[List[str], str]] = None,
# default_help: bool = True,
# version: Any = None,
# options_first: bool = False,
# more_magic: bool = False,
# ) -> ParsedOptions:
/** Parse `argv` based on command-line interface described in `doc`.
*
* `docopt` creates your command-line interface based on its
* description that you pass as `docstring`. Such description can contain
* --options, <positional-argument>, commands, which could be
* [optional], (required), (mutually | exclusive) or repeated...
*
* Example
* -------
*
* > use MensBeam\Docopt\Docopt;
* > $doc = <<<DOCSTRING
* <<< Usage:
* <<< my_program tcp <host> <port> [--timeout=<seconds>]
* <<< my_program serial <port> [--baud=<n>] [--timeout=<seconds>]
* <<< my_program (-h | --help | --version)
* <<<
* <<< Options:
* <<< -h, --help Show this screen and exit.
* <<< --baud=<n> Baudrate [default: 9600]
* <<< DOCSTRING;
* > $argv = ['tcp', '127.0.0.1', '80', '--timeout', '30'];
* > echo json_encode(Docopt::docopt($doc, $argv), \JSON_PRETTY_PRINT);
* {
* "--baud": "9600",
* "--help": false,
* "--timeout": "30",
* "--version": false,
* "<host>": "127.0.0.1",
* "<port>": "80",
* "serial": false,
* "tcp": true
* }
*
* @param string $docstring Description of your command-line interface
* @param string[]|string|null $argv Argument list to be parsed. $_SERVER['argv'] is used if null is provided
* @param bool $default_help Set to false to disable automatic help on -h or --help options
* @param \Stringable|string|null $version If passed, the string will be printed if --version is in `argv`
* @param bool $options_first Set to True to require options precede positional arguments, i.e. to forbid options and positional arguments intermix
* @param bool $more_magic Try to be extra-helpful; offer advanced pattern-matching and spellcheck
*/
public function docopt(
string $docstring, // DEVIATION: Our docstring is not optional since we can't get one from the parent context
$argv = null,
bool $default_help = true,
$version = null,
bool $options_first = false,
bool $more_magic = false
): ParsedOptions {
# argv = sys.argv[1:] if argv is None else argv
# maybe_frame = inspect.currentframe()
# if maybe_frame:
# parent_frame = doc_parent_frame = magic_parent_frame = maybe_frame.f_back
# if not more_magic: # make sure 'magic' isn't in the calling name
# while not more_magic and magic_parent_frame:
# imported_as = {v: k for k, v in magic_parent_frame.f_globals.items() if hasattr(v, "__name__") and v.__name__ == docopt.__name__}.get(docopt)
# if imported_as and "magic" in imported_as:
# more_magic = True
# else:
# magic_parent_frame = magic_parent_frame.f_back
# if not docstring: # go look for one, if none exists, raise Exception
# while not docstring and doc_parent_frame:
# docstring = doc_parent_frame.f_locals.get("__doc__")
# if not docstring:
# doc_parent_frame = doc_parent_frame.f_back
# if not docstring:
# raise DocoptLanguageError("Either __doc__ must be defined in the scope of a parent or passed as the first argument.")
# output_value_assigned = False
# if more_magic and parent_frame:
# import dis
#
# instrs = dis.get_instructions(parent_frame.f_code)
# for instr in instrs:
# if instr.offset == parent_frame.f_lasti:
# break
# assert instr.opname.startswith("CALL_")
# MAYBE_STORE = next(instrs)
# if MAYBE_STORE and (MAYBE_STORE.opname.startswith("STORE") or MAYBE_STORE.opname.startswith("RETURN")):
# output_value_assigned = True
# usage_sections = parse_section("usage:", docstring)
# if len(usage_sections) == 0:
# raise DocoptLanguageError('"usage:" section (case-insensitive) not found. Perhaps missing indentation?')
# if len(usage_sections) > 1:
# raise DocoptLanguageError('More than one "usage:" (case-insensitive).')
# options_pattern = re.compile(r"\n\s*?options:", re.IGNORECASE)
# if options_pattern.search(usage_sections[0]):
# raise DocoptExit("Warning: options (case-insensitive) was found in usage." "Use a blank line between each section..")
# DocoptExit.usage = usage_sections[0]
# options = parse_defaults(docstring)
# pattern = parse_pattern(formal_usage(DocoptExit.usage), options)
# pattern_options = set(pattern.flat(Option))
# for options_shortcut in pattern.flat(OptionsShortcut):
# doc_options = parse_defaults(docstring)
# options_shortcut.children = [opt for opt in doc_options if opt not in pattern_options]
# parsed_arg_vector = parse_argv(Tokens(argv), list(options), options_first, more_magic)
# extras(default_help, version, parsed_arg_vector, docstring)
# matched, left, collected = pattern.fix().match(parsed_arg_vector)
# if matched and left == []:
# output_obj = ParsedOptions((a.name, a.value) for a in (pattern.flat() + collected))
# target_parent_frame = parent_frame or magic_parent_frame or doc_parent_frame
# if more_magic and target_parent_frame and not output_value_assigned:
# if not target_parent_frame.f_globals.get("arguments"):
# target_parent_frame.f_globals["arguments"] = output_obj
# return output_obj
# if left:
# raise DocoptExit(f"Warning: found unmatched (duplicate?) arguments {left}")
# raise DocoptExit(collected=collected, left=left)
}
# magic = magic_docopt = docopt
/** Helper function to invoke the docopt() method with $more_magic always true */
public function magic(string $docstring, $argv = null, bool $default_help = true, $version = null, bool $options_first = false, bool $more_magic = false): ParsedOptions {
return static::docopt($docstring, $argv, $default_help, $version, $options_first, true);
}
/** Helper function to invoke the docopt() method with $more_magic always true */
public function magic_docopt(string $docstring, $argv = null, bool $default_help = true, $version = null, bool $options_first = false, bool $more_magic = false): ParsedOptions {
return static::docopt($docstring, $argv, $default_help, $version, $options_first, true);
}
}
class Util {
@ -421,14 +549,16 @@ class BranchPattern extends Pattern {
$either[] = (array) $child->children;
}
# for case in either:
# for e in [child for child in case if case.count(child) > 1]:
# if type(e) is Argument or type(e) is Option and e.argcount:
# if e.value is None:
# e.value = []
# elif type(e.value) is not list:
# e.value = e.value.split()
# if type(e) is Command or type(e) is Option and e.argcount == 0:
# e.value = 0
foreach ($either as $case) {
# for e in [child for child in case if case.count(child) > 1]:
# if type(e) is Argument or type(e) is Option and e.argcount:
# if e.value is None:
# e.value = []
# elif type(e.value) is not list:
# e.value = e.value.split()
# if type(e) is Command or type(e) is Option and e.argcount == 0:
# e.value = 0
}
# return self
}
@ -840,134 +970,3 @@ class BranchPattern extends Pattern {
# def __getattr__(self, name: str) -> Optional[Union[str, bool]]:
# return self.get(name) or {name: self.get(k) for k in self.keys() if name in [k.lstrip("-"), k.lstrip("<").rstrip(">")]}.get(name)
# def docopt(
# docstring: Optional[str] = None,
# argv: Optional[Union[List[str], str]] = None,
# default_help: bool = True,
# version: Any = None,
# options_first: bool = False,
# more_magic: bool = False,
# ) -> ParsedOptions:
# """Parse `argv` based on command-line interface described in `doc`.
# `docopt` creates your command-line interface based on its
# description that you pass as `docstring`. Such description can contain
# --options, <positional-argument>, commands, which could be
# [optional], (required), (mutually | exclusive) or repeated...
# Parameters
# ----------
# docstring : str (default: first __doc__ in parent scope)
# Description of your command-line interface.
# argv : list of str, optional
# Argument vector to be parsed. sys.argv[1:] is used if not
# provided.
# default_help : bool (default: True)
# Set to False to disable automatic help on -h or --help
# options.
# version : any object
# If passed, the object will be printed if --version is in
# `argv`.
# options_first : bool (default: False)
# Set to True to require options precede positional arguments,
# i.e. to forbid options and positional arguments intermix.
# more_magic : bool (default: False)
# Try to be extra-helpful; pull results into globals() of caller as 'arguments',
# offer advanced pattern-matching and spellcheck.
# Also activates if `docopt` aliased to a name containing 'magic'.
# Returns
# -------
# arguments: dict-like
# A dictionary, where keys are names of command-line elements
# such as e.g. "--verbose" and "<path>", and values are the
# parsed values of those elements. Also supports dot acccess.
# Example
# -------
# >>> from docopt import docopt
# >>> doc = '''
# ... Usage:
# ... my_program tcp <host> <port> [--timeout=<seconds>]
# ... my_program serial <port> [--baud=<n>] [--timeout=<seconds>]
# ... my_program (-h | --help | --version)
# ...
# ... Options:
# ... -h, --help Show this screen and exit.
# ... --baud=<n> Baudrate [default: 9600]
# ... '''
# >>> argv = ['tcp', '127.0.0.1', '80', '--timeout', '30']
# >>> docopt(doc, argv)
# {'--baud': '9600',
# '--help': False,
# '--timeout': '30',
# '--version': False,
# '<host>': '127.0.0.1',
# '<port>': '80',
# 'serial': False,
# 'tcp': True}
# """
# argv = sys.argv[1:] if argv is None else argv
# maybe_frame = inspect.currentframe()
# if maybe_frame:
# parent_frame = doc_parent_frame = magic_parent_frame = maybe_frame.f_back
# if not more_magic: # make sure 'magic' isn't in the calling name
# while not more_magic and magic_parent_frame:
# imported_as = {v: k for k, v in magic_parent_frame.f_globals.items() if hasattr(v, "__name__") and v.__name__ == docopt.__name__}.get(docopt)
# if imported_as and "magic" in imported_as:
# more_magic = True
# else:
# magic_parent_frame = magic_parent_frame.f_back
# if not docstring: # go look for one, if none exists, raise Exception
# while not docstring and doc_parent_frame:
# docstring = doc_parent_frame.f_locals.get("__doc__")
# if not docstring:
# doc_parent_frame = doc_parent_frame.f_back
# if not docstring:
# raise DocoptLanguageError("Either __doc__ must be defined in the scope of a parent or passed as the first argument.")
# output_value_assigned = False
# if more_magic and parent_frame:
# import dis
# instrs = dis.get_instructions(parent_frame.f_code)
# for instr in instrs:
# if instr.offset == parent_frame.f_lasti:
# break
# assert instr.opname.startswith("CALL_")
# MAYBE_STORE = next(instrs)
# if MAYBE_STORE and (MAYBE_STORE.opname.startswith("STORE") or MAYBE_STORE.opname.startswith("RETURN")):
# output_value_assigned = True
# usage_sections = parse_section("usage:", docstring)
# if len(usage_sections) == 0:
# raise DocoptLanguageError('"usage:" section (case-insensitive) not found. Perhaps missing indentation?')
# if len(usage_sections) > 1:
# raise DocoptLanguageError('More than one "usage:" (case-insensitive).')
# options_pattern = re.compile(r"\n\s*?options:", re.IGNORECASE)
# if options_pattern.search(usage_sections[0]):
# raise DocoptExit("Warning: options (case-insensitive) was found in usage." "Use a blank line between each section..")
# DocoptExit.usage = usage_sections[0]
# options = parse_defaults(docstring)
# pattern = parse_pattern(formal_usage(DocoptExit.usage), options)
# pattern_options = set(pattern.flat(Option))
# for options_shortcut in pattern.flat(OptionsShortcut):
# doc_options = parse_defaults(docstring)
# options_shortcut.children = [opt for opt in doc_options if opt not in pattern_options]
# parsed_arg_vector = parse_argv(Tokens(argv), list(options), options_first, more_magic)
# extras(default_help, version, parsed_arg_vector, docstring)
# matched, left, collected = pattern.fix().match(parsed_arg_vector)
# if matched and left == []:
# output_obj = ParsedOptions((a.name, a.value) for a in (pattern.flat() + collected))
# target_parent_frame = parent_frame or magic_parent_frame or doc_parent_frame
# if more_magic and target_parent_frame and not output_value_assigned:
# if not target_parent_frame.f_globals.get("arguments"):
# target_parent_frame.f_globals["arguments"] = output_obj
# return output_obj
# if left:
# raise DocoptExit(f"Warning: found unmatched (duplicate?) arguments {left}")
# raise DocoptExit(collected=collected, left=left)
# magic = magic_docopt = docopt
Loading…
Cancel
Save