"""
analyst.base:
<NAME> <<EMAIL>>
Copyright 2020, <NAME>
License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0)

Contents:
    Analyst (SimpleManager):
    Report (SimpleSummary):
    
"""
from __future__ import annotations
import dataclasses
from typing import (Any, Callable, ClassVar, Dict, Iterable, List, Mapping, 
                    Optional, Sequence, Tuple, Type, Union)

import numpy as np
import pandas as pd
import sklearn
import sourdough

import simplify
from simplify.utilities import decorators


@dataclasses.dataclass
class Analyst(sourdough.project.Worker):
    """Base class for primitive objects in a sourdough composite object.
    
    The 'contents' and 'parameters' attributes are combined at the last moment
    to allow for runtime alterations.
    
    Args:
        name (str): designates the name of a class instance that is used for 
            internal referencing throughout sourdough. For example, if a 
            sourdough instance needs settings from a Configuration instance, 
            'name' should match the appropriate section name in a Configuration 
            instance. Defaults to None.
        contents (Any): stored item for use by a Component subclass instance.
        workflow (sourdough.project.Workflow): a workflow of a project subpart 
            derived from an Outline. Defaults to None.
        iterations (Union[int, str]): number of times the 'implement' method 
            should  be called. If 'iterations' is 'infinite', the 'implement' 
            method will continue indefinitely unless the method stops further 
            iteration. Defaults to 1.
        parameters (Mapping[Any, Any]]): parameters to be attached to 'contents' 
            when the 'implement' method is called. Defaults to an empty dict.
        parallel (ClassVar[bool]): indicates whether this Component design is
            meant to be at the end of a parallel workflow structure. Defaults to 
            False.
                                               
    """
    name: str = None
    contents: Callable = None
    workflow: sourdough.project.Workflow = None
    iterations: Union[int, str] = 1
    parameters: Mapping[Any, Any] = dataclasses.field(default_factory = dict)
    parallel: ClassVar[bool] = False  
        
    """ Public Methods """
    
    def implement(self, project: sourdough.Project, 
                  **kwargs) -> sourdough.Project:
        return project  


    @decorators.numpy_shield
    def fit(self,
            x: Optional[Union[pd.DataFrame, np.ndarray]] = None,
            y: Optional[Union[pd.Series, np.ndarray]] = None) -> None:
        """Generic fit method for partial compatibility to sklearn.

        Args:
            x (Optional[Union[pd.DataFrame, np.ndarray]]): independent
                variables/features.
            y (Optional[Union[pd.Series, np.ndarray]]): dependent
                variable/label.

        Raises:
            AttributeError if no 'fit' method exists for 'technique'.

        """
        x, y = sklearn.utils.check_X_y(X = x, y = y, accept_sparse = True)
        if self.fit_method is not None:
            if y is None:
                getattr(self.algorithm, self.fit_method)(x)
            else:
                self.algorithm = self.algorithm.fit(x, y)
        return self

    @decorators.numpy_shield
    def transform(self,
            x: Optional[Union[pd.DataFrame, np.ndarray]] = None,
            y: Optional[Union[pd.Series, np.ndarray]] = None) -> pd.DataFrame:
        """Generic transform method for partial compatibility to sklearn.

        Args:
            x (Optional[Union[pd.DataFrame, np.ndarray]]): independent
                variables/features.
            y (Optional[Union[pd.Series, np.ndarray]]): dependent
                variable/label.

        Returns:
            transformed x or data, depending upon what is passed to the
                method.

        Raises:
            AttributeError if no 'transform' method exists for local
                'process'.

        """
        if self.transform_method is not None:
            try:
                return getattr(self.algorithm, self.transform_method)(x)
            except AttributeError:
                return x
        else:
            return x



