taskcluster-taskgraph 9.1.0__tar.gz → 9.2.1__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 (139) hide show
  1. {taskcluster-taskgraph-9.1.0/src/taskcluster_taskgraph.egg-info → taskcluster-taskgraph-9.2.1}/PKG-INFO +1 -1
  2. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1/src/taskcluster_taskgraph.egg-info}/PKG-INFO +1 -1
  3. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/__init__.py +1 -1
  4. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/run-task/fetch-content +22 -7
  5. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_scripts_fetch_content.py +6 -0
  6. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/LICENSE +0 -0
  7. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/MANIFEST.in +0 -0
  8. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/README.rst +0 -0
  9. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/pyproject.toml +0 -0
  10. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/requirements/base.in +0 -0
  11. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/requirements/base.txt +0 -0
  12. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/requirements/dev.in +0 -0
  13. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/requirements/dev.txt +0 -0
  14. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/requirements/test.in +0 -0
  15. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/requirements/test.txt +0 -0
  16. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/setup.cfg +0 -0
  17. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/setup.py +0 -0
  18. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskcluster_taskgraph.egg-info/SOURCES.txt +0 -0
  19. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskcluster_taskgraph.egg-info/dependency_links.txt +0 -0
  20. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskcluster_taskgraph.egg-info/entry_points.txt +0 -0
  21. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskcluster_taskgraph.egg-info/requires.txt +0 -0
  22. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskcluster_taskgraph.egg-info/top_level.txt +0 -0
  23. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/actions/__init__.py +0 -0
  24. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/actions/add_new_jobs.py +0 -0
  25. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/actions/cancel.py +0 -0
  26. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/actions/cancel_all.py +0 -0
  27. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/actions/rebuild_cached_tasks.py +0 -0
  28. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/actions/registry.py +0 -0
  29. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/actions/retrigger.py +0 -0
  30. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/actions/util.py +0 -0
  31. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/config.py +0 -0
  32. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/create.py +0 -0
  33. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/decision.py +0 -0
  34. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/docker.py +0 -0
  35. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/filter_tasks.py +0 -0
  36. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/generator.py +0 -0
  37. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/graph.py +0 -0
  38. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/loader/__init__.py +0 -0
  39. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/loader/default.py +0 -0
  40. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/loader/transform.py +0 -0
  41. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/main.py +0 -0
  42. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/morph.py +0 -0
  43. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/optimize/__init__.py +0 -0
  44. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/optimize/base.py +0 -0
  45. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/optimize/strategies.py +0 -0
  46. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/parameters.py +0 -0
  47. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/run-task/hgrc +0 -0
  48. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/run-task/robustcheckout.py +0 -0
  49. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/run-task/run-task +0 -0
  50. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/target_tasks.py +0 -0
  51. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/task.py +0 -0
  52. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/taskgraph.py +0 -0
  53. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/transforms/__init__.py +0 -0
  54. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/transforms/base.py +0 -0
  55. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/transforms/cached_tasks.py +0 -0
  56. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/transforms/chunking.py +0 -0
  57. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/transforms/code_review.py +0 -0
  58. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/transforms/docker_image.py +0 -0
  59. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/transforms/fetch.py +0 -0
  60. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/transforms/from_deps.py +0 -0
  61. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/transforms/notify.py +0 -0
  62. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/transforms/run/__init__.py +0 -0
  63. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/transforms/run/common.py +0 -0
  64. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/transforms/run/index_search.py +0 -0
  65. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/transforms/run/run_task.py +0 -0
  66. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/transforms/run/toolchain.py +0 -0
  67. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/transforms/task.py +0 -0
  68. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/transforms/task_context.py +0 -0
  69. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/util/__init__.py +0 -0
  70. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/util/archive.py +0 -0
  71. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/util/attributes.py +0 -0
  72. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/util/cached_tasks.py +0 -0
  73. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/util/copy.py +0 -0
  74. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/util/dependencies.py +0 -0
  75. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/util/docker.py +0 -0
  76. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/util/hash.py +0 -0
  77. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/util/keyed_by.py +0 -0
  78. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/util/parameterization.py +0 -0
  79. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/util/path.py +0 -0
  80. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/util/python_path.py +0 -0
  81. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/util/readonlydict.py +0 -0
  82. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/util/schema.py +0 -0
  83. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/util/set_name.py +0 -0
  84. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/util/shell.py +0 -0
  85. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/util/taskcluster.py +0 -0
  86. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/util/taskgraph.py +0 -0
  87. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/util/templates.py +0 -0
  88. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/util/time.py +0 -0
  89. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/util/treeherder.py +0 -0
  90. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/util/vcs.py +0 -0
  91. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/util/verify.py +0 -0
  92. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/util/workertypes.py +0 -0
  93. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/src/taskgraph/util/yaml.py +0 -0
  94. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_actions_rebuild_cached_tasks.py +0 -0
  95. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_actions_registry.py +0 -0
  96. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_create.py +0 -0
  97. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_decision.py +0 -0
  98. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_docker.py +0 -0
  99. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_generator.py +0 -0
  100. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_graph.py +0 -0
  101. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_main.py +0 -0
  102. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_morph.py +0 -0
  103. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_optimize.py +0 -0
  104. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_optimize_strategies.py +0 -0
  105. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_parameters.py +0 -0
  106. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_scripts_run_task.py +0 -0
  107. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_target_tasks.py +0 -0
  108. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_taskgraph.py +0 -0
  109. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_transform_chunking.py +0 -0
  110. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_transform_docker_image.py +0 -0
  111. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_transform_task_context.py +0 -0
  112. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_transforms_base.py +0 -0
  113. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_transforms_cached_tasks.py +0 -0
  114. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_transforms_fetch.py +0 -0
  115. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_transforms_from_deps.py +0 -0
  116. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_transforms_notify.py +0 -0
  117. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_transforms_run.py +0 -0
  118. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_transforms_run_run_task.py +0 -0
  119. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_transforms_run_toolchain.py +0 -0
  120. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_transforms_task.py +0 -0
  121. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_util_archive.py +0 -0
  122. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_util_attributes.py +0 -0
  123. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_util_cached_tasks.py +0 -0
  124. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_util_copy.py +0 -0
  125. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_util_dependencies.py +0 -0
  126. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_util_docker.py +0 -0
  127. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_util_parameterization.py +0 -0
  128. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_util_path.py +0 -0
  129. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_util_python_path.py +0 -0
  130. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_util_readonlydict.py +0 -0
  131. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_util_schema.py +0 -0
  132. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_util_taskcluster.py +0 -0
  133. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_util_templates.py +0 -0
  134. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_util_time.py +0 -0
  135. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_util_treeherder.py +0 -0
  136. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_util_vcs.py +0 -0
  137. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_util_verify.py +0 -0
  138. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_util_workertypes.py +0 -0
  139. {taskcluster-taskgraph-9.1.0 → taskcluster-taskgraph-9.2.1}/test/test_util_yaml.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: taskcluster-taskgraph
