lkj 0.1.41__py3-none-any.whl → 0.1.43__py3-none-any.whl

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.
lkj/__init__.py CHANGED
@@ -40,7 +40,12 @@ from lkj.loggers import (
40
40
  wrapped_print, # Prints a string or list ensuring the total line width does not exceed `max_width`.
41
41
  CallOnError, # Context manager that calls a function on error (subclass of suppress)
42
42
  )
43
- from lkj.importing import import_object, register_namespace_forwarding
43
+ from lkj.importing import (
44
+ parent_dir_of_module, # Get the parent directory of a module
45
+ import_from_path, # Import a module from a specified path
46
+ import_object, # Import an object from a module by its name
47
+ register_namespace_forwarding, # Register a namespace forwarding for a module
48
+ )
44
49
  from lkj.chunking import chunk_iterable, chunker
45
50
  from lkj.misc import identity, value_in_interval
46
51
 
lkj/dicts.py CHANGED
@@ -224,6 +224,10 @@ Comparison = Any
224
224
  Comparator = Callable[[dict, dict], Comparison]
225
225
 
226
226
 
227
+ def _common_keys_list(dict1, dict2):
228
+ return [k for k in dict1.keys() if k in dict2.keys()]
229
+
230
+
227
231
  def compare_field_values(
228
232
  dict1,
229
233
  dict2,
@@ -232,7 +236,8 @@ def compare_field_values(
232
236
  default_comparator: Comparator = operator.eq,
233
237
  aggregator: Callable[
234
238
  [Dict[KT, Comparison]], Any
235
- ] = lambda d: d, # lambda d: np.mean(list(d.values()))
239
+ ] = lambda d: d, # lambda d: np.mean(list(d.values())),
240
+ get_comparison_fields: Callable[[dict], Iterable[KT]] = _common_keys_list,
236
241
  ):
237
242
  """
238
243
  Compare two dictionaries' values field by field
@@ -266,7 +271,7 @@ def compare_field_values(
266
271
  0.5
267
272
 
268
273
  """
269
- common_keys = [k for k in dict1.keys() if k in dict2.keys()]
274
+ common_keys = get_comparison_fields(dict1, dict2)
270
275
 
271
276
  comparisons = {}
272
277
  for key in common_keys:
lkj/importing.py CHANGED
@@ -1,6 +1,88 @@
1
1
  """Tools for importing"""
2
2
 
3
3
 
4
+ def parent_dir_of_module(module_obj, *, parent_levels: int = 0):
5
+ """
6
+ Get the parent directory of a given module object.
7
+ :param module_obj: The module object for which to find the parent directory.
8
+ :return: The parent directory of the module as a string.
9
+
10
+ >>> import os # a standard library module
11
+ >>> parent_dir_of_module(os) # doctest: +ELLIPSIS
12
+ '...python...'
13
+ >>> import lkj # a third-party module
14
+ >>> parent_dir_of_module(lkj) # doctest: +ELLIPSIS
15
+ '.../lkj'
16
+ """
17
+ import os
18
+ import inspect
19
+
20
+ # Get the file path of the module
21
+ module_file = inspect.getfile(module_obj)
22
+
23
+ # Get the parent directory
24
+ parent_dir = os.path.dirname(module_file)
25
+
26
+ if parent_levels > 0:
27
+ for _ in range(parent_levels):
28
+ parent_dir = os.path.dirname(parent_dir)
29
+
30
+ return parent_dir
31
+
32
+
33
+ def import_from_path(
34
+ pkg_path: str = None, *, rootdir: str = "", insert_in_globals: bool = False
35
+ ):
36
+ """
37
+ Import a package from a specified path.
38
+
39
+ :param pkg_path: The path to the package to import. If None, returns a partial function.
40
+ :param rootdir: The root directory from which to resolve the package path.
41
+ :param insert_in_globals: If True, insert the imported package into the global namespace.
42
+ :return: The imported package or a partial function for deferred import.
43
+ :rtype: module or functools.partial
44
+ :raises ImportError: If the package cannot be found or imported.
45
+
46
+ >>> import os, inspect # standard library modules (that are surely installed)
47
+ >>> rootdir = parent_dir_of_module(os) # get the parent directory of os module
48
+ >>> os_module = import_from_path('os', rootdir=rootdir) # doctest: +ELLIPSIS
49
+ >>> os_module == os
50
+ True
51
+
52
+ >>> import lkj # a third-party module (that is surely installed)
53
+ >>> parent_dir_of_lkj = parent_dir_of_module(lkj, parent_levels=2) # get the great-grandma directory of lkj module
54
+
55
+ Make a partial function to import lkj from its parent directory:
56
+
57
+ >>> my_import_from_path = import_from_path(rootdir=parent_dir_of_lkj, insert_in_globals=True)
58
+ >>> lkj_module = my_import_from_path('lkj')
59
+ >>> assert 'lkj' in globals(), "Module 'lkj' should be imported into globals"
60
+ >>> lkj_module == lkj
61
+ True
62
+ """
63
+ import sys
64
+ import os
65
+ from functools import partial
66
+
67
+ if pkg_path is None:
68
+ return partial(
69
+ import_from_path, rootdir=rootdir, insert_in_globals=insert_in_globals
70
+ )
71
+
72
+ pkg_rootdir = os.path.join(rootdir, pkg_path)
73
+ pkg_rootdir = os.path.abspath(pkg_rootdir)
74
+
75
+ # Add the directory to sys.path
76
+ if pkg_rootdir not in sys.path:
77
+ sys.path.insert(0, pkg_rootdir) # Use insert(0, ...) to give it high priority
78
+
79
+ pkg = __import__(pkg_path)
80
+
81
+ if insert_in_globals:
82
+ globals()[pkg_path] = pkg
83
+ return pkg
84
+
85
+
4
86
  def import_object(dot_path: str):
