insightfactory-cli 1.0.0.dev1__py3-none-any.whl → 1.0.0.dev2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
if_cli/cli.py CHANGED
@@ -21,6 +21,102 @@ class _ArgumentParser(argparse.ArgumentParser):
21
21
  die(message)
22
22
 
23
23
 
24
+ def _option_flag_label(name: str, spec: dict[str, Any]) -> str:
25
+ short = spec.get("short")
26
+ if short:
27
+ return f"--{name}/-{short}"
28
+ return f"--{name}"
29
+
30
+
31
+ def _resolve_short_option(
32
+ arg: str,
33
+ *,
34
+ options: Options,
35
+ short_options: dict[str, str],
36
+ ) -> tuple[str, str | None] | None:
37
+ """Return (option_name, inline_value) for a short-option token, or None if not an option."""
38
+ option_name = short_options.get(arg)
39
+ if option_name is not None:
40
+ return option_name, None
41
+
42
+ for short_flag, name in short_options.items():
43
+ if not arg.startswith(short_flag) or len(arg) <= len(short_flag):
44
+ continue
45
+ if options[name]["type"] == "boolean":
46
+ die(f"Unknown option '{arg}'")
47
+ return name, arg[len(short_flag) :]
48
+
49
+ return None
50
+
51
+
52
+ def _parse_args_with_positionals(argv: list[str], *, options: Options) -> tuple[dict[str, Any], list[str]]:
53
+ """Parse argv allowing options and positionals in any order (Node util.parseArgs parity)."""
54
+ values: dict[str, Any] = {}
55
+ for name, spec in options.items():
56
+ if spec["type"] == "boolean":
57
+ values[name] = spec.get("default", False)
58
+ else:
59
+ values[name] = spec.get("default")
60
+
61
+ long_options = {f"--{name}": name for name in options}
62
+ short_options = {f"-{spec['short']}": name for name, spec in options.items() if spec.get("short") is not None}
63
+
64
+ positionals: list[str] = []
65
+ index = 0
66
+ while index < len(argv):
67
+ arg = argv[index]
68
+ if arg == "--":
69
+ positionals.extend(argv[index + 1 :])
70
+ break
71
+
72
+ option_name: str | None = None
73
+ inline_value: str | None = None
74
+
75
+ if arg.startswith("--"):
76
+ if "=" in arg:
77
+ flag, inline_value = arg.split("=", 1)
78
+ option_name = long_options.get(flag)
79
+ if option_name is None:
80
+ die(f"Unknown option '{flag}'")
81
+ else:
82
+ option_name = long_options.get(arg)
83
+ if option_name is None:
84
+ die(f"Unknown option '{arg}'")
85
+ elif arg.startswith("-") and len(arg) > 1:
86
+ resolved = _resolve_short_option(arg, options=options, short_options=short_options)
87
+ if resolved is None:
88
+ die(f"Unknown option '{arg}'")
89
+ option_name, inline_value = resolved
90
+ else:
91
+ positionals.append(arg)
92
+ index += 1
93
+ continue
94
+
95
+ spec = options[option_name]
96
+ if spec["type"] == "boolean":
97
+ if inline_value is not None:
98
+ die(f"argument {_option_flag_label(option_name, spec)}: does not take an argument")
99
+ values[option_name] = True
100
+ index += 1
101
+ continue
102
+
103
+ value = inline_value
104
+ if value is None:
105
+ if index + 1 >= len(argv):
106
+ die(f"argument {_option_flag_label(option_name, spec)}: expected one argument")
107
+ next_arg = argv[index + 1]
108
+ if next_arg == "--" or next_arg.startswith("-"):
109
+ die(f"argument {_option_flag_label(option_name, spec)}: expected one argument")
110
+ value = next_arg
111
+ index += 2
112
+ else:
113
+ index += 1
114
+
115
+ values[option_name] = value
116
+
117
+ return values, positionals
118
+
119
+
24
120
  def parse_args(
25
121
  argv: list[str],
26
122
  *,
@@ -28,6 +124,9 @@ def parse_args(
28
124
  allow_positionals: bool = False,
29
125
  ) -> tuple[dict[str, Any], list[str]]:
30
126
  """Parse argv with argparse, using the same flags as the TypeScript parseArgs specs."""
127
+ if allow_positionals:
128
+ return _parse_args_with_positionals(argv, options=options)
129
+
31
130
  parser = _ArgumentParser(add_help=False, allow_abbrev=False)
32
131
  for name, spec in options.items():
33
132
  flags = [f"--{name}"]
@@ -39,13 +138,9 @@ def parse_args(
39
138
  parser.add_argument(*flags, dest=dest, action="store_true", default=spec.get("default", False))
40
139
  else:
41
140
  parser.add_argument(*flags, dest=dest, default=spec.get("default"))
42
- if allow_positionals:
43
- parser.add_argument("positionals", nargs="*")
44
141
  namespace = parser.parse_args(argv)
45
142
  raw = vars(namespace)
46
143
  values = {name: raw.get(name.replace("-", "_")) for name in options}
47
- if allow_positionals:
48
- return values, list(raw.get("positionals") or [])
49
144
  return values, []
50
145
 
51
146
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: insightfactory-cli
3
- Version: 1.0.0.dev1
3
+ Version: 1.0.0.dev2
4
4
  Summary: Profile-based authentication CLI for the InsightFactory Interfaces API
5
5
  Project-URL: Homepage, https://github.com/insightfactory-ai/insightfactory-cli
6
6
  Project-URL: Repository, https://github.com/insightfactory-ai/insightfactory-cli
@@ -1,7 +1,7 @@
1
1
  if_cli/__init__.py,sha256=YYcz-hEiXXUjdBFGipOrVHynsyH4ZLqQOCDobvCAu8Y,26
2
2
  if_cli/__main__.py,sha256=2hLFIiT-gocMb0VJVzVYtGVIoHrxyMChucRgexbXLSQ,68
3
3
  if_cli/cache.py,sha256=UfvHs3GQIVg0sVfKYWw4UGlq8d-8BEXuZIDfC1hwwjA,6587
4
- if_cli/cli.py,sha256=kBblhYrKEHFcWhI14imvEykxFYvagRTVrnc_hHEHzLY,2573
4
+ if_cli/cli.py,sha256=1pdYz3bhsNO120aWs9Fqjchj4UvNByn5Otk62IiBvzY,5832
5
5
  if_cli/colour.py,sha256=2hbaM4ubTHGja6YZRD886eqnB7T2IaZyW5rvfOjxe4M,682
6
6
  if_cli/config.py,sha256=IZhuo0cMsP-L9rLIKYVB87YRhCF-tcuyBTWp0-um4vM,6338
7
7
  if_cli/constants.py,sha256=7pY68ZXSspE3dDVFnSQ461CnKNSDu2ibMbPT3WfYWFA,209
@@ -17,7 +17,7 @@ if_cli/commands/logout.py,sha256=TW0P4_tXcTtiHHR73xVPHyhlbOWD1jBnkZsMImCiCBw,668
17
17
  if_cli/commands/profiles.py,sha256=JNBrYWdHQ9MHauwZxH33IAOYgRYRniX7bwd7KBT6Vyk,3869
18
18
  if_cli/commands/set_token.py,sha256=BVyv_QmByvllr04pE2sz8JFEscHbIgOC-7ZPg61PRoc,1886
19
19
  if_cli/commands/token.py,sha256=CyiXkyH7vxgH91-n-XJzeHnLI6mZJwO9Js5AHvfHaeM,1120
20
- insightfactory_cli-1.0.0.dev1.dist-info/METADATA,sha256=m4q9y44Zw6yLllpCVHnK4z5RYQcv9TR3uY24W17c2H8,10880
21
- insightfactory_cli-1.0.0.dev1.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
22
- insightfactory_cli-1.0.0.dev1.dist-info/entry_points.txt,sha256=UlX854D7f-7dBj5F0wGdakVy6vopvP9hA1BN-gv739w,44
23
- insightfactory_cli-1.0.0.dev1.dist-info/RECORD,,
20
+ insightfactory_cli-1.0.0.dev2.dist-info/METADATA,sha256=xeezJWtMgGE5eV6nU0YF2fkSGl1du6cwrHd2rRBktPk,10880
21
+ insightfactory_cli-1.0.0.dev2.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
22
+ insightfactory_cli-1.0.0.dev2.dist-info/entry_points.txt,sha256=UlX854D7f-7dBj5F0wGdakVy6vopvP9hA1BN-gv739w,44
23
+ insightfactory_cli-1.0.0.dev2.dist-info/RECORD,,