cdxcore 0.1.32__tar.gz → 0.1.34__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.
Potentially problematic release.
This version of cdxcore might be problematic. Click here for more details.
- {cdxcore-0.1.32 → cdxcore-0.1.34}/PKG-INFO +1 -1
- {cdxcore-0.1.32 → cdxcore-0.1.34}/cdxcore/__init__.py +1 -1
- {cdxcore-0.1.32 → cdxcore-0.1.34}/cdxcore/dynaplot.py +48 -21
- {cdxcore-0.1.32 → cdxcore-0.1.34}/cdxcore/subdir.py +95 -44
- {cdxcore-0.1.32 → cdxcore-0.1.34}/cdxcore.egg-info/PKG-INFO +1 -1
- {cdxcore-0.1.32 → cdxcore-0.1.34}/pyproject.toml +1 -1
- {cdxcore-0.1.32 → cdxcore-0.1.34}/LICENSE +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/README.md +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/cdxcore/config.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/cdxcore/deferred.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/cdxcore/dynalimits.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/cdxcore/err.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/cdxcore/filelock.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/cdxcore/jcpool.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/cdxcore/npio.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/cdxcore/npshm.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/cdxcore/pretty.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/cdxcore/uniquehash.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/cdxcore/util.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/cdxcore/verbose.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/cdxcore/version.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/cdxcore.egg-info/SOURCES.txt +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/cdxcore.egg-info/dependency_links.txt +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/cdxcore.egg-info/requires.txt +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/cdxcore.egg-info/top_level.txt +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/docs/source/conf.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/setup.cfg +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/tests/test_config.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/tests/test_deferred.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/tests/test_err.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/tests/test_jcpool.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/tests/test_npio.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/tests/test_npshm.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/tests/test_pretty.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/tests/test_subdir.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/tests/test_uniquehash.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/tests/test_util.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/tests/test_verbose.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/tests/test_version.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/tmp/filelock.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/tmp/np.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/tmp/npsh1.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/tmp/sharedarray.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/up/git_message.py +0 -0
- {cdxcore-0.1.32 → cdxcore-0.1.34}/up/pip_modify_setup.py +0 -0
|
@@ -504,10 +504,10 @@ class DynaAx(_DynaDeferred):
|
|
|
504
504
|
|
|
505
505
|
def plot(self, *args, scalex=True, scaley=True, data=None, **kwargs ):
|
|
506
506
|
"""
|
|
507
|
-
Wrapper around :
|
|
507
|
+
Wrapper around :meth:`matplotlib.axes.Axes.plot`.
|
|
508
508
|
|
|
509
509
|
This function wrapper does not support the ``data`` interface
|
|
510
|
-
of :
|
|
510
|
+
of :meth:`matplotlib.axes.Axes.plot`.
|
|
511
511
|
|
|
512
512
|
If automatic limits are not used, this is a wrapper with deferred pass-through.
|
|
513
513
|
If automatic limits are used, then this function will update
|
|
@@ -516,7 +516,7 @@ class DynaAx(_DynaDeferred):
|
|
|
516
516
|
Parameters
|
|
517
517
|
----------
|
|
518
518
|
args, scalex, scaley, data, kwargs : ...
|
|
519
|
-
See :
|
|
519
|
+
See :meth:`matplotlib.axes.plot`.
|
|
520
520
|
|
|
521
521
|
Returns
|
|
522
522
|
-------
|
|
@@ -626,12 +626,12 @@ class _DynaGridSpec(_DynaDeferred):
|
|
|
626
626
|
|
|
627
627
|
class DynaFig(_DynaDeferred):
|
|
628
628
|
"""
|
|
629
|
-
Deferred wrapper around :class:`matplotlib.
|
|
629
|
+
Deferred wrapper around :class:`matplotlib.figure.Figure`.
|
|
630
630
|
|
|
631
|
-
|
|
631
|
+
Provides a simple :meth:`cdxcore.dynaplot.DynaFig.add_subplot` without the need to pre-specify axes positions
|
|
632
632
|
as is common for :mod:`matplotlib`.
|
|
633
633
|
|
|
634
|
-
|
|
634
|
+
Construct elements of this class with :func:`cdxcore.dynaplot.figure`.
|
|
635
635
|
"""
|
|
636
636
|
|
|
637
637
|
def __init__(self, title : str|None = None, *,
|
|
@@ -645,7 +645,10 @@ class DynaFig(_DynaDeferred):
|
|
|
645
645
|
"""
|
|
646
646
|
__init__
|
|
647
647
|
"""
|
|
648
|
-
|
|
648
|
+
if not fig_size is None:
|
|
649
|
+
verify( not 'figsize' in fig_kwargs, "Cannot specify both `figsize` and `fig_size`", exception=ValueError)
|
|
650
|
+
fig_kwargs['figsize'] = fig_size
|
|
651
|
+
|
|
649
652
|
self._hdisplay = None
|
|
650
653
|
self._axes = [] #:
|
|
651
654
|
#:
|
|
@@ -675,10 +678,6 @@ class DynaFig(_DynaDeferred):
|
|
|
675
678
|
|
|
676
679
|
verify( not 'cols' in fig_kwargs, "Unknown keyword 'cols'. Did you mean 'columns'?", exception=ValueError)
|
|
677
680
|
|
|
678
|
-
if not fig_size is None:
|
|
679
|
-
verify( not 'figsize' in fig_kwargs, "Cannot specify both `figsize` and `fig_size`", exception=ValueError)
|
|
680
|
-
fig_kwargs['figsize'] = fig_size
|
|
681
|
-
|
|
682
681
|
dyna_title = ( title if len(title) <= 20 else ( title[:17] + "..." ) ) if not title is None else None
|
|
683
682
|
_DynaDeferred.__init__(self, f"figure('{dyna_title}')" if not title is None else "figure()" )
|
|
684
683
|
|
|
@@ -808,6 +807,27 @@ class DynaFig(_DynaDeferred):
|
|
|
808
807
|
return ax
|
|
809
808
|
|
|
810
809
|
add_plot = add_subplot
|
|
810
|
+
|
|
811
|
+
def add_subplots( self, *titles ) -> tuple[DynaAx]:
|
|
812
|
+
"""
|
|
813
|
+
Generate a number of sub-plots in one function call.
|
|
814
|
+
|
|
815
|
+
Parameters
|
|
816
|
+
----------
|
|
817
|
+
titles : list[str] | int
|
|
818
|
+
Either a list of plot titles, or a number.
|
|
819
|
+
|
|
820
|
+
Returns
|
|
821
|
+
-------
|
|
822
|
+
Sub-plots: tuple
|
|
823
|
+
A tuple of sub-plots, one for each ``title``.
|
|
824
|
+
"""
|
|
825
|
+
if len(titles) == 0:
|
|
826
|
+
return ()
|
|
827
|
+
if len(titles) == 1 and isinstance(titles[0], int):
|
|
828
|
+
return tuple( self.add_subplot() for _ in range(titles) )
|
|
829
|
+
else:
|
|
830
|
+
return tuple( self.add_subplot(title) for title in titles )
|
|
811
831
|
|
|
812
832
|
def add_axes( self,
|
|
813
833
|
rect : tuple,
|
|
@@ -949,7 +969,8 @@ class DynaFig(_DynaDeferred):
|
|
|
949
969
|
"""
|
|
950
970
|
Saves the figure to a file.
|
|
951
971
|
|
|
952
|
-
Wrapper around :func:`matplotlib.pyplot.savefig`. Essentially, this function
|
|
972
|
+
Wrapper around :func:`matplotlib.pyplot.savefig`. Essentially, `this function <https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.savefig.html>`__
|
|
973
|
+
writes the figure to a file
|
|
953
974
|
rather than displaying itl.
|
|
954
975
|
|
|
955
976
|
Parameters
|
|
@@ -1008,7 +1029,8 @@ class DynaFig(_DynaDeferred):
|
|
|
1008
1029
|
|
|
1009
1030
|
@staticmethod
|
|
1010
1031
|
def store():
|
|
1011
|
-
""" Create a FigStore
|
|
1032
|
+
""" Create a :class:`cdxcore.dynaplot.FigStore`. Such a store allows managing graphical elements (artists) dynamically. See the examples
|
|
1033
|
+
in the introduction. """
|
|
1012
1034
|
return FigStore()
|
|
1013
1035
|
|
|
1014
1036
|
def close(self, render : bool = True,
|
|
@@ -1022,7 +1044,7 @@ class DynaFig(_DynaDeferred):
|
|
|
1022
1044
|
Parameters
|
|
1023
1045
|
----------
|
|
1024
1046
|
render : bool, default ``True``
|
|
1025
|
-
If ``True``, the default, this function will call :meth:`cdxcore.dynaplot.DynaFig
|
|
1047
|
+
If ``True``, the default, this function will call :meth:`cdxcore.dynaplot.DynaFig.render` and therefore renders the figure before closing the figure.
|
|
1026
1048
|
clear : bool, default ``False``
|
|
1027
1049
|
If ``True``, all axes will be cleared. *This is experimental.* The default is ``False``.
|
|
1028
1050
|
"""
|
|
@@ -1052,7 +1074,7 @@ class DynaFig(_DynaDeferred):
|
|
|
1052
1074
|
|
|
1053
1075
|
def delaxes( self, ax : DynaAx, *, render : bool = False ):
|
|
1054
1076
|
"""
|
|
1055
|
-
Equivalent of :
|
|
1077
|
+
Equivalent of :meth:`matplotlib.figure.Figure.delaxes`, but this function can also take a list.
|
|
1056
1078
|
"""
|
|
1057
1079
|
verify( not self._closed, "Cannot call render() after close() was called")
|
|
1058
1080
|
if isinstance( ax, Collection ):
|
|
@@ -1085,6 +1107,7 @@ def figure( title : str|None = None, *,
|
|
|
1085
1107
|
columns : int = 5,
|
|
1086
1108
|
tight : bool = True,
|
|
1087
1109
|
draw_mode: int = MODE.DEFAULT,
|
|
1110
|
+
add_plots: int|list|None = None,
|
|
1088
1111
|
**fig_kwargs ):
|
|
1089
1112
|
"""
|
|
1090
1113
|
Creates a dynamic figure of type :class:`cdxcore.dynaplot.DynaFig`.
|
|
@@ -1101,7 +1124,8 @@ def figure( title : str|None = None, *,
|
|
|
1101
1124
|
|
|
1102
1125
|
2) Call :meth:`cdxcore.dynaplot.DynaFig.render` to place those plots.
|
|
1103
1126
|
|
|
1104
|
-
3) Call :meth:`cdxcore.dynaplot.DynaFig.close` to close the figure and avoid duplicate copies in Jupyter
|
|
1127
|
+
3) Call :meth:`cdxcore.dynaplot.DynaFig.close` to close the figure and avoid duplicate copies in Jupyter; a convient wrapper is to use
|
|
1128
|
+
``with`` to ensure ``close()`` gets called. This pattern is used below.
|
|
1105
1129
|
|
|
1106
1130
|
**Examples:**
|
|
1107
1131
|
|
|
@@ -1131,6 +1155,8 @@ def figure( title : str|None = None, *,
|
|
|
1131
1155
|
defer all other function calls to the figure
|
|
1132
1156
|
object until :meth:`cdxcore.dynaplot.DynaFig.render`
|
|
1133
1157
|
or :meth:`cdxcore.dynaplot.DynaFig.close` are called.
|
|
1158
|
+
Whenever you use ``with`` at the end of the context window :meth:`cdxcore.dynaplot.DynaFig.close`
|
|
1159
|
+
will be called for you.
|
|
1134
1160
|
|
|
1135
1161
|
The following direct members are important for using the framework:
|
|
1136
1162
|
|
|
@@ -1155,7 +1181,7 @@ def figure( title : str|None = None, *,
|
|
|
1155
1181
|
An optional title which will be passed to :meth:`matplotlib.pyplot.suptitle`.
|
|
1156
1182
|
|
|
1157
1183
|
fig_size : tuple[int] | None, default ``None``
|
|
1158
|
-
By default the ``fig_size`` of the underlying :
|
|
1184
|
+
By default the ``fig_size`` of the underlying :func:`matplotlib.pyplot.figure`
|
|
1159
1185
|
will be derived from the number of plots vs ``cols``, ``row_size`` and ``col_size``
|
|
1160
1186
|
as ``(col_size* (N%col_num), row_size (N//col_num))``.
|
|
1161
1187
|
|
|
@@ -1178,7 +1204,7 @@ def figure( title : str|None = None, *,
|
|
|
1178
1204
|
|
|
1179
1205
|
Note that when ``tight`` is ``True`` and :meth:`cdxcore.dynaplot.DynaFig.add_axes`
|
|
1180
1206
|
is called a :class:`UserWarning` is generated. Turn ``tight`` off to avoid this.
|
|
1181
|
-
|
|
1207
|
+
|
|
1182
1208
|
draw_mode : int, default ``MODE.DEFAULT``
|
|
1183
1209
|
A combination of :class:`cdxcore.dynaplot.MODE` flags on how to draw plots
|
|
1184
1210
|
once they were rendered. The required function call differs by IPython platform.
|
|
@@ -1199,7 +1225,7 @@ def figure( title : str|None = None, *,
|
|
|
1199
1225
|
figure: :class:`cdxcore.dynaplot.DynaFig`
|
|
1200
1226
|
A dynamic figure.
|
|
1201
1227
|
"""
|
|
1202
|
-
|
|
1228
|
+
fig = DynaFig( title=title,
|
|
1203
1229
|
row_size=row_size,
|
|
1204
1230
|
col_size=col_size,
|
|
1205
1231
|
fig_size=fig_size,
|
|
@@ -1208,6 +1234,7 @@ def figure( title : str|None = None, *,
|
|
|
1208
1234
|
draw_mode=draw_mode,
|
|
1209
1235
|
**fig_kwargs
|
|
1210
1236
|
)
|
|
1237
|
+
return fig
|
|
1211
1238
|
|
|
1212
1239
|
# ----------------------------------------------------------------------------------
|
|
1213
1240
|
# Utility class for animated content
|
|
@@ -1369,8 +1396,8 @@ def color(i : int, table : str ="css4"):
|
|
|
1369
1396
|
i : int
|
|
1370
1397
|
Integer number. Colors will be rotated.
|
|
1371
1398
|
|
|
1372
|
-
table : str,
|
|
1373
|
-
Which color table from
|
|
1399
|
+
table : str, default ``css4``
|
|
1400
|
+
Which `color table from matplotlib <https://matplotlib.org/stable/users/explain/colors/index.html>`__ to use: `"css4"`, `"base"`, `"tableau"` or `"xkcd"`.
|
|
1374
1401
|
Default is ``"css4"``.
|
|
1375
1402
|
|
|
1376
1403
|
Returns
|
|
@@ -300,12 +300,14 @@ To test existence of 'file' in a directory, use one of::
|
|
|
300
300
|
Deleting files
|
|
301
301
|
^^^^^^^^^^^^^^
|
|
302
302
|
|
|
303
|
-
To delete a
|
|
303
|
+
To delete a file, use either of the following::
|
|
304
304
|
|
|
305
305
|
subdir.delete("file")
|
|
306
306
|
del subdir['file']
|
|
307
307
|
|
|
308
|
-
All of these are *silent*, and will not throw errors if ``file`` does not exist.
|
|
308
|
+
All of these are *silent*, and will by default not throw errors if ``file`` does not exist.
|
|
309
|
+
|
|
310
|
+
|
|
309
311
|
In order to throw an error use::
|
|
310
312
|
|
|
311
313
|
subdir.delete('file', raise_on_error=True)
|
|
@@ -320,7 +322,7 @@ A few member functions assist in deleting a number of files:
|
|
|
320
322
|
Caching
|
|
321
323
|
^^^^^^^
|
|
322
324
|
|
|
323
|
-
A :class:`cdxcore.subdir.SubDir` object offers an advanced context for caching calls to :class:`collection.abc.Callable
|
|
325
|
+
A :class:`cdxcore.subdir.SubDir` object offers an advanced context for caching calls to :class:`collection.abc.Callable`
|
|
324
326
|
objects with :dec:`cdxcore.subdir.SubDir.cache`.
|
|
325
327
|
|
|
326
328
|
.. code-block:: python
|
|
@@ -341,13 +343,13 @@ This involves keying the cache by the function name and its current parameters u
|
|
|
341
343
|
and monitoring the functions version using :dec:`cdxcore.version.version`. The caching behaviour itself can be controlled by
|
|
342
344
|
specifying the desired :class:`cdxcore.subdir.CacheMode`.
|
|
343
345
|
|
|
344
|
-
See :dec:`cdxcore.subdir.SubDir.cache` for full feature set
|
|
346
|
+
**See** :dec:`cdxcore.subdir.SubDir.cache` **for full feature set.**
|
|
345
347
|
|
|
346
348
|
Import
|
|
347
349
|
------
|
|
348
350
|
.. code-block:: python
|
|
349
351
|
|
|
350
|
-
|
|
352
|
+
from cdxcore.subdir import SubDir
|
|
351
353
|
|
|
352
354
|
Documentation
|
|
353
355
|
-------------
|
|
@@ -786,8 +788,11 @@ class SubDir(object):
|
|
|
786
788
|
|
|
787
789
|
* ``'.'`` for current directory.
|
|
788
790
|
* ``'~'`` for home directory.
|
|
789
|
-
* ``'!'`` for system default temp directory.
|
|
790
|
-
|
|
791
|
+
* ``'!'`` for system default temp directory. Note that outside any administator imposed policies, sub directories
|
|
792
|
+
of ``!`` are permanent.
|
|
793
|
+
* ``'?'`` for a temporary temp directory; see :meth:`cdxcore.subdir.SubDir.temp_temp_dir` regarding semantics.
|
|
794
|
+
Most importantly, every ``SubDir`` will be constructed with a different (truly) temporary sub directory.
|
|
795
|
+
If used, ``delete_everything_upon_exit`` is always ``True``.
|
|
791
796
|
|
|
792
797
|
The directory name may also contain a formatting string for defining ``ext`` on the fly:
|
|
793
798
|
for example use ``"!/test;*.bin"`` to specify a directory ``"test"`` in the user's
|
|
@@ -1285,9 +1290,7 @@ class SubDir(object):
|
|
|
1285
1290
|
|
|
1286
1291
|
def full_file_name(self, file : str, *, ext : str = None) -> str:
|
|
1287
1292
|
"""
|
|
1288
|
-
Returns fully qualified file name.
|
|
1289
|
-
|
|
1290
|
-
The function tests that ``file`` does not contain directory information.
|
|
1293
|
+
Returns fully qualified file name, based on a given unqualified file name (e.g. without path or extension).
|
|
1291
1294
|
|
|
1292
1295
|
Parameters
|
|
1293
1296
|
----------
|
|
@@ -1319,13 +1322,25 @@ class SubDir(object):
|
|
|
1319
1322
|
if len(ext) > 0 and file[-len(ext):] != ext:
|
|
1320
1323
|
return self._path + file + ext
|
|
1321
1324
|
return self._path + file
|
|
1322
|
-
full_file_name = full_file_name # backwards compatibility
|
|
1323
1325
|
|
|
1324
1326
|
@staticmethod
|
|
1325
1327
|
def temp_dir() -> str:
|
|
1326
1328
|
"""
|
|
1327
1329
|
Return system temp directory. Short-cut to :func:`tempfile.gettempdir`.
|
|
1328
|
-
|
|
1330
|
+
|
|
1331
|
+
This function creates a "permanent temporary" directoy (i.e. under ``/tmp/`` for Linux or ``%TEMP%`` for Windows).
|
|
1332
|
+
Most importantly, it is somewhat persisient: you expect it to be there after a reboot.
|
|
1333
|
+
|
|
1334
|
+
To cater for the use case of a one-off temporary directory use :meth:`cdxcore.subdir.SubDir.temp_temp_dir`.
|
|
1335
|
+
|
|
1336
|
+
This function is called when the ``!`` parameter is used when constructing
|
|
1337
|
+
:class:`cdxcore.subdir.SubDir` objects.
|
|
1338
|
+
|
|
1339
|
+
Returns
|
|
1340
|
+
-------
|
|
1341
|
+
Path : str
|
|
1342
|
+
This function returns a string contains trailing ``'/'``.
|
|
1343
|
+
|
|
1329
1344
|
"""
|
|
1330
1345
|
d = tempfile.gettempdir()
|
|
1331
1346
|
assert len(d) == 0 or not (d[-1] == '/' or d[-1] == '\\'), ("*** Internal error 13123212-1", d)
|
|
@@ -1334,9 +1349,17 @@ class SubDir(object):
|
|
|
1334
1349
|
@staticmethod
|
|
1335
1350
|
def temp_temp_dir() -> str:
|
|
1336
1351
|
"""
|
|
1337
|
-
|
|
1338
|
-
|
|
1352
|
+
Returns a temporary temp directory name using :func:`tempfile.mkdtemp` which is temporary
|
|
1353
|
+
for the current process and thread, and is not guaranteed to be persisted e.g. when the system is rebooted.
|
|
1354
|
+
Accordingly, this function will return a different directory upon every function call.
|
|
1339
1355
|
|
|
1356
|
+
This function is called when the ``?/`` is used when constructing
|
|
1357
|
+
:class:`cdxcore.subdir.SubDir` objects.
|
|
1358
|
+
|
|
1359
|
+
**Implementation notoce:**
|
|
1360
|
+
|
|
1361
|
+
In most cirsumstances, a temporary temp directioy is *not* deleted from a system upon reboot.
|
|
1362
|
+
Do not rely on regular clean ups.
|
|
1340
1363
|
It is strongly recommended to clean up after usage, for example using the pattern::
|
|
1341
1364
|
|
|
1342
1365
|
from cdxcore.subdir import SubDir
|
|
@@ -1349,7 +1372,11 @@ class SubDir(object):
|
|
|
1349
1372
|
finally:
|
|
1350
1373
|
shutil.rmtree(tmp_dir)
|
|
1351
1374
|
|
|
1352
|
-
|
|
1375
|
+
Returns
|
|
1376
|
+
-------
|
|
1377
|
+
Path : str
|
|
1378
|
+
This function returns a string contains trailing ``'/'``.
|
|
1379
|
+
|
|
1353
1380
|
"""
|
|
1354
1381
|
d = tempfile.mkdtemp()
|
|
1355
1382
|
assert len(d) == 0 or not (d[-1] == '/' or d[-1] == '\\'), ("*** Internal error 13123212-1", d)
|
|
@@ -1359,7 +1386,15 @@ class SubDir(object):
|
|
|
1359
1386
|
def working_dir() -> str:
|
|
1360
1387
|
"""
|
|
1361
1388
|
Return current working directory. Short-cut for :func:`os.getcwd`.
|
|
1362
|
-
|
|
1389
|
+
|
|
1390
|
+
This function is called when the ``./`` is used when constructing
|
|
1391
|
+
:class:`cdxcore.subdir.SubDir` objects.
|
|
1392
|
+
|
|
1393
|
+
Returns
|
|
1394
|
+
-------
|
|
1395
|
+
Path : str
|
|
1396
|
+
This function returns a string contains trailing ``'/'``.
|
|
1397
|
+
|
|
1363
1398
|
"""
|
|
1364
1399
|
d = os.getcwd()
|
|
1365
1400
|
assert len(d) == 0 or not (d[-1] == '/' or d[-1] == '\\'), ("*** Internal error 13123212-2", d)
|
|
@@ -1369,7 +1404,15 @@ class SubDir(object):
|
|
|
1369
1404
|
def user_dir() -> str:
|
|
1370
1405
|
"""
|
|
1371
1406
|
Return current working directory. Short-cut for :func:`os.path.expanduser` with parameter ``' '``.
|
|
1372
|
-
|
|
1407
|
+
|
|
1408
|
+
This function is called when the ``~/`` is used when constructing
|
|
1409
|
+
:class:`cdxcore.subdir.SubDir` objects.
|
|
1410
|
+
|
|
1411
|
+
Returns
|
|
1412
|
+
-------
|
|
1413
|
+
Path : str
|
|
1414
|
+
This function returns a string contains trailing ``'/'``.
|
|
1415
|
+
|
|
1373
1416
|
"""
|
|
1374
1417
|
d = os.path.expanduser('~')
|
|
1375
1418
|
assert len(d) == 0 or not (d[-1] == '/' or d[-1] == '\\'), ("*** Internal error 13123212-3", d)
|
|
@@ -1709,7 +1752,7 @@ class SubDir(object):
|
|
|
1709
1752
|
-------
|
|
1710
1753
|
Content : type | list
|
|
1711
1754
|
For a single ``file`` returns the content of the file if successfully read, or ``default`` otherwise.
|
|
1712
|
-
If ``file
|
|
1755
|
+
If ``file`` is a list, this function returns a list of contents.
|
|
1713
1756
|
|
|
1714
1757
|
Raises
|
|
1715
1758
|
------
|
|
@@ -1924,7 +1967,7 @@ class SubDir(object):
|
|
|
1924
1967
|
obj :
|
|
1925
1968
|
Object to write, or list thereof if ``file`` is a list.
|
|
1926
1969
|
|
|
1927
|
-
raise_on_error : bool
|
|
1970
|
+
raise_on_error : bool, default ``
|
|
1928
1971
|
If ``False``, this function will return ``False`` upon failure.
|
|
1929
1972
|
|
|
1930
1973
|
version : str | None, default ``None``
|
|
@@ -2352,15 +2395,15 @@ class SubDir(object):
|
|
|
2352
2395
|
|
|
2353
2396
|
Parameters
|
|
2354
2397
|
----------
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2398
|
+
file :
|
|
2399
|
+
Filename, or list of filenames.
|
|
2400
|
+
|
|
2401
|
+
ext : str | None, default ``None``
|
|
2402
|
+
Extension to be used:
|
|
2403
|
+
|
|
2404
|
+
* ``None`` for the directory default.
|
|
2405
|
+
* ``""`` to not use an automatic extension.
|
|
2406
|
+
* ``"*"`` to use the extension associated with the format of the directory.
|
|
2364
2407
|
|
|
2365
2408
|
Returns
|
|
2366
2409
|
-------
|
|
@@ -2498,7 +2541,7 @@ class SubDir(object):
|
|
|
2498
2541
|
|
|
2499
2542
|
The file name is generated by applying a unique hash
|
|
2500
2543
|
to the current directory, ``file``, the current process and thread IDs, and
|
|
2501
|
-
:
|
|
2544
|
+
:meth:`datetime.datetime.now`.
|
|
2502
2545
|
|
|
2503
2546
|
If ``file`` is not ``None`` it will be used as a label.
|
|
2504
2547
|
|
|
@@ -2951,16 +2994,17 @@ class SubDir(object):
|
|
|
2951
2994
|
ctrl = CacheController(exclude_arg_types=[Debugger]) # <- exclude 'Debugger' parameters from hasing
|
|
2952
2995
|
cache = SubDir("!/.cache")
|
|
2953
2996
|
|
|
2954
|
-
@cache.cache("0.1", dependencies=[f]
|
|
2997
|
+
@cache.cache("0.1", dependencies=[f])
|
|
2955
2998
|
def g(x,y,debugger : Debugger): # <-- 'debugger' is a non-functional parameter
|
|
2956
2999
|
debugger.output(f"h(x={x},y={y})")
|
|
2957
3000
|
return g(x,y)**2
|
|
2958
3001
|
|
|
2959
3002
|
**Unique IDs and File Naming**
|
|
2960
3003
|
|
|
2961
|
-
The
|
|
3004
|
+
The *nique call ID of a decorated function* is by logicaly generated by its fully qualified name
|
|
2962
3005
|
and a unique hash of its functional parameters.
|
|
2963
3006
|
|
|
3007
|
+
By default, :class:`cdxcore.uniquehash.NamedUniqueHash` is used to compute unique hashes.
|
|
2964
3008
|
Key default behaviours of :class:`cdxcore.uniquehash.NamedUniqueHash`:
|
|
2965
3009
|
|
|
2966
3010
|
* :class:`cdxcore.uniquehash.NamedUniqueHash` hashes objects via their ``__dict__`` or ``__slot__`` members.
|
|
@@ -3044,11 +3088,11 @@ class SubDir(object):
|
|
|
3044
3088
|
|
|
3045
3089
|
In particular, the filename is now ``h2(1,1).pck`` without any hash.
|
|
3046
3090
|
If ``uid`` is used the parameter of the function are not hashed. Like ``label``
|
|
3047
|
-
the parameter ``uid`` can also be a :
|
|
3091
|
+
the parameter ``uid`` can also be a :meth:`str.format` string or a callable.
|
|
3048
3092
|
|
|
3049
3093
|
**Controlliong which Parameters to Hash**
|
|
3050
3094
|
|
|
3051
|
-
To specify which parameters are pertinent for identifying a unique
|
|
3095
|
+
To specify which parameters are pertinent for identifying a unique ID, use:
|
|
3052
3096
|
|
|
3053
3097
|
* ``include_args``: list of functions arguments to include. If ``None``, use all parameteres as input in the next step
|
|
3054
3098
|
|
|
@@ -3057,7 +3101,7 @@ class SubDir(object):
|
|
|
3057
3101
|
* ``exclude_arg_types``: a list of types to exclude.
|
|
3058
3102
|
This is helpful if control flow is managed with dedicated data types.
|
|
3059
3103
|
An example of such a type is :class:`cdxcore.verbose.Context` which is used to print hierarchical output messages.
|
|
3060
|
-
Types can be globally excluded using a :class:`
|
|
3104
|
+
Types can be globally excluded using a :class:`cdxcore.subdir.CacheController`
|
|
3061
3105
|
when calling
|
|
3062
3106
|
:class:`cdxcore.subdir.SubDir`.
|
|
3063
3107
|
|
|
@@ -3150,7 +3194,8 @@ class SubDir(object):
|
|
|
3150
3194
|
_ = b.f(y=1) # same unique call ID as previous call
|
|
3151
3195
|
# -> restore result from disk
|
|
3152
3196
|
|
|
3153
|
-
**WARNING
|
|
3197
|
+
**WARNING:**
|
|
3198
|
+
|
|
3154
3199
|
:class:`cdxcore.uniquehash.UniqueHash` does *not* by default process members of objects or dictionaries
|
|
3155
3200
|
which start with a "_". This behaviour can be changed using :class:`cdxcore.subdir.CacheController`.
|
|
3156
3201
|
For reasonably complex objects it is recommended to implement for your objects
|
|
@@ -3311,12 +3356,15 @@ class SubDir(object):
|
|
|
3311
3356
|
version : str | None, default ``None``
|
|
3312
3357
|
Version of the function.
|
|
3313
3358
|
|
|
3314
|
-
* If ``None`` then a common
|
|
3315
|
-
|
|
3359
|
+
* If ``None`` then a common ``F`` must be decorated manually
|
|
3360
|
+
ith :dec:`cdxcore.version.version`.
|
|
3361
|
+
* If set, the function ``F`` is automatically first decorated
|
|
3362
|
+
with :dec:`cdxcore.version.version` for you.
|
|
3316
3363
|
|
|
3317
3364
|
dependencies : list[type] | None, default ``None``
|
|
3318
3365
|
A list of version dependencies, either by reference or by name.
|
|
3319
|
-
See :dec:`cdxcore.version.version` for details on
|
|
3366
|
+
See :dec:`cdxcore.version.version` for details on
|
|
3367
|
+
name lookup if strings are used.
|
|
3320
3368
|
|
|
3321
3369
|
label : str | Callable | None, default ``None``
|
|
3322
3370
|
Specify a human-readable label for the function call given its parameters.
|
|
@@ -3404,7 +3452,8 @@ class SubDir(object):
|
|
|
3404
3452
|
|
|
3405
3453
|
.. code-block:: python
|
|
3406
3454
|
|
|
3407
|
-
@cache.cache("0.1",
|
|
3455
|
+
@cache.cache("0.1", x : f"{new_func_name}(): {func_name} {x}",
|
|
3456
|
+
name_of_func_name_arg="new_func_name")
|
|
3408
3457
|
def f( func_name, x ):
|
|
3409
3458
|
pass
|
|
3410
3459
|
|
|
@@ -3412,25 +3461,26 @@ class SubDir(object):
|
|
|
3412
3461
|
-------
|
|
3413
3462
|
Decorated F: Callable
|
|
3414
3463
|
|
|
3415
|
-
A
|
|
3464
|
+
A decorated ``F`` whose ``__call__`` implements the cached call to ``F``.
|
|
3416
3465
|
|
|
3417
|
-
This
|
|
3466
|
+
This decorator has a member ``cache_info``
|
|
3418
3467
|
of type :class:`cdxcore.subdir.CacheInfo`
|
|
3419
3468
|
which can be used to access information on caching activity.
|
|
3420
3469
|
|
|
3421
|
-
* Information available at any time after decoration
|
|
3470
|
+
* Information available at any time after decoration:
|
|
3422
3471
|
|
|
3423
3472
|
* ``F.cache_info.name`` : qualified name of the function
|
|
3424
3473
|
* ``F.cache_info.signature`` : signature of the function
|
|
3425
3474
|
|
|
3426
|
-
* Additonal information available during a call to a decorated function F
|
|
3475
|
+
* Additonal information available during a call to a decorated function ``F``, and thereafter
|
|
3476
|
+
(these proprties are not thread-safe):
|
|
3427
3477
|
|
|
3428
3478
|
* ``F.cache_info.version`` : unique version string reflecting all dependencies.
|
|
3429
3479
|
* ``F.cache_info.filename`` : unique filename used for caching logic during the last function call.
|
|
3430
3480
|
* ``F.cache_info.label`` : last label generated, or ``None``.
|
|
3431
3481
|
* ``F.cache_info.arguments`` : arguments parsed to create a unique call ID, or ``None``.
|
|
3432
3482
|
|
|
3433
|
-
* Additonal information available after a call to ``F
|
|
3483
|
+
* Additonal information available after a call to ``F`` (these proprties are not thread-safe):
|
|
3434
3484
|
|
|
3435
3485
|
* ``F.cache_info.last_cached`` : whether the last function call returned a cached object.
|
|
3436
3486
|
|
|
@@ -3453,6 +3503,7 @@ class SubDir(object):
|
|
|
3453
3503
|
If ``True``, then the decorated function will return a tuple ``uid, result``
|
|
3454
3504
|
where ``uid`` is the unique filename generated for this function call,
|
|
3455
3505
|
and where ``result`` is the actual result from the function, cached or not.
|
|
3506
|
+
This ``uid`` is thread-safe.
|
|
3456
3507
|
|
|
3457
3508
|
Usage::
|
|
3458
3509
|
|
|
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "cdxcore"
|
|
9
|
-
version = "0.1.
|
|
9
|
+
version = "0.1.34"
|
|
10
10
|
description = "Basic Python Tools; upgraded cdxbasics"
|
|
11
11
|
authors = [{ name = "Hans Buehler", email = "github@buehler.london" }]
|
|
12
12
|
readme = "README.md"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|