5
87
  """Imports and returns an object from a dot string path.
6
88
 
@@ -102,10 +184,11 @@ def register_namespace_forwarding(source_base, target_base):
102
184
 
103
185
  Usage:
104
186
 
105
- # if you put this code in the imbed.mdat package (say, containing a hcp module),
187
+ If you put this code in the imbed.mdat package (say, containing a hcp module),
188
+
106
189
  >>> register_namespace_forwarding('imbed.mdat', 'imbed_data_prep') # doctest: +SKIP
107
190
 
108
- # Then when you do
191
+ Then when you do
109
192
 
110
193
  >>> import imbed.mdat.hcp # doctest: +SKIP
111
194
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lkj
3
- Version: 0.1.41
3
+ Version: 0.1.43
4
4
  Summary: A dump of homeless useful utils
5
5
  Home-page: https://github.com/thorwhalen/lkj
6
6
  Author: Thor Whalen
@@ -1,15 +1,15 @@
1
- lkj/__init__.py,sha256=Vceal0uY2jW1y0sQHOk1WHXc9aTAEXXOJ9vgyOmnrNk,6868
1
+ lkj/__init__.py,sha256=cGy0S6ZYacRlKA981i_lkqEJzDYSDuNx6LiQfBXvd5k,7104
2
2
  lkj/chunking.py,sha256=RpNdx5jEuO4mFg2qoTkD47iL35neBneuZ5xgQ_cBkiM,3755
3
- lkj/dicts.py,sha256=vmdOXgGVWe3LTz40dHamj7-c8ob4B5SxL3zPJcylf40,10216
3
+ lkj/dicts.py,sha256=z2o7njvLNJkh1ZgSH-SLtz13SdW_YfUsTA1yTY-kVLE,10382
4
4
  lkj/filesys.py,sha256=NbWDuc848h8O42gwX7d9yNJkrWBgzSFnkoEdSRgvBAg,8883
5
5
  lkj/funcs.py,sha256=LXJlj3gMMsbD0t2gn2NZZ6mOqmW5bxM-94uGoYgrhzI,8930
6
- lkj/importing.py,sha256=_BFBmdaKCBnk5broltWDeAPeEKG1dEkS8DhIdv6UhSI,3809
6
+ lkj/importing.py,sha256=TcW3qUDmw7jqswpxXnksjlHkkbOJq70NbUk1ZyaafT0,6658
7
7
  lkj/iterables.py,sha256=9jeO36w-IGiZryge7JKgXZOGZAgehUvhwKV3nHPcZWk,2801
8
8
  lkj/loggers.py,sha256=ImmBdacz89Lvb3dg_xI5jOct_44rSRv0hNI_CVehy60,13706
9
9
  lkj/misc.py,sha256=IZf05tkl0cgiMgBwCMH5cLSC59fRXwnemPRo8G0OxQg,1436
10
10
  lkj/strings.py,sha256=3YjlxOWUfzWqwu51uq_pv9XZReLqRFvziGtRsdzEtw8,24662
11
- lkj-0.1.41.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
12
- lkj-0.1.41.dist-info/METADATA,sha256=Tc9RoFOGPs137L9Mw1--sGkVEtmc455ZLx2lHRMqUDc,4684
13
- lkj-0.1.41.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
14
- lkj-0.1.41.dist-info/top_level.txt,sha256=3DZOUwYmyurJFBXQCvCmEIVm8z2b42O5Sx3RDQyePfg,4
15
- lkj-0.1.41.dist-info/RECORD,,
11
+ lkj-0.1.43.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
12
+ lkj-0.1.43.dist-info/METADATA,sha256=3aKQoeulKxTjgrPcjUzrY6qMbxjHeAAaFlqL__29zgA,4684
13
+ lkj-0.1.43.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
14
+ lkj-0.1.43.dist-info/top_level.txt,sha256=3DZOUwYmyurJFBXQCvCmEIVm8z2b42O5Sx3RDQyePfg,4
15
+ lkj-0.1.43.dist-info/RECORD,,
File without changes
File without changes