howso-engine 67.0.1__tar.gz → 67.2.0__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.
Files changed (129) hide show
  1. {howso_engine-67.0.1 → howso_engine-67.2.0}/LICENSE-3RD-PARTY.txt +38 -38
  2. {howso_engine-67.0.1/howso_engine.egg-info → howso_engine-67.2.0}/PKG-INFO +2 -2
  3. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/client/base.py +23 -4
  4. howso_engine-67.2.0/howso/client/cache.py +189 -0
  5. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/client/schemas/reaction.py +49 -56
  6. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/direct/client.py +92 -1
  7. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/engine/trainee.py +17 -0
  8. howso_engine-67.2.0/howso/howso-engine/howso.caml +0 -0
  9. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/howso-engine/version.json +3 -3
  10. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/internals.py +11 -1
  11. {howso_engine-67.0.1 → howso_engine-67.2.0/howso_engine.egg-info}/PKG-INFO +2 -2
  12. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso_engine.egg-info/requires.txt +1 -1
  13. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso_engine.egg-info/scm_file_list.json +1 -0
  14. {howso_engine-67.0.1 → howso_engine-67.2.0}/pyproject.toml +1 -1
  15. {howso_engine-67.0.1 → howso_engine-67.2.0}/requirements-3.11-dev.txt +12 -12
  16. {howso_engine-67.0.1 → howso_engine-67.2.0}/requirements-3.11.txt +7 -7
  17. {howso_engine-67.0.1 → howso_engine-67.2.0}/requirements-3.12-dev.txt +12 -12
  18. {howso_engine-67.0.1 → howso_engine-67.2.0}/requirements-3.12.txt +7 -7
  19. {howso_engine-67.0.1 → howso_engine-67.2.0}/requirements-3.13-dev.txt +12 -12
  20. {howso_engine-67.0.1 → howso_engine-67.2.0}/requirements-3.13.txt +7 -7
  21. {howso_engine-67.0.1 → howso_engine-67.2.0}/requirements-3.14-dev.txt +12 -12
  22. {howso_engine-67.0.1 → howso_engine-67.2.0}/requirements-3.14.txt +7 -7
  23. howso_engine-67.2.0/version.json +5 -0
  24. howso_engine-67.0.1/howso/client/cache.py +0 -105
  25. howso_engine-67.0.1/howso/howso-engine/howso.caml +0 -0
  26. howso_engine-67.0.1/version.json +0 -5
  27. {howso_engine-67.0.1 → howso_engine-67.2.0}/.coveragerc +0 -0
  28. {howso_engine-67.0.1 → howso_engine-67.2.0}/.flake8 +0 -0
  29. {howso_engine-67.0.1 → howso_engine-67.2.0}/.github/CODEOWNERS +0 -0
  30. {howso_engine-67.0.1 → howso_engine-67.2.0}/.github/templates/version_summary.md +0 -0
  31. {howso_engine-67.0.1 → howso_engine-67.2.0}/.github/workflows/build-pr.yml +0 -0
  32. {howso_engine-67.0.1 → howso_engine-67.2.0}/.github/workflows/build-release.yml +0 -0
  33. {howso_engine-67.0.1 → howso_engine-67.2.0}/.github/workflows/build.yml +0 -0
  34. {howso_engine-67.0.1 → howso_engine-67.2.0}/.github/workflows/rebuild-requirements.yml +0 -0
  35. {howso_engine-67.0.1 → howso_engine-67.2.0}/.github/workflows/version-update.yml +0 -0
  36. {howso_engine-67.0.1 → howso_engine-67.2.0}/.gitignore +0 -0
  37. {howso_engine-67.0.1 → howso_engine-67.2.0}/.gitmodules +0 -0
  38. {howso_engine-67.0.1 → howso_engine-67.2.0}/.pylintrc +0 -0
  39. {howso_engine-67.0.1 → howso_engine-67.2.0}/CONTRIBUTING.md +0 -0
  40. {howso_engine-67.0.1 → howso_engine-67.2.0}/LICENSE.txt +0 -0
  41. {howso_engine-67.0.1 → howso_engine-67.2.0}/MANIFEST.in +0 -0
  42. {howso_engine-67.0.1 → howso_engine-67.2.0}/Makefile +0 -0
  43. {howso_engine-67.0.1 → howso_engine-67.2.0}/README.md +0 -0
  44. {howso_engine-67.0.1 → howso_engine-67.2.0}/bin/build.sh +0 -0
  45. {howso_engine-67.0.1 → howso_engine-67.2.0}/config/latest-mt-debug-howso.yml +0 -0
  46. {howso_engine-67.0.1 → howso_engine-67.2.0}/config/latest-mt-howso.yml +0 -0
  47. {howso_engine-67.0.1 → howso_engine-67.2.0}/config/latest-mt-noavx-traces-howso.yml +0 -0
  48. {howso_engine-67.0.1 → howso_engine-67.2.0}/config/latest-mt-traces-howso.yml +0 -0
  49. {howso_engine-67.0.1 → howso_engine-67.2.0}/config/latest-st-debug-howso.yml +0 -0
  50. {howso_engine-67.0.1 → howso_engine-67.2.0}/config/latest-st-howso.yml +0 -0
  51. {howso_engine-67.0.1 → howso_engine-67.2.0}/config/latest-st-traces-howso.yml +0 -0
  52. {howso_engine-67.0.1 → howso_engine-67.2.0}/config/powershell/Download-Tzdata.ps1 +0 -0
  53. {howso_engine-67.0.1 → howso_engine-67.2.0}/config/powershell/Helper-Functions.ps1 +0 -0
  54. {howso_engine-67.0.1 → howso_engine-67.2.0}/hatch.toml +0 -0
  55. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/__main__.py +0 -0
  56. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/client/__init__.py +0 -0
  57. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/client/api.py +0 -0
  58. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/client/client.py +0 -0
  59. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/client/configuration.py +0 -0
  60. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/client/exceptions.py +0 -0
  61. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/client/feature_flags.py +0 -0
  62. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/client/pandas/__init__.py +0 -0
  63. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/client/pandas/client.py +0 -0
  64. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/client/protocols.py +0 -0
  65. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/client/schemas/__init__.py +0 -0
  66. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/client/schemas/aggregate_reaction.py +0 -0
  67. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/client/schemas/base.py +0 -0
  68. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/client/schemas/group_reaction.py +0 -0
  69. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/client/schemas/project.py +0 -0
  70. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/client/schemas/session.py +0 -0
  71. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/client/schemas/trainee.py +0 -0
  72. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/client/schemas/version.py +0 -0
  73. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/client/typing.py +0 -0
  74. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/direct/__init__.py +0 -0
  75. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/direct/_utilities.py +0 -0
  76. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/direct/schemas/__init__.py +0 -0
  77. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/direct/schemas/trainee.py +0 -0
  78. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/engine/__init__.py +0 -0
  79. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/engine/client.py +0 -0
  80. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/engine/project.py +0 -0
  81. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/engine/session.py +0 -0
  82. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/howso-engine/migrations/migrations.caml +0 -0
  83. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/scikit/__init__.py +0 -0
  84. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/scikit/scikit.py +0 -0
  85. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/__init__.py +0 -0
  86. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/decorators.py +0 -0
  87. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/fanout_features.py +0 -0
  88. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/feature_attributes/__init__.py +0 -0
  89. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/feature_attributes/abstract_data.py +0 -0
  90. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/feature_attributes/base.py +0 -0
  91. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/feature_attributes/infer_feature_attributes.py +0 -0
  92. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/feature_attributes/pandas.py +0 -0
  93. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/feature_attributes/protocols.py +0 -0
  94. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/feature_attributes/relational.py +0 -0
  95. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/feature_attributes/serializers.py +0 -0
  96. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/feature_attributes/suggestions.py +0 -0
  97. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/feature_attributes/time_series.py +0 -0
  98. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/feature_attributes/warnings.py +0 -0
  99. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/features.py +0 -0
  100. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/installation_verification/__init__.py +0 -0
  101. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/installation_verification/__main__.py +0 -0
  102. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/installation_verification/_constants.py +0 -0
  103. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/installation_verification/_helpers.py +0 -0
  104. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/installation_verification/_output.py +0 -0
  105. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/installation_verification/_probes.py +0 -0
  106. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/installation_verification/_types.py +0 -0
  107. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/installation_verification/checks_cpu.py +0 -0
  108. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/installation_verification/checks_engine.py +0 -0
  109. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/installation_verification/checks_environment.py +0 -0
  110. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/installation_verification/checks_optional.py +0 -0
  111. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/installation_verification/main.py +0 -0
  112. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/installation_verification/registry.py +0 -0
  113. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/json_wrapper.py +0 -0
  114. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/locale.py +0 -0
  115. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/monitors.py +0 -0
  116. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/posix.py +0 -0
  117. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/progress.py +0 -0
  118. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/random.py +0 -0
  119. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/reaction.py +0 -0
  120. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/testing.py +0 -0
  121. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/tokenizing.py +0 -0
  122. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso/utilities/utilities.py +0 -0
  123. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso_engine.egg-info/SOURCES.txt +0 -0
  124. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso_engine.egg-info/dependency_links.txt +0 -0
  125. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso_engine.egg-info/entry_points.txt +0 -0
  126. {howso_engine-67.0.1 → howso_engine-67.2.0}/howso_engine.egg-info/top_level.txt +0 -0
  127. {howso_engine-67.0.1 → howso_engine-67.2.0}/pyrightconfig.json +0 -0
  128. {howso_engine-67.0.1 → howso_engine-67.2.0}/ruff.toml +0 -0
  129. {howso_engine-67.0.1 → howso_engine-67.2.0}/setup.cfg +0 -0
