openbb-cli 1.0.2__tar.gz → 1.0.4__tar.gz

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.
Files changed (47) hide show
  1. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/PKG-INFO +2 -3
  2. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/argparse_translator/obbject_registry.py +42 -9
  3. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/argparse_translator/reference_processor.py +5 -0
  4. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/argparse_translator/utils.py +8 -3
  5. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/cli.py +9 -1
  6. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/controllers/base_controller.py +89 -32
  7. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/controllers/base_platform_controller.py +69 -28
  8. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/controllers/choices.py +17 -0
  9. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/controllers/cli_controller.py +9 -16
  10. openbb_cli-1.0.4/openbb_cli/controllers/settings_controller.py +142 -0
  11. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/controllers/utils.py +53 -47
  12. openbb_cli-1.0.4/openbb_cli/models/settings.py +167 -0
  13. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/session.py +0 -3
  14. openbb_cli-1.0.4/openbb_cli/utils/utils.py +34 -0
  15. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/pyproject.toml +2 -3
  16. openbb_cli-1.0.2/openbb_cli/controllers/settings_controller.py +0 -373
  17. openbb_cli-1.0.2/openbb_cli/models/settings.py +0 -76
  18. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/README.md +0 -0
  19. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/__init__.py +0 -0
  20. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/argparse_translator/__init__.py +0 -0
  21. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/argparse_translator/argparse_argument.py +0 -0
  22. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/argparse_translator/argparse_class_processor.py +0 -0
  23. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/argparse_translator/argparse_translator.py +0 -0
  24. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/assets/routines/routine_example.openbb +0 -0
  25. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/assets/styles/default/Consolas.ttf +0 -0
  26. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/assets/styles/default/dark.mpfstyle.json +0 -0
  27. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/assets/styles/default/dark.mplrc.json +0 -0
  28. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/assets/styles/default/dark.mplstyle +0 -0
  29. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/assets/styles/default/dark.pltstyle.json +0 -0
  30. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/assets/styles/default/dark.richstyle.json +0 -0
  31. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/assets/styles/default/light.mpfstyle.json +0 -0
  32. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/assets/styles/default/light.mplrc.json +0 -0
  33. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/assets/styles/default/light.mplstyle +0 -0
  34. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/assets/styles/default/light.pltstyle.json +0 -0
  35. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/assets/styles/default/light.richstyle.json +0 -0
  36. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/assets/styles/default/tables.pltstyle.json +0 -0
  37. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/assets/styles/user/openbb.richstyle.json +0 -0
  38. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/config/__init__.py +0 -0
  39. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/config/completer.py +0 -0
  40. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/config/console.py +0 -0
  41. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/config/constants.py +0 -0
  42. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/config/menu_text.py +0 -0
  43. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/config/setup.py +0 -0
  44. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/config/style.py +0 -0
  45. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/controllers/hub_service.py +0 -0
  46. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/controllers/platform_controller_factory.py +0 -0
  47. {openbb_cli-1.0.2 → openbb_cli-1.0.4}/openbb_cli/controllers/script_parser.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: openbb-cli
3
- Version: 1.0.2
3
+ Version: 1.0.4
4
4
  Summary: Investment Research for Everyone, Anywhere.
5
5
  Home-page: https://openbb.co
6
6
  License: AGPL-3.0-only
@@ -12,8 +12,7 @@ Classifier: Programming Language :: Python :: 3
12
12
  Classifier: Programming Language :: Python :: 3.9
13
13
  Classifier: Programming Language :: Python :: 3.10
14
14
  Classifier: Programming Language :: Python :: 3.11
15
- Requires-Dist: openbb-core (>=1.2.4,<2.0.0)
16
- Requires-Dist: openbb[all] (>=4.2.1,<5.0.0)
15
+ Requires-Dist: openbb[all] (>=4.2.3,<5.0.0)
17
16
  Requires-Dist: openpyxl (>=3.1.2,<4.0.0)
18
17
  Requires-Dist: prompt-toolkit (>=3.0.16,<4.0.0)
19
18
  Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
