nkululeko 0.93.12__py3-none-any.whl → 0.93.13__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.
nkululeko/constants.py CHANGED
@@ -1,2 +1,2 @@
1
- VERSION="0.93.12"
1
+ VERSION="0.93.13"
2
2
  SAMPLING_RATE = 16000
nkululeko/data/dataset.py CHANGED
@@ -34,11 +34,9 @@ class Dataset:
34
34
  self.plot = Plots()
35
35
  self.limit = int(self.util.config_val_data(self.name, "limit", 0))
36
36
  self.target_tables_append = eval(
37
- self.util.config_val_data(
38
- self.name, "target_tables_append", "False")
37
+ self.util.config_val_data(self.name, "target_tables_append", "False")
39
38
  )
40
- self.start_fresh = eval(
41
- self.util.config_val("DATA", "no_reuse", "False"))
39
+ self.start_fresh = eval(self.util.config_val("DATA", "no_reuse", "False"))
42
40
  self.is_labeled, self.got_speaker, self.got_gender, self.got_age = (
43
41
  False,
44
42
  False,
@@ -72,8 +70,7 @@ class Dataset:
72
70
  try:
73
71
  self.db = audformat.Database.load(root)
74
72
  except FileNotFoundError:
75
- self.util.error(
76
- f"{self.name}: no audformat database found at {root}")
73
+ self.util.error(f"{self.name}: no audformat database found at {root}")
77
74
  return root
78
75
 
79
76
  def _check_cols(self, df):
@@ -95,8 +92,7 @@ class Dataset:
95
92
  )
96
93
  self.util.debug(r_string)
97
94
  if glob_conf.report.initial:
98
- glob_conf.report.add_item(ReportItem(
99
- "Data", "Load report", r_string))
95
+ glob_conf.report.add_item(ReportItem("Data", "Load report", r_string))
100
96
  glob_conf.report.initial = False
101
97
 
102
98
  def load(self):
@@ -107,8 +103,7 @@ class Dataset:
107
103
  store_file = f"{store}{self.name}.{store_format}"
108
104
  self.root = self._load_db()
109
105
  if not self.start_fresh and os.path.isfile(store_file):
110
- self.util.debug(
111
- f"{self.name}: reusing previously stored file {store_file}")
106
+ self.util.debug(f"{self.name}: reusing previously stored file {store_file}")
112
107
  self.df = self.util.get_store(store_file, store_format)
113
108
  self.is_labeled = self.target in self.df
114
109
  self.got_gender = "gender" in self.df
@@ -123,12 +118,10 @@ class Dataset:
123
118
  # map the audio file paths
124
119
  self.db.map_files(lambda x: os.path.join(self.root, x))
125
120
  # the dataframes (potentially more than one) with at least the file names
126
- df_files = self.util.config_val_data(
127
- self.name, "files_tables", "['files']")
121
+ df_files = self.util.config_val_data(self.name, "files_tables", "['files']")
128
122
  df_files_tables = ast.literal_eval(df_files)
129
123
  # The label for the target column