@@ -1,10 +1,10 @@
1
1
  Faker
2
- 40.39.0
2
+ 40.41.0
3
3
  MIT License
4
4
  joke2k
5
5
  https://github.com/joke2k/faker
6
6
  Faker is a Python package that generates fake data for you.
7
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/faker-40.39.0.dist-info/licenses/LICENSE.txt
7
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/faker-40.41.0.dist-info/licenses/LICENSE.txt
8
8
  Copyright (c) 2012 Daniele Faraglia
9
9
 
10
10
  Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -32,7 +32,7 @@ MIT License
32
32
  Kirill Simonov
33
33
  https://pyyaml.org/
34
34
  YAML parser and emitter for Python
35
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/pyyaml-6.0.3.dist-info/licenses/LICENSE
35
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/pyyaml-6.0.3.dist-info/licenses/LICENSE
36
36
  Copyright (c) 2017-2021 Ingy döt Net
37
37
  Copyright (c) 2006-2016 Kirill Simonov
38
38
 
@@ -61,7 +61,7 @@ BSD-2-Clause
61
61
  Georg Brandl <georg@python.org>
62
62
  https://pygments.org
63
63
  Pygments is a syntax highlighting package written in Python.
64
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/pygments-2.21.0.dist-info/licenses/LICENSE
64
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/pygments-2.21.0.dist-info/licenses/LICENSE
65
65
  Copyright (c) 2006-2022 by the respective authors (see AUTHORS file).