@@ -1,7 +1,7 @@
1
1
  """Registry for OBBjects."""
2
2
 
3
3
  import json
4
- from typing import Dict, List
4
+ from typing import Dict, List, Optional, Union
5
5
 
6
6
  from openbb_core.app.model.obbject import OBBject
7
7
 
@@ -29,11 +29,32 @@ class Registry:
29
29
  return True
30
30
  return False
31
31
 
32
- def get(self, idx: int) -> OBBject:
32
+ def get(self, arg: Union[int, str]) -> Optional[OBBject]:
33
+ """Return the obbject with index or key."""
34
+ if isinstance(arg, int):
35
+ return self._get_by_index(arg)
36
+ if isinstance(arg, str):
37
+ return self._get_by_key(arg)
38
+
39
+ raise ValueError("Couldn't get the `OBBject` with the provided argument.")
40
+
41
+ def _get_by_key(self, key: str) -> Optional[OBBject]:
42
+ """Return the obbject with key."""
43
+ for obbject in self._obbjects:
44
+ if obbject.extra.get("register_key", "") == key:
45
+ return obbject
46
+ return None
47
+
48
+ def _get_by_index(self, idx: int) -> Optional[OBBject]:
33
49
  """Return the obbject at index idx."""
34
50
  # the list should work as a stack
35
51
  # i.e., the last element needs to be accessed by idx=0 and so on
36
52
  reversed_list = list(reversed(self._obbjects))
53
+
54
+ # check if the index is out of bounds
55
+ if idx >= len(reversed_list):
56
+ return None
57
+
37
58
  return reversed_list[idx]
38
59
 
39
60
  def remove(self, idx: int = -1):
@@ -46,22 +67,24 @@ class Registry:
46
67
 
47
68
  @property
48
69
  def all(self) -> Dict[int, Dict]:
49
- """Return all obbjects in the registry"""
70
+ """Return all obbjects in the registry."""
50
71
 
51
72
  def _handle_standard_params(obbject: OBBject) -> str:
52
- """Handle standard params for obbjects"""
73
+ """Handle standard params for obbjects."""
53
74
  standard_params_json = ""
54
- std_params = obbject._standard_params # pylint: disable=protected-access
55
- if hasattr(std_params, "__dict__"):
75
+ std_params = getattr(
76
+ obbject, "_standard_params", {}
77
+ ) # pylint: disable=protected-access
78
+ if std_params:
56
79
  standard_params = {
57
- k: str(v)[:30] for k, v in std_params.__dict__.items() if v
80
+ k: str(v)[:30] for k, v in std_params.items() if v and k != "data"
58
81
  }
59
82
  standard_params_json = json.dumps(standard_params)
60
83
 
61
84
  return standard_params_json
62
85
 
63
86
  def _handle_data_repr(obbject: OBBject) -> str:
64
- """Handle data representation for obbjects"""
87
+ """Handle data representation for obbjects."""
65
88
  data_repr = ""
66
89
  if hasattr(obbject, "results") and obbject.results:
67
90
  data_schema = (
@@ -84,11 +107,21 @@ class Registry:
84
107
  "standard params": _handle_standard_params(obbject),
85
108
  "data": _handle_data_repr(obbject),
86
109
  "command": obbject.extra.get("command", ""),
110
+ "key": obbject.extra.get("register_key", ""),
87
111
  }
88
112
 
89
113
  return obbjects
90
114
 
91
115
  @property
92
116
  def obbjects(self) -> List[OBBject]:
93
- """Return all obbjects in the registry"""
117
+ """Return all obbjects in the registry."""
94
118
  return self._obbjects
119
+
120
+ @property
121
+ def obbject_keys(self) -> List[str]:
122
+ """Return all obbject keys in the registry."""
123
+ return [
124
+ obbject.extra["register_key"]
125
+ for obbject in self._obbjects
126
+ if "register_key" in obbject.extra
127
+ ]
@@ -1,8 +1,13 @@
1
1
  """Module for the ReferenceToArgumentsProcessor class."""
2
2
 
