howso-engine 60.3.1__tar.gz → 60.3.2__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 (112) hide show
  1. {howso_engine-60.3.1/howso_engine.egg-info → howso_engine-60.3.2}/PKG-INFO +1 -1
  2. howso_engine-60.3.2/howso/howso-engine/howso.caml +0 -0
  3. howso_engine-60.3.2/howso/howso-engine/migrations/migrations.caml +0 -0
  4. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/howso-engine/version.json +3 -3
  5. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/utilities/features.py +172 -164
  6. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/utilities/tokenizing.py +5 -5
  7. {howso_engine-60.3.1 → howso_engine-60.3.2/howso_engine.egg-info}/PKG-INFO +1 -1
  8. howso_engine-60.3.2/version.json +5 -0
  9. howso_engine-60.3.1/howso/howso-engine/howso.caml +0 -0
  10. howso_engine-60.3.1/howso/howso-engine/migrations/migrations.caml +0 -0
  11. howso_engine-60.3.1/version.json +0 -5
  12. {howso_engine-60.3.1 → howso_engine-60.3.2}/.coveragerc +0 -0
  13. {howso_engine-60.3.1 → howso_engine-60.3.2}/.flake8 +0 -0
  14. {howso_engine-60.3.1 → howso_engine-60.3.2}/.github/CODEOWNERS +0 -0
  15. {howso_engine-60.3.1 → howso_engine-60.3.2}/.github/templates/version_summary.md +0 -0
  16. {howso_engine-60.3.1 → howso_engine-60.3.2}/.github/workflows/build-pr.yml +0 -0
  17. {howso_engine-60.3.1 → howso_engine-60.3.2}/.github/workflows/build-release.yml +0 -0
  18. {howso_engine-60.3.1 → howso_engine-60.3.2}/.github/workflows/build.yml +0 -0
  19. {howso_engine-60.3.1 → howso_engine-60.3.2}/.github/workflows/rebuild-requirements.yml +0 -0
  20. {howso_engine-60.3.1 → howso_engine-60.3.2}/.github/workflows/version-update.yml +0 -0
  21. {howso_engine-60.3.1 → howso_engine-60.3.2}/.gitignore +0 -0
  22. {howso_engine-60.3.1 → howso_engine-60.3.2}/.gitmodules +0 -0
  23. {howso_engine-60.3.1 → howso_engine-60.3.2}/.pylintrc +0 -0
  24. {howso_engine-60.3.1 → howso_engine-60.3.2}/CONTRIBUTING.md +0 -0
  25. {howso_engine-60.3.1 → howso_engine-60.3.2}/LICENSE-3RD-PARTY.txt +0 -0
  26. {howso_engine-60.3.1 → howso_engine-60.3.2}/LICENSE.txt +0 -0
  27. {howso_engine-60.3.1 → howso_engine-60.3.2}/MANIFEST.in +0 -0
  28. {howso_engine-60.3.1 → howso_engine-60.3.2}/Makefile +0 -0
  29. {howso_engine-60.3.1 → howso_engine-60.3.2}/README.md +0 -0
  30. {howso_engine-60.3.1 → howso_engine-60.3.2}/bin/build.sh +0 -0
  31. {howso_engine-60.3.1 → howso_engine-60.3.2}/config/latest-mt-debug-howso.yml +0 -0
  32. {howso_engine-60.3.1 → howso_engine-60.3.2}/config/latest-mt-howso.yml +0 -0
  33. {howso_engine-60.3.1 → howso_engine-60.3.2}/config/latest-mt-noavx-traces-howso.yml +0 -0
  34. {howso_engine-60.3.1 → howso_engine-60.3.2}/config/latest-mt-traces-howso.yml +0 -0
  35. {howso_engine-60.3.1 → howso_engine-60.3.2}/config/latest-st-debug-howso.yml +0 -0
  36. {howso_engine-60.3.1 → howso_engine-60.3.2}/config/latest-st-howso.yml +0 -0
  37. {howso_engine-60.3.1 → howso_engine-60.3.2}/config/latest-st-traces-howso.yml +0 -0
  38. {howso_engine-60.3.1 → howso_engine-60.3.2}/config/powershell/Download-Tzdata.ps1 +0 -0
  39. {howso_engine-60.3.1 → howso_engine-60.3.2}/config/powershell/Helper-Functions.ps1 +0 -0
  40. {howso_engine-60.3.1 → howso_engine-60.3.2}/hatch.toml +0 -0
  41. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/__main__.py +0 -0
  42. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/client/__init__.py +0 -0
  43. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/client/api.py +0 -0
  44. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/client/base.py +0 -0
  45. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/client/cache.py +0 -0
  46. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/client/client.py +0 -0
  47. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/client/configuration.py +0 -0
  48. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/client/exceptions.py +0 -0
  49. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/client/feature_flags.py +0 -0
  50. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/client/pandas/__init__.py +0 -0
  51. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/client/pandas/client.py +0 -0
  52. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/client/protocols.py +0 -0
  53. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/client/schemas/__init__.py +0 -0
  54. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/client/schemas/aggregate_reaction.py +0 -0
  55. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/client/schemas/base.py +0 -0
  56. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/client/schemas/group_reaction.py +0 -0
  57. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/client/schemas/project.py +0 -0
  58. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/client/schemas/reaction.py +0 -0
  59. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/client/schemas/session.py +0 -0
  60. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/client/schemas/trainee.py +0 -0
  61. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/client/schemas/version.py +0 -0
  62. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/client/typing.py +0 -0
  63. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/direct/__init__.py +0 -0
  64. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/direct/_utilities.py +0 -0
  65. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/direct/client.py +0 -0
  66. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/direct/schemas/__init__.py +0 -0
  67. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/direct/schemas/trainee.py +0 -0
  68. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/engine/__init__.py +0 -0
  69. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/engine/client.py +0 -0
  70. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/engine/project.py +0 -0
  71. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/engine/session.py +0 -0
  72. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/engine/trainee.py +0 -0
  73. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/scikit/__init__.py +0 -0
  74. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/scikit/scikit.py +0 -0
  75. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/utilities/__init__.py +0 -0
  76. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/utilities/decorators.py +0 -0
  77. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/utilities/feature_attributes/__init__.py +0 -0
  78. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/utilities/feature_attributes/abstract_data.py +0 -0
  79. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/utilities/feature_attributes/base.py +0 -0
  80. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/utilities/feature_attributes/infer_feature_attributes.py +0 -0
  81. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/utilities/feature_attributes/pandas.py +0 -0
  82. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/utilities/feature_attributes/protocols.py +0 -0
  83. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/utilities/feature_attributes/relational.py +0 -0
  84. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/utilities/feature_attributes/serializers.py +0 -0
  85. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/utilities/feature_attributes/suggestions.py +0 -0
  86. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/utilities/feature_attributes/time_series.py +0 -0
  87. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/utilities/feature_attributes/warnings.py +0 -0
  88. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/utilities/installation_verification.py +0 -0
  89. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/utilities/internals.py +0 -0
  90. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/utilities/json_wrapper.py +0 -0
  91. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/utilities/locale.py +0 -0
  92. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/utilities/monitors.py +0 -0
  93. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/utilities/posix.py +0 -0
  94. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/utilities/random.py +0 -0
  95. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/utilities/reaction.py +0 -0
  96. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/utilities/testing.py +0 -0
  97. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso/utilities/utilities.py +0 -0
  98. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso_engine.egg-info/SOURCES.txt +0 -0
  99. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso_engine.egg-info/dependency_links.txt +0 -0
  100. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso_engine.egg-info/entry_points.txt +0 -0
  101. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso_engine.egg-info/requires.txt +0 -0
  102. {howso_engine-60.3.1 → howso_engine-60.3.2}/howso_engine.egg-info/top_level.txt +0 -0
  103. {howso_engine-60.3.1 → howso_engine-60.3.2}/pyproject.toml +0 -0
  104. {howso_engine-60.3.1 → howso_engine-60.3.2}/requirements-3.10-dev.txt +0 -0
  105. {howso_engine-60.3.1 → howso_engine-60.3.2}/requirements-3.10.txt +0 -0
  106. {howso_engine-60.3.1 → howso_engine-60.3.2}/requirements-3.11-dev.txt +0 -0
  107. {howso_engine-60.3.1 → howso_engine-60.3.2}/requirements-3.11.txt +0 -0
  108. {howso_engine-60.3.1 → howso_engine-60.3.2}/requirements-3.12-dev.txt +0 -0
  109. {howso_engine-60.3.1 → howso_engine-60.3.2}/requirements-3.12.txt +0 -0
  110. {howso_engine-60.3.1 → howso_engine-60.3.2}/requirements-3.13-dev.txt +0 -0
  111. {howso_engine-60.3.1 → howso_engine-60.3.2}/requirements-3.13.txt +0 -0
  112. {howso_engine-60.3.1 → howso_engine-60.3.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: howso-engine
3
- Version: 60.3.1
3
+ Version: 60.3.2
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
@@ -1,10 +1,10 @@
1
1
  {
2
- "version": "115.4.1",
2
+ "version": "115.4.2",
3
3
  "dependencies": {
4
4
  "amalgam": "80.0.2"
5
5
  },
6
6
  "display_title": "",
7
7
  "build_date": "",
8
- "sha": "7857102e12dcbfe51ea98f9806595a0e9cc594af",
9
- "url": "https://github.com/howsoai/howso-engine/releases/tag/115.4.1"
8
+ "sha": "fe48463b73c67b588acee0fcfa1c0aafb43a2de5",
9
+ "url": "https://github.com/howsoai/howso-engine/releases/tag/115.4.2"
10
10
  }
@@ -1,12 +1,12 @@
1
1
  from __future__ import annotations
2
2
 
3
- from collections.abc import Iterable, Mapping
3
+ from collections.abc import Iterable, Mapping, Sequence
4
4
  import decimal
5
5
  from enum import Enum
6
6
  from functools import partial
7
7
  import json
8
8
  import locale
9
- import typing as t
9
+ from typing import Any, cast
10
10
  import warnings
11
11
  from zoneinfo import ZoneInfo
12
12
 
@@ -17,11 +17,7 @@ from pandas.core.dtypes.common import (
17
17
  is_timedelta64_dtype,
18
18
  )
19
19
 
20
- from .internals import (
21
- deserialize_to_dataframe,
22
- IgnoreWarnings,
23
- to_pandas_datetime_format
24
- )
20
+ from .internals import deserialize_to_dataframe, IgnoreWarnings, to_pandas_datetime_format
25
21
  from .tokenizing import (
26
22
  HowsoTokenizer,
27
23
  TokenizerProtocol,
@@ -36,7 +32,6 @@ from .utilities import (
36
32
  tokenize_strings,
37
33
  )
38
34
 
39
-
40
35
  __all__ = [
41
36
  "FeatureSerializer",
42
37
  "FeatureType",
@@ -61,7 +56,7 @@ class FeatureType(Enum):
61
56
  TIMEDELTA = "timedelta"
62
57
  CONTAINER = "container"
63
58
 
64
- def __str__(self):
59
+ def __str__(self) -> str:
65
60
  """Return a string representation."""
66
61
  return str(self.value)
67
62
 
@@ -70,23 +65,23 @@ class FeatureSerializer:
70
65
  """Adapter for serialization and deserialization of feature data."""
71
66
 
72
67
  @classmethod
73
- def serialize( # noqa: C901
68
+ def serialize( # noqa: PLR0912
74
69
  cls,
75
- data: t.Optional[pd.DataFrame | np.ndarray | Iterable[t.Any]],
76
- columns: Iterable[str] | None,
77
- features: Mapping,
70
+ data: pd.DataFrame | np.ndarray | Iterable[Any] | None,
71
+ columns: Sequence[str] | None,
72
+ features: Mapping[str, Any],
78
73
  *,
79
- tokenizer: TokenizerProtocol = None,
80
- warn: bool = False
81
- ) -> list[list[t.Any]] | None:
74
+ tokenizer: TokenizerProtocol | None = None,
75
+ warn: bool = False,
76
+ ) -> list[list[Any]] | None:
82
77
  """
83
78
  Serialize case data into list of lists.
84
79
 
85
80
  Parameters
86
81
  ----------
87
- data : pd.DataFrame or np.ndarray or Iterable, default None
82
+ data : pd.DataFrame or np.ndarray or Iterable or None
88
83
  The data to serialize, typically in a Pandas DataFrame, Numpy ndarray or Python Iterable such as a list.
89
- columns : Iterable of str, default None
84
+ columns : Sequence of str or None
90
85
  The case column mapping. The order corresponds to the order of cases in output.
91
86
  `columns` must be provided for non-DataFrame Iterables.
92
87
  features : Mapping
@@ -115,15 +110,13 @@ class FeatureSerializer:
115
110
  was received (should be either pd.DataFrame, np.ndarray or Python Iterable (non-str)).
116
111
  """
117
112
  # Import locally to prevent a circular import
118
- from howso.client.exceptions import HowsoError
113
+ from howso.client.exceptions import HowsoError # noqa: PLC0415
119
114
 
120
115
  if data is None:
121
116
  return None
122
117
  if isinstance(data, np.ndarray):
123
118
  if columns is None:
124
- raise HowsoError(
125
- "Columns must be provided with numpy arrays."
126
- )
119
+ raise HowsoError("Columns must be provided with numpy arrays.")
127
120
  data = pd.DataFrame.from_records(data, columns=columns)
128
121
 
129
122
  if isinstance(data, pd.DataFrame):
@@ -133,8 +126,7 @@ class FeatureSerializer:
133
126
  filtered_data = data[columns]
134
127
  except KeyError as key_error:
135
128
  raise HowsoError(
136
- "The provided DataFrame is missing one or more of the "
137
- f"expected named columns: {columns}."
129
+ f"The provided DataFrame is missing one or more of the expected named columns: {columns}."
138
130
  ) from key_error
139
131
  else:
140
132
  columns = data.columns.tolist()
@@ -145,8 +137,8 @@ class FeatureSerializer:
145
137
  col_data = filtered_data[col]
146
138
  if isinstance(col_data, pd.DataFrame):
147
139
  raise ValueError(
148
- "The provided DataFrame contains duplicate column "
149
- "names. All column names must be unique.")
140
+ "The provided DataFrame contains duplicate column names. All column names must be unique."
141
+ )
150
142
  dtype = col_data.dtype
151
143
  if is_datetime64_any_dtype(dtype):
152
144
  # `to_pydatetime` emits a FutureWarning even when the issue
@@ -163,14 +155,12 @@ class FeatureSerializer:
163
155
 
164
156
  elif isinstance(data, Iterable) and not isinstance(data, str):
165
157
  if columns is None:
166
- raise HowsoError(
167
- "Columns must be provided with python Iterables."
168
- )
158
+ raise HowsoError("Columns must be provided with python Iterables.")
169
159
  result = list(data)
170
160
  else:
171
161
  raise ValueError(
172
- "Received unexpected data type for case data. Cases "
173
- "should be either a DataFrame or a list.")
162
+ "Received unexpected data type for case data. Cases should be either a DataFrame or a list."
163
+ )
174
164
 
175
165
  # Convert 1d list (single case) to 2d list for serialization
176
166
  # We check if the first item in the serialized list is a list
@@ -193,10 +183,10 @@ class FeatureSerializer:
193
183
  @classmethod
194
184
  def deserialize(
195
185
  cls,
196
- data: Iterable[Iterable[t.Any] | Mapping[str, t.Any]],
197
- columns: t.Optional[Iterable[str]] = None,
198
- features: t.Optional[Mapping] = None,
199
- tokenizer: t.Optional[TokenizerProtocol] = None,
186
+ data: Iterable[Iterable[Any] | Mapping[str, Any]],
187
+ columns: Sequence[str] | None = None,
188
+ features: Mapping[str, Any] | None = None,
189
+ tokenizer: TokenizerProtocol | None = None,
200
190
  ) -> pd.DataFrame:
201
191
  """
202
192
  Deserialize case data into a DataFrame.
@@ -208,7 +198,7 @@ class FeatureSerializer:
208
198
  ----------
209
199
  data : list of list or list of dict
210
200
  The context data.
211
- columns : Iterable of str, optional
201
+ columns : Sequence of str, optional
212
202
  The case column mapping. The order corresponds to the order of cases in output.
213
203
  `columns` must be provided for non-DataFrame Iterables.
214
204
 
@@ -235,8 +225,12 @@ class FeatureSerializer:
235
225
  return df
236
226
 
237
227
  @classmethod
238
- def format_dataframe(cls, df: pd.DataFrame, features: Mapping,
239
- tokenizer: t.Optional[TokenizerProtocol] = None) -> pd.DataFrame:
228
+ def format_dataframe(
229
+ cls,
230
+ df: pd.DataFrame,
231
+ features: Mapping[str, Any],
232
+ tokenizer: TokenizerProtocol | None = None,
233
+ ) -> pd.DataFrame:
240
234
  """
241
235
  Format DataFrame columns to original type using feature attributes.
242
236
 
@@ -271,8 +265,12 @@ class FeatureSerializer:
271
265
  return df
272
266
 
273
267
  @classmethod
274
- def format_column(cls, column: pd.Series, # noqa: C901
275
- feature: Mapping, tokenizer: t.Optional[TokenizerProtocol] = None) -> pd.Series:
268
+ def format_column( # noqa: PLR0911
269
+ cls,
270
+ column: pd.Series,
271
+ feature: Mapping[str, Any] | None,
272
+ tokenizer: TokenizerProtocol | None = None,
273
+ ) -> pd.Series:
276
274
  """
277
275
  Format column based on feature typing information.
278
276
 
@@ -298,30 +296,28 @@ class FeatureSerializer:
298
296
 
299
297
  if data_type == FeatureType.NUMERIC.value:
300
298
  return cls.format_numeric_column(column, feature)
301
- elif data_type == FeatureType.INTEGER.value:
299
+ if data_type == FeatureType.INTEGER.value:
302
300
  return cls.format_integer_column(column, feature)
303
- elif data_type == FeatureType.STRING.value:
301
+ if data_type == FeatureType.STRING.value:
304
302
  return cls.format_string_column(column, feature)
305
- elif data_type == FeatureType.TOKENIZABLE_STRING.value:
303
+ if data_type == FeatureType.TOKENIZABLE_STRING.value:
306
304
  return cls.format_tokenizable_string_column(column, feature, tokenizer=tokenizer)
307
- elif data_type == FeatureType.DATETIME.value:
305
+ if data_type == FeatureType.DATETIME.value:
308
306
  return cls.format_datetime_column(column, feature)
309
- elif data_type == FeatureType.DATE.value:
307
+ if data_type == FeatureType.DATE.value:
310
308
  return cls.format_date_column(column, feature)
311
- elif data_type == FeatureType.TIME.value:
309
+ if data_type == FeatureType.TIME.value:
312
310
  return cls.format_time_column(column, feature)
313
- elif data_type == FeatureType.TIMEDELTA.value:
311
+ if data_type == FeatureType.TIMEDELTA.value:
314
312
  return cls.format_timedelta_column(column, feature)
315
- elif data_type == FeatureType.BOOLEAN.value:
313
+ if data_type == FeatureType.BOOLEAN.value:
316
314
  return cls.format_boolean_column(column, feature)
317
- elif data_type == FeatureType.CONTAINER.value:
315
+ if data_type == FeatureType.CONTAINER.value:
318
316
  return cls.format_container_column(column, feature)
319
- else:
320
- return cls.format_unknown_column(column, feature)
317
+ return cls.format_unknown_column(column, feature)
321
318
 
322
319
  @classmethod
323
- def format_timedelta_column(cls, column: pd.Series, feature: Mapping
324
- ) -> pd.Series:
320
+ def format_timedelta_column(cls, column: pd.Series, feature: Mapping[str, Any]) -> pd.Series:
325
321
  """
326
322
  Format timedelta column.
327
323
 
@@ -339,27 +335,26 @@ class FeatureSerializer:
339
335
  """
340
336
  typing_info = cls._get_typing_info(feature)
341
337
  try:
342
- unit = typing_info['unit']
343
- if unit not in ['days', 'seconds', 'nanoseconds']:
344
- raise ValueError('invalid unit type')
338
+ unit = typing_info["unit"]
339
+ if unit not in ["days", "seconds", "nanoseconds"]:
340
+ raise ValueError("invalid unit type") # noqa: TRY301
345
341
  except (TypeError, KeyError, ValueError):
346
342
  warnings.warn(
347
- f'Unknown timedelta unit for column "{column.name}", '
348
- 'column will not be translated to a timedelta64.')
343
+ f'Unknown timedelta unit for column "{column.name}", column will not be translated to a timedelta64.'
344
+ )
349
345
  return column
350
346
 
351
347
  try:
352
348
  return pd.to_timedelta(column, unit=unit)
353
- except Exception: # noqa: Deliberately broad
349
+ except Exception: # noqa: BLE001
354
350
  warnings.warn(
355
351
  f'Timedelta column "{column.name}" failed to be parsed as '
356
- 'timedelta64 values, column will retain current dtype.'
352
+ "timedelta64 values, column will retain current dtype."
357
353
  )
358
354
  return column
359
355
 
360
356
  @classmethod
361
- def format_datetime_column(cls, column: pd.Series, feature: Mapping # noqa: C901
362
- ) -> pd.Series:
357
+ def format_datetime_column(cls, column: pd.Series, feature: Mapping[str, Any]) -> pd.Series:
363
358
  """
364
359
  Format datetime column.
365
360
 
@@ -376,30 +371,30 @@ class FeatureSerializer:
376
371
  The formatted column.
377
372
  """
378
373
  typing_info = cls._get_typing_info(feature)
379
- date_time_format = feature.get('date_time_format') or None
380
- date_locale = feature.get('locale') or None
374
+ date_time_format = feature.get("date_time_format") or None
375
+ date_locale = feature.get("locale") or None
381
376
  format_includes_timezone = False
382
- if (
383
- date_time_format and
384
- DATETIME_TIMEZONE_PATTERN.findall(date_time_format)
385
- ):
377
+ if date_time_format and DATETIME_TIMEZONE_PATTERN.findall(date_time_format):
386
378
  format_includes_timezone = True
387
379
 
388
380
  # Load timezone information if provided
389
- tz = typing_info.get('timezone')
381
+ tz = typing_info.get("timezone")
390
382
  if tz is not None:
391
383
  try:
392
384
  tz = ZoneInfo(tz)
393
385
  except KeyError:
394
386
  warnings.warn(
395
387
  f'Unknown timezone "{tz}" for feature "{column.name}", '
396
- 'datetime column may not contain original timezone '
397
- 'information.')
388
+ "datetime column may not contain original timezone "
389
+ "information."
390
+ )
398
391
  tz = None
399
392
 
400
- def _to_datetime():
393
+ def _to_datetime() -> pd.Series:
401
394
  # Format column to datetime
402
- target_format = to_pandas_datetime_format(date_time_format)
395
+ target_format = None
396
+ if date_time_format is not None:
397
+ target_format = to_pandas_datetime_format(date_time_format)
403
398
  if tz is not None:
404
399
  if format_includes_timezone:
405
400
  # When format string includes timezone we want to load
@@ -425,18 +420,20 @@ class FeatureSerializer:
425
420
  warnings.warn(
426
421
  f'Unable to parse column "{column.name}" as datetime64, the '
427
422
  f'locale "{date_locale}" of the datetime does not appear to be '
428
- 'available on this system. Column will retain current dtype. '
429
- 'Note: This feature may not work properly until this locale '
430
- 'is installed.')
431
- except Exception: # noqa: Deliberately broad
432
- warnings.warn(f'Unable to parse column "{column.name}" as '
433
- f'datetime64 using format "{date_time_format}". '
434
- 'Column will retain current dtype.')
423
+ "available on this system. Column will retain current dtype. "
424
+ "Note: This feature may not work properly until this locale "
425
+ "is installed."
426
+ )
427
+ except Exception: # noqa: BLE001
428
+ warnings.warn(
429
+ f'Unable to parse column "{column.name}" as '
430
+ f'datetime64 using format "{date_time_format}". '
431
+ "Column will retain current dtype."
432
+ )
435
433
  return column
436
434
 
437
435
  @classmethod
438
- def format_date_column(cls, column: pd.Series, feature: Mapping
439
- ) -> pd.Series:
436
+ def format_date_column(cls, column: pd.Series, feature: Mapping[str, Any]) -> pd.Series:
440
437
  """
441
438
  Format date only column.
442
439
 
@@ -452,9 +449,11 @@ class FeatureSerializer:
452
449
  pandas.Series
453
450
  The formatted column.
454
451
  """
455
- date_time_format = feature.get('date_time_format') or None
456
- date_locale = feature.get('locale') or None
457
- target_format = to_pandas_datetime_format(date_time_format)
452
+ date_time_format = feature.get("date_time_format") or None
453
+ date_locale = feature.get("locale") or None
454
+ target_format = None
455
+ if date_time_format is not None:
456
+ target_format = to_pandas_datetime_format(date_time_format)
458
457
  try:
459
458
  if date_locale:
460
459
  with LocaleOverride(date_locale, category=locale.LC_TIME):
@@ -465,18 +464,20 @@ class FeatureSerializer:
465
464
  warnings.warn(
466
465
  f'Unable to parse column "{column.name}" as datetime64, the '
467
466
  f'locale "{date_locale}" of the date does not appear to be '
468
- 'available on this system. Column will retain current dtype. '
469
- 'Note: This feature may not work properly until this locale '
470
- 'is installed.')
471
- except Exception: # noqa: Deliberately broad
472
- warnings.warn(f'Unable to parse column "{column.name}" as '
473
- f'datetime64 using format {date_time_format}. '
474
- 'Column will retain current dtype.')
467
+ "available on this system. Column will retain current dtype. "
468
+ "Note: This feature may not work properly until this locale "
469
+ "is installed."
470
+ )
471
+ except Exception: # noqa: BLE001
472
+ warnings.warn(
473
+ f'Unable to parse column "{column.name}" as '
474
+ f"datetime64 using format {date_time_format}. "
475
+ "Column will retain current dtype."
476
+ )
475
477
  return column
476
478
 
477
479
  @classmethod
478
- def format_time_column(cls, column: pd.Series, feature: Mapping # noqa: C901
479
- ) -> pd.Series:
480
+ def format_time_column(cls, column: pd.Series, feature: Mapping[str, Any]) -> pd.Series:
480
481
  """
481
482
  Format time only column.
482
483
 
@@ -493,29 +494,28 @@ class FeatureSerializer:
493
494
  The formatted column.
494
495
  """
495
496
  typing_info = cls._get_typing_info(feature)
496
- date_time_format = feature.get('date_time_format') or None
497
+ date_time_format = feature.get("date_time_format") or None
497
498
  if date_time_format:
498
499
  return cls.format_datetime_column(column, feature)
499
- else:
500
- # Time feature does not use a date_time_format, treat as seconds
501
- tz = None
502
- try:
503
- tz_name = typing_info['timezone']
504
- if tz_name is not None:
505
- try:
506
- tz = ZoneInfo(tz_name)
507
- except KeyError:
508
- warnings.warn(
509
- f'Unknown timezone defined for column "{column.name}", '
510
- 'column will not be timezone aware.')
511
- except (TypeError, KeyError):
512
- pass
513
500
 
514
- return column.apply(partial(seconds_to_time, tzinfo=tz))
501
+ # Time feature does not use a date_time_format, treat as seconds
502
+ tz = None
503
+ try:
504
+ tz_name = typing_info["timezone"]
505
+ if tz_name is not None:
506
+ try:
507
+ tz = ZoneInfo(tz_name)
508
+ except KeyError:
509
+ warnings.warn(
510
+ f'Unknown timezone defined for column "{column.name}", column will not be timezone aware.'
511
+ )
512
+ except (TypeError, KeyError):
513
+ pass
514
+
515
+ return column.apply(partial(seconds_to_time, tzinfo=tz))
515
516
 
516
517
  @classmethod
517
- def format_boolean_column(cls, column: pd.Series, feature: Mapping
518
- ) -> pd.Series:
518
+ def format_boolean_column(cls, column: pd.Series, feature: Mapping[str, Any]) -> pd.Series: # noqa: ARG003
519
519
  """
520
520
  Format boolean column.
521
521
 
@@ -532,20 +532,21 @@ class FeatureSerializer:
532
532
  The formatted column.
533
533
  """
534
534
  try:
535
- def _apply_bool(value):
535
+
536
+ def _apply_bool(value: Any) -> bool | None:
537
+ if pd.isna(value):
538
+ return value
536
539
  if isinstance(value, str):
537
540
  return value.lower() in ["true", "yes", "on", "(true)"]
538
541
  return bool(value)
539
542
 
540
543
  return column.apply(_apply_bool)
541
- except Exception: # noqa: Deliberately broad
542
- warnings.warn(f'Unable to parse column "{column.name}" as '
543
- f'boolean. Column will retain current dtype.')
544
+ except Exception: # noqa: BLE001
545
+ warnings.warn(f'Unable to parse column "{column.name}" as boolean. Column will retain current dtype.')
544
546
  return column
545
547
 
546
548
  @classmethod
547
- def format_integer_column(cls, column: pd.Series, feature: Mapping
548
- ) -> pd.Series:
549
+ def format_integer_column(cls, column: pd.Series, feature: Mapping[str, Any]) -> pd.Series:
549
550
  """
550
551
  Format integer column.
551
552
 
@@ -563,42 +564,45 @@ class FeatureSerializer:
563
564
  """
564
565
  typing_info = cls._get_typing_info(feature)
565
566
 
566
- has_nulls = column.isnull().any()
567
+ has_nulls = column.isna().any()
567
568
  if has_nulls:
568
569
  # Use pandas extension type for nullable integer
569
- type_name = 'Int'
570
+ type_name = "Int"
570
571
  else:
571
- type_name = 'int'
572
+ type_name = "int"
572
573
 
573
- size = typing_info.get('size')
574
+ size = typing_info.get("size")
574
575
  if size in [1, 2, 4, 8]:
575
- type_name = f'{type_name}{size * 8}'
576
- unsigned = typing_info.get('unsigned')
576
+ type_name = f"{type_name}{size * 8}"
577
+ unsigned = typing_info.get("unsigned")
577
578
  if unsigned:
578
- type_name = f'U{type_name}' if has_nulls else f'u{type_name}'
579
+ type_name = f"U{type_name}" if has_nulls else f"u{type_name}"
579
580
 
580
581
  # unique or int-id features are output as 64bit ints, leave them
581
582
  # as-is if original datatype is less than 64 bits
582
- if size < 8 and (getattr(feature, 'unique', False) or
583
- getattr(feature, 'subtype', None) == 'int-id'):
584
- warnings.warn(f'Unable to restore column "{column.name}" as '
585
- f'{type_name}. Column will retain current dtype.')
583
+ if (
584
+ size is not None
585
+ and size < 8
586
+ and (getattr(feature, "unique", False) or getattr(feature, "subtype", None) == "int-id")
587
+ ):
588
+ warnings.warn(
589
+ f'Unable to restore column "{column.name}" as {type_name}. Column will retain current dtype.'
590
+ )
586
591
  return column
587
592
 
588
593
  try:
589
594
  # We use floor and to_numeric here to handle cases where the value
590
595
  # may be a string of float like values, so we get the column as a
591
596
  # generic number first, remove the decimal places and then set the
592
- # type to the expected format
593
- return np.floor(pd.to_numeric(column)).astype(type_name)
594
- except Exception: # noqa: Deliberately broad
595
- warnings.warn(f'Unable to parse column "{column.name}" as '
596
- f'{type_name}. Column will retain current dtype.')
597
+ # type to the expected format (np.floor will actually return a
598
+ # pandas series when given one, but the type hint only shows ndarray)
599
+ return cast(pd.Series, np.floor(pd.to_numeric(column)).astype(cast(np.dtype, type_name)))
600
+ except Exception: # noqa: BLE001
601
+ warnings.warn(f'Unable to parse column "{column.name}" as {type_name}. Column will retain current dtype.')
597
602
  return column
598
603
 
599
604
  @classmethod
600
- def format_numeric_column(cls, column: pd.Series, feature: Mapping
601
- ) -> pd.Series:
605
+ def format_numeric_column(cls, column: pd.Series, feature: Mapping[str, Any]) -> pd.Series:
602
606
  """
603
607
  Format numeric column.
604
608
 
@@ -615,41 +619,40 @@ class FeatureSerializer:
615
619
  The formatted column.
616
620
  """
617
621
  typing_info = cls._get_typing_info(feature)
618
- number_format = typing_info.get('format')
619
- type_name = 'float'
622
+ number_format = typing_info.get("format")
623
+ type_name = "float"
620
624
 
621
625
  try:
622
- if number_format == 'decimal':
623
- type_name = 'Decimal'
626
+ if number_format == "decimal":
627
+ type_name = "Decimal"
624
628
  # Note: We cast to string first here in attempt to prevent
625
629
  # floating point errors.
626
- return column.apply(lambda x: decimal.Decimal(
627
- str(x)) if x is not None else None)
630
+ return column.apply(lambda x: decimal.Decimal(str(x)) if x is not None else None)
628
631
  else:
629
- type_name = 'float'
630
- size = typing_info.get('size')
632
+ type_name = "float"
633
+ size = typing_info.get("size")
631
634
  if size in [1, 2, 4, 8, 16]:
632
- type_name = f'{type_name}{size * 8}'
635
+ type_name = f"{type_name}{size * 8}"
633
636
 
634
637
  # unique or int-id features are output as 64bit ints, leave them
635
638
  # as-is if original datatype is less than 64 bits
636
- if size < 8 and (getattr(feature, 'unique', False) or
637
- getattr(feature, 'subtype', None) == 'int-id'):
639
+ if (
640
+ size is not None
641
+ and size < 8
642
+ and (getattr(feature, "unique", False) or getattr(feature, "subtype", None) == "int-id")
643
+ ):
638
644
  warnings.warn(
639
- f'Unable to restore column "{column.name}" as '
640
- f'{type_name}. Column will retain current dtype.'
645
+ f'Unable to restore column "{column.name}" as {type_name}. Column will retain current dtype.'
641
646
  )
642
647
  return column
643
648
 
644
- return column.astype(type_name)
645
- except Exception: # noqa: Deliberately broad
646
- warnings.warn(f'Unable to parse column "{column.name}" as '
647
- f'{type_name}. Column will retain current dtype.')
649
+ return column.astype(cast(np.dtype, type_name))
650
+ except Exception: # noqa: BLE001
651
+ warnings.warn(f'Unable to parse column "{column.name}" as {type_name}. Column will retain current dtype.')
648
652
  return column
649
653
 
650
654
  @classmethod
651
- def format_string_column(cls, column: pd.Series, feature: Mapping
652
- ) -> pd.Series:
655
+ def format_string_column(cls, column: pd.Series, feature: Mapping[str, Any]) -> pd.Series: # noqa: ARG003
653
656
  """
654
657
  Format string column.
655
658
 
@@ -669,8 +672,12 @@ class FeatureSerializer:
669
672
  return column
670
673
 
671
674
  @classmethod
672
- def format_tokenizable_string_column(cls, column: pd.Series, feature: Mapping,
673
- tokenizer: t.Optional[TokenizerProtocol]) -> pd.Series:
675
+ def format_tokenizable_string_column(
676
+ cls,
677
+ column: pd.Series,
678
+ feature: Mapping[str, Any], # noqa: ARG003
679
+ tokenizer: TokenizerProtocol | None = None,
680
+ ) -> pd.Series:
674
681
  """
675
682
  Format tokenizable string column.
676
683
 
@@ -694,8 +701,7 @@ class FeatureSerializer:
694
701
  return pd.Series(tokenizer.detokenize(json.loads(case)) for case in column)
695
702
 
696
703
  @classmethod
697
- def format_unknown_column(cls, column: pd.Series, feature: Mapping
698
- ) -> pd.Series:
704
+ def format_unknown_column(cls, column: pd.Series, feature: Mapping[str, Any]) -> pd.Series: # noqa: ARG003
699
705
  """
700
706
  Format unknown typed column.
701
707
 
@@ -715,7 +721,7 @@ class FeatureSerializer:
715
721
  return column
716
722
 
717
723
  @classmethod
718
- def format_container_column(cls, column: pd.Series, feature: Mapping) -> pd.Series:
724
+ def format_container_column(cls, column: pd.Series, feature: Mapping[str, Any]) -> pd.Series:
719
725
  """
720
726
  Format a container column (a Python Mapping/Sequence).
721
727
 
@@ -734,7 +740,7 @@ class FeatureSerializer:
734
740
  return destringify_json(column, feature)
735
741
 
736
742
  @staticmethod
737
- def _get_typing_info(feature: t.Optional[Mapping]) -> dict:
743
+ def _get_typing_info(feature: Mapping[str, Any] | None) -> dict:
738
744
  """
739
745
  Get typing info from feature attributes.
740
746
 
@@ -748,11 +754,13 @@ class FeatureSerializer:
748
754
  dict
749
755
  The typing info for the feature. Or empty dict if none found.
750
756
  """
757
+ if feature is None:
758
+ return {}
751
759
  try:
752
- typing_info = feature['original_type']
760
+ typing_info = feature["original_type"]
753
761
  except (TypeError, KeyError):
754
- return dict()
755
- return typing_info or dict()
762
+ return {}
763
+ return typing_info or {}
756
764
 
757
765
 
758
766
  serialize_cases = FeatureSerializer.serialize
@@ -1,4 +1,4 @@
1
- from typing import Protocol, runtime_checkable
1
+ from typing import Any, Protocol, runtime_checkable
2
2
 
3
3
  from sacremoses import MosesDetokenizer, MosesTokenizer
4
4
 
@@ -9,11 +9,11 @@ class TokenizerProtocol(Protocol):
9
9
 
10
10
  def tokenize(self, text: str, **kwargs) -> list[str]:
11
11
  """Tokenize a string."""
12
- pass
12
+ ...
13
13
 
14
14
  def detokenize(self, tokens: list[str], **kwargs) -> str:
15
15
  """Detokenize a list of tokens into a string."""
16
- pass
16
+ ...
17
17
 
18
18
 
19
19
  class HowsoTokenizer:
@@ -25,7 +25,7 @@ class HowsoTokenizer:
25
25
  self._mt = MosesTokenizer(lang=self.lang)
26
26
  self._md = MosesDetokenizer(lang=self.lang)
27
27
 
28
- def tokenize(self, text: str) -> list[str]:
28
+ def tokenize(self, text: str, **kwargs: Any) -> list[str]:
29
29
  """
30
30
  Tokenizes a string into a list of strings.
31
31
 
@@ -41,7 +41,7 @@ class HowsoTokenizer:
41
41
  """
42
42
  return self._mt.tokenize(text)
43
43
 
44
- def detokenize(self, tokens: list[str]) -> str:
44
+ def detokenize(self, tokens: list[str], **kwargs: Any) -> str:
45
45
  """
46
46
  Detokenizes a list of strings into a string.
47
47
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: howso-engine
3
- Version: 60.3.1
3
+ Version: 60.3.2
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
@@ -0,0 +1,5 @@
1
+ {
2
+ "dependencies": {
3
+ "howso-engine": "115.4.2"
4
+ }
5
+ }
@@ -1,5 +0,0 @@
1
- {
2
- "dependencies": {
3
- "howso-engine": "115.4.1"
4
- }
5
- }
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