130
- self.col_label = self.util.config_val_data(
131
- self.name, "label", self.target)
124
+ self.col_label = self.util.config_val_data(self.name, "label", self.target)
132
125
  (
133
126
  df,
134
127
  self.is_labeled,
@@ -164,8 +157,7 @@ class Dataset:
164
157
  self.got_age = got_age2 or self.got_age
165
158
  if audformat.is_filewise_index(df_target.index):
166
159
  try:
167
- df_target = df_target.loc[df.index.get_level_values(
168
- "file")]
160
+ df_target = df_target.loc[df.index.get_level_values("file")]
169
161
  df_target = df_target.set_index(df.index)
170
162
  except KeyError:
171
163
  # just a try...
@@ -214,8 +206,7 @@ class Dataset:
214
206
  end = self.df.index.get_level_values(2)
215
207
  self.df["duration"] = (end - start).total_seconds()
216
208
  elif self.df.duration.dtype == "timedelta64[ns]":
217
- self.df["duration"] = self.df["duration"].map(
218
- lambda x: x.total_seconds())
209
+ self.df["duration"] = self.df["duration"].map(lambda x: x.total_seconds())
219
210
  # Perform some filtering if desired
220
211
  required = self.util.config_val_data(self.name, "required", False)
221
212
  if required:
@@ -245,18 +236,15 @@ class Dataset:
245
236
  res.append(abs(n - max))
246
237
  return res
247
238
 
248
- reverse = eval(self.util.config_val_data(
249
- self.name, "reverse", "False"))
239
+ reverse = eval(self.util.config_val_data(self.name, "reverse", "False"))
250
240
  if reverse:
251
- max = eval(self.util.config_val_data(
252
- self.name, "reverse.max", "False"))
241
+ max = eval(self.util.config_val_data(self.name, "reverse.max", "False"))
253
242
  if max:
254
243
  max = float(max)
255
244
  else:
256
245
  max = self.df[self.target].values.max()
257
246
  self.util.debug(f"reversing target numbers with max values: {max}")
258
- self.df[self.target] = reverse_array(
259
- self.df[self.target].values, max)
247
+ self.df[self.target] = reverse_array(self.df[self.target].values, max)
260
248
 
261
249
  # check if the target variable should be scaled (z-transformed)
262
250
  scale = self.util.config_val_data(self.name, "scale", False)
@@ -329,15 +317,13 @@ class Dataset:
329
317
  pass
330
318
  try:
331
319
  # also it might be possible that the age is part of the speaker description
332
- df_local["age"] = db[table]["speaker"].get(
333
- map="age").astype(int)
320
+ df_local["age"] = db[table]["speaker"].get(map="age").astype(int)
334
321
  got_age = True
335
322
  except (ValueError, audformat.errors.BadKeyError):
336
323
  pass
337
324
  try:
338
325
  # same for the target, e.g. "age"
339
- df_local[self.target] = db[table]["speaker"].get(
340
- map=self.target)
326
+ df_local[self.target] = db[table]["speaker"].get(map=self.target)
341
327
  is_labeled = True
342
328
  except (ValueError, audformat.core.errors.BadKeyError):
343
329
  pass
@@ -398,10 +384,8 @@ class Dataset:
398
384
  testdf = self.db.tables[self.target + ".test"].df
399
385
  traindf = self.db.tables[self.target + ".train"].df
400
386
  # use only the train and test samples that were not perhaps filtered out by an earlier processing step
401
- self.df_test = self.df.loc[self.df.index.intersection(
402
- testdf.index)]
403
- self.df_train = self.df.loc[self.df.index.intersection(
404
- traindf.index)]
387
+ self.df_test = self.df.loc[self.df.index.intersection(testdf.index)]
388
+ self.df_train = self.df.loc[self.df.index.intersection(traindf.index)]
405
389
  elif split_strategy == "train":
406
390
  self.df_train = self.df
407
391
  self.df_test = pd.DataFrame()
@@ -424,23 +408,18 @@ class Dataset:
424
408
  if entry_train_tables:
425
409
  train_tables = ast.literal_eval(entry_train_tables)
426
410
  for train_table in train_tables:
427
- traindf = pd.concat(
428
- [traindf, self.db.tables[train_table].df])
411
+ traindf = pd.concat([traindf, self.db.tables[train_table].df])
429
412
  # use only the train and test samples that were not perhaps filtered out by an earlier processing step
430
413
  # testdf.index.map(lambda x: os.path.join(self.root, x))
431
414
  # testdf.index = testdf.index.to_series().apply(lambda x: self.root+x)
432
415
  testdf = testdf.set_index(
433
- audformat.utils.to_segmented_index(
434
- testdf.index, allow_nat=False)
416
+ audformat.utils.to_segmented_index(testdf.index, allow_nat=False)
435
417
  )
436
418
  traindf = traindf.set_index(
437
- audformat.utils.to_segmented_index(
438
- traindf.index, allow_nat=False)
419
+ audformat.utils.to_segmented_index(traindf.index, allow_nat=False)
439
420
  )
440
- self.df_test = self.df.loc[self.df.index.intersection(
441
- testdf.index)]
442
- self.df_train = self.df.loc[self.df.index.intersection(
443
- traindf.index)]
421
+ self.df_test = self.df.loc[self.df.index.intersection(testdf.index)]
422
+ self.df_train = self.df.loc[self.df.index.intersection(traindf.index)]
444
423
  # it might be necessary to copy the target values
445
424
  try:
446
425
  self.df_test[self.target] = testdf[self.target]
@@ -467,12 +446,10 @@ class Dataset:
467
446
  self.util.error(f"unknown split strategy: {split_strategy}")
468
447
 
469
448
  # check if train or test set should be ignored
470
- as_test = eval(self.util.config_val_data(
471
- self.name, "as_test", "False"))
449
+ as_test = eval(self.util.config_val_data(self.name, "as_test", "False"))
472
450
  if as_test:
473
451
  self.df_train = pd.DataFrame()
474
- as_train = eval(self.util.config_val_data(
475
- self.name, "as_train", "False"))
452
+ as_train = eval(self.util.config_val_data(self.name, "as_train", "False"))
476
453
  if as_train:
477
454
  self.df_test = pd.DataFrame()
478
455
 
@@ -503,8 +480,7 @@ class Dataset:
503
480
 
504
481
  seed = 42
505
482
  k = 30
506
- test_size = int(self.util.config_val_data(
507
- self.name, "test_size", 20)) / 100.0
483
+ test_size = int(self.util.config_val_data(self.name, "test_size", 20)) / 100.0
508
484
  df = self.df
509
485
  # split target
510
486
  targets = df[self.target].to_numpy()
@@ -520,8 +496,7 @@ class Dataset:
520
496
  stratif_vars = self.util.config_val("DATA", "balance", False)
521
497
  stratif_vars_array = {}
522
498
  if not stratif_vars:
523
- self.util.error(
524
- "balanced split needs stratif_vars to stratify the splits")
499
+ self.util.error("balanced split needs stratif_vars to stratify the splits")
525
500
  else:
526
501
  stratif_vars = ast.literal_eval(stratif_vars)
527
502
  for stratif_var in stratif_vars.keys():
@@ -530,8 +505,7 @@ class Dataset:
530
505
  continue
531
506
  else:
532
507
  data = df[stratif_var].to_numpy()
533
- bins = self.util.config_val(
534
- "DATA", f"{stratif_var}_bins", False)
508
+ bins = self.util.config_val("DATA", f"{stratif_var}_bins", False)
535
509
  if bins:
536
510
  data = binning(data, nbins=int(bins))
537
511
  stratif_vars_array[stratif_var] = data
@@ -582,8 +556,7 @@ class Dataset:
582
556
 
583
557
  def split_speakers(self):
584
558
  """One way to split train and eval sets: Specify percentage of evaluation speakers"""
585
- test_percent = int(self.util.config_val_data(
586
- self.name, "test_size", 20))
559
+ test_percent = int(self.util.config_val_data(self.name, "test_size", 20))
587
560
  df = self.df
588
561
  s_num = df.speaker.nunique()
589
562
  test_num = int(s_num * (test_percent / 100))
@@ -602,8 +575,7 @@ class Dataset:
602
575
 
603
576
  def random_split(self):
604
577
  """One way to split train and eval sets: Specify percentage of random samples"""
605
- test_percent = int(self.util.config_val_data(
606
- self.name, "test_size", 20))
578
+ test_percent = int(self.util.config_val_data(self.name, "test_size", 20))
607
579
  df = self.df
608
580
  s_num = len(df)
609
581
  test_num = int(s_num * (test_percent / 100))
@@ -707,8 +679,7 @@ class Dataset:
707
679
  if df.empty:
708
680
  return
709
681
  if self.check_continuous_classification():
710
- self.util.debug(
711
- f"{self.name}: binning continuous variable to categories")
682
+ self.util.debug(f"{self.name}: binning continuous variable to categories")
712
683
  cat_vals = self.util.continuous_to_categorical(df[self.target])
713
684
  df[self.target] = cat_vals.values
714
685
  labels = ast.literal_eval(glob_conf.config["DATA"]["labels"])
@@ -4,8 +4,10 @@ import ast
4
4
  import matplotlib.pyplot as plt
5
5
  import pandas as pd
6
6
  from sklearn.inspection import permutation_importance
7
- from sklearn.linear_model import LinearRegression, LogisticRegression
8
- from sklearn.tree import DecisionTreeClassifier, DecisionTreeRegressor
7
+ from sklearn.linear_model import LinearRegression
8
+ from sklearn.linear_model import LogisticRegression
9
+ from sklearn.tree import DecisionTreeClassifier
10
+ from sklearn.tree import DecisionTreeRegressor
9
11
 
10
12
  import nkululeko.glob_conf as glob_conf
11
13
  from nkululeko.plots import Plots
@@ -49,6 +49,7 @@ class Wav2vec2(Featureset):
49
49
  hidden_layer = int(self.util.config_val("FEATS", "wav2vec2.layer", "0"))
50
50
  config.num_hidden_layers = layer_num - hidden_layer
51
51
  self.util.debug(f"using hidden layer #{config.num_hidden_layers}")
52
+
52
53
  self.processor = Wav2Vec2FeatureExtractor.from_pretrained(model_path)
53
54
  self.model = Wav2Vec2Model.from_pretrained(model_path, config=config).to(
54
55
  self.device
nkululeko/plots.py CHANGED
@@ -297,6 +297,9 @@ class Plots:
297
297
  if cat_col == "class_label":
298
298
  plot_df = plot_df.rename(columns={cat_col: self.target})
299
299
  cat_col = self.target
300
+ elif cont_col == "class_label":
301
+ plot_df = plot_df.rename(columns={cont_col: self.target})
302
+ cont_col = self.target
300
303
  dist_type = self.util.config_val("EXPL", "dist_type", "kde")
301
304
  cats, cat_str, es = su.get_effect_size(plot_df, cat_col, cont_col)
302
305
  model_type = self.util.get_model_type()
@@ -327,7 +330,7 @@ class Plots:
327
330
  if col2 == "class_label":
328
331
  plot_df = plot_df.rename(columns={col2: self.target})
329
332
  col2 = self.target
330
- if col1 == "class_label":
333
+ elif col1 == "class_label":
331
334
  plot_df = plot_df.rename(columns={col1: self.target})
332
335
  col1 = self.target
333
336
  crosstab = pd.crosstab(index=plot_df[col1], columns=plot_df[col2])
@@ -0,0 +1,39 @@
1
+ Metadata-Version: 2.2
2
+ Name: nkululeko
3
+ Version: 0.93.13
4
+ Summary: Machine learning audio prediction experiments based on templates
5
+ Home-page: https://github.com/felixbur/nkululeko
6
+ Author: Felix Burkhardt
7
+ Author-email: fxburk@gmail.com
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Topic :: Scientific/Engineering
13
+ Requires-Python: >=3.9
14
+ License-File: LICENSE
15
+ Requires-Dist: audeer
16
+ Requires-Dist: audformat
17
+ Requires-Dist: audinterface
18
+ Requires-Dist: audiofile
19
+ Requires-Dist: audiomentations
20
+ Requires-Dist: audmetric
21
+ Requires-Dist: audonnx
22
+ Requires-Dist: confidence_intervals
23
+ Requires-Dist: datasets
24
+ Requires-Dist: imageio
25
+ Requires-Dist: matplotlib
26
+ Requires-Dist: numpy
27
+ Requires-Dist: opensmile
28
+ Requires-Dist: pandas
29
+ Requires-Dist: praat-parselmouth
30
+ Requires-Dist: scikit_learn
31
+ Requires-Dist: scipy
32
+ Requires-Dist: seaborn
33
+ Requires-Dist: sounddevice
34
+ Requires-Dist: torch
35
+ Requires-Dist: torchvision
36
+ Requires-Dist: transformers
37
+ Requires-Dist: umap-learn
38
+ Requires-Dist: xgboost
39
+ Requires-Dist: pylatex
@@ -2,7 +2,7 @@ nkululeko/__init__.py,sha256=62f8HiEzJ8rG2QlTFJXUCMpvuH3fKI33DoJSj33mscc,63
2
2
  nkululeko/aug_train.py,sha256=FoMbBrfyOZd4QAw7oIHl3X6-UpsqAKWVDIolCA7qOWs,3196
3
3
  nkululeko/augment.py,sha256=3RzaxB3gRxovgJVjHXi0glprW01J7RaHhUkqotW2T3U,2955
4
4
  nkululeko/cacheddataset.py,sha256=XFpWZmbJRg0pvhnIgYf0TkclxllD-Fctu-Ol0PF_00c,969
5
- nkululeko/constants.py,sha256=T9YZzqdg_ltKpuIf2XZdrqFmmlZQmhak97DpM5GQQhI,40
5
+ nkululeko/constants.py,sha256=B_SoEW_E21VyJqFUyh_XG4GvVYNPEsgUF31slyJ2fFY,40
6
6
  nkululeko/demo-ft.py,sha256=iD9Pzp9QjyAv31q1cDZ75vPez7Ve8A4Cfukv5yfZdrQ,770
7
7
  nkululeko/demo.py,sha256=4Yzhg6pCPBYPGJrP7JX2TysVosl_R1llpVDKc2P_gUA,4955
8
8
  nkululeko/demo_feats.py,sha256=BvZjeNFTlERIRlq34OHM4Z96jdDQAhB01BGQAUcX9dM,2026
@@ -20,7 +20,7 @@ nkululeko/modelrunner.py,sha256=lJy-xM4QfDDWeL0dLTE_VIb4sYrnd_Z_yJRK3wwohQA,1119
20
20
  nkululeko/multidb.py,sha256=sO6OwJn8sn1-C-ig3thsIL8QMWHdV9SnJhDodKjeKrI,6876
21
21
  nkululeko/nkuluflag.py,sha256=PGWSmZz-PiiHLgcZJAoGOI_Y-sZDVI1ksB8p5r7riWM,3725
22
22
  nkululeko/nkululeko.py,sha256=M7baIq2nAoi6dEoBL4ATEuqAs5U1fvl_hyqAl5DybAQ,2040
23
- nkululeko/plots.py,sha256=Mm30pDLBb55iE9SYaSg76KFBKnebZTlypFQIBo26wuY,25991
23
+ nkululeko/plots.py,sha256=2G5yNR3Q3qWDt8ncKwKUZBLE-O1rbGUiG6omwfFudVk,26138
24
24
  nkululeko/predict.py,sha256=MLnHEyFmSiHLLs-HDczag8Vu3zKF5T1rXLKdZZJ6py8,2083
25
25
  nkululeko/resample.py,sha256=rn3-M1A-iwVGibfQNGyeYNa7briD24lIN9Szq_1uTJo,5194
26
26
  nkululeko/runmanager.py,sha256=AswmORVUkCIH0gTx6zEyufvFATQBS8C5TXo2erSNdVg,7611
@@ -49,12 +49,12 @@ nkululeko/autopredict/ap_stoi.py,sha256=UEQg1ZV0meAsxgdWB8ieRs9GPXHqArmsaOyCGRwp
49
49
  nkululeko/autopredict/ap_valence.py,sha256=WrW4Ltqi_odW49_4QEVKkfnrcztLIVZ4cXIEHu4dBN8,1026
50
50
  nkululeko/autopredict/estimate_snr.py,sha256=1k9-XadABudnsNOeFZD_Fg0E64-GUQVS7JEp82MLQS4,4995
51
51
  nkululeko/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
- nkululeko/data/dataset.py,sha256=H65rvQ8sPwEwv_T-FqOEa7FeQ3JBn88v3xOzBOjARe4,30582
52
+ nkululeko/data/dataset.py,sha256=G6RFK2msSVHxpzDm8gZSAD4GK6ieMS5fTbqVS-NOFuY,30081
53
53
  nkululeko/data/dataset_csv.py,sha256=p2b4eS5R2Q5zdOIc56NRRU2PTFXSRt0qrdHGafHkWKo,4830
54
54
  nkululeko/feat_extract/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
55
  nkululeko/feat_extract/feats_agender.py,sha256=onfAQ6-xx_mFMJXEF1IX8cHBmGtGeX6weJmxbkfh1_o,3184
56
56
  nkululeko/feat_extract/feats_agender_agender.py,sha256=_YQv1qw--3uQfnyTQDCwlmPRnrhdMhgXbYK2yQtseW0,3464
57
- nkululeko/feat_extract/feats_analyser.py,sha256=luTV2-yw7rk0aQPI88vvtW1GLV8cGypp7LJW1v_YBrw,13450
57
+ nkululeko/feat_extract/feats_analyser.py,sha256=txuIEgO4uprle35RzBczvZm5Hc7iUl2p9oBEfdrvg_I,13506
58
58
  nkululeko/feat_extract/feats_ast.py,sha256=w62xEoLiFtU-rj6SXkqXAktmoFaXcAcAWpUyEjp8JWo,4652
59
59
  nkululeko/feat_extract/feats_auddim.py,sha256=CGLp_aYhudfwoU5522vjrvjPxfZcyw593A8xLjYefV8,3134
60
60
  nkululeko/feat_extract/feats_audmodel.py,sha256=OsZyB1rdcG0Fai2gAwBlbuubmWor1_-P4IDkZLqgPKE,3161
@@ -71,7 +71,7 @@ nkululeko/feat_extract/feats_spectra.py,sha256=6WhFUpB0WTutg7OFMlAw9lSwVU5OBYCDc
71
71
  nkululeko/feat_extract/feats_spkrec.py,sha256=o_6bdU4lIkj64S5Kdjf1iyuo1VASeYxE4XdxV94a8gE,4732
72
72
  nkululeko/feat_extract/feats_squim.py,sha256=yJifsp9kj9iJjW_UAKr3LlvVhX5rv7el4bepn0wN2a8,4578
73
73
  nkululeko/feat_extract/feats_trill.py,sha256=JgyUQ8ihIL5PlUpxjchlbC9547GI0SyUwkFEquya85Q,3197
74
- nkululeko/feat_extract/feats_wav2vec2.py,sha256=WYB9XlRzgDi8cGSKzhV5jahA0GZ_SiWgaQ25IcEemto,5296
74
+ nkululeko/feat_extract/feats_wav2vec2.py,sha256=q1QzMD3KbhF2SOmxdwI7CiViRmhlFRyghxN_6SmUc0E,5297
75
75
  nkululeko/feat_extract/feats_wavlm.py,sha256=O9cfc39VF5aPJRRATKb37pHT4W11i2cu5O1mY9LOjIA,4755
76
76
  nkululeko/feat_extract/feats_whisper.py,sha256=n3ESZtva7wshs8E8diBlQYa9xCH_P0UY1DncSrxz-FY,4508
77
77
  nkululeko/feat_extract/featureset.py,sha256=clcBv9rzBRW-bfw7JC_FYTjU5uUS-c0UE1XtQLYYRiE,1615
@@ -112,9 +112,9 @@ nkululeko/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
112
112
  nkululeko/utils/files.py,sha256=SrrYaU7AB80MZHiV1jcB0h_zigvYLYgSVNTXV4ao38g,4593
113
113
  nkululeko/utils/stats.py,sha256=vCRzhCR0Gx5SiJyAGbj1TIto8ocGz58CM5Pr3LltagA,2948
114
114
  nkululeko/utils/util.py,sha256=wFDslqxpCVDwi6LBakIFDDy1kYsxt5G7ykE38CocmtA,16880
115
- nkululeko-0.93.12.dist-info/LICENSE,sha256=0zGP5B_W35yAcGfHPS18Q2B8UhvLRY3dQq1MhpsJU_U,1076
116
- nkululeko-0.93.12.dist-info/METADATA,sha256=jjO-vG0POWF3v_v3QfliA4uT8jzZPikwmEj2O6v6rhg,42823
117
- nkululeko-0.93.12.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
118
- nkululeko-0.93.12.dist-info/entry_points.txt,sha256=lNTkFEdh6Kjo5o95ZAWf_0Lq-4ztGoAoMVSDuPtuyS0,442
119
- nkululeko-0.93.12.dist-info/top_level.txt,sha256=DPFNNSHPjUeVKj44dVANAjuVGRCC3MusJ08lc2a8xFA,10
120
- nkululeko-0.93.12.dist-info/RECORD,,
115
+ nkululeko-0.93.13.dist-info/LICENSE,sha256=0zGP5B_W35yAcGfHPS18Q2B8UhvLRY3dQq1MhpsJU_U,1076
116
+ nkululeko-0.93.13.dist-info/METADATA,sha256=G0DPQrKRoSO4lB0NjR5hjc715sggueUA3lcokR1NyUQ,1148
117
+ nkululeko-0.93.13.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
118
+ nkululeko-0.93.13.dist-info/entry_points.txt,sha256=lNTkFEdh6Kjo5o95ZAWf_0Lq-4ztGoAoMVSDuPtuyS0,442
119
+ nkululeko-0.93.13.dist-info/top_level.txt,sha256=DPFNNSHPjUeVKj44dVANAjuVGRCC3MusJ08lc2a8xFA,10
120
+ nkululeko-0.93.13.dist-info/RECORD,,