hdx-python-utilities 4.0.2__tar.gz → 4.0.3__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 (138) hide show
  1. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/PKG-INFO +1 -1
  2. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/src/hdx/utilities/_version.py +2 -2
  3. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/src/hdx/utilities/path.py +1 -1
  4. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/src/hdx/utilities/saver.py +17 -8
  5. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/src/hdx/utilities/useragent.py +1 -1
  6. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/hdx/utilities/test_saver.py +9 -0
  7. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/.coveragerc +0 -0
  8. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/.github/workflows/publish-test.yaml +0 -0
  9. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/.github/workflows/publish.yaml +0 -0
  10. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/.github/workflows/run-python-tests.yaml +0 -0
  11. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/.gitignore +0 -0
  12. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/.pre-commit-config.yaml +0 -0
  13. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/CONTRIBUTING.md +0 -0
  14. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/LICENSE +0 -0
  15. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/README.md +0 -0
  16. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/documentation/.readthedocs.yaml +0 -0
  17. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/documentation/index.md +0 -0
  18. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/documentation/mkdocs.yaml +0 -0
  19. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/hatch.toml +0 -0
  20. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/pyproject.toml +0 -0
  21. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/pytest.ini +0 -0
  22. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/requirements.txt +0 -0
  23. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/ruff.toml +0 -0
  24. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/src/hdx/utilities/__init__.py +0 -0
  25. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/src/hdx/utilities/base_downloader.py +0 -0
  26. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/src/hdx/utilities/compare.py +0 -0
  27. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/src/hdx/utilities/dateparse.py +0 -0
  28. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/src/hdx/utilities/dictandlist.py +0 -0
  29. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/src/hdx/utilities/downloader.py +0 -0
  30. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/src/hdx/utilities/easy_logging.py +0 -0
  31. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/src/hdx/utilities/email.py +0 -0
  32. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/src/hdx/utilities/encoding.py +0 -0
  33. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/src/hdx/utilities/error_handler.py +0 -0
  34. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/src/hdx/utilities/errors_onexit.py +0 -0
  35. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/src/hdx/utilities/file_hashing.py +0 -0
  36. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/src/hdx/utilities/frictionless_wrapper.py +0 -0
  37. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/src/hdx/utilities/html.py +0 -0
  38. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/src/hdx/utilities/loader.py +0 -0
  39. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/src/hdx/utilities/matching.py +0 -0
  40. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/src/hdx/utilities/retriever.py +0 -0
  41. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/src/hdx/utilities/session.py +0 -0
  42. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/src/hdx/utilities/state.py +0 -0
  43. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/src/hdx/utilities/text.py +0 -0
  44. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/src/hdx/utilities/uuid.py +0 -0
  45. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/src/hdx/utilities/zip_crc.py +0 -0
  46. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/compare/test_csv_processing.csv +0 -0
  47. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/compare/test_csv_processing2.csv +0 -0
  48. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/config/empty.yaml +0 -0
  49. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/config/hdx_config.json +0 -0
  50. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/config/hdx_config.yaml +0 -0
  51. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/config/hdx_email_configuration.json +0 -0
  52. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/config/hdx_email_configuration.yaml +0 -0
  53. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/config/json_csv.yaml +0 -0
  54. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/config/logging_config.json +0 -0
  55. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/config/logging_config.yaml +0 -0
  56. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/config/project_configuration.json +0 -0
  57. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/config/project_configuration.yaml +0 -0
  58. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/config/smtp_config.json +0 -0
  59. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/config/smtp_config.yaml +0 -0
  60. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/config/user_agent_config.yaml +0 -0
  61. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/config/user_agent_config2.yaml +0 -0
  62. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/config/user_agent_config3.yaml +0 -0
  63. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/config/user_agent_config_wrong.yaml +0 -0
  64. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/downloader/basicauth.txt +0 -0
  65. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/downloader/bearertoken.txt +0 -0
  66. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/downloader/extra_params.json +0 -0
  67. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/downloader/extra_params.yaml +0 -0
  68. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/downloader/extra_params_tree.yaml +0 -0
  69. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/downloader/test_csv_processing.csv +0 -0
  70. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/downloader/test_csv_processing_blanks.csv +0 -0
  71. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/downloader/test_data.csv +0 -0
  72. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/downloader/test_data.xlsx +0 -0
  73. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/downloader/test_data1.csv/empty.txt +0 -0
  74. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/downloader/test_data2.csv +0 -0
  75. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/downloader/test_json_processing.json +0 -0
  76. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/downloader/test_xls_processing.xls +0 -0
  77. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/downloader/test_xlsx_processing.xlsx +0 -0
  78. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/file_hashing/bad_header.zip +0 -0
  79. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/file_hashing/bad_index.xlsx +0 -0
  80. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/file_hashing/empty.zip +0 -0
  81. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/file_hashing/test.xlsx +0 -0
  82. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/file_hashing/test_shapefile.zip +0 -0
  83. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/file_hashing/valid_sig_invalid_body.zip +0 -0
  84. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/html/response.html +0 -0
  85. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/loader/empty.json +0 -0
  86. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/loader/empty.yaml +0 -0
  87. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/loader/empty_list.json +0 -0
  88. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/retriever/fallbacks/test.csv +0 -0
  89. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/retriever/fallbacks/test.json +0 -0
  90. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/retriever/fallbacks/test.txt +0 -0
  91. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/retriever/fallbacks/test.yaml +0 -0
  92. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/retriever/retriever-test.csv +0 -0
  93. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/retriever/test.csv +0 -0
  94. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/retriever/test.json +0 -0
  95. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/retriever/test.txt +0 -0
  96. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/retriever/test.yaml +0 -0
  97. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/retriever/test_hxl.csv +0 -0
  98. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/saver/out.csv +0 -0
  99. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/saver/out.json +0 -0
  100. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/saver/out2.csv +0 -0
  101. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/saver/out2.json +0 -0
  102. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/saver/out5.json +0 -0
  103. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/saver/out6.json +0 -0
  104. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/saver/out7.json +0 -0
  105. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/saver/out8.csv +0 -0
  106. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/saver/out8.json +0 -0
  107. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/saver/pretty-false_sortkeys-false.json +0 -0
  108. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/saver/pretty-false_sortkeys-false.yaml +0 -0
  109. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/saver/pretty-false_sortkeys-true.json +0 -0
  110. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/saver/pretty-false_sortkeys-true.yaml +0 -0
  111. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/saver/pretty-true_sortkeys-false.json +0 -0
  112. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/saver/pretty-true_sortkeys-false.yaml +0 -0
  113. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/saver/pretty-true_sortkeys-true.json +0 -0
  114. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/saver/pretty-true_sortkeys-true.yaml +0 -0
  115. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/state/analysis_dates.txt +0 -0
  116. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/state/last_build_date.txt +0 -0
  117. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/fixtures/test_data.csv +0 -0
  118. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/hdx/conftest.py +0 -0
  119. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/hdx/utilities/test_compare.py +0 -0
  120. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/hdx/utilities/test_dateparse.py +0 -0
  121. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/hdx/utilities/test_dictandlist.py +0 -0
  122. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/hdx/utilities/test_downloader.py +0 -0
  123. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/hdx/utilities/test_easy_logging.py +0 -0
  124. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/hdx/utilities/test_email.py +0 -0
  125. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/hdx/utilities/test_encoding.py +0 -0
  126. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/hdx/utilities/test_error_handler.py +0 -0
  127. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/hdx/utilities/test_file_hashing.py +0 -0
  128. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/hdx/utilities/test_html.py +0 -0
  129. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/hdx/utilities/test_loader.py +0 -0
  130. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/hdx/utilities/test_matching.py +0 -0
  131. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/hdx/utilities/test_path.py +0 -0
  132. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/hdx/utilities/test_retriever.py +0 -0
  133. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/hdx/utilities/test_state.py +0 -0
  134. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/hdx/utilities/test_text.py +0 -0
  135. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/hdx/utilities/test_useragent.py +0 -0
  136. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/hdx/utilities/test_uuid.py +0 -0
  137. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/hdx/utilities/test_zip_crc.py +0 -0
  138. {hdx_python_utilities-4.0.2 → hdx_python_utilities-4.0.3}/tests/hdx/utilities/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hdx-python-utilities