66
66
  All rights reserved.
67
67
 
@@ -95,7 +95,7 @@ MIT
95
95
  Filipe Laíns <lains@riseup.net>, Bernát Gábor <gaborjbernat@gmail.com>, layday <layday@protonmail.com>, Henry Schreiner <henryschreineriii@gmail.com>
96
96
  https://build.pypa.io
97
97
  A simple, correct Python build frontend
98
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/build-1.6.1.dist-info/licenses/LICENSE
98
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/build-1.6.1.dist-info/licenses/LICENSE
99
99
  Copyright © 2019 Filipe Laíns <filipe.lains@gmail.com>
100
100
 
101
101
  Permission is hereby granted, free of charge, to any person obtaining a
@@ -124,7 +124,7 @@ Mozilla Public License 2.0 (MPL 2.0)
124
124
  Kenneth Reitz
125
125
  https://github.com/certifi/python-certifi
126
126
  Python package for providing Mozilla's CA Bundle.
127
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/certifi-2026.7.22.dist-info/licenses/LICENSE
127
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/certifi-2026.7.22.dist-info/licenses/LICENSE
128
128
  This package contains a modified version of ca-bundle.crt:
129
129
 
130
130
  ca-bundle.crt -- Bundle of CA Root Certificates
@@ -148,12 +148,12 @@ one at http://mozilla.org/MPL/2.0/.
148
148
 
149
149
 
150
150
  charset-normalizer
151
- 3.5.1
151
+ 3.5.2
152
152
  MIT
153
153
  "Ahmed R. TAHRI" <tahri.ahmed@proton.me>
154
154
  https://github.com/jawah/charset_normalizer/blob/master/CHANGELOG.md
155
155
  The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet.
156
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/charset_normalizer-3.5.1.dist-info/licenses/LICENSE
156
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/charset_normalizer-3.5.2.dist-info/licenses/LICENSE
157
157
  MIT License
158
158
 
159
159
  Copyright (c) 2025 TAHRI Ahmed R.
@@ -183,7 +183,7 @@ BSD-3-Clause
183
183
  UNKNOWN
184
184
  https://github.com/pallets/click/
185
185
  Composable command line interface toolkit
186
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/click-8.5.0.dist-info/licenses/LICENSE.txt
186
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/click-8.5.0.dist-info/licenses/LICENSE.txt
187
187
  Copyright 2014 Pallets
188
188
 
189
189
  Redistribution and use in source and binary forms, with or without
@@ -220,7 +220,7 @@ BSD License
220
220
  The cloudpickle developer team
221
221
  https://github.com/cloudpipe/cloudpickle
222
222
  Pickler class to extend the standard pickle.Pickler functionality
223
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/cloudpickle-3.1.2.dist-info/licenses/LICENSE
223
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/cloudpickle-3.1.2.dist-info/licenses/LICENSE
224
224
  This module was extracted from the `cloud` package, developed by
225
225
  PiCloud, Inc.
226
226
 
@@ -261,7 +261,7 @@ MIT
261
261
  Jason Moiron <jmoiron@jmoiron.net>
262
262
  https://github.com/python-humanize/humanize
263
263
  Python humanize utilities
264
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/humanize-4.16.0.dist-info/licenses/LICENCE
264
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/humanize-4.16.0.dist-info/licenses/LICENCE
265
265
  Copyright (c) 2010-2020 Jason Moiron and Contributors
266
266
 
267
267
  Permission is hereby granted, free of charge, to any person obtaining
@@ -290,7 +290,7 @@ BSD-3-Clause
290
290
  Kim Davies <kim+pypi@gumleaf.org>
291
291
  https://github.com/kjd/idna
292
292
  Internationalized Domain Names in Applications (IDNA)
293
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/idna-3.20.dist-info/licenses/LICENSE.md
293
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/idna-3.20.dist-info/licenses/LICENSE.md
294
294
  BSD 3-Clause License