3
+ # `ForwardRef`needs to be imported because the usage of `eval()`,
4
+ # which creates a ForwardRef
5
+ # which would raise a not defined error if it's not imported here.
6
+ # pylint: disable=unused-import
3
7
  from typing import (
4
8
  Any,
5
9
  Dict,
10
+ ForwardRef, # noqa: F401
6
11
  List,
7
12
  Literal,
8
13
  Optional,
@@ -59,9 +59,14 @@ def get_argument_optional_choices(parser: ArgumentParser, argument_name: str) ->
59
59
  """Get the optional_choices attribute of an argument from an ArgumentParser."""
60
60
  for action in parser._actions: # pylint: disable=protected-access
61
61
  opts = action.option_strings
62
- if (opts and opts[0] == argument_name) or action.dest == argument_name:
63
- if hasattr(action, "optional_choices"):
64
- return action.optional_choices
62
+ if (
63
+ (opts and opts[0] == argument_name)
64
+ or action.dest == argument_name
65
+ and hasattr(action, "optional_choices")
66
+ ):
67
+ return (
68
+ action.optional_choices # type: ignore[attr-defined] # this is a custom attribute
69
+ )
65
70
  return False
66
71
 
67
72
 
@@ -2,6 +2,8 @@
2
2
 
3
3
  import sys
4
4
 
5
+ from openbb_cli.utils.utils import change_logging_sub_app, reset_logging_sub_app
6
+
5
7
 
6
8
  def main():
7
9
  """Use the main entry point for the OpenBB Platform CLI."""
@@ -20,4 +22,10 @@ def main():
20
22
 
21
23
 
22
24
  if __name__ == "__main__":
23
- main()
25
+ initial_logging_sub_app = change_logging_sub_app()
26
+ try:
27
+ main()
28
+ except Exception:
29
+ pass
30
+ finally:
31
+ reset_logging_sub_app(initial_logging_sub_app)
@@ -24,6 +24,7 @@ from openbb_cli.controllers.utils import (
24
24
  print_rich_table,
25
25
  remove_file,
26
26
  system_clear,
27
+ validate_register_key,
27
28
  )
28
29
  from openbb_cli.session import Session
29
30
  from prompt_toolkit.formatted_text import HTML
@@ -138,27 +139,10 @@ class BaseController(metaclass=ABCMeta):
138
139
 
139
140
  def load_class(self, class_ins, *args, **kwargs):
140
141
  """Check for an existing instance of the controller before creating a new one."""
141
- settings = session.settings
142
142
  self.save_class()
143
143
  arguments = len(args) + len(kwargs)
144
- # Due to the 'arguments == 1' condition, we actually NEVER load a class
145
- # that has arguments (The 1 argument corresponds to self.queue)
146
- # Advantage: If the user changes something on one controller and then goes to the
147
- # controller below, it will create such class from scratch bringing all new variables
148
- # in and considering latest changes.
149
- # Disadvantage: If the user goes on a controller below and we have been there before
150
- # it will not load that previous class, but create a new one from scratch.
151
- # SCENARIO: If the user is in stocks and does load AAPL/ta the TA menu will get AAPL,
152
- # and if then the user goes back to the stocks menu using .. that menu will have AAPL
153
- # Now, if "arguments == 1" condition exists, if the user does "load TSLA" and then
154
- # goes into "TA", the "TSLA" ticker will appear. If that condition doesn't exist
155
- # the previous class will be loaded and even if the user changes the ticker on
156
- # the stocks context it will not impact the one of TA menu - unless changes are done.
157
- if (
158
- class_ins.PATH in controllers
159
- and arguments == 1
160
- and settings.REMEMBER_CONTEXTS
161
- ):
144
+
145
+ if class_ins.PATH in controllers and arguments == 1:
162
146
  old_class = controllers[class_ins.PATH]
163
147
  old_class.queue = self.queue
164
148
  return old_class.menu()
@@ -166,8 +150,7 @@ class BaseController(metaclass=ABCMeta):
166
150
 
167
151
  def save_class(self) -> None:
168
152
  """Save the current instance of the class to be loaded later."""
169
- if session.settings.REMEMBER_CONTEXTS:
170
- controllers[self.PATH] = self
153
+ controllers[self.PATH] = self
171
154
 
172
155
  def custom_reset(self) -> List[str]:
173
156
  """Implement custom reset.
@@ -646,19 +629,77 @@ class BaseController(metaclass=ABCMeta):
646
629
  "'OBBjects' where all execution results are stored. "
647
630
  "It is organized as a stack, with the most recent result at index 0.",
648
631
  )
632
+ parser.add_argument("--index", dest="index", help="Index of the result.")
633
+ parser.add_argument("--key", dest="key", help="Key of the result.")
634
+ parser.add_argument(
635
+ "--chart", action="store_true", dest="chart", help="Display chart."
636
+ )
637
+ parser.add_argument(
638
+ "--export", dest="export", help="Export data.", nargs="+", default=None
639
+ )
640
+
649
641
  ns_parser = self.parse_simple_args(parser, other_args)
650
642
  if ns_parser:
651
- results = session.obbject_registry.all
652
- if results:
653
- df = pd.DataFrame.from_dict(results, orient="index")
654
- print_rich_table(
655
- df,
656
- show_index=True,
657
- index_name="stack index",
658
- title="OBBject Results",
659
- )
660
- else:
661
- session.console.print("[info]No results found.[/info]")
643
+ if not ns_parser.index and not ns_parser.key:
644
+ results = session.obbject_registry.all
645
+ if results:
646
+ df = pd.DataFrame.from_dict(results, orient="index")
647
+ print_rich_table(
648
+ df,
649
+ show_index=True,
650
+ index_name="stack index",
651
+ title="OBBject Results",
652
+ )
653
+ else:
654
+ session.console.print("[info]No results found.[/info]")
655
+ elif ns_parser.index:
656
+ try:
657
+ index = int(ns_parser.index)
658
+ obbject = session.obbject_registry.get(index)
659
+ if obbject:
660
+ if ns_parser.chart and obbject.chart:
661
+ obbject.show()
662
+ else:
663
+ title = obbject.extra.get("command", "")
664
+ df = obbject.to_dataframe()
665
+ print_rich_table(
666
+ df=df,
667
+ show_index=True,
668
+ title=title,
669
+ export=ns_parser.export,
670
+ )
671
+ if ns_parser.chart and not obbject.chart:
672
+ session.console.print(
673
+ "[info]No chart available.[/info]"
674
+ )
675
+ else:
676
+ session.console.print(
677
+ f"[info]No result found at index {index}.[/info]"
678
+ )
679
+ except ValueError:
680
+ session.console.print(
681
+ f"[red]Index must be an integer, not '{ns_parser.index}'.[/red]"
682
+ )
683
+ elif ns_parser.key:
684
+ obbject = session.obbject_registry.get(ns_parser.key)
685
+ if obbject:
686
+ if ns_parser.chart and obbject.chart:
687
+ obbject.show()
688
+ else:
689
+ title = obbject.extra.get("command", "")
690
+ df = obbject.to_dataframe()
691
+ print_rich_table(
692
+ df=df,
693
+ show_index=True,
694
+ title=title,
695
+ export=ns_parser.export,
696
+ )
697
+ if ns_parser.chart and not obbject.chart:
698
+ session.console.print("[info]No chart available.[/info]")
699
+ else:
700
+ session.console.print(
701
+ f"[info]No result found with key '{ns_parser.key}'.[/info]"
702
+ )
662
703
 
663
704
  @staticmethod
664
705
  def parse_simple_args(parser: argparse.ArgumentParser, other_args: List[str]):
@@ -792,6 +833,22 @@ class BaseController(metaclass=ABCMeta):
792
833
  help="Number of entries to show in data.",
793
834
  type=check_positive,
794
835
  )
836
+
837
+ parser.add_argument(
838
+ "--register_obbject",
839
+ dest="register_obbject",
840
+ action="store_false",
841
+ default=True,
842
+ help="Flag to store data in the OBBject registry, True by default.",
843
+ )
844
+ parser.add_argument(
845
+ "--register_key",
846
+ dest="register_key",
847
+ default="",
848
+ help="Key to reference data in the OBBject registry.",
849
+ type=validate_register_key,
850
+ )
851
+
795
852
  if session.settings.USE_CLEAR_AFTER_CMD:
796
853
  system_clear()
797
854
 
@@ -75,20 +75,31 @@ class PlatformController(BaseController):
75
75
  for _, trl in self.translators.items():
76
76
  for action in trl._parser._actions: # pylint: disable=protected-access
77
77
  if action.dest == "data":
78
+ # Generate choices by combining indexed and key-based choices
78
79
  action.choices = [
79
80
  "OBB" + str(i)
80
81
  for i in range(len(session.obbject_registry.obbjects))
82
+ ] + [
83
+ obbject.extra["register_key"]
84
+ for obbject in session.obbject_registry.obbjects
85
+ if "register_key" in obbject.extra
81
86
  ]
87
+
82
88
  action.type = str
83
89
  action.nargs = None
84
90
 
85
91
  def _intersect_data_processing_commands(self, ns_parser):
86
92
  """Intersect data processing commands and change the obbject id into an actual obbject."""
87
93
  if hasattr(ns_parser, "data"):
88
- ns_parser.data = int(ns_parser.data.replace("OBB", ""))
89
- if ns_parser.data in range(len(session.obbject_registry.obbjects)):
94
+ if "OBB" in ns_parser.data:
95
+ ns_parser.data = int(ns_parser.data.replace("OBB", ""))
96
+
97
+ if (ns_parser.data in range(len(session.obbject_registry.obbjects))) or (
98
+ ns_parser.data in session.obbject_registry.obbject_keys
99
+ ):
90
100
  obbject = session.obbject_registry.get(ns_parser.data)
91
- setattr(ns_parser, "data", obbject.results)
101
+ if obbject and isinstance(obbject, OBBject):
102
+ setattr(ns_parser, "data", obbject.results)
92
103
 
93
104
  return ns_parser
94
105
 
@@ -151,6 +162,11 @@ class PlatformController(BaseController):
151
162
  ):
152
163
  try:
153
164
  ns_parser = self._intersect_data_processing_commands(ns_parser)
165
+ export = hasattr(ns_parser, "export") and ns_parser.export
166
+ store_obbject = (
167
+ hasattr(ns_parser, "register_obbject")
168
+ and ns_parser.register_obbject
169
+ )
154
170
 
155
171
  obbject = translator.execute_func(parsed_args=ns_parser)
156
172
  df: pd.DataFrame = pd.DataFrame()
@@ -159,7 +175,11 @@ class PlatformController(BaseController):
159
175
 
160
176
  if obbject:
161
177
  if isinstance(obbject, OBBject):
162
- if session.max_obbjects_exceeded() and obbject.results:
178
+ if (
179
+ session.max_obbjects_exceeded()
180
+ and obbject.results
181
+ and store_obbject
182
+ ):
163
183
  session.obbject_registry.remove()
164
184
  session.console.print(
165
185
  "[yellow]Maximum number of OBBjects reached. The oldest entry was removed.[yellow]"
@@ -167,48 +187,69 @@ class PlatformController(BaseController):
167
187
 
168
188
  # use the obbject to store the command so we can display it later on results
169
189
  obbject.extra["command"] = f"{title} {' '.join(other_args)}"
170
-
171
- register_result = session.obbject_registry.register(obbject)
172
-
173
- # we need to force to re-link so that the new obbject
174
- # is immediately available for data processing commands
175
- self._link_obbject_to_data_processing_commands()
176
- # also update the completer
177
- self.update_completer(self.choices_default)
178
-
190
+ # if there is a registry key in the parser, store to the obbject
179
191
  if (
180
- session.settings.SHOW_MSG_OBBJECT_REGISTRY
181
- and register_result
192
+ hasattr(ns_parser, "register_key")
193
+ and ns_parser.register_key
182
194
  ):
183
- session.console.print(
184
- "Added `OBBject` to cached results."
195
+ if (
196
+ ns_parser.register_key
197
+ not in session.obbject_registry.obbject_keys
198
+ ):
199
+ obbject.extra["register_key"] = str(
200
+ ns_parser.register_key
201
+ )
202
+ else:
203
+ session.console.print(
204
+ f"[yellow]Key `{ns_parser.register_key}` already exists in the registry."
205
+ "The `OBBject` was kept without the key.[/yellow]"
206
+ )
207
+
208
+ if store_obbject:
209
+ # store the obbject in the registry
210
+ register_result = session.obbject_registry.register(
211
+ obbject
185
212
  )
186
213
 
187
- # making the dataframe available
188
- # either for printing or exporting (or both)
214
+ # we need to force to re-link so that the new obbject
215
+ # is immediately available for data processing commands
216
+ self._link_obbject_to_data_processing_commands()
217
+ # also update the completer
218
+ self.update_completer(self.choices_default)
219
+
220
+ if (
221
+ session.settings.SHOW_MSG_OBBJECT_REGISTRY
222
+ and register_result
223
+ ):
224
+ session.console.print(
225
+ "Added `OBBject` to cached results."
226
+ )
227
+
228
+ # making the dataframe available either for printing or exporting
189
229
  df = obbject.to_dataframe()
190
230
 
191
231
  if hasattr(ns_parser, "chart") and ns_parser.chart:
192
- obbject.show()
193
232
  fig = obbject.chart.fig if obbject.chart else None
233
+ if not export:
234
+ obbject.show()
194
235
  else:
195
236
  if isinstance(df.columns, pd.RangeIndex):
196
237
  df.columns = [str(i) for i in df.columns]
197
238
 
198
- print_rich_table(df=df, show_index=True, title=title)
239
+ print_rich_table(
240
+ df=df, show_index=True, title=title, export=export
241
+ )
199
242
 
200
243
  elif isinstance(obbject, dict):
201
244
  df = pd.DataFrame.from_dict(obbject, orient="columns")
202
- print_rich_table(df=df, show_index=True, title=title)
245
+ print_rich_table(
246
+ df=df, show_index=True, title=title, export=export
247
+ )
203
248
 
204
249
  elif not isinstance(obbject, OBBject):
205
250
  session.console.print(obbject)
206
251
 
207
- if (
208
- hasattr(ns_parser, "export")
209
- and ns_parser.export
210
- and not df.empty
211
- ):
252
+ if export and not df.empty:
212
253
  sheet_name = getattr(ns_parser, "sheet_name", None)
213
254
  if sheet_name and isinstance(sheet_name, list):
214
255
  sheet_name = sheet_name[0]
@@ -221,7 +262,7 @@ class PlatformController(BaseController):
221
262
  sheet_name=sheet_name,
222
263
  figure=fig,
223
264
  )
224
- elif hasattr(ns_parser, "export") and ns_parser.export and df.empty:
265
+ elif export and df.empty:
225
266
  session.console.print("[yellow]No data to export.[/yellow]")
226
267
 
227
268
  except Exception as e:
@@ -10,6 +10,7 @@ from unittest.mock import patch
10
10
  from openbb_cli.controllers.utils import (
11
11
  check_file_type_saved,
12
12
  check_positive,
13
+ validate_register_key,
13
14
  )
14
15
  from openbb_cli.session import Session
15
16
 
@@ -93,6 +94,21 @@ def __mock_parse_known_args_and_warn(
93
94
  type=check_positive,
94
95
  )
95
96
 
97
+ parser.add_argument(
98
+ "--register_obbject",
99
+ dest="register_obbject",
100
+ action="store_false",
101
+ default=True,
102
+ help="Flag to store data in the OBBject registry, True by default.",
103
+ )
104
+ parser.add_argument(
105
+ "--register_key",
106
+ dest="register_key",
107
+ default="",
108
+ help="Key to reference data in the OBBject registry.",
109
+ type=validate_register_key,
110
+ )
111
+
96
112
 
97
113
  def __mock_parse_simple_args(parser: ArgumentParser, other_args: List[str]) -> None:
98
114
  """Add arguments.
@@ -274,6 +290,7 @@ def _get_argument_parser(
274
290
  " - parse_known_args_and_warn\n"
275
291
  )
276
292
 
293
+ # pylint: disable=possibly-used-before-assignment
277
294
  return argument_parser
278
295
 
279
296
 
@@ -4,7 +4,6 @@
4
4
  import argparse
5
5
  import contextlib
6
6
  import difflib
7
- import logging
8
7
  import os
9
8
  import re
10
9
  import sys
@@ -59,8 +58,6 @@ DATA_PROCESSING_ROUTERS = ["technical", "quantitative", "econometrics"]
59
58
  # pylint: disable=too-many-public-methods,import-outside-toplevel, too-many-function-args
60
59
  # pylint: disable=too-many-branches,no-member,C0302,too-many-return-statements, inconsistent-return-statements
61
60
 
62
- logger = logging.getLogger(__name__)
63
-
64
61
  env_file = str(ENV_FILE_SETTINGS)
65
62
  session = Session()
66
63
 
@@ -205,7 +202,14 @@ class CLIController(BaseController):
205
202
  "-h": "--help",
206
203
  }