@dataclasses.dataclass
class Report(simplify.base.SimpleSummary):
    """Collects and stores results of executing a data science project workflow.
    
    Args:
        contents (Mapping[Any, Any]]): stored dictionary. Defaults to an empty 
            dict.
        default (Any): default value to return when the 'get' method is used.
        prefix (str): prefix to use when storing different paths through a 
            workflow. So, for example, a prefix of 'path' will create keys of
            'path_1', 'path_2', etc. Defaults to 'experiment'.
        needs (ClassVar[Union[Sequence[str], str]]): attributes needed from 
            another instance for some method within a subclass. Defaults to 
            a list with 'workflow' and 'data'.          
              
    """
    contents: Mapping[Any, Any] = dataclasses.field(default_factory = dict)
    default: Any = None
    prefix: str = 'experiment'
    needs: ClassVar[Union[Sequence[str], str]] = ['workflow', 'data'] 
    
"""
analyst.base:
<NAME> <<EMAIL>>
Copyright 2020, <NAME>
License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0)

Contents:
    Analyst (SimpleManager):
    Report (SimpleSummary):
    
"""
from __future__ import annotations
import dataclasses
from typing import (Any, Callable, ClassVar, Dict, Iterable, List, Mapping, 
                    Optional, Sequence, Tuple, Type, Union)

import numpy as np
import pandas as pd
import sklearn
import sourdough

import simplify
from simplify.utilities import decorators


@dataclasses.dataclass
class Analyst(sourdough.project.Worker):
    """Base class for primitive objects in a sourdough composite object.
    
    The 'contents' and 'parameters' attributes are combined at the last moment
    to allow for runtime alterations.
    
    Args:
        name (str): designates the name of a class instance that is used for 
            internal referencing throughout sourdough. For example, if a 
            sourdough instance needs settings from a Configuration instance, 
            'name' should match the appropriate section name in a Configuration 
            instance. Defaults to None.
        contents (Any): stored item for use by a Component subclass instance.
        workflow (sourdough.project.Workflow): a workflow of a project subpart 
            derived from an Outline. Defaults to None.
        iterations (Union[int, str]): number of times the 'implement' method 
            should  be called. If 'iterations' is 'infinite', the 'implement' 
            method will continue indefinitely unless the method stops further 
            iteration. Defaults to 1.
        parameters (Mapping[Any, Any]]): parameters to be attached to 'contents' 
            when the 'implement' method is called. Defaults to an empty dict.
        parallel (ClassVar[bool]): indicates whether this Component design is
            meant to be at the end of a parallel workflow structure. Defaults to 
            False.
                                               
    """
    name: str = None
    contents: Callable = None
    workflow: sourdough.project.Workflow = None
    iterations: Union[int, str] = 1
    parameters: Mapping[Any, Any] = dataclasses.field(default_factory = dict)
    parallel: ClassVar[bool] = False  
        
    """ Public Methods """
    
    def implement(self, project: sourdough.Project, 
                  **kwargs) -> sourdough.Project:
        return project  


    @decorators.numpy_shield
    def fit(self,
            x: Optional[Union[pd.DataFrame, np.ndarray]] = None,
            y: Optional[Union[pd.Series, np.ndarray]] = None) -> None:
        """Generic fit method for partial compatibility to sklearn.

        Args:
            x (Optional[Union[pd.DataFrame, np.ndarray]]): independent
                variables/features.
            y (Optional[Union[pd.Series, np.ndarray]]): dependent
                variable/label.

        Raises:
            AttributeError if no 'fit' method exists for 'technique'.

        """
        x, y = sklearn.utils.check_X_y(X = x, y = y, accept_sparse = True)
        if self.fit_method is not None:
            if y is None:
                getattr(self.algorithm, self.fit_method)(x)
            else:
                self.algorithm = self.algorithm.fit(x, y)
        return self

    @decorators.numpy_shield
    def transform(self,
            x: Optional[Union[pd.DataFrame, np.ndarray]] = None,
            y: Optional[Union[pd.Series, np.ndarray]] = None) -> pd.DataFrame:
        """Generic transform method for partial compatibility to sklearn.

        Args:
            x (Optional[Union[pd.DataFrame, np.ndarray]]): independent
                variables/features.
            y (Optional[Union[pd.Series, np.ndarray]]): dependent
                variable/label.

        Returns:
            transformed x or data, depending upon what is passed to the
                method.

        Raises:
            AttributeError if no 'transform' method exists for local
                'process'.

        """
        if self.transform_method is not None:
            try:
                return getattr(self.algorithm, self.transform_method)(x)
            except AttributeError:
                return x
        else:
            return x