295
295
 
296
296
  Copyright (c) 2013-2026, Kim Davies and contributors.
@@ -330,7 +330,7 @@ BSD-3-Clause
330
330
  Gael Varoquaux <gael.varoquaux@normalesup.org>
331
331
  https://joblib.readthedocs.io
332
332
  Lightweight pipelining with Python functions
333
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/joblib-1.6.0.dist-info/licenses/LICENSE.txt
333
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/joblib-1.6.0.dist-info/licenses/LICENSE.txt
334
334
  BSD 3-Clause License
335
335
 
336
336
  Copyright (c) 2008-2021, The joblib developers.
@@ -368,7 +368,7 @@ MIT License
368
368
  Chris Sewell <chrisj_sewell@hotmail.com>
369
369
  https://github.com/executablebooks/markdown-it-py
370
370
  Python port of markdown-it. Markdown parsing, done right!
371
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/markdown_it_py-4.2.0.dist-info/licenses/LICENSE
371
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/markdown_it_py-4.2.0.dist-info/licenses/LICENSE
372
372
  MIT License
373
373
 
374
374
  Copyright (c) 2020 ExecutableBookProject
@@ -398,7 +398,7 @@ MIT License
398
398
  Taneli Hukkinen <hukkin@users.noreply.github.com>
399
399
  https://github.com/executablebooks/mdurl
400
400
  Markdown URL utilities
401
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/mdurl-0.1.2.dist-info/LICENSE
401
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/mdurl-0.1.2.dist-info/LICENSE
402
402
  Copyright (c) 2015 Vitaly Puzrin, Alex Kocharin.
403
403
  Copyright (c) 2021 Taneli Hukkinen
404
404
 
@@ -448,12 +448,12 @@ IN THE SOFTWARE.
448
448
 
449
449
 
450
450
  mmh3
451
- 5.3.0
451
+ 5.3.1
452
452
  MIT License
453
453
  Hajime Senuma <hajime.senuma@gmail.com>
454
454
  https://pypi.org/project/mmh3/
455
455
  Python extension for MurmurHash (MurmurHash3), a set of fast and robust hash functions.
456
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/mmh3-5.3.0.dist-info/licenses/LICENSE
456
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/mmh3-5.3.1.dist-info/licenses/LICENSE
457
457
  MIT License
458
458
 
459
459
  Copyright (c) 2011-2026 Hajime Senuma
@@ -482,7 +482,7 @@ BSD-3-Clause AND 0BSD AND MIT AND Zlib AND CC0-1.0
482
482
  Travis E. Oliphant et al.
483
483
  https://numpy.org
484
484
  Fundamental package for array computing in Python
485
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/numpy-2.4.6.dist-info/licenses/LICENSE.txt
485
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/numpy-2.4.6.dist-info/licenses/LICENSE.txt
486
486
  Copyright (c) 2005-2025, NumPy Developers.
487
487
  All rights reserved.
488
488
 
@@ -1426,7 +1426,7 @@ Apache-2.0 OR BSD-2-Clause
1426
1426
  Donald Stufft <donald@stufft.io>
1427
1427
  https://github.com/pypa/packaging
1428
1428
  Core utilities for Python packages
1429
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/packaging-26.3.dist-info/licenses/LICENSE
1429
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/packaging-26.3.dist-info/licenses/LICENSE
1430
1430
  This software is made available under the terms of *either* of the licenses
1431
1431
  found in LICENSE.APACHE or LICENSE.BSD. Contributions to this software is made
1432
1432
  under the terms of *both* these licenses.
@@ -1438,7 +1438,7 @@ BSD License
1438
1438
  The Pandas Development Team <pandas-dev@python.org>
1439
1439
  https://pandas.pydata.org
1440
1440
  Powerful data structures for data analysis, time series, and statistics
1441
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/pandas-2.3.3.dist-info/LICENSE
1441
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/pandas-2.3.3.dist-info/LICENSE
1442
1442
  BSD 3-Clause License
1443
1443
 
1444
1444
  Copyright (c) 2008-2011, AQR Capital Management, LLC, Lambda Foundry, Inc. and PyData Development Team
@@ -2696,7 +2696,7 @@ BSD License
2696
2696
  Vincent Driessen <me@nvie.com>
2697
2697
  https://github.com/jazzband/pip-tools/
2698
2698
  pip-tools keeps your pinned dependencies fresh.
2699
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/pip_tools-7.4.1.dist-info/LICENSE
2699
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/pip_tools-7.4.1.dist-info/LICENSE
2700
2700
  BSD 3-Clause License
2701
2701
 
2702
2702
  Copyright (c). All rights reserved.
@@ -2733,7 +2733,7 @@ BSD-3-Clause
2733
2733
  Giampaolo Rodola
2734
2734
  https://github.com/giampaolo/psutil
2735
2735
  Cross-platform lib for process and system monitoring.
2736
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/psutil-7.2.2.dist-info/LICENSE
2736
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/psutil-7.2.2.dist-info/LICENSE
2737
2737
  BSD 3-Clause License
2738
2738
 
