1- # -*- coding: utf-8 -*-
2-
31"""Top-level package for Copulas."""
42
53__author__ = 'DataCebo, Inc.'
647- __version__ = '0.11.1 '
5+ __version__ = '0.12.0.dev1 '
86
9- import contextlib
10- import importlib
117import sys
128import warnings
139from copy import deepcopy
1410from importlib .metadata import entry_points
1511from operator import attrgetter
16-
17- import numpy as np
18- import pandas as pd
19-
20- EPSILON = np .finfo (np .float32 ).eps
21-
22-
23- class NotFittedError (Exception ):
24- """NotFittedError class."""
25-
26-
27- @contextlib .contextmanager
28- def set_random_state (random_state , set_model_random_state ):
29- """Context manager for managing the random state.
30-
31- Args:
32- random_state (int or np.random.RandomState):
33- The random seed or RandomState.
34- set_model_random_state (function):
35- Function to set the random state on the model.
36- """
37- original_state = np .random .get_state ()
38-
39- np .random .set_state (random_state .get_state ())
40-
41- try :
42- yield
43- finally :
44- current_random_state = np .random .RandomState ()
45- current_random_state .set_state (np .random .get_state ())
46- set_model_random_state (current_random_state )
47- np .random .set_state (original_state )
48-
49-
50- def random_state (function ):
51- """Set the random state before calling the function.
52-
53- Args:
54- function (Callable):
55- The function to wrap around.
56- """
57-
58- def wrapper (self , * args , ** kwargs ):
59- if self .random_state is None :
60- return function (self , * args , ** kwargs )
61-
62- else :
63- with set_random_state (self .random_state , self .set_random_state ):
64- return function (self , * args , ** kwargs )
65-
66- return wrapper
67-
68-
69- def validate_random_state (random_state ):
70- """Validate random state argument.
71-
72- Args:
73- random_state (int, numpy.random.RandomState, tuple, or None):
74- Seed or RandomState for the random generator.
75-
76- Output:
77- numpy.random.RandomState
78- """
79- if random_state is None :
80- return None
81-
82- if isinstance (random_state , int ):
83- return np .random .RandomState (seed = random_state )
84- elif isinstance (random_state , np .random .RandomState ):
85- return random_state
86- else :
87- raise TypeError (
88- f'`random_state` { random_state } expected to be an int '
89- 'or `np.random.RandomState` object.'
90- )
91-
92-
93- def get_instance (obj , ** kwargs ):
94- """Create new instance of the ``obj`` argument.
95-
96- Args:
97- obj (str, type, instance):
98- """
99- instance = None
100- if isinstance (obj , str ):
101- package , name = obj .rsplit ('.' , 1 )
102- instance = getattr (importlib .import_module (package ), name )(** kwargs )
103- elif isinstance (obj , type ):
104- instance = obj (** kwargs )
105- else :
106- if kwargs :
107- instance = obj .__class__ (** kwargs )
108- else :
109- args = getattr (obj , '__args__' , ())
110- kwargs = getattr (obj , '__kwargs__' , {})
111- instance = obj .__class__ (* args , ** kwargs )
112-
113- return instance
114-
115-
116- def store_args (__init__ ):
117- """Save ``*args`` and ``**kwargs`` used in the ``__init__`` of a copula.
118-
119- Args:
120- __init__(callable): ``__init__`` function to store their arguments.
121-
122- Returns:
123- callable: Decorated ``__init__`` function.
124- """
125-
126- def new__init__ (self , * args , ** kwargs ):
127- args_copy = deepcopy (args )
128- kwargs_copy = deepcopy (kwargs )
129- __init__ (self , * args , ** kwargs )
130- self .__args__ = args_copy
131- self .__kwargs__ = kwargs_copy
132-
133- return new__init__
134-
135-
136- def get_qualified_name (_object ):
137- """Return the Fully Qualified Name from an instance or class."""
138- module = _object .__module__
139- if hasattr (_object , '__name__' ):
140- _class = _object .__name__
141-
142- else :
143- _class = _object .__class__ .__name__
144-
145- return module + '.' + _class
146-
147-
148- def vectorize (function ):
149- """Allow a method that only accepts scalars to accept vectors too.
150-
151- This decorator has two different behaviors depending on the dimensionality of the
152- array passed as an argument:
153-
154- **1-d array**
155-
156- It will work under the assumption that the `function` argument is a callable
157- with signature::
158-
159- function(self, X, *args, **kwargs)
160-
161- where X is an scalar magnitude.
162-
163- In this case the arguments of the input array will be given one at a time, and
164- both the input and output of the decorated function will have shape (n,).
165-
166- **2-d array**
167-
168- It will work under the assumption that the `function` argument is a callable with signature::
169-
170- function(self, X0, ..., Xj, *args, **kwargs)
171-
172- where `Xi` are scalar magnitudes.
173-
174- It will pass the contents of each row unpacked on each call. The input is espected to have
175- shape (n, j), the output a shape of (n,)
176-
177- It will return a function that is guaranteed to return a `numpy.array`.
178-
179- Args:
180- function(callable): Function that only accept and return scalars.
181-
182- Returns:
183- callable: Decorated function that can accept and return :attr:`numpy.array`.
184-
185- """
186-
187- def decorated (self , X , * args , ** kwargs ):
188- if not isinstance (X , np .ndarray ):
189- return function (self , X , * args , ** kwargs )
190-
191- if len (X .shape ) == 1 :
192- X = X .reshape ([- 1 , 1 ])
193-
194- if len (X .shape ) == 2 :
195- return np .fromiter (
196- (function (self , * x , * args , ** kwargs ) for x in X ), np .dtype ('float64' )
197- )
198-
199- else :
200- raise ValueError ('Arrays of dimensionality higher than 2 are not supported.' )
201-
202- decorated .__doc__ = function .__doc__
203- return decorated
204-
205-
206- def scalarize (function ):
207- """Allow methods that only accepts 1-d vectors to work with scalars.
208-
209- Args:
210- function(callable): Function that accepts and returns vectors.
211-
212- Returns:
213- callable: Decorated function that accepts and returns scalars.
214- """
215-
216- def decorated (self , X , * args , ** kwargs ):
217- scalar = not isinstance (X , np .ndarray )
218-
219- if scalar :
220- X = np .array ([X ])
221-
222- result = function (self , X , * args , ** kwargs )
223- if scalar :
224- result = result [0 ]
225-
226- return result
227-
228- decorated .__doc__ = function .__doc__
229- return decorated
230-
231-
232- def check_valid_values (function ):
233- """Raise an exception if the given values are not supported.
234-
235- Args:
236- function(callable): Method whose unique argument is a numpy.array-like object.
237-
238- Returns:
239- callable: Decorated function
240-
241- Raises:
242- ValueError: If there are missing or invalid values or if the dataset is empty.
243- """
244-
245- def decorated (self , X , * args , ** kwargs ):
246- if isinstance (X , pd .DataFrame ):
247- W = X .to_numpy ()
248-
249- else :
250- W = X
251-
252- if not len (W ):
253- raise ValueError ('Your dataset is empty.' )
254-
255- if not (np .issubdtype (W .dtype , np .floating ) or np .issubdtype (W .dtype , np .integer )):
256- raise ValueError ('There are non-numerical values in your data.' )
257-
258- if np .isnan (W ).any ().any ():
259- raise ValueError ('There are nan values in your data.' )
260-
261- return function (self , X , * args , ** kwargs )
262-
263- return decorated
12+ from types import ModuleType
26413
26514
26615def _get_addon_target (addon_path_name ):
@@ -319,8 +68,8 @@ def _find_addons():
31968 for entry_point in eps :
32069 try :
32170 addon = entry_point .load ()
322- except Exception : # pylint: disable=broad-exception-caught
323- msg = f'Failed to load "{ entry_point .name } " from "{ entry_point .value } ". '
71+ except Exception as e : # pylint: disable=broad-exception-caught
72+ msg = f'Failed to load "{ entry_point .name } " from "{ entry_point .value } " with error: \n { e } '
32473 warnings .warn (msg )
32574 continue
32675
@@ -331,6 +80,11 @@ def _find_addons():
33180 warnings .warn (msg )
33281 continue
33382
83+ if isinstance (addon , ModuleType ):
84+ addon_module_name = f'{ addon_target .__name__ } .{ addon_name } '
85+ if addon_module_name not in sys .modules :
86+ sys .modules [addon_module_name ] = addon
87+
33488 setattr (addon_target , addon_name , addon )
33589
33690
0 commit comments