nodestream
nodestream copied to clipboard
[REQUEST] Provide Friendlier Errors for `MissingFromRegistryError`s and `KeyError`s
Is your feature request related to a problem? Please describe. Its not obvious from this error message what is not found and what the pipeline is trying to load that it can.
KeyError
None
at ~\AppData\Local\pypoetry\Cache\virtualenvs\test1-WxuTdTEg-py3.11\Lib\site-packages\nodestream\subclass_registry.py:60 in get
56│
57│ def get(self, name):
58│ """Get a subclass by name."""
59│ try:
→ 60│ return self.registry[name]
61│ except KeyError:
62│ raise MissingFromRegistryError(name)
63│
64│ @property
The following error occurred when trying to handle this error:
Stack trace:
24 ~\AppData\Local\pypoetry\Cache\virtualenvs\test1-WxuTdTEg-py3.11\Lib\site-packages\cleo\application.py:327 in run
325│
326│ try:
→ 327│ exit_code = self._run(io)
328│ except BrokenPipeError:
329│ # If we are piped to another process, it may close early and send a
23 ~\AppData\Local\pypoetry\Cache\virtualenvs\test1-WxuTdTEg-py3.11\Lib\site-packages\cleo\application.py:431 in _run
429│ io.input.interactive(interactive)
430│
→ 431│ exit_code = self._run_command(command, io)
432│ self._running_command = None
433│
22 ~\AppData\Local\pypoetry\Cache\virtualenvs\test1-WxuTdTEg-py3.11\Lib\site-packages\cleo\application.py:438 in _run_command
436│ def _run_command(self, command: Command, io: IO) -> int:
437│ if self._event_dispatcher is None:
→ 438│ return command.run(io)
439│
440│ # Bind before the console.command event,
21 ~\AppData\Local\pypoetry\Cache\virtualenvs\test1-WxuTdTEg-py3.11\Lib\site-packages\cleo\commands\base_command.py:119 in run
117│ io.input.validate()
118│
→ 119│ status_code = self.execute(io)
120│
121│ if status_code is None:
20 ~\AppData\Local\pypoetry\Cache\virtualenvs\test1-WxuTdTEg-py3.11\Lib\site-packages\cleo\commands\command.py:62 in execute
60│
61│ try:
→ 62│ return self.handle()
63│ except KeyboardInterrupt:
64│ return 1
19 ~\AppData\Local\pypoetry\Cache\virtualenvs\test1-WxuTdTEg-py3.11\Lib\site-packages\nodestream\cli\commands\nodestream_command.py:21 in handle
19│
20│ def handle(self):
→ 21│ return asyncio.run(self.handle_async())
22│
23│ async def handle_async(self):
18 ~\AppData\Local\Programs\Python\Python311\Lib\asyncio\runners.py:190 in run
188│
189│ with Runner(debug=debug) as runner:
→ 190│ return runner.run(main)
191│
192│
17 ~\AppData\Local\Programs\Python\Python311\Lib\asyncio\runners.py:118 in run
116│ self._interrupt_count = 0
117│ try:
→ 118│ return self._loop.run_until_complete(task)
119│ except exceptions.CancelledError:
120│ if self._interrupt_count > 0:
16 ~\AppData\Local\Programs\Python\Python311\Lib\asyncio\base_events.py:653 in run_until_complete
651│ raise RuntimeError('Event loop stopped before Future completed.')
652│
→ 653│ return future.result()
654│
655│ def stop(self):
15 ~\AppData\Local\pypoetry\Cache\virtualenvs\test1-WxuTdTEg-py3.11\Lib\site-packages\nodestream\cli\commands\run.py:41 in handle_async
39│ await self.run_operation(InitializeLogger())
40│ project = await self.run_operation(InitializeProject())
→ 41│ await self.run_operation(RunPipeline(project))
42│
14 ~\AppData\Local\pypoetry\Cache\virtualenvs\test1-WxuTdTEg-py3.11\Lib\site-packages\nodestream\cli\commands\nodestream_command.py:30 in run_operation
28│ f"Running: {operation.name}", verbosity=Verbosity.VERBOSE
29│ )
→ 30│ return await operation.perform(self)
31│
32│ def get_project_path(self) -> Path:
13 ~\AppData\Local\pypoetry\Cache\virtualenvs\test1-WxuTdTEg-py3.11\Lib\site-packages\nodestream\cli\operations\run_pipeline.py:32 in perform
30│ for pipeline_name in self.get_pipelines_to_run(command):
31│ request = self.make_run_request(command, pipeline_name)
→ 32│ pipelines_ran += await self.project.run(request)
33│
34│ if pipelines_ran == 0:
12 ~\AppData\Local\pypoetry\Cache\virtualenvs\test1-WxuTdTEg-py3.11\Lib\site-packages\nodestream\project\project.py:122 in run
120│ pipelines_ran = 0
121│ for scope in self.scopes_by_name.values():
→ 122│ pipelines_ran += await scope.run_request(request)
123│ return pipelines_ran
124│
11 ~\AppData\Local\pypoetry\Cache\virtualenvs\test1-WxuTdTEg-py3.11\Lib\site-packages\nodestream\project\pipeline_scope.py:85 in run_request
83│ return 0
84│
→ 85│ await run_request.execute_with_definition(self[name], self.config)
86│ return 1
87│
10 ~\AppData\Local\pypoetry\Cache\virtualenvs\test1-WxuTdTEg-py3.11\Lib\site-packages\nodestream\project\run_request.py:59 in execute_with_definition
57│ """
58│ with start_context(self.pipeline_name):
→ 59│ pipeline = definition.initialize(self.initialization_arguments, config)
60│ await pipeline.run(self.progress_reporter)
61│
9 ~\AppData\Local\pypoetry\Cache\virtualenvs\test1-WxuTdTEg-py3.11\Lib\site-packages\nodestream\project\pipeline_definition.py:91 in initialize
89│ self, init_args: PipelineInitializationArguments, config: ScopeConfig = None
90│ ) -> Pipeline:
→ 91│ return PipelineFileLoader(self.file_path).load_pipeline(init_args, config)
92│
93│ def remove_file(self, missing_ok: bool = True):
8 ~\AppData\Local\pypoetry\Cache\virtualenvs\test1-WxuTdTEg-py3.11\Lib\site-packages\nodestream\pipeline\pipeline_file_loader.py:118 in load_pipeline
116│ ) -> Pipeline:
117│ init_args = init_args or PipelineInitializationArguments()
→ 118│ return self.load_pipeline_from_file_data(
119│ self.load_pipeline_file_data(config), init_args
120│ )
7 ~\AppData\Local\pypoetry\Cache\virtualenvs\test1-WxuTdTEg-py3.11\Lib\site-packages\nodestream\pipeline\pipeline_file_loader.py:130 in load_pipeline_from_file_data
128│ )
129│
→ 130│ return init_args.initialize_from_file_data(file_data)
131│
132│ def load_pipeline_file_data(self, config: ScopeConfig = None):
6 ~\AppData\Local\pypoetry\Cache\virtualenvs\test1-WxuTdTEg-py3.11\Lib\site-packages\nodestream\pipeline\pipeline_file_loader.py:74 in initialize_from_file_data
72│ def initialize_from_file_data(self, file_data: List[dict]):
73│ return Pipeline(
→ 74│ steps=self.load_steps(ClassLoader(Step), file_data),
75│ step_outbox_size=self.step_outbox_size,
76│ )
5 ~\AppData\Local\pypoetry\Cache\virtualenvs\test1-WxuTdTEg-py3.11\Lib\site-packages\nodestream\pipeline\pipeline_file_loader.py:82 in load_steps
80│ if self.on_effective_configuration_resolved:
81│ self.on_effective_configuration_resolved(file_data)
→ 82│ return [class_loader.load_class(**step_data) for step_data in effective]
83│
84│ def get_effective_configuration(self, file_data):
4 ~\AppData\Local\pypoetry\Cache\virtualenvs\test1-WxuTdTEg-py3.11\Lib\site-packages\nodestream\pipeline\pipeline_file_loader.py:82 in <listcomp>
80│ if self.on_effective_configuration_resolved:
81│ self.on_effective_configuration_resolved(file_data)
→ 82│ return [class_loader.load_class(**step_data) for step_data in effective]
83│
84│ def get_effective_configuration(self, file_data):
3 ~\AppData\Local\pypoetry\Cache\virtualenvs\test1-WxuTdTEg-py3.11\Lib\site-packages\nodestream\pipeline\class_loader.py:62 in load_class
60│ initializer = self.find_class_initializer(implementation, factory)
61│ try:
→ 62│ result = initializer(**arguments)
63│ except TypeError as e:
64│ raise PipelineComponentInitializationError(initializer, arguments) from e
2 ~\AppData\Local\pypoetry\Cache\virtualenvs\test1-WxuTdTEg-py3.11\Lib\site-packages\nodestream\databases\writer.py:21 in from_file_data
19│ # Import all query executors so that they can register themselves
20│ DatabaseConnector.import_all()
→ 21│ connector = DatabaseConnector.from_database_args(
22│ database=database, **database_args
23│ )
1 ~\AppData\Local\pypoetry\Cache\virtualenvs\test1-WxuTdTEg-py3.11\Lib\site-packages\nodestream\databases\database_connector.py:19 in from_database_args
17│ cls, database: str = "neo4j", **database_args
18│ ) -> "DatabaseConnector":
→ 19│ return DATABASE_CONNECTOR_SUBCLASS_REGISTRY.get(database).from_file_data(
20│ **database_args
21│ )
MissingFromRegistryError
None is not in the subclass registry
at ~\AppData\Local\pypoetry\Cache\virtualenvs\test1-WxuTdTEg-py3.11\Lib\site-packages\nodestream\subclass_registry.py:62 in get
58│ """Get a subclass by name."""
59│ try:
60│ return self.registry[name]
61│ except KeyError:
→ 62│ raise MissingFromRegistryError(name)
63│
64│ @property
65│ def all_subclasses(self):
66│ return self.registry.values()
Describe the solution you'd like I think we should catch and re-raise these errors better to provide a better indicator as to what is wrong.
Describe alternatives you've considered n/a
Additional context n/a