2739
2739
  Copyright (c) 2009, Jay Loden, Dave Daeschler, Giampaolo Rodola
@@ -2771,7 +2771,7 @@ MIT
2771
2771
  Thomas Kluyver <thomas@kluyver.me.uk>
2772
2772
  https://github.com/pypa/pyproject-hooks
2773
2773
  Wrappers to call pyproject.toml-based build backend hooks.
2774
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/pyproject_hooks-1.3.3.dist-info/licenses/LICENSE
2774
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/pyproject_hooks-1.3.3.dist-info/licenses/LICENSE
2775
2775
  The MIT License (MIT)
2776
2776
 
2777
2777
  Copyright (c) 2017 Thomas Kluyver
@@ -2801,7 +2801,7 @@ Apache Software License; BSD License
2801
2801
  Gustavo Niemeyer
2802
2802
  https://github.com/dateutil/dateutil
2803
2803
  Extensions to the standard Python datetime module
2804
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/python_dateutil-2.9.0.post0.dist-info/LICENSE
2804
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/python_dateutil-2.9.0.post0.dist-info/LICENSE
2805
2805
  Copyright 2017- Paul Ganssle <paul@ganssle.io>
2806
2806
  Copyright 2017- dateutil contributors (see AUTHORS file)
2807
2807
 
@@ -2858,12 +2858,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2858
2858
  The above BSD License Applies to all code, even that also covered by Apache 2.0.
2859
2859
 
2860
2860
  pytz
2861
- 2026.4
2861
+ 2026.5
2862
2862
  MIT License
2863
2863
  Stuart Bishop
2864
2864
  http://pythonhosted.org/pytz
2865
2865
  World timezone definitions, modern and historical
2866
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/pytz-2026.4.dist-info/LICENSE.txt
2866
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/pytz-2026.5.dist-info/LICENSE.txt
2867
2867
  Copyright (c) 2003-2019 Stuart Bishop <stuart@stuartbishop.net>
2868
2868
 
2869
2869
  Permission is hereby granted, free of charge, to any person obtaining a
@@ -2886,12 +2886,12 @@ DEALINGS IN THE SOFTWARE.
2886
2886
 
2887
2887
 
2888
2888
  regex
2889
- 2026.9.10
2889
+ 2026.9.29
2890
2890
  Apache-2.0 AND CNRI-Python
2891
2891
  Matthew Barnett <regex@mrabarnett.plus.com>
2892
2892
  https://github.com/mrabarnett/mrab-regex
2893
2893
  Alternative regular expression module, to replace re.
2894
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/regex-2026.9.10.dist-info/licenses/LICENSE.txt
2894
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/regex-2026.9.29.dist-info/licenses/LICENSE.txt
2895
2895
  This work was derived from the 're' module of CPython 2.6 and CPython 3.1,
2896
2896
  copyright (c) 1998-2001 by Secret Labs AB and licensed under CNRI's Python 1.6
2897
2897
  license.
@@ -3108,7 +3108,7 @@ Apache Software License
3108
3108
  Kenneth Reitz <me@kennethreitz.org>
3109
3109
  https://github.com/psf/requests
3110
3110
  Python HTTP for Humans.
3111
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/requests-2.34.2.dist-info/licenses/LICENSE
3111
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/requests-2.34.2.dist-info/licenses/LICENSE
3112
3112
 
3113
3113
  Apache License
3114
3114
  Version 2.0, January 2004
@@ -3292,7 +3292,7 @@ MIT License
3292
3292
  Will McGugan
3293
3293
  https://github.com/Textualize/rich
3294
3294
  Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal
3295
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/rich-15.0.0.dist-info/licenses/LICENSE
3295
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/rich-15.0.0.dist-info/licenses/LICENSE
3296
3296
  Copyright (c) 2020 Will McGugan
3297
3297
 
3298
3298
  Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -3320,7 +3320,7 @@ MIT License
3320
3320
  UNKNOWN
3321
3321
  https://github.com/hplt-project/sacremoses
3322
3322
  SacreMoses
3323
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/sacremoses-0.2.0.dist-info/licenses/LICENSE
3323
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/sacremoses-0.2.0.dist-info/licenses/LICENSE
3324
3324
  MIT License
3325
3325
 
3326
3326
  Copyright (c) 2020 alvations
@@ -3350,7 +3350,7 @@ BSD License
3350
3350
  Raphaël Barrois
3351
3351
  https://github.com/rbarrois/python-semanticversion
3352
3352
  A library implementing the 'SemVer' scheme.
3353
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/semantic_version-2.10.0.dist-info/LICENSE
3353
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/semantic_version-2.10.0.dist-info/LICENSE
3354
3354
  Copyright (c) The python-semanticversion project
3355
3355
  All rights reserved.
3356
3356
 
@@ -3381,7 +3381,7 @@ MIT License
3381
3381
  Benjamin Peterson
3382
3382
  https://github.com/benjaminp/six
3383
3383
  Python 2 and 3 compatibility utilities