207
204
  choices["stop"] = {"--help": None, "-h": "--help"}
208
- choices["results"] = {"--help": None, "-h": "--help"}
205
+ choices["results"] = {
206
+ "--help": None,
207
+ "-h": "--help",
208
+ "--export": None,
209
+ "--index": None,
210
+ "--key": None,
211
+ "--chart": None,
212
+ }
209
213
 
210
214
  self.update_completer(choices)
211
215
 
@@ -291,7 +295,7 @@ class CLIController(BaseController):
291
295
  : session.settings.N_TO_DISPLAY_OBBJECT_REGISTRY
292
296
  ]:
293
297
  mt.add_raw(
294
- f"[yellow]OBB{key}[/yellow]: {value['command']}",
298
+ f"[yellow]OBB{key}[/yellow]: {value['command']}", # type: ignore[index]
295
299
  left_spacing=True,
296
300
  )
297
301
 
@@ -497,11 +501,6 @@ class CLIController(BaseController):
497
501
 
498
502
  def handle_job_cmds(jobs_cmds: Optional[List[str]]) -> Optional[List[str]]:
499
503
  """Handle job commands."""
500
- # If the path selected does not start from the user root,
501
- # give relative location from root
502
- if jobs_cmds is not None and jobs_cmds:
503
- logger.info("INPUT: %s", "/".join(jobs_cmds))
504
-
505
504
  export_path = ""
