# Path: picatrix/lib/error.py
# class Error(Exception):
# class ArgParserNonZeroStatus(Error):
# 
# Path: picatrix/lib/manager.py
# class Helper:
# class MagicManager:
#   MAGICS_DF_COLUMNS = ['name', 'description', 'line', 'cell', 'function']
#   def clear_helpers(cls):
#   def clear_magics(cls):
#   def deregister_helper(cls, helper_name: Text):
#   def deregister_magic(cls, magic_name: Text):
#   def get_helper(cls, helper_name: Text) -> Optional[Callable[..., Any]]:
#   def get_magic(cls, magic_name: Text) -> Callable[[Text, Text], Text]:
#   def get_helper_info(
#       cls,
#       as_pandas: Optional[bool] = True
#   ) -> Union[pandas.DataFrame, List[Tuple[Text, Text]]]:
#   def get_magic_info(
#       cls,
#       as_pandas: Optional[bool] = True
#   ) -> Union[pandas.DataFrame, List[Tuple[Text, Text]]]:
#   def register_helper(
#       cls, name: Text, helper: Any, typing_help: Dict[Text, Any]):
#   def register_magic(
#       cls,
#       function: Callable[[Text, Text], Text],
#       conditional: Callable[[], bool] = None):
#     def capture_output(function, name):
#       def wrapper(*args, **kwargs):
# 
# Path: picatrix/lib/state.py
# def state(refresh_state: bool = False):
#   """Property that returns a state object."""
#   # pylint: disable=global-statement
#   # Making sure we have only one state object.
#   global __state
# 
#   with _LOCK:
#     if refresh_state or __state is None:
#       __state = State()
# 
#     return __state
# 
# Path: picatrix/lib/utils.py
# def ask_question(question: Text, input_type: Optional[Any] = Text) -> Any:
# def clear_notebook_output():
# def ipython_bind_global(name: Text, value: Any) -> Any:
# def ipython_get_global(name: Text) -> Any:
# def ipython_remove_global(name: Text):


import argparse
import functools
import inspect
import types
import typing
from typing import Any, Callable, Dict, List, Optional, Text
  from typing import Protocol
  from typing_extensions import Protocol
from picatrix.lib import error, manager, state, utils
  return function


def picatrix_magic(
    function: Optional[MagicProtocol] = None,
    arguments: Optional[List[MagicArgument]] = None,
    name_func: Optional[Callable[[Text], Text]] = None,
    conditional: Optional[Callable[[None], bool]] = None) -> MagicProtocol:
  """Decorator to turn functions into IPYthon magics for picatrix.

  Args:
    function (function): if the decorator is called without any arguments
        the magic function is passed to the decorator.
    arguments (list): list of MagicArgument objects to pass to the magic
        argument parser.
    name_func (function: a name function that will accept a single argument
        and return back a name that will be used to register the magic.
        Optional and if not provide the name of tbe function will be used.
    conditional (function): a function that should return a bool, used to
        determine whether to register magic or not. This can be used by
        magics to determine whether a magic should be registered or not, for
        instance basing that on whether a certain magic is able to reach the
        service it requires. This is optional and if not provided a magic
        will be registered.

  Returns:
    the decorator function.
  """
  if function:
    magic_function = _Magic(function, name_func=name_func, arguments=arguments)

# Path: picatrix/lib/error.py
# class Error(Exception):
# class ArgParserNonZeroStatus(Error):
# 
# Path: picatrix/lib/manager.py
# class Helper:
# class MagicManager:
#   MAGICS_DF_COLUMNS = ['name', 'description', 'line', 'cell', 'function']
#   def clear_helpers(cls):
#   def clear_magics(cls):
#   def deregister_helper(cls, helper_name: Text):
#   def deregister_magic(cls, magic_name: Text):
#   def get_helper(cls, helper_name: Text) -> Optional[Callable[..., Any]]:
#   def get_magic(cls, magic_name: Text) -> Callable[[Text, Text], Text]:
#   def get_helper_info(
#       cls,
#       as_pandas: Optional[bool] = True
#   ) -> Union[pandas.DataFrame, List[Tuple[Text, Text]]]:
#   def get_magic_info(
#       cls,
#       as_pandas: Optional[bool] = True
#   ) -> Union[pandas.DataFrame, List[Tuple[Text, Text]]]:
#   def register_helper(
#       cls, name: Text, helper: Any, typing_help: Dict[Text, Any]):
#   def register_magic(
#       cls,
#       function: Callable[[Text, Text], Text],
#       conditional: Callable[[], bool] = None):
#     def capture_output(function, name):
#       def wrapper(*args, **kwargs):
# 
# Path: picatrix/lib/state.py
# def state(refresh_state: bool = False):
#   """Property that returns a state object."""
#   # pylint: disable=global-statement
#   # Making sure we have only one state object.
#   global __state
# 
#   with _LOCK:
#     if refresh_state or __state is None:
#       __state = State()
# 
#     return __state
# 
# Path: picatrix/lib/utils.py
# def ask_question(question: Text, input_type: Optional[Any] = Text) -> Any:
# def clear_notebook_output():
# def ipython_bind_global(name: Text, value: Any) -> Any:
# def ipython_get_global(name: Text) -> Any:
# def ipython_remove_global(name: Text):


# Path: picatrix/lib/framework.py
import argparse
import functools
import inspect
import types
import typing
from typing import Any, Callable, Dict, List, Optional, Text
  from typing import Protocol
  from typing_extensions import Protocol
from picatrix.lib import error, manager, state, utils

  return function


def picatrix_magic(
    function: Optional[MagicProtocol] = None,
    arguments: Optional[List[MagicArgument]] = None,
    name_func: Optional[Callable[[Text], Text]] = None,
    conditional: Optional[Callable[[None], bool]] = None) -> MagicProtocol:
  """Decorator to turn functions into IPYthon magics for picatrix.

  Args:
    function (function): if the decorator is called without any arguments
        the magic function is passed to the decorator.
    arguments (list): list of MagicArgument objects to pass to the magic
        argument parser.
    name_func (function: a name function that will accept a single argument
        and return back a name that will be used to register the magic.
        Optional and if not provide the name of tbe function will be used.
    conditional (function): a function that should return a bool, used to
        determine whether to register magic or not. This can be used by
        magics to determine whether a magic should be registered or not, for
        instance basing that on whether a certain magic is able to reach the
        service it requires. This is optional and if not provided a magic
        will be registered.

  Returns:
    the decorator function.
  """
  if function:
    magic_function = _Magic(function, name_func=name_func, arguments=arguments)

    manager.MagicManager.register_magic(magic_function, conditional)