3384
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/six-1.17.0.dist-info/LICENSE
3384
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/six-1.17.0.dist-info/LICENSE
3385
3385
  Copyright (c) 2010-2024 Benjamin Peterson
3386
3386
 
3387
3387
  Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -3408,7 +3408,7 @@ MPL-2.0 AND MIT
3408
3408
  UNKNOWN
3409
3409
  https://tqdm.github.io
3410
3410
  Fast, Extensible Progress Meter
3411
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/tqdm-4.70.1.dist-info/licenses/LICENCE
3411
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/tqdm-4.70.1.dist-info/licenses/LICENCE
3412
3412
  `tqdm` is a product of collaborative work.
3413
3413
  Unless otherwise stated, all authors (see commit logs) retain copyright
3414
3414
  for their respective work, and release the work under the MIT licence
@@ -3466,7 +3466,7 @@ PSF-2.0
3466
3466
  "Guido van Rossum, Jukka Lehtosalo, Łukasz Langa, Michael Lee" <levkivskyi@gmail.com>
3467
3467
  https://github.com/python/typing_extensions
3468
3468
  Backported and Experimental Type Hints for Python 3.9+
3469
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/typing_extensions-4.16.0.dist-info/licenses/LICENSE
3469
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/typing_extensions-4.16.0.dist-info/licenses/LICENSE
3470
3470
  A. HISTORY OF THE SOFTWARE
3471
3471
  ==========================
3472
3472
 
@@ -3749,12 +3749,12 @@ PERFORMANCE OF THIS SOFTWARE.
3749
3749
 
3750
3750
 
3751
3751
  tzdata
3752
- 2026.4
3752
+ 2026.5
3753
3753
  Apache-2.0
3754
3754
  Python Software Foundation
3755
3755
  https://github.com/python/tzdata
3756
3756
  Provider of IANA time zone data
3757
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/tzdata-2026.4.dist-info/licenses/LICENSE
3757
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/tzdata-2026.5.dist-info/licenses/LICENSE
3758
3758
  Apache Software License 2.0
3759
3759
 
3760
3760
  Copyright (c) 2020, Paul Ganssle (Google)
@@ -3779,7 +3779,7 @@ MIT
3779
3779
  Andrey Petrov <andrey.petrov@shazow.net>
3780
3780
  https://github.com/urllib3/urllib3/blob/main/CHANGES.rst
3781
3781
  HTTP library with thread-safe connection pooling, file post, and more.
3782
- /home/runner/.pyenv/versions/3.14.7/lib/python3.14/site-packages/urllib3-2.8.0.dist-info/licenses/LICENSE.txt
3782
+ /home/runner/.pyenv/versions/3.14.8/lib/python3.14/site-packages/urllib3-2.8.0.dist-info/licenses/LICENSE.txt
3783
3783
  MIT License
3784
3784
 
3785
3785
  Copyright (c) 2008-2020 Andrey Petrov and contributors.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: howso-engine
3
- Version: 67.0.1
3
+ Version: 67.2.0
4
4
  Summary: The Howso Engine™ is a natively and fully explainable ML engine, serving as an alternative to black box AI neural networks.
5
5
  Author: Howso Incorporated
6
6
  Author-email: support@howso.com
@@ -705,7 +705,7 @@ Requires-Dist: sacremoses
705
705
  Requires-Dist: semantic-version~=2.0
706
706
  Requires-Dist: typing-extensions~=4.9
707
707
  Requires-Dist: urllib3>=2.6.3
708
- Requires-Dist: amalgam-lang==35.0.1
708
+ Requires-Dist: amalgam-lang==35.1.0
709
709
  Provides-Extra: dev
710
710
  Requires-Dist: dill~=0.0; extra == "dev"
711
711
  Requires-Dist: flake8-docstrings; extra == "dev"
@@ -164,15 +164,17 @@ class AbstractHowsoClient(ABC):
164
164
  The Trainee feature attributes.
165
165
  """
166
166
  cached = self.trainee_cache.get_item(trainee_id, None)
167
- if cached:
167
+ if cached is None:
168
168
  # Trainee not yet cached, resolve it first
169
169
  trainee_id = self._resolve_trainee(trainee_id).id
170
170
  cached = self.trainee_cache.get_item(trainee_id)
171
171
 
172
- if cached["feature_attributes"] is None:
172
+ feature_attributes = cached.get("feature_attributes")
173
+ if feature_attributes is None:
173
174
  # Feature attributes not yet cached, get them
174
- cached["feature_attributes"] = self.get_feature_attributes(trainee_id)
175
- return cached["feature_attributes"]
175
+ feature_attributes = self.get_feature_attributes(trainee_id)
176
+ cached["feature_attributes"] = feature_attributes
177
+ return feature_attributes
176
178
 
177
179
  @abstractmethod
178
180
  def _resolve_trainee(self, trainee_id: str, **kwargs) -> Trainee:
@@ -1863,6 +1865,10 @@ class AbstractHowsoClient(ABC):
1863
1865
  produces action_values for the specified action_features conditioned
1864
1866
  on the optionally provided contexts.
1865
1867
 
1868
+ Large requests are split into batches (see ``batch_size``). When the
1869
+ client runs batches concurrently, they do not report engine progress
1870
+ under ``task_id``; ``progress_callback`` reports overall progress.
1871
+
1866
1872
  Parameters
1867
1873
  ----------
1868
1874
  trainee_id : str
@@ -3022,6 +3028,10 @@ class AbstractHowsoClient(ABC):
3022
3028
  corresponding "action" where "action" is the completed 'matrix' for the
3023
3029
  corresponding `action_features` and `derived_action_features`.
3024
3030
 
3031
+ Large requests are split into batches (see ``batch_size``). When the
3032
+ client runs batches concurrently, they do not report engine progress
3033
+ under ``task_id``; ``progress_callback`` reports overall progress.
3034
+
3025
3035
  Parameters
3026
3036
  ----------
3027
3037
  trainee_id : str
@@ -3556,6 +3566,10 @@ class AbstractHowsoClient(ABC):
3556
3566
  r"""