3
- Version: 4.0.2
3
+ Version: 4.0.3
4
4
  Summary: HDX Python Utilities for streaming tabular data, date and time handling and other helpful functions
5
5
  Project-URL: Homepage, https://github.com/OCHA-DAP/hdx-python-utilities
6
6
  Author-email: Michael Rans <rans@email.com>
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '4.0.2'
32
- __version_tuple__ = version_tuple = (4, 0, 2)
31
+ __version__ = version = '4.0.3'
32
+ __version_tuple__ = version_tuple = (4, 0, 3)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -95,7 +95,7 @@ def get_temp_dir(
95
95
  tempdir = Path(tempdir)
96
96
  if folder:
97
97
  tempdir = tempdir / folder
98
- if exists(tempdir):
98
+ if tempdir.exists():
99
99
  if delete_if_exists:
100
100
  rmtree(tempdir)
101
101
  makedirs(tempdir)
@@ -279,6 +279,7 @@ def save_iterable(
279
279
  format: str = "csv",
280
280
  encoding: str | None = None,
281
281
  row_function: Callable[[dict], dict | None] | None = None,
282
+ no_empty: bool = True,
282
283
  ) -> list:
283
284
  """Save an iterable of rows in dict or list form to a csv. (The headers
284
285
  argument is either a row number (rows start counting at 1), or the actual
@@ -293,6 +294,7 @@ def save_iterable(
293
294
  format: Format to write. Defaults to csv.
294
295
  encoding: Encoding to use. Defaults to None (infer encoding).
295
296
  row_function: Row function to call for each row. Defaults to None.
297
+ no_empty: Don't save file if there are no data rows. Defaults to True.
296
298
 
297
299
  Returns:
298
300
  List of rows written to file
@@ -302,12 +304,26 @@ def save_iterable(
302
304
  def row_function(row):
303
305
  return row
304
306
 
307
+ def write_rows(newrows, has_header, headers) -> None:
308
+ resource = get_frictionless_tableresource(
309
+ data=newrows,
310
+ has_header=has_header,
311
+ headers=headers,
312
+ encoding=encoding,
313
+ )
314
+ resource.write(filepath, format=format, encoding=encoding)
315
+ resource.close()
316
+
305
317
  newrows = []
306
318
  rows = iter(rows)
307
319
  try:
308
320
  row = next(rows)
309
321
  except StopIteration:
322
+ if not no_empty and headers:
323
+ newrows = [headers]
324
+ write_rows(newrows, None, None)
310
325
  return newrows
326
+
311
327
  if isinstance(row, dict):
312
328
  has_header = True
313
329
  row = row_function(row)
@@ -371,12 +387,5 @@ def save_iterable(
371
387
  if row is None:
372
388
  continue
373
389
  newrows.append(row)
374
- resource = get_frictionless_tableresource(
375
- data=newrows,
376
- has_header=has_header,
377
- headers=headers,
378
- encoding=encoding,
379
- )
380
- resource.write(filepath, format=format, encoding=encoding)
381
- resource.close()
390
+ write_rows(newrows, has_header, headers)
382
391
  return newrows
@@ -83,7 +83,7 @@ class UserAgent:
83
83
  user agent
84
84
  """
85
85
  if not user_agent_config_yaml:
86
- user_agent_config_yaml = cls.default_user_agent_config_yaml
86
+ user_agent_config_yaml = Path(cls.default_user_agent_config_yaml)
87
87
  if not user_agent_config_yaml.is_file():
88
88
  user_agent_config_yaml = user_agent_config_yaml.with_suffix(".yml")
89
89
  if user_agent_config_yaml.is_file():
@@ -521,3 +521,12 @@ class TestLoader:
521
521
 
522
522
  rows = save_iterable(filepath, [], headers=["h1", "h3", "h4"])
523
523
  assert rows == []
524
+
525
+ rows = save_iterable(
526
+ filepath, [], headers=["h1", "h3", "h4"], no_empty=False
527
+ )
528
+ assert rows == [["h1", "h3", "h4"]]
529
+
530
+ newll = read_list_from_csv(str(filepath))
531
+ remove(filepath)
532
+ assert newll == [["h1", "h3", "h4"]]