workbench 0.8.184__py3-none-any.whl → 0.8.185__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of workbench might be problematic. Click here for more details.

@@ -475,17 +475,20 @@ class EndpointCore(Artifact):
475
475
  training_df = fs.view("training").pull_dataframe()
476
476
 
477
477
  # Run inference on the endpoint to get UQ outputs
478
- full_inference_df = self.inference(training_df)
478
+ uq_df = self.inference(training_df)
479
479
 
480
480
  # Identify UQ-specific columns (quantiles and prediction_std)
481
- uq_columns = [col for col in full_inference_df.columns if col.startswith("q_") or col == "prediction_std"]
481
+ uq_columns = [col for col in uq_df.columns if col.startswith("q_") or col == "prediction_std"]
482
482
 
483
483
  # Merge UQ columns with out-of-fold predictions
484
484
  if uq_columns:
485
- # Keep id_column and UQ columns, drop 'prediction' to avoid conflict
486
- merge_columns = [id_column] + uq_columns
487
- uq_df = full_inference_df[merge_columns]
485
+ # Keep id_column and UQ columns, drop 'prediction' to avoid conflict when merging
486
+ uq_df = uq_df[[id_column] + uq_columns]
488
487
 
488
+ # Drop duplicates in uq_df based on id_column
489
+ uq_df = uq_df.drop_duplicates(subset=[id_column])
490
+
491
+ # Merge UQ columns into out_of_fold_df
489
492
  out_of_fold_df = pd.merge(out_of_fold_df, uq_df, on=id_column, how="left")
490
493
  additional_columns = uq_columns
491
494
  self.log.info(f"Added UQ columns: {', '.join(additional_columns)}")
@@ -327,9 +327,36 @@ class PandasToFeatures(Transform):
327
327
  self.delete_existing()
328
328
  self.output_feature_group = self.create_feature_group()
329
329
 
330
+ def mac_spawn_hack(self):
331
+ """Workaround for macOS Tahoe fork/spawn issue with SageMaker FeatureStore ingest.
332
+
333
+ See: https://github.com/aws/sagemaker-python-sdk/issues/5312
334
+ macOS Tahoe 26+ has issues with forked processes creating boto3 sessions.
335
+ This forces spawn mode on macOS to avoid the hang.
336
+ """
337
+ import platform
338
+
339
+ if platform.system() == "Darwin": # macOS
340
+ self.log.warning("macOS detected, forcing 'spawn' mode for multiprocessing (Tahoe hang workaround)")
341
+ import multiprocessing
342
+
343
+ try:
344
+ import multiprocess
345
+
346
+ multiprocess.set_start_method("spawn", force=True)
347
+ except (RuntimeError, ImportError):
348
+ pass # Already set or multiprocess not available
349
+ try:
350
+ multiprocessing.set_start_method("spawn", force=True)
351
+ except RuntimeError:
352
+ pass # Already set
353
+
330
354
  def transform_impl(self):
331
355
  """Transform Implementation: Ingest the data into the Feature Group"""
332
356
 
357
+ # Workaround for macOS Tahoe hang issue
358
+ self.mac_spawn_hack()
359
+
333
360
  # Now we actually push the data into the Feature Group (called ingestion)
334
361
  self.log.important(f"Ingesting rows into Feature Group {self.output_name}...")
335
362
  ingest_manager = self.output_feature_group.ingest(self.output_df, max_workers=8, max_processes=4, wait=False)
@@ -19,7 +19,7 @@ from typing import List, Tuple
19
19
  # Template Placeholders