3
- Version: 9.1.0
3
+ Version: 9.2.1
4
4
  Summary: Build taskcluster taskgraphs
5
5
  Home-page: https://github.com/taskcluster/taskgraph
6
6
  Classifier: Development Status :: 5 - Production/Stable
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: taskcluster-taskgraph
3
- Version: 9.1.0
3
+ Version: 9.2.1
4
4
  Summary: Build taskcluster taskgraphs
5
5
  Home-page: https://github.com/taskcluster/taskgraph
6
6
  Classifier: Development Status :: 5 - Production/Stable
@@ -2,7 +2,7 @@
2
2
  # License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
4
 
5
- __version__ = "9.1.0"
5
+ __version__ = "9.2.1"
6
6
 
7
7
  # Maximum number of dependencies a single task can have
8
8
  # https://docs.taskcluster.net/reference/platform/taskcluster-queue/references/api#createTask
@@ -194,6 +194,25 @@ def stream_download(url, sha256=None, size=None, headers=None):
194
194
  ) if certifi else urllib.request.urlopen(req, timeout=60) as fh:
195
195
  if not url.endswith(".gz") and fh.info().get("Content-Encoding") == "gzip":
196
196
  fh = gzip.GzipFile(fileobj=fh)
197
+ else:
198
+ # when using gzip we can't compare size or length (inflated) against content-length (compressed)
199
+ content_length = fh.getheader("content-length")
200
+ if content_length:
201
+ try:
202
+ content_length = int(content_length)
203
+ except ValueError:
204
+ raise IntegrityError(
205
+ "content-length header for %s is not an integer; got %s"
206
+ % (url, content_length)
207
+ )
208
+ if size:
209
+ if size != content_length:
210
+ raise IntegrityError(
211
+ "size mismatch on %s: wanted %d; content-length is %d"
212
+ % (url, size, content_length)
213
+ )
214
+ else:
215
+ size = content_length
197
216
 
198
217
  while True:
199
218
  chunk = fh.read(65536)
@@ -252,8 +271,6 @@ def download_to_path(url, path, sha256=None, size=None, headers=None):
252
271
  fh.write(chunk)
253
272
 
254
273
  return
255
- except IntegrityError:
256
- raise
257
274
  except Exception as e:
258
275
  log("Download failed: {}".format(e))
259
276
  continue
@@ -264,17 +281,15 @@ def download_to_path(url, path, sha256=None, size=None, headers=None):
264
281
  def download_to_memory(url, sha256=None, size=None):
265
282
  """Download a URL to memory, possibly with verification."""
266
283
 
267
- data = b""
268
284
  for _ in retrier(attempts=5, sleeptime=60):
269
- try:
270
- log("Downloading %s" % (url))
285
+ data = b""
286
+ log("Downloading %s" % (url))
271
287
 
288
+ try:
272
289
  for chunk in stream_download(url, sha256=sha256, size=size):
273
290
  data += chunk
274
291
 
275
292
  return data
276
- except IntegrityError:
277
- raise
278
293
  except Exception as e:
279
294
  log("Download failed: {}".format(e))
280
295
  continue
@@ -73,7 +73,13 @@ def test_stream_download(
73
73
  # create a mock context manager
74
74
  cm = MagicMock()
75
75
  cm.getcode.return_value = 200
76
+
77
+ def getheader(field):
78
+ if field.lower() == "content-length":
79
+ return size
80
+
76
81
  # simulates chunking
82
+ cm.getheader = getheader
77
83
  cm.read.side_effect = [b"foo", b"bar", None]
78
84
  cm.__enter__.return_value = cm
79
85
  return cm