3557
3567
  React to series data predicting stationary feature values.
3558
3568
 
3569
+ Large requests are split into batches (see ``batch_size``). When the
3570
+ client runs batches concurrently, they do not report engine progress
3571
+ under ``task_id``; ``progress_callback`` reports overall progress.
3572
+
3559
3573
  Parameters
3560
3574
  ----------
3561
3575
  trainee_id : str
@@ -4655,6 +4669,7 @@ class AbstractHowsoClient(ABC):
4655
4669
  num_deviation_samples: int | None = None,
4656
4670
  num_feature_probability_samples: int | None = None,
4657
4671
  p_values: Collection[float] | None = None,
4672
+ rand_seed: int | str | None = None,
4658
4673
  rebalance_features: Collection[str] | None = None,
4659
4674
  reduce_only: bool = False,
4660
4675
  targeted_model: TargetedModel | None = None,
@@ -4721,6 +4736,9 @@ class AbstractHowsoClient(ABC):
4721
4736
  multiplied by :math:`10000 \\cdot \\left(1 - \\frac{1}{e}\\right)`.
4722
4737
  p_values : Collection of float, optional
4723
4738
  The p value data parameters to analyze with.
4739
+ rand_seed : int or str, optional
4740
+ A random seed to use for analysis, making the results reproducible.
4741
+ When unspecified, the Trainee's current random state is used.
4724
4742
  rebalance_features : Collection[str], optional
4725
4743
  The list of features whose values to use to rebalance case
4726
4744
  weighting of the data and to store into weight_feature.
@@ -4790,6 +4808,7 @@ class AbstractHowsoClient(ABC):
4790
4808
  num_deviation_samples=num_deviation_samples,
4791
4809
  num_feature_probability_samples=num_feature_probability_samples,
4792
4810
  p_values=p_values,
4811
+ rand_seed=rand_seed,
4793
4812
  rebalance_features=rebalance_features,
4794
4813
  reduce_only=reduce_only,
4795
4814
  targeted_model=targeted_model,