20
20
  TEMPLATE_PARAMS = {
21
21
  "target": "udm_asy_res_free_percent",
22
- "features": ['naromatom', 'fr_nh2', 'mollogp', 'numheterocycles', 'bcut2d_mrhi', 'numaromaticrings', 'smr_vsa7', 'peoe_vsa4', 'slogp_vsa6', 'peoe_vsa8', 'vsa_estate3', 'maxabspartialcharge', 'fr_arn', 'bcut2d_logplow', 'chi1v', 'axp_6d', 'bcut2d_chglo', 'balabanj', 'slogp_vsa10', 'hallkieralpha', 'vsa_estate6', 'fpdensitymorgan1', 'sps', 'qed', 'peoe_vsa7', 'maxestateindex', 'estate_vsa8', 'vsa_estate9', 'fr_nhpyrrole', 'mz', 'mp', 'bcut2d_mwhi', 'peoe_vsa13', 'c2sp2', 'numrotatablebonds', 'kappa3', 'peoe_vsa1', 'slogp_vsa2', 'xc_5dv', 'bertzct', 'estate_vsa10', 'axp_0d', 'estate_vsa2', 'xc_4d', 'smr_vsa1', 'phi', 'estate_vsa3', 'vsa_estate2', 'mv', 'estate_vsa4', 'mm', 'fr_nh1', 'slogp_vsa7', 'chi4n', 'estate_vsa6', 'fpdensitymorgan2', 'molmr', 'mse', 'bcut2d_mwlow', 'bcut2d_mrlow', 'chi2v', 'minestateindex', 'xpc_4dv', 'fr_nh0', 'axp_2d', 'vsa_estate8', 'nhohcount', 'smr_vsa6', 'peoe_vsa9', 'smr_vsa5', 'num_r_centers', 'xpc_6dv', 'xc_3d', 'slogp_vsa5', 'axp_7dv', 'minabsestateindex', 'xc_5d', 'vsa_estate10', 'fr_hoccn', 'smr_vsa3', 'vsa_estate1', 'axp_5d', 'num_s_centers', 'axp_1d', 'estate_vsa1', 'fpdensitymorgan3', 'axp_5dv', 'chi3n', 'peoe_vsa6', 'labuteasa', 'chi2n', 'xc_6d', 'xp_7d', 'tpsa', 'xpc_4d', 'avgipc', 'xp_5d', 'vsa_estate5', 'xch_7d', 'xch_5d', 'axp_4dv', 'nbase', 'xc_3dv', 'kappa2', 'axp_3d', 'c1sp3', 'numhacceptors', 'bcut2d_logphi', 'smr_vsa10', 'fr_piperzine', 'peoe_vsa11', 'axp_6dv', 'peoe_vsa10', 'estate_vsa9', 'bcut2d_chghi', 'xp_6d', 'xch_6dv', 'chi0', 'vsa_estate7', 'mi', 'xpc_5d', 'fractioncsp3', 'xp_0dv', 'kappa1', 'minpartialcharge', 'xp_6dv', 'peoe_vsa2', 'chi3v', 'axp_0dv', 'mare', 'xch_5dv', 'vsa_estate4', 'xp_4dv', 'estate_vsa7', 'xp_3d', 'numaliphaticheterocycles', 'chi1', 'xp_3dv', 'fr_ether', 'xch_6d', 'peoe_vsa12', 'xch_7dv', 'axp_1dv', 'axp_7d', 'fr_ndealkylation2', 'smr_vsa9', 'axp_2dv', 'estate_vsa5', 'mpe', 'molwt', 'xch_4d', 'axp_3dv', 'xp_5dv', 'chi4v', 'heavyatommolwt', 'fr_al_oh', 'xpc_5dv', 'xpc_6d', 'maxpartialcharge', 'numatomstereocenters', 'peoe_vsa3', 'fr_aniline', 'minabspartialcharge', 'c3sp3', 'slogp_vsa1', 'exactmolwt', 'chi1n', 'xp_7dv', 'chi0n', 'xp_2d', 'xch_4dv', 'fr_bicyclic', 'xc_4dv', 'axp_4d', 'slogp_vsa4', 'fr_benzene', 'numaromaticheterocycles', 'fr_aryl_methyl', 'fr_pyridine', 'fr_imine', 'chi0v', 'slogp_vsa12'],
22
+ "features": ['naromatom', 'minabspartialcharge', 'bcut2d_mrhi', 'smr_vsa10', 'vsa_estate2', 'minpartialcharge', 'xpc_5d', 'sps', 'xc_3dv', 'smr_vsa7', 'bcut2d_logplow', 'mollogp', 'vsa_estate1', 'num_s_centers', 'vsa_estate4', 'peoe_vsa13', 'fr_nh2', 'bertzct', 'estate_vsa4', 'vsa_estate9', 'smr_vsa3', 'fr_nh1', 'molwt', 'estate_vsa5', 'slogp_vsa5', 'maxpartialcharge', 'estate_vsa1', 'fr_hoccn', 'xc_5d', 'nbase', 'chi1v', 'peoe_vsa10', 'tpsa', 'vsa_estate3', 'chi2v', 'estate_vsa8', 'numheteroatoms', 'estate_vsa2', 'peoe_vsa1', 'labuteasa', 'axp_4d', 'xch_7dv', 'chi0n', 'num_r_centers', 'vsa_estate8', 'minabsestateindex', 'bcut2d_chglo', 'bcut2d_mwhi', 'fr_nh0', 'chi4n', 'estate_vsa9', 'smr_vsa5', 'peoe_vsa2', 'peoe_vsa7', 'peoe_vsa9', 'kappa3', 'slogp_vsa3', 'fr_arn', 'estate_vsa3', 'avgipc', 'axp_5d', 'xpc_6d', 'c2sp2', 'peoe_vsa5', 'vsa_estate5', 'balabanj', 'maxabspartialcharge', 'fr_aniline', 'fr_piperdine', 'vsa_estate6', 'bcut2d_mwlow', 'numsaturatedheterocycles', 'vsa_estate10', 'smr_vsa1', 'estate_vsa6', 'smr_vsa6', 'fpdensitymorgan1', 'peoe_vsa3', 'peoe_vsa8', 'smr_vsa9', 'slogp_vsa2', 'nocount', 'fpdensitymorgan3', 'axp_6d', 'bcut2d_mrlow', 'bcut2d_logphi', 'axp_4dv', 'fpdensitymorgan2', 'mp', 'xp_5d', 'fr_nhpyrrole', 'mz', 'mv', 'vsa_estate7', 'axp_7dv', 'mi', 'c1sp2', 'xpc_6dv', 'slogp_vsa10', 'xp_7d', 'axp_3dv', 'peoe_vsa4', 'peoe_vsa6', 'axp_2dv', 'xch_5dv', 'qed', 'estate_vsa7', 'numaromaticrings', 'chi1n', 'axp_0d', 'axp_6dv', 'numrotatablebonds', 'hallkieralpha', 'c1sp3', 'xc_4dv', 'kappa2', 'bcut2d_chghi', 'xch_7d', 'axp_0dv', 'slogp_vsa7', 'axp_7d', 'minestateindex', 'axp_2d', 'axp_1d', 'chi0', 'fractioncsp3', 'slogp_vsa6', 'axp_1dv', 'chi2n', 'xp_6dv', 'maxestateindex', 'xpc_4d', 'numaliphaticheterocycles', 'chi1', 'phi', 'chi3n', 'xc_4d', 'xc_3d', 'peoe_vsa12', 'xp_6d', 'chi3v', 'axp_3d', 'axp_5dv', 'fr_benzene', 'slogp_vsa4', 'fr_pyridine', 'fr_aryl_methyl', 'xp_5dv', 'c3sp3', 'xp_7dv', 'slogp_vsa1', 'peoe_vsa11', 'mse', 'xc_5dv', 'xpc_5dv', 'xc_6dv', 'xp_0dv', 'xch_5d', 'c3sp2', 'numatomstereocenters', 'numhacceptors', 'fr_imidazole', 'numsaturatedrings', 'xpc_4dv', 'chi0v', 'numheterocycles', 'xch_6dv', 'estate_vsa10', 'chi4v', 'mare', 'numhdonors', 'xch_6d', 'xp_4d', 'fr_ar_n', 'numunspecifiedatomstereocenters', 'numspiroatoms', 'xch_4dv', 'fr_morpholine', 'fr_methoxy', 'mm', 'fr_piperzine'],
23
23
  "compressed_features": [],
24
24
  "train_all_data": True,
25
25
  "hyperparameters": {},
@@ -386,6 +386,106 @@ def cross_fold_inference(workbench_model: Any, nfolds: int = 5) -> Tuple[Dict[st
386
386
  return metrics_dict, predictions_df
387
387
 
388
388
 
389
+ def leave_one_out_inference(workbench_model: Any) -> pd.DataFrame:
390
+ """
391
+ Performs leave-one-out cross-validation (parallelized).
392
+ For datasets > 1000 rows, first identifies top 100 worst predictions via 10-fold CV,
393
+ then performs true leave-one-out on those 100 samples.
394
+ Each model trains on ALL data except one sample.
395
+ """
396
+ from workbench.api import FeatureSet
397
+ from joblib import Parallel, delayed
398
+ from tqdm import tqdm
399
+
400
+ def train_and_predict_one(model_params, is_classifier, X, y, train_idx, val_idx):
401
+ """Train on train_idx, predict on val_idx."""
402
+ model = xgb.XGBClassifier(**model_params) if is_classifier else xgb.XGBRegressor(**model_params)
403
+ model.fit(X[train_idx], y[train_idx])
404
+ return model.predict(X[val_idx])[0]
405
+
406
+ # Load model and get params
407
+ model_artifact_uri = workbench_model.model_data_url()
408
+ loaded_model = xgboost_model_from_s3(model_artifact_uri)
409
+ if loaded_model is None:
410
+ log.error("No XGBoost model found in the artifact.")
411
+ return pd.DataFrame()
412
+
413
+ if isinstance(loaded_model, (xgb.XGBClassifier, xgb.XGBRegressor)):
414
+ is_classifier = isinstance(loaded_model, xgb.XGBClassifier)
415
+ model_params = loaded_model.get_params()
416
+ elif isinstance(loaded_model, xgb.Booster):
417
+ log.warning("Deprecated: Loaded model is a Booster, wrapping in sklearn model.")
418
+ is_classifier = workbench_model.model_type.value == "classifier"
419
+ model_params = {"enable_categorical": True}
420
+ else:
421
+ log.error(f"Unexpected model type: {type(loaded_model)}")
422
+ return pd.DataFrame()
423
+
424
+ # Load and prepare data
425
+ fs = FeatureSet(workbench_model.get_input())
426
+ df = fs.view("training").pull_dataframe()
427
+ id_col = fs.id_column
428
+ target_col = workbench_model.target()
429
+ feature_cols = workbench_model.features()
430
+
431
+ # Convert string features to categorical
432
+ for col in feature_cols:
433
+ if df[col].dtype in ["object", "string"]:
434
+ df[col] = df[col].astype("category")
435
+
436
+ # Determine which samples to run LOO on
437
+ if len(df) > 1000:
438
+ log.important(f"Dataset has {len(df)} rows. Running 10-fold CV to identify top 1000 worst predictions...")
439
+ _, predictions_df = cross_fold_inference(workbench_model, nfolds=10)
440
+ predictions_df["residual_abs"] = np.abs(predictions_df[target_col] - predictions_df["prediction"])
441
+ worst_samples = predictions_df.nlargest(1000, "residual_abs")
442
+ worst_ids = worst_samples[id_col].values
443
+ loo_indices = df[df[id_col].isin(worst_ids)].index.values
444
+ log.important(f"Running leave-one-out CV on 1000 worst samples. Each model trains on {len(df)-1} rows...")
445
+ else:
446
+ log.important(f"Running leave-one-out CV on all {len(df)} samples...")
447
+ loo_indices = df.index.values
448
+
449
+ # Prepare full dataset for training
450
+ X_full = df[feature_cols].values
451
+ y_full = df[target_col].values
452
+
453
+ # Encode target if classifier
454
+ label_encoder = LabelEncoder() if is_classifier else None
455
+ if label_encoder:
456
+ y_full = label_encoder.fit_transform(y_full)
457
+
458
+ # Generate LOO splits
459
+ splits = []
460
+ for loo_idx in loo_indices:
461
+ train_idx = np.delete(np.arange(len(X_full)), loo_idx)
462
+ val_idx = np.array([loo_idx])
463
+ splits.append((train_idx, val_idx))
464
+
465
+ # Parallel execution
466
+ predictions = Parallel(n_jobs=4)(
467
+ delayed(train_and_predict_one)(model_params, is_classifier, X_full, y_full, train_idx, val_idx)
468
+ for train_idx, val_idx in tqdm(splits, desc="LOO CV")
469
+ )
470
+
471
+ # Build results dataframe
472
+ predictions_array = np.array(predictions)
473
+ if label_encoder:
474
+ predictions_array = label_encoder.inverse_transform(predictions_array.astype(int))
475
+
476
+ predictions_df = pd.DataFrame(
477
+ {
478
+ id_col: df.loc[loo_indices, id_col].values,
479
+ target_col: df.loc[loo_indices, target_col].values,
480
+ "prediction": predictions_array,
481
+ }
482
+ )
483
+
484
+ predictions_df["residual_abs"] = np.abs(predictions_df[target_col] - predictions_df["prediction"])
485
+
486
+ return predictions_df
487
+
488
+
389
489
  if __name__ == "__main__":
390
490
  """Exercise the Model Utilities"""
391
491
  from workbench.api import Model, FeatureSet
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: workbench
3
- Version: 0.8.184
3
+ Version: 0.8.185
4
4
  Summary: Workbench: A Dashboard and Python API for creating and deploying AWS SageMaker Model Pipelines
5
5
  Author-email: SuperCowPowers LLC <support@supercowpowers.com>
6
6
  License-Expression: MIT
@@ -54,7 +54,7 @@ workbench/core/artifacts/cached_artifact_mixin.py,sha256=ngqFLZ4cQx_TFouXZgXZQsv
54
54
  workbench/core/artifacts/data_capture_core.py,sha256=q8f79rRTYiZ7T4IQRWXl8ZvPpcvZyNxYERwvo8o0OQc,14858
55
55
  workbench/core/artifacts/data_source_abstract.py,sha256=5IRCzFVK-17cd4NXPMRfx99vQAmQ0WHE5jcm5RfsVTg,10619
56
56
  workbench/core/artifacts/data_source_factory.py,sha256=YL_tA5fsgubbB3dPF6T4tO0rGgz-6oo3ge4i_YXVC-M,2380
57
- workbench/core/artifacts/endpoint_core.py,sha256=b3cNj1UnlHmQdG1C8bmD2jWpD4h-O6F-75fWSm01uGU,51850
57
+ workbench/core/artifacts/endpoint_core.py,sha256=gQdOHtjEeC1WCHbKZNaDQ0eeOka1sCO-zcABDO4_Egk,51965
58
58
  workbench/core/artifacts/feature_set_core.py,sha256=7b1o_PzxtwaYC-W2zxlkltiO0fYULA8CVGWwHNmqgtI,31457
59
59
  workbench/core/artifacts/model_core.py,sha256=wjoa2GQnzrrTM-E2VgYZHT9Ixebl3LaKbJL0YvEdrJY,51546
60
60
  workbench/core/artifacts/monitor_core.py,sha256=M307yz7tEzOEHgv-LmtVy9jKjSbM98fHW3ckmNYrwlU,27897
@@ -109,7 +109,7 @@ workbench/core/transforms/pandas_transforms/__init__.py,sha256=xL4MT8-fZ1SFqDbTL
109
109
  workbench/core/transforms/pandas_transforms/data_to_pandas.py,sha256=sJHPeuNF8Q8aQqgRnkdWkyvur5cbggdUVIwR-xF3Dlo,3621
110
110
  workbench/core/transforms/pandas_transforms/features_to_pandas.py,sha256=af6xdPt2V4zhh-SzQa_UYxdmNMzMLXbrbsznV5QoIJg,3441
111
111
  workbench/core/transforms/pandas_transforms/pandas_to_data.py,sha256=cqo6hQmzUGUFACvNuVLZQdgrlXrQIu4NjqK-ujPmoIc,9181
112
- workbench/core/transforms/pandas_transforms/pandas_to_features.py,sha256=XiUz2BqOX4N34g6hvFvcLswhkEouyU0AjyIy9EGv2zg,20440
112
+ workbench/core/transforms/pandas_transforms/pandas_to_features.py,sha256=mj00L40PXhw-JHG2SZe53yJAzicgn4xuM2VbmOY-wsM,21480
113
113
  workbench/core/transforms/pandas_transforms/pandas_to_features_chunked.py,sha256=0R8mQlWfbIlTVmYUmrtu2gsw0AE815k6kqPgpd0bmyQ,4422
114
114
  workbench/core/views/__init__.py,sha256=UZJMAJBCMVM3uSYmnFg8c2LWtdu9-479WNAdVMIohAc,962
115
115
  workbench/core/views/column_subset_view.py,sha256=vGDKTTGrPIY-IFOeWvudJrhKiq0OjWDp5rTuuj-X40U,4261
@@ -156,7 +156,7 @@ workbench/model_scripts/pytorch_model/requirements.txt,sha256=ICS5nW0wix44EJO2tJ
156
156
  workbench/model_scripts/scikit_learn/generated_model_script.py,sha256=c73ZpJBlU5k13Nx-ZDkLXu7da40CYyhwjwwmuPq6uLg,12870
157
157
  workbench/model_scripts/scikit_learn/requirements.txt,sha256=aVvwiJ3LgBUhM_PyFlb2gHXu_kpGPho3ANBzlOkfcvs,107
158
158
  workbench/model_scripts/scikit_learn/scikit_learn.template,sha256=QQvqx-eX9ZTbYmyupq6R6vIQwosmsmY_MRBPaHyfjdk,12586
159
- workbench/model_scripts/uq_models/generated_model_script.py,sha256=OS_ufhyLR9IQcyRV2ukO_CfDnjp60UE9kwcAN4RY0Is,21191
159
+ workbench/model_scripts/uq_models/generated_model_script.py,sha256=gJb_5jBb4mcf41jb6578H9uYYH6Y-uFtPp1MNKXNFQQ,21231
160
160
  workbench/model_scripts/uq_models/mapie.template,sha256=8VzoP-Wp3ECVIDqXVkiTS6bwmn3cd3dDZ2WjYPzXTi8,18955
161
161
  workbench/model_scripts/uq_models/requirements.txt,sha256=fw7T7t_YJAXK3T6Ysbesxh_Agx_tv0oYx72cEBTqRDY,98
162
162
  workbench/model_scripts/xgb_model/generated_model_script.py,sha256=Tbn7EMXxZZO8rDdKQ5fYCbpltACsMXNvuusLL9p-U5c,22319
@@ -242,7 +242,7 @@ workbench/utils/workbench_cache.py,sha256=IQchxB81iR4eVggHBxUJdXxUCRkqWz1jKe5gxN
242
242
  workbench/utils/workbench_event_bridge.py,sha256=z1GmXOB-Qs7VOgC6Hjnp2DI9nSEWepaSXejACxTIR7o,4150
243
243
  workbench/utils/workbench_logging.py,sha256=WCuMWhQwibrvcGAyj96h2wowh6dH7zNlDJ7sWUzdCeI,10263
244
244
  workbench/utils/workbench_sqs.py,sha256=RwM80z7YWwdtMaCKh7KWF8v38f7eBRU7kyC7ZhTRuI0,2072
245
- workbench/utils/xgboost_model_utils.py,sha256=wSUrs9VlftaTZ-cWZMEeHY6TmcLvxwrKk4S4lr7kWWw,17482
245
+ workbench/utils/xgboost_model_utils.py,sha256=rPfbl5sCZOttkilAHSmYU_u9JIDeYsGi2JrEs-zzcwI,21597
246
246
  workbench/utils/chem_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
247
247
  workbench/utils/chem_utils/fingerprints.py,sha256=Qvs8jaUwguWUq3Q3j695MY0t0Wk3BvroW-oWBwalMUo,5255
248
248
  workbench/utils/chem_utils/misc.py,sha256=Nevf8_opu-uIPrv_1_0ubuFVVo2_fGUkMoLAHB3XAeo,7372
@@ -287,9 +287,9 @@ workbench/web_interface/page_views/main_page.py,sha256=X4-KyGTKLAdxR-Zk2niuLJB2Y
287
287
  workbench/web_interface/page_views/models_page_view.py,sha256=M0bdC7bAzLyIaE2jviY12FF4abdMFZmg6sFuOY_LaGI,2650
288
288
  workbench/web_interface/page_views/page_view.py,sha256=Gh6YnpOGlUejx-bHZAf5pzqoQ1H1R0OSwOpGhOBO06w,455
289
289
  workbench/web_interface/page_views/pipelines_page_view.py,sha256=v2pxrIbsHBcYiblfius3JK766NZ7ciD2yPx0t3E5IJo,2656
290
- workbench-0.8.184.dist-info/licenses/LICENSE,sha256=z4QMMPlLJkZjU8VOKqJkZiQZCEZ--saIU2Z8-p3aVc0,1080
291
- workbench-0.8.184.dist-info/METADATA,sha256=3B5uP_y9cOctNaxDK6Z9Fwfcwzf7p9f3HyjJ35B-nqY,9210
292
- workbench-0.8.184.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
293
- workbench-0.8.184.dist-info/entry_points.txt,sha256=zPFPruY9uayk8-wsKrhfnIyIB6jvZOW_ibyllEIsLWo,356
294
- workbench-0.8.184.dist-info/top_level.txt,sha256=Dhy72zTxaA_o_yRkPZx5zw-fwumnjGaeGf0hBN3jc_w,10
295
- workbench-0.8.184.dist-info/RECORD,,
290
+ workbench-0.8.185.dist-info/licenses/LICENSE,sha256=z4QMMPlLJkZjU8VOKqJkZiQZCEZ--saIU2Z8-p3aVc0,1080
291
+ workbench-0.8.185.dist-info/METADATA,sha256=4S2A5vuZPlJZpRqFGQFe7nL4DzQjTsKIo-V2x0WzDF0,9210
292
+ workbench-0.8.185.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
293
+ workbench-0.8.185.dist-info/entry_points.txt,sha256=zPFPruY9uayk8-wsKrhfnIyIB6jvZOW_ibyllEIsLWo,356
294
+ workbench-0.8.185.dist-info/top_level.txt,sha256=Dhy72zTxaA_o_yRkPZx5zw-fwumnjGaeGf0hBN3jc_w,10
295
+ workbench-0.8.185.dist-info/RECORD,,