@dataclasses.dataclass
class Report(simplify.base.SimpleSummary):
    """Collects and stores results of executing a data science project workflow.
    
    Args:
        contents (Mapping[Any, Any]]): stored dictionary. Defaults to an empty 
            dict.
        default (Any): default value to return when the 'get' method is used.
        prefix (str): prefix to use when storing different paths through a 
            workflow. So, for example, a prefix of 'path' will create keys of
            'path_1', 'path_2', etc. Defaults to 'experiment'.
        needs (ClassVar[Union[Sequence[str], str]]): attributes needed from 
            another instance for some method within a subclass. Defaults to 
            a list with 'workflow' and 'data'.          
              
    """
    contents: Mapping[Any, Any] = dataclasses.field(default_factory = dict)
    default: Any = None
    prefix: str = 'experiment'
    needs: ClassVar[Union[Sequence[str], str]] = ['workflow', 'data'] 
    
analyst.base: <NAME> <<EMAIL>> Copyright 2020, <NAME> License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0)  Contents:     Analyst (SimpleManager):     Report (SimpleSummary): Base class for primitive objects in a sourdough composite object.          The 'contents' and 'parameters' attributes are combined at the last moment     to allow for runtime alterations.          Args:         name (str): designates the name of a class instance that is used for              internal referencing throughout sourdough. For example, if a              sourdough instance needs settings from a Configuration instance,              'name' should match the appropriate section name in a Configuration              instance. Defaults to None.         contents (Any): stored item for use by a Component subclass instance.         workflow (sourdough.project.Workflow): a workflow of a project subpart              derived from an Outline. Defaults to None.         iterations (Union[int, str]): number of times the 'implement' method              should  be called. If 'iterations' is 'infinite', the 'implement'              method will continue indefinitely unless the method stops further              iteration. Defaults to 1.         parameters (Mapping[Any, Any]]): parameters to be attached to 'contents'              when the 'implement' method is called. Defaults to an empty dict.         parallel (ClassVar[bool]): indicates whether this Component design is             meant to be at the end of a parallel workflow structure. Defaults to              False. Public Methods Generic fit method for partial compatibility to sklearn.          Args:             x (Optional[Union[pd.DataFrame, np.ndarray]]): independent                 variables/features.             y (Optional[Union[pd.Series, np.ndarray]]): dependent                 variable/label.          Raises:             AttributeError if no 'fit' method exists for 'technique'. Generic transform method for partial compatibility to sklearn.          Args:             x (Optional[Union[pd.DataFrame, np.ndarray]]): independent                 variables/features.             y (Optional[Union[pd.Series, np.ndarray]]): dependent                 variable/label.          Returns:             transformed x or data, depending upon what is passed to the                 method.          Raises:             AttributeError if no 'transform' method exists for local                 'process'. Collects and stores results of executing a data science project workflow.          Args:         contents (Mapping[Any, Any]]): stored dictionary. Defaults to an empty              dict.         default (Any): default value to return when the 'get' method is used.         prefix (str): prefix to use when storing different paths through a              workflow. So, for example, a prefix of 'path' will create keys of             'path_1', 'path_2', etc. Defaults to 'experiment'.         needs (ClassVar[Union[Sequence[str], str]]): attributes needed from              another instance for some method within a subclass. Defaults to              a list with 'workflow' and 'data'.