@@ -0,0 +1,189 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Collection, Iterator
4
+ import threading
5
+ import typing as t
6
+
7
+ from semantic_version import Version
8
+ from typing_extensions import NotRequired
9
+
10
+ if t.TYPE_CHECKING:
11
+ from howso.client.schemas import Trainee
12
+
13
+ _T = t.TypeVar("_T")
14
+
15
+
16
+ class TraineeCacheItem(t.TypedDict):
17
+ """Type definition for trainee cache items."""
18
+
19
+ trainee: Trainee
20
+ """Trainee object."""
21
+
22
+ feature_attributes: dict[str, dict] | None
23
+ """Trainee's feature attributes."""
24
+
25
+ version: NotRequired[Version]
26
+ """Version of the Trainee."""
27
+
28
+
29
+ class TraineeCache(Collection):
30
+ """
31
+ Thread-safe cache of trainee related information, keyed by trainee id.
32
+
33
+ A single cache may be shared by clients running on several threads. All
34
+ access to the cache's set of entries is serialized by a lock owned by the
35
+ cache.
36
+
37
+ The enumeration methods (``ids``, ``items``, ``trainees`` and iteration
38
+ over the cache) snapshot *which* entries exist, under that lock.
39
+ Concurrent ``set``, ``discard`` and ``clear`` calls never disturb an
40
+ enumeration in progress, and an enumeration does not reflect entries
41
+ added or removed after it was taken.
42
+
43
+ The entries themselves are not snapshotted. Each ``TraineeCacheItem``
44
+ returned by ``get_item`` or ``items`` is the cache's own live entry:
45
+ assigning to one of its keys updates the cache for every holder, and a
46
+ later ``set`` for the same trainee id updates a dictionary already handed
47
+ out. The lock does not cover reads or writes made through an entry.
48
+ """
49
+
50
+ __slots__ = ("_items", "_lock")
51
+
52
+ __marker = object()
53
+
54
+ def __init__(self) -> None:
55
+ """Initialize an empty cache."""
56
+ self._items: dict[str, TraineeCacheItem] = {}
57
+ self._lock = threading.Lock()
58
+
59
+ def set(self, trainee: Trainee, **kwargs) -> None:
60
+ """
61
+ Set trainee in cache.
62
+
63
+ A trainee id not yet in the cache gets a new entry whose
64
+ ``feature_attributes`` is ``None``. For an id already in the cache,
65
+ the entry's ``trainee`` is replaced and ``kwargs`` are merged into
66
+ the existing entry, keeping any keys not named in ``kwargs``.
67
+
68
+ Parameters
69
+ ----------
70
+ trainee : Trainee
71
+ The trainee to cache. Trainees without an id are ignored.
72
+ **kwargs
73
+ Additional entry keys to store alongside the trainee.
74
+ """
75
+ if trainee.id:
76
+ with self._lock:
77
+ item = self._items.setdefault(trainee.id, {"trainee": trainee, "feature_attributes": None})
78
+ item["trainee"] = trainee
79
+ # kwargs may carry keys TraineeCacheItem does not declare
80
+ # (for example a platform ``revision``), so they are assigned
81
+ # one at a time.
82
+ for key, value in kwargs.items():
83
+ item[key] = value
84
+
85
+ def get(self, trainee_id: str, default=__marker) -> Trainee:
86
+ """Get trainee instance by id."""
87
+ with self._lock:
88
+ try:
89
+ return self._items[trainee_id]["trainee"]
90
+ except KeyError:
91
+ if default is self.__marker:
92
+ raise
93
+ return default
94
+
95
+ @t.overload
96
+ def get_item(self, trainee_id: str) -> TraineeCacheItem: ...
97
+
98
+ @t.overload
99
+ def get_item(self, trainee_id: str, default: _T) -> TraineeCacheItem | _T: ...
100
+
101
+ def get_item(self, trainee_id: str, default: object = __marker) -> TraineeCacheItem | object:
102
+ """
103
+ Get the cache entry for a trainee, by id.
104
+
105
+ The returned dictionary is the cache's own live entry, not a copy.
106
+ Assigning to its keys (for example ``feature_attributes``) changes
107
+ what the cache holds for this trainee, and a later ``set`` call for
108
+ the same id changes this dictionary. Once the trainee is discarded,
109
+ the dictionary is detached from the cache: it keeps its contents, and
110
+ a subsequent ``set`` for that id creates a new entry.
111
+
112
+ Parameters
113
+ ----------
114
+ trainee_id : str
115
+ The id of the trainee.
116
+ default : optional
117
+ The value to return if the trainee is not in the cache. If not
118
+ provided, a missing trainee raises ``KeyError``.
119
+
120
+ Returns
121
+ -------
122
+ TraineeCacheItem or the type of ``default``
123
+ The trainee's live cache entry, or ``default``.
124
+
125
+ Raises
126
+ ------
127
+ KeyError
128
+ If the trainee is not in the cache and no ``default`` is given.
129
+ """
130
+ with self._lock:
131
+ try:
132
+ return self._items[trainee_id]
133
+ except KeyError:
134
+ if default is self.__marker:
135
+ raise
136
+ return default
137
+
138
+ def discard(self, trainee_id: str) -> None:
139
+ """Remove trainee from cache if exists."""
140
+ with self._lock:
141
+ self._items.pop(trainee_id, None)
142
+
143
+ def ids(self) -> list[str]:
144
+ """Return a snapshot list of the ids in the cache."""
145
+ with self._lock:
146
+ return list(self._items)
147
+
148
+ def items(self) -> list[tuple[str, TraineeCacheItem]]:
149
+ """
150
+ Return a list of the ``(id, item)`` pairs in the cache.
151
+
152
+ The list is a snapshot of which trainees are cached, but each
153
+ ``item`` is the cache's own live entry, as returned by ``get_item``.
154
+ """
155
+ with self._lock:
156
+ return list(self._items.items())
157
+
158
+ def trainees(self) -> Iterator[tuple[str, Trainee]]:
159
+ """Return an iterator over a snapshot of the ``(id, trainee)`` pairs in the cache."""
160
+ with self._lock:
161
+ snapshot = [(key, item["trainee"]) for key, item in self._items.items()]
162
+ return iter(snapshot)
163
+
164
+ def clear(self) -> None:
165
+ """Clear the cache."""
166
+ with self._lock:
167
+ self._items.clear()
168
+
169
+ def __contains__(self, key: object) -> bool:
170
+ """Return if trainee id is in cache."""
171
+ with self._lock:
172
+ return key in self._items
173
+
174
+ def __iter__(self) -> Iterator[str]:
175
+ """Return an iterator over a snapshot of the cached trainee ids."""
176
+ with self._lock:
177
+ snapshot = list(self._items)
178
+ return iter(snapshot)
179
+
180
+ def __len__(self) -> int:
181
+ """Return length of the cache."""
182
+ with self._lock:
183
+ return len(self._items)
184
+
185
+ def __str__(self) -> str:
186
+ """Return string representation of the cache."""
187
+ with self._lock:
188
+ snapshot = dict(self._items)
189
+ return str(snapshot)