def make_command(self, meta, val, existing): v = sb.set_options(path=sb.required(sb.string_spec()), allow_ws_only=sb.defaulted(sb.boolean(), False)).normalise( meta, val) path = v["path"] allow_ws_only = v["allow_ws_only"] if path not in self.paths: raise NoSuchPath(path, sorted(self.paths)) val = sb.set_options(body=sb.required( sb.set_options(args=sb.dictionary_spec(), command=sb.required(sb.string_spec())))).normalise( meta, val) args = val["body"]["args"] name = val["body"]["command"] if existing: name = val["body"]["command"] = f"{existing['path']}:{name}" extra_context = {} if existing: extra_context["_parent_command"] = existing["command"] everything = meta.everything if isinstance(meta.everything, MergedOptions): everything = meta.everything.wrapped() everything.update(extra_context) meta = Meta(everything, []).at("body") available_commands = self.paths[path] if name not in available_commands: raise BadSpecValue( "Unknown command", wanted=name, available=self.available(available_commands, allow_ws_only=allow_ws_only), meta=meta.at("command"), ) command = available_commands[name]["spec"].normalise( meta.at("args"), args) if not allow_ws_only and command.__whirlwind_ws_only__: raise BadSpecValue( "Command is for websockets only", wanted=name, available=self.available(available_commands, allow_ws_only=allow_ws_only), meta=meta.at("command"), ) return command, name
thing = await store.command_spec.normalise( meta, {"path": "/v1", "body": {"command": "thing", "args": {"one": 20}}} )() assert thing == {"one": 20} assert isinstance(thing, Thing) try: await store.command_spec.normalise( meta, {"path": "/v1", "body": {"command": "other"}} )() assert False, "expected an error" except BadSpecValue as error: assert len(error.errors) == 1 assert error.errors[0].as_dict() == { "message": "Bad value. Expected a value but got none", "meta": meta.at("body").at("args").at("two").delfick_error_format("two"), } stuff = await store.command_spec.normalise( meta, {"path": "/v2", "body": {"command": "stuff"}} )() assert stuff == {"three": wat} assert isinstance(stuff, Stuff) assert len(store.command_spec.existing_commands) == 0 async it "doesn't allow ws_only commands if told not to": store = Store(default_path="/v1", formatter=MergedOptionStringFormatter) @store.command("interactive") class Interactive(store.Command):