506
505
  if jobs_cmds and "export" in jobs_cmds[0]:
507
506
  commands = jobs_cmds[0].split("/")
@@ -619,10 +618,6 @@ def run_cli(jobs_cmds: Optional[List[str]] = None, test_mode=False):
619
618
  break
620
619
 
621
620
  except SystemExit:
622
- logger.exception(
623
- "The command '%s' doesn't exist on the / menu.",
624
- an_input,
625
- )
626
621
  session.console.print(
627
622
  f"[red]The command '{an_input}' doesn't exist on the / menu.[/red]\n",
628
623
  )
@@ -769,7 +764,6 @@ def replace_dynamic(match: re.Match, special_arguments: Dict[str, str]) -> str:
769
764
  str
770
765
  The new string
771
766
  """
772
-
773
767
  cleaned = match[0].replace("{", "").replace("}", "").replace("$", "")
774
768
  key, default = cleaned.split("=")
775
769
  dict_value = special_arguments.get(key, default)
@@ -939,7 +933,6 @@ def launch(
939
933
  debug: bool = False, dev: bool = False, queue: Optional[List[str]] = None
940
934
  ) -> None:
941
935
  """Launch CLI."""
942
-
943
936
  if queue:
944
937
  main(debug, dev, queue, module="")
945
938
  else: