toolsos 0.2.0__py3-none-any.whl → 0.2.2__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.
@@ -33,7 +33,7 @@ def get_db_connection_strings(
33
33
  for dbname, params in db_info.items():
34
34
  flush = dbname in reset_pw if reset_pw else False
35
35
 
36
- if params["pw"] == "acces_token":
36
+ if params["password"] == "access_token":
37
37
  pw = get_azure_access_token()
38
38
  else:
39
39
  pw = get_pw_from_keyring(dbname=dbname, user=params["user"], reset_pw=flush)
@@ -104,11 +104,13 @@ if __name__ == "__main__":
104
104
  # Examples
105
105
 
106
106
  # Get database connection settings from yaml
107
- # engine_strings = get_db_connection_strings("python/database_config.yml")
108
- # print(engine_strings.ruimte_analyse222)
107
+ engine_strings = get_db_connection_strings(
108
+ "src/toolsos/database/database_config.yml"
109
+ )
110
+ print(engine_strings.ruimte_analyse222)
109
111
 
110
112
  # Get database connection settings from yaml and reset password
111
- # engine_strings = get_db_connection_strings(
112
- # "python/database_config.yml", reset_pw=["ruimte_analyse222"]
113
- # )
114
- # print(engine_strings.ruimte_analyse222)
113
+ engine_strings = get_db_connection_strings(
114
+ "src/toolsos/database/database_config.yml", reset_pw=["ruimte_analyse222"]
115
+ )
116
+ print(engine_strings.ruimte_analyse222)
@@ -0,0 +1,76 @@
1
+ from pathlib import Path
2
+
3
+ import pandas as pd
4
+ import win32com.client as win32
5
+
6
+
7
+ def remove_underscores_from_columns(df: pd.DataFrame) -> pd.DataFrame:
8
+ df.columns = df.columns.str.replace("_", " ")
9
+ return df
10
+
11
+
12
+ def get_excel_files_from_folder(folder: str) -> list[str]:
13
+ return [str(f.resolve()) for f in Path("to_merge").glob("*") if f.suffix == ".xlsx"]
14
+
15
+
16
+ def combine_excel_files(out_path: str, files: list[str] = None, overwrite: bool = True):
17
+ out_path = Path(out_path)
18
+
19
+ if overwrite:
20
+ if out_path.exists():
21
+ out_path.unlink()
22
+
23
+ # INITIALIZE EXCEL COM APP
24
+ try:
25
+ xlapp = win32.gencache.EnsureDispatch("Excel.Application")
26
+
27
+ # constants
28
+ xlPasteValues = -4163
29
+ lPasteFormats = -4122
30
+ xlWorkbookDefault = 51
31
+
32
+ # create new workbook
33
+ new_wb = xlapp.Workbooks.Add()
34
+ new_wb.SaveAs(Filename=str(out_path), FileFormat=xlWorkbookDefault)
35
+
36
+ dup_count = 1
37
+
38
+ for wb in files:
39
+ xlwb = xlapp.Workbooks.Open(wb)
40
+
41
+ for xlsh in xlwb.Worksheets:
42
+ new_sh = new_wb.Worksheets.Add()
43
+
44
+ try:
45
+ new_sh.Name = xlsh.Name
46
+
47
+ # Ugly non defined exception. Be aware that this wil caputre
48
+ except Exception as e:
49
+ new_sh.Name = f"{xlsh.Name}_{dup_count}"
50
+ dup_count += 1
51
+
52
+ new_wb.Save()
53
+ new_sh.Move(After=new_wb.Worksheets(new_wb.Worksheets.Count))
54
+
55
+ xlsh.Cells.Copy(new_sh.Cells)
56
+ new_sh = None
57
+
58
+ xlwb.Close(True)
59
+ xlwb = None
60
+
61
+ # remove default blad1
62
+ new_wb.Worksheets("Blad1").Delete()
63
+ new_wb.Save()
64
+
65
+ except Exception as e:
66
+ print(e)
67
+
68
+ # RELEASE RESOURCES
69
+ finally:
70
+ xlsh = None
71
+ new_sh = None
72
+ xlwb = None
73
+ new_wb = None
74
+ xlapp.Quit()
75
+ xlapp = None
76
+ xlwb = None
@@ -7,8 +7,7 @@ from typing import Any, Callable, Dict
7
7
  import numpy as np
8
8
  import pandas as pd
9
9
  from openpyxl import Workbook
10
- from openpyxl.styles import (Alignment, Border, Font, PatternFill, Protection,
11
- Side)
10
+ from openpyxl.styles import Alignment, Border, Font, PatternFill, Protection, Side
12
11
  from openpyxl.utils import get_column_letter
13
12
 
14
13
  Fmt = list[list[dict[str, Any]]]
@@ -47,6 +46,36 @@ def set_global_style(style: str) -> None:
47
46
  STYLES = STYLE_NEW
48
47
 
49
48
 
49
+ def cols_to_str(df: pd.DataFrame) -> pd.DataFrame:
50
+ """Change column names in to string. Multiindex column names are nog changed because
51
+ these are always strings
52
+
53
+ Args:
54
+ df (pd.DataFrame): Dataframe
55
+
56
+ Returns:
57
+ pd.DataFrame: Dataframe with column names as strings
58
+ """
59
+ if df.columns.nlevels == 1:
60
+ df.columns = df.columns.astype(str)
61
+
62
+ return df
63
+
64
+
65
+ def get_max_col_widths(data: pd.DataFrame | np.ndarray) -> list[float]:
66
+ col_widths = []
67
+ if isinstance(data, pd.DataFrame):
68
+ for col in zip(*flatten_multiindex_columns(data)):
69
+ col_widths.append(max(len(e) for e in col))
70
+ else:
71
+ for col in zip(*data):
72
+ col_widths.append(max(len(str(e)) for e in col))
73
+
74
+ col_widths = [col_width * 1.13 for col_width in col_widths]
75
+
76
+ return col_widths
77
+
78
+
50
79
  def flatten_multiindex_columns(df):
51
80
  column_multi = []
52
81
  for level in range(df.columns.nlevels):
@@ -68,7 +97,18 @@ def df_to_array(df: pd.DataFrame) -> np.ndarray:
68
97
  return np.vstack([column_names, df.to_numpy()])
69
98
 
70
99
 
71
- def get_cells_to_merge(df: pd.DataFrame) -> list[list[int]]:
100
+ def get_cells_to_merge(df: pd.DataFrame) -> dict[int : list[int, int]]:
101
+ """Pandas dataframes sometimes have mutliindex columns. For all but the last level
102
+ a dictionary is created to merge the cells. The last level isn't merged because these
103
+ are these contain unique column names
104
+
105
+ Args:
106
+ df (pd.DataFrame): Pandas dataframe. If the dataframe has multicolumn indices
107
+ a dictionary containg the cells to merge is returned
108
+
109
+ Returns:
110
+ dict[int: list[int, int]]: Dictionary containg the cells to merge
111
+ """
72
112
  levels = flatten_multiindex_columns(df)[:-1]
73
113
 
74
114
  cells_to_merge = {}
@@ -331,14 +371,14 @@ def cell_formatting(
331
371
  return fmt
332
372
 
333
373
 
334
- def write_worksheet(
374
+ def write_to_worksheet(
335
375
  ws: Any,
336
376
  arr: np.ndarray,
337
377
  fmt: Fmt,
338
378
  title: str | None = None,
339
379
  source: str | None = None,
340
380
  col_filter: bool | None = None,
341
- autofit_columns: bool | None = None,
381
+ col_widths: list | None = None,
342
382
  cells_to_merge: list[list[int]] | None = None,
343
383
  ) -> None:
344
384
  """Writing data to worksheet. Used for writing values to cells and formatting the cells
@@ -379,36 +419,32 @@ def write_worksheet(
379
419
  filters = ws.auto_filter
380
420
  filters.ref = f"A1:{excel_style(len(fmt), len(fmt[0]))}"
381
421
 
382
- if autofit_columns:
383
- _autofit_columns(ws)
384
-
385
422
  if source:
386
423
  _insert_source(ws, source, arr)
387
424
 
425
+ if col_widths:
426
+ _set_column_widths(ws, col_widths)
427
+
388
428
  if title:
389
429
  _insert_title(ws, title)
390
430
 
391
431
  if cells_to_merge:
392
- _merge_cells(ws, cells_to_merge)
432
+ _merge_cells(ws, cells_to_merge, title)
393
433
 
394
434
 
395
- # def _set_column_width(ws: Any, column_widths: list) -> None:
396
- # for i, column_number in enumerate(range(ws.max_column)):
397
- # column_letter = get_column_letter(column_letter)
398
- # column_width = column_widths[i]
399
- # ws.column_dimensions[column_letter].width = column_width
435
+ def _set_column_widths(ws: Any, col_widths: list[int]) -> None:
436
+ for idx, col_width in enumerate(col_widths):
437
+ col_letter = get_column_letter(idx + 1)
438
+ ws.column_dimensions[col_letter].width = col_width
400
439
 
401
440
 
402
- def _autofit_columns(ws: Any) -> None:
403
- column_letters = tuple(
404
- get_column_letter(col_number + 1) for col_number in range(ws.max_column)
405
- )
406
- for column_letter in column_letters:
407
- ws.column_dimensions[column_letter].auto_fit = True
408
-
441
+ def _merge_cells(ws, cells_to_merge, title: str | None = None) -> None:
442
+ add = 0
443
+ if title:
444
+ add = 1
409
445
 
410
- def _merge_cells(ws, cells_to_merge):
411
446
  for row_idx, merge in cells_to_merge.items():
447
+ row_idx = row_idx + add
412
448
  for start, stop in merge:
413
449
  cell = ws.cell(row_idx + 1, start)
414
450
  cell.alignment = Alignment(horizontal="center")
@@ -422,14 +458,15 @@ def _merge_cells(ws, cells_to_merge):
422
458
 
423
459
  def _insert_source(ws, source, arr):
424
460
  height, width = arr.shape
425
- cell = ws.cell(width, height + 1, source)
426
- cell.font = Font(**STYLES["calibri"]["font"])
461
+ cell = ws.cell(height + 1, width, source)
427
462
  cell.alignment = Alignment(horizontal="right")
463
+ cell.font = Font(**STYLES["calibri"]["font"])
428
464
 
429
465
 
430
466
  def _insert_title(ws: Any, title: str) -> None:
431
467
  ws.insert_rows(0)
432
468
  cell = ws.cell(1, 1, title)
469
+ cell.alignment = Alignment(horizontal="left")
433
470
  for t, kwa in STYLES["title_bold"].items():
434
471
  setattr(cell, t, LOOKUP[t](**kwa))
435
472
 
@@ -455,10 +492,99 @@ def write_table(
455
492
  blue_border: bool | None = True,
456
493
  blue_border_row_ids: int | list[int] | None = None,
457
494
  number_format: str = "0.0",
458
- autofit_columns: bool | None = False,
495
+ autofit_columns: str | None = "column_names",
459
496
  col_filter: bool | None = False,
460
497
  style: str = "old",
461
498
  combine_multiindex: bool | int = False,
499
+ column_names_to_string: bool = True,
500
+ ):
501
+ wb = Workbook()
502
+ # Empty sheet is created on Workbook creation
503
+ del wb["Sheet"]
504
+
505
+ set_global_style(style)
506
+
507
+ if not isinstance(data, dict):
508
+ data = {"Sheet1": data}
509
+
510
+ for sheet_name, df in data.items():
511
+ if column_names_to_string == True:
512
+ df = cols_to_str(df)
513
+
514
+ format_worksheet(
515
+ wb=wb,
516
+ df=df,
517
+ sheet_name=sheet_name,
518
+ header_row=header_row,
519
+ title=title,
520
+ source=source,
521
+ total_row=total_row,
522
+ light_blue_row_ids=light_blue_row_ids,
523
+ total_col=total_col,
524
+ right_align_ids=right_align_ids,
525
+ right_align_pattern=right_align_pattern,
526
+ right_align_numeric=right_align_numeric,
527
+ left_align_ids=left_align_ids,
528
+ left_align_pattern=left_align_pattern,
529
+ left_align_string=left_align_string,
530
+ perc_ids=perc_ids,
531
+ perc_pattern=perc_pattern,
532
+ perc_col_format=perc_col_format,
533
+ blue_border=blue_border,
534
+ blue_border_row_ids=blue_border_row_ids,
535
+ number_format=number_format,
536
+ autofit_columns=autofit_columns,
537
+ col_filter=col_filter,
538
+ combine_multiindex=combine_multiindex,
539
+ column_names_to_string=column_names_to_string,
540
+ )
541
+
542
+ wb.save(file)
543
+
544
+
545
+ def write_table_from_dict(
546
+ file,
547
+ write_info,
548
+ style: str = "old",
549
+ ):
550
+ wb = Workbook()
551
+ # Empty sheet is created on Workbook creation
552
+ del wb["Sheet"]
553
+
554
+ set_global_style(style)
555
+
556
+ for sheet in write_info:
557
+ format_worksheet(wb=wb, **sheet)
558
+
559
+ wb.save(file)
560
+
561
+
562
+ def format_worksheet(
563
+ wb: Any,
564
+ df: pd.DataFrame,
565
+ sheet_name: str,
566
+ header_row: int = 0,
567
+ title: str | dict[str, str] | None = None,
568
+ source: str | None = None,
569
+ total_row: bool | None = None,
570
+ light_blue_row_ids: int | list[int] | None = None,
571
+ total_col: bool | None = None,
572
+ right_align_ids: list | None = None,
573
+ right_align_pattern: str | None = None,
574
+ right_align_numeric: bool | None = True,
575
+ left_align_ids: list | None = None,
576
+ left_align_pattern: str | None = None,
577
+ left_align_string: bool | None = True,
578
+ perc_ids: list | None = None,
579
+ perc_pattern: str | None = None,
580
+ perc_col_format: str | None = None,
581
+ blue_border: bool | None = True,
582
+ blue_border_row_ids: int | list[int] | None = None,
583
+ number_format: str = "0.0",
584
+ autofit_columns: str | None = "column_names",
585
+ col_filter: bool | None = False,
586
+ combine_multiindex: bool | int = False,
587
+ column_names_to_string: bool = True,
462
588
  ):
463
589
  """_summary_
464
590
 
@@ -481,107 +607,108 @@ def write_table(
481
607
  perc_col_format (str, optional): The formatting string of percentage columns. Defaults to None.
482
608
  col_filter (bool, optional): Set filter on columns. Defaults to False.
483
609
  """
610
+ arr = df_to_array(df)
611
+
612
+ blue_rows = []
613
+ light_blue_rows = []
614
+ light_blue_cols = []
615
+ blue_border_ids = []
616
+ r_align_ids = []
617
+ l_align_ids = []
618
+ p_ids = []
619
+ cells_to_merge = []
620
+ title_tbl = None
621
+ title_src = None
622
+
623
+ if isinstance(header_row, int):
624
+ blue_rows.extend(list(range(0, header_row + 1)))
484
625
 
485
- wb = Workbook()
486
- # Empty sheet is created on Workbook creation
487
- del wb["Sheet"]
488
-
489
- set_global_style(style)
490
-
491
- if not isinstance(data, dict):
492
- data = {"Sheet1": data}
493
-
494
- for sheet_name, df in data.items():
495
- arr = df_to_array(df)
496
-
497
- blue_rows = []
498
- light_blue_rows = []
499
- light_blue_cols = []
500
- blue_border_ids = []
501
- r_align_ids = []
502
- l_align_ids = []
503
- p_ids = []
504
- cells_to_merge = []
505
- title_tbl = None
506
-
507
- if isinstance(header_row, int):
508
- blue_rows.extend(list(range(0, header_row + 1)))
509
-
510
- if title:
511
- if isinstance(title, str):
512
- title_tbl = title
513
- elif isinstance(title, dict):
514
- title_tbl = title.get(sheet_name)
515
-
516
- if right_align_ids:
517
- r_align_ids.extend(right_align_ids)
626
+ if title:
627
+ if isinstance(title, str):
628
+ title_tbl = title
629
+ elif isinstance(title, dict):
630
+ title_tbl = title.get(sheet_name)
518
631
 
519
- if right_align_pattern:
520
- r_align_ids.extend(get_cols_id_with_pattern(df, right_align_pattern))
632
+ if source:
633
+ if isinstance(source, str):
634
+ title_src = source
635
+ elif isinstance(title, dict):
636
+ title_src = source.get(sheet_name)
521
637
 
522
- if right_align_numeric:
523
- r_align_ids.extend(get_numeric_col_ids(df))
638
+ if right_align_ids:
639
+ r_align_ids.extend(right_align_ids)
524
640
 
525
- if left_align_ids:
526
- r_align_ids.extend(left_align_ids)
641
+ if right_align_pattern:
642
+ r_align_ids.extend(get_cols_id_with_pattern(df, right_align_pattern))
527
643
 
528
- if left_align_pattern:
529
- l_align_ids.extend(get_cols_id_with_pattern(df, left_align_pattern))
644
+ if right_align_numeric:
645
+ r_align_ids.extend(get_numeric_col_ids(df))
530
646
 
531
- if left_align_string:
532
- l_align_ids.extend(get_string_cols_ids(df))
647
+ if left_align_ids:
648
+ r_align_ids.extend(left_align_ids)
533
649
 
534
- if perc_ids:
535
- p_ids.extend(perc_ids)
650
+ if left_align_pattern:
651
+ l_align_ids.extend(get_cols_id_with_pattern(df, left_align_pattern))
536
652
 
537
- if perc_pattern:
538
- r_id = get_cols_id_with_pattern(df, perc_pattern)
539
- p_ids.extend(r_id)
540
- r_align_ids.extend(r_id)
653
+ if left_align_string:
654
+ l_align_ids.extend(get_string_cols_ids(df))
541
655
 
542
- if total_row:
543
- light_blue_rows.append(arr.shape[0] - 1)
656
+ if perc_ids:
657
+ p_ids.extend(perc_ids)
544
658
 
545
- if light_blue_row_ids:
546
- light_blue_rows.extend(light_blue_row_ids)
659
+ if perc_pattern:
660
+ r_id = get_cols_id_with_pattern(df, perc_pattern)
661
+ p_ids.extend(r_id)
662
+ r_align_ids.extend(r_id)
547
663
 
548
- if total_col:
549
- light_blue_cols.append(arr.shape[1] - 1)
664
+ if total_row:
665
+ light_blue_rows.append(arr.shape[0] - 1)
550
666
 
551
- if blue_border:
552
- blue_border_ids.append(arr.shape[0] - 1)
667
+ if light_blue_row_ids:
668
+ light_blue_rows.extend(light_blue_row_ids)
553
669
 
554
- if blue_border_row_ids:
555
- blue_border_ids.extend(blue_border_row_ids)
670
+ if total_col:
671
+ light_blue_cols.append(arr.shape[1] - 1)
556
672
 
557
- if combine_multiindex:
558
- cells_to_merge = get_cells_to_merge(df)
673
+ if blue_border:
674
+ blue_border_ids.append(arr.shape[0] - 1)
559
675
 
560
- ws = wb.create_sheet(sheet_name)
676
+ if blue_border_row_ids:
677
+ blue_border_ids.extend(blue_border_row_ids)
561
678
 
562
- fmt = cell_formatting(
563
- arr=arr,
564
- default_format=STYLES["calibri"],
565
- blue_row_ids=blue_rows,
566
- light_blue_row_ids=light_blue_rows,
567
- light_blue_col_ids=light_blue_cols,
568
- left_align_ids=l_align_ids,
569
- right_align_ids=r_align_ids,
570
- perc_col_ids=p_ids,
571
- perc_col_format=perc_col_format,
572
- number_format=number_format,
573
- blue_border_ids=blue_border_ids,
574
- )
679
+ if combine_multiindex:
680
+ cells_to_merge = get_cells_to_merge(df)
575
681
 
576
- write_worksheet(
577
- ws=ws,
578
- arr=arr,
579
- fmt=fmt,
580
- title=title_tbl,
581
- source=source,
582
- col_filter=col_filter,
583
- autofit_columns=autofit_columns,
584
- cells_to_merge=cells_to_merge,
585
- )
682
+ if autofit_columns == "column_names":
683
+ col_widths = get_max_col_widths(df)
684
+ elif autofit_columns == "all_data":
685
+ col_widths = get_max_col_widths(arr)
686
+ else:
687
+ col_widths = None
688
+
689
+ ws = wb.create_sheet(sheet_name)
690
+
691
+ fmt = cell_formatting(
692
+ arr=arr,
693
+ default_format=STYLES["calibri"],
694
+ blue_row_ids=blue_rows,
695
+ light_blue_row_ids=light_blue_rows,
696
+ light_blue_col_ids=light_blue_cols,
697
+ left_align_ids=l_align_ids,
698
+ right_align_ids=r_align_ids,
699
+ perc_col_ids=p_ids,
700
+ perc_col_format=perc_col_format,
701
+ number_format=number_format,
702
+ blue_border_ids=blue_border_ids,
703
+ )
586
704
 
587
- wb.save(file)
705
+ write_to_worksheet(
706
+ ws=ws,
707
+ arr=arr,
708
+ fmt=fmt,
709
+ title=title_tbl,
710
+ source=title_src,
711
+ col_filter=col_filter,
712
+ col_widths=col_widths,
713
+ cells_to_merge=cells_to_merge,
714
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: toolsos
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: OS tools
5
5
  Author-email: OS <d.schmitz@amsterdam.nl>
6
6
  Keywords: tools,Onderzoek & Statistiek
@@ -1,12 +1,12 @@
1
1
  toolsos/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  toolsos/cbs_tools.py,sha256=VLhptzy7m5EaET07s6VeAfDz79g1Hs38qeWPyA14wkw,2823
3
3
  toolsos/create_tables.py,sha256=43FHK3EERjumBtnGhngIdtthZzcc_Qi37lJ1MgATzBg,908
4
- toolsos/database_connection.py,sha256=BlHzLS17KzJP_7R5-IBd8WqgwAt-zDRwJXD4Jx6Tetw,3323
5
- toolsos/database_transfer.py,sha256=1ghq5VEtKyOdCKdM45uOyrZSoXMuWsdC35R3WNuFvdU,1827
6
4
  toolsos/download.py,sha256=88hehmPL5m5d1nrcJjltuh4xrCItF5EYHaZdHOcSt-g,2652
7
5
  toolsos/geo.py,sha256=_OexkeUgXcnPW1mw27VN6fMcX2PMUSljLwIg48Xkv3M,2412
8
6
  toolsos/helpers.py,sha256=VeOl-fLgePCbjEmAQdVmYe7z8OE1pISeDDuP1t5QSxM,997
9
7
  toolsos/polars_helpers.py,sha256=P3RHLQFeDL7-9U_Q1n4ma_NSkdYAiker4pnc57uluHw,770
8
+ toolsos/database/database_connection.py,sha256=z5uDDfw3GPAjWp4rVLwNaE2xpW8n_pgfrZ7cf1D-Mks,3362
9
+ toolsos/database/database_transfer.py,sha256=1ghq5VEtKyOdCKdM45uOyrZSoXMuWsdC35R3WNuFvdU,1827
10
10
  toolsos/huisstijl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  toolsos/huisstijl/colors.py,sha256=lSCHCdSjge5cGfLfAObd6mV6TaXq3QGImLOmoGJpGkw,1484
12
12
  toolsos/huisstijl/graphs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -16,9 +16,10 @@ toolsos/huisstijl/graphs/linegraph.py,sha256=xTYgBwY_aaWnOL9Oz9Ogzhis9OIkEhDSIBk
16
16
  toolsos/huisstijl/graphs/piegraph.py,sha256=Pzc3vrbvlkv40V3OYWh6bDDc5arRRwJq7dfRzplPKWY,571
17
17
  toolsos/huisstijl/graphs/styler.py,sha256=XmPLX8sRxcH2OFWn49hzZ6IhAlmCHjUC_m9LKE9c3Sw,6626
18
18
  toolsos/huisstijl/tables/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
+ toolsos/huisstijl/tables/table_helpers.py,sha256=jsQ6lw93sxtGJGrUn8X2_LyA2vYYnytngpUI5A_wpWQ,2037
19
20
  toolsos/huisstijl/tables/table_styles.py,sha256=oYU6GJcfqlKpZof5PUjPsA7woJ3Tew78CHPyT0_jY6w,1343
20
- toolsos/huisstijl/tables/tables.py,sha256=geu-udWBbVFKk5CArhaTqJvoWPSmQ4-sC66CBkUWZug,19779
21
- toolsos-0.2.0.dist-info/METADATA,sha256=4AFPTjCSnQYcNRk7-m4ZgP40NIwl-Dv9SZbNb0iv0v8,2433
22
- toolsos-0.2.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
23
- toolsos-0.2.0.dist-info/top_level.txt,sha256=2ClEjUBbtfDQ8oPwvWRy1Sz2nrkLCXlg0mHaMdCWia0,8
24
- toolsos-0.2.0.dist-info/RECORD,,
21
+ toolsos/huisstijl/tables/tables.py,sha256=GDoo526nXq61tWM86KFaPy67ZmCza9GhkkksW_ATtM4,23575
22
+ toolsos-0.2.2.dist-info/METADATA,sha256=-3UieU8bcMm51-B6N1wdf8atHpOZFCdjakc7D1hp4Bk,2433
23
+ toolsos-0.2.2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
24
+ toolsos-0.2.2.dist-info/top_level.txt,sha256=2ClEjUBbtfDQ8oPwvWRy1Sz2nrkLCXlg0mHaMdCWia0,8
25
+ toolsos-0.2.2.dist-info/RECORD,,