tensorbored 2.21.0rc1769983804__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.
Files changed (271) hide show
  1. tensorbored/__init__.py +112 -0
  2. tensorbored/_vendor/__init__.py +0 -0
  3. tensorbored/_vendor/bleach/__init__.py +125 -0
  4. tensorbored/_vendor/bleach/_vendor/__init__.py +0 -0
  5. tensorbored/_vendor/bleach/_vendor/html5lib/__init__.py +35 -0
  6. tensorbored/_vendor/bleach/_vendor/html5lib/_ihatexml.py +289 -0
  7. tensorbored/_vendor/bleach/_vendor/html5lib/_inputstream.py +918 -0
  8. tensorbored/_vendor/bleach/_vendor/html5lib/_tokenizer.py +1735 -0
  9. tensorbored/_vendor/bleach/_vendor/html5lib/_trie/__init__.py +5 -0
  10. tensorbored/_vendor/bleach/_vendor/html5lib/_trie/_base.py +40 -0
  11. tensorbored/_vendor/bleach/_vendor/html5lib/_trie/py.py +67 -0
  12. tensorbored/_vendor/bleach/_vendor/html5lib/_utils.py +159 -0
  13. tensorbored/_vendor/bleach/_vendor/html5lib/constants.py +2946 -0
  14. tensorbored/_vendor/bleach/_vendor/html5lib/filters/__init__.py +0 -0
  15. tensorbored/_vendor/bleach/_vendor/html5lib/filters/alphabeticalattributes.py +29 -0
  16. tensorbored/_vendor/bleach/_vendor/html5lib/filters/base.py +12 -0
  17. tensorbored/_vendor/bleach/_vendor/html5lib/filters/inject_meta_charset.py +73 -0
  18. tensorbored/_vendor/bleach/_vendor/html5lib/filters/lint.py +93 -0
  19. tensorbored/_vendor/bleach/_vendor/html5lib/filters/optionaltags.py +207 -0
  20. tensorbored/_vendor/bleach/_vendor/html5lib/filters/sanitizer.py +916 -0
  21. tensorbored/_vendor/bleach/_vendor/html5lib/filters/whitespace.py +38 -0
  22. tensorbored/_vendor/bleach/_vendor/html5lib/html5parser.py +2795 -0
  23. tensorbored/_vendor/bleach/_vendor/html5lib/serializer.py +409 -0
  24. tensorbored/_vendor/bleach/_vendor/html5lib/treeadapters/__init__.py +30 -0
  25. tensorbored/_vendor/bleach/_vendor/html5lib/treeadapters/genshi.py +54 -0
  26. tensorbored/_vendor/bleach/_vendor/html5lib/treeadapters/sax.py +50 -0
  27. tensorbored/_vendor/bleach/_vendor/html5lib/treebuilders/__init__.py +88 -0
  28. tensorbored/_vendor/bleach/_vendor/html5lib/treebuilders/base.py +417 -0
  29. tensorbored/_vendor/bleach/_vendor/html5lib/treebuilders/dom.py +239 -0
  30. tensorbored/_vendor/bleach/_vendor/html5lib/treebuilders/etree.py +343 -0
  31. tensorbored/_vendor/bleach/_vendor/html5lib/treebuilders/etree_lxml.py +392 -0
  32. tensorbored/_vendor/bleach/_vendor/html5lib/treewalkers/__init__.py +154 -0
  33. tensorbored/_vendor/bleach/_vendor/html5lib/treewalkers/base.py +252 -0
  34. tensorbored/_vendor/bleach/_vendor/html5lib/treewalkers/dom.py +43 -0
  35. tensorbored/_vendor/bleach/_vendor/html5lib/treewalkers/etree.py +131 -0
  36. tensorbored/_vendor/bleach/_vendor/html5lib/treewalkers/etree_lxml.py +215 -0
  37. tensorbored/_vendor/bleach/_vendor/html5lib/treewalkers/genshi.py +69 -0
  38. tensorbored/_vendor/bleach/_vendor/parse.py +1078 -0
  39. tensorbored/_vendor/bleach/callbacks.py +32 -0
  40. tensorbored/_vendor/bleach/html5lib_shim.py +757 -0
  41. tensorbored/_vendor/bleach/linkifier.py +633 -0
  42. tensorbored/_vendor/bleach/parse_shim.py +1 -0
  43. tensorbored/_vendor/bleach/sanitizer.py +638 -0
  44. tensorbored/_vendor/bleach/six_shim.py +19 -0
  45. tensorbored/_vendor/webencodings/__init__.py +342 -0
  46. tensorbored/_vendor/webencodings/labels.py +231 -0
  47. tensorbored/_vendor/webencodings/mklabels.py +59 -0
  48. tensorbored/_vendor/webencodings/x_user_defined.py +325 -0
  49. tensorbored/assets.py +36 -0
  50. tensorbored/auth.py +102 -0
  51. tensorbored/backend/__init__.py +0 -0
  52. tensorbored/backend/application.py +604 -0
  53. tensorbored/backend/auth_context_middleware.py +38 -0
  54. tensorbored/backend/client_feature_flags.py +113 -0
  55. tensorbored/backend/empty_path_redirect.py +46 -0
  56. tensorbored/backend/event_processing/__init__.py +0 -0
  57. tensorbored/backend/event_processing/data_ingester.py +276 -0
  58. tensorbored/backend/event_processing/data_provider.py +535 -0
  59. tensorbored/backend/event_processing/directory_loader.py +142 -0
  60. tensorbored/backend/event_processing/directory_watcher.py +272 -0
  61. tensorbored/backend/event_processing/event_accumulator.py +950 -0
  62. tensorbored/backend/event_processing/event_file_inspector.py +463 -0
  63. tensorbored/backend/event_processing/event_file_loader.py +292 -0
  64. tensorbored/backend/event_processing/event_multiplexer.py +521 -0
  65. tensorbored/backend/event_processing/event_util.py +68 -0
  66. tensorbored/backend/event_processing/io_wrapper.py +223 -0
  67. tensorbored/backend/event_processing/plugin_asset_util.py +104 -0
  68. tensorbored/backend/event_processing/plugin_event_accumulator.py +721 -0
  69. tensorbored/backend/event_processing/plugin_event_multiplexer.py +522 -0
  70. tensorbored/backend/event_processing/reservoir.py +266 -0
  71. tensorbored/backend/event_processing/tag_types.py +29 -0
  72. tensorbored/backend/experiment_id.py +71 -0
  73. tensorbored/backend/experimental_plugin.py +51 -0
  74. tensorbored/backend/http_util.py +263 -0
  75. tensorbored/backend/json_util.py +70 -0
  76. tensorbored/backend/path_prefix.py +67 -0
  77. tensorbored/backend/process_graph.py +74 -0
  78. tensorbored/backend/security_validator.py +202 -0
  79. tensorbored/compat/__init__.py +69 -0
  80. tensorbored/compat/proto/__init__.py +0 -0
  81. tensorbored/compat/proto/allocation_description_pb2.py +35 -0
  82. tensorbored/compat/proto/api_def_pb2.py +82 -0
  83. tensorbored/compat/proto/attr_value_pb2.py +80 -0
  84. tensorbored/compat/proto/cluster_pb2.py +58 -0
  85. tensorbored/compat/proto/config_pb2.py +271 -0
  86. tensorbored/compat/proto/coordination_config_pb2.py +45 -0
  87. tensorbored/compat/proto/cost_graph_pb2.py +87 -0
  88. tensorbored/compat/proto/cpp_shape_inference_pb2.py +70 -0
  89. tensorbored/compat/proto/debug_pb2.py +65 -0
  90. tensorbored/compat/proto/event_pb2.py +149 -0
  91. tensorbored/compat/proto/full_type_pb2.py +74 -0
  92. tensorbored/compat/proto/function_pb2.py +157 -0
  93. tensorbored/compat/proto/graph_debug_info_pb2.py +111 -0
  94. tensorbored/compat/proto/graph_pb2.py +41 -0
  95. tensorbored/compat/proto/histogram_pb2.py +39 -0
  96. tensorbored/compat/proto/meta_graph_pb2.py +254 -0
  97. tensorbored/compat/proto/node_def_pb2.py +61 -0
  98. tensorbored/compat/proto/op_def_pb2.py +81 -0
  99. tensorbored/compat/proto/resource_handle_pb2.py +48 -0
  100. tensorbored/compat/proto/rewriter_config_pb2.py +93 -0
  101. tensorbored/compat/proto/rpc_options_pb2.py +35 -0
  102. tensorbored/compat/proto/saved_object_graph_pb2.py +193 -0
  103. tensorbored/compat/proto/saver_pb2.py +38 -0
  104. tensorbored/compat/proto/step_stats_pb2.py +116 -0
  105. tensorbored/compat/proto/struct_pb2.py +144 -0
  106. tensorbored/compat/proto/summary_pb2.py +111 -0
  107. tensorbored/compat/proto/tensor_description_pb2.py +38 -0
  108. tensorbored/compat/proto/tensor_pb2.py +68 -0
  109. tensorbored/compat/proto/tensor_shape_pb2.py +46 -0
  110. tensorbored/compat/proto/tfprof_log_pb2.py +307 -0
  111. tensorbored/compat/proto/trackable_object_graph_pb2.py +90 -0
  112. tensorbored/compat/proto/types_pb2.py +105 -0
  113. tensorbored/compat/proto/variable_pb2.py +62 -0
  114. tensorbored/compat/proto/verifier_config_pb2.py +38 -0
  115. tensorbored/compat/proto/versions_pb2.py +35 -0
  116. tensorbored/compat/tensorflow_stub/__init__.py +38 -0
  117. tensorbored/compat/tensorflow_stub/app.py +124 -0
  118. tensorbored/compat/tensorflow_stub/compat/__init__.py +131 -0
  119. tensorbored/compat/tensorflow_stub/compat/v1/__init__.py +20 -0
  120. tensorbored/compat/tensorflow_stub/dtypes.py +692 -0
  121. tensorbored/compat/tensorflow_stub/error_codes.py +169 -0
  122. tensorbored/compat/tensorflow_stub/errors.py +507 -0
  123. tensorbored/compat/tensorflow_stub/flags.py +124 -0
  124. tensorbored/compat/tensorflow_stub/io/__init__.py +17 -0
  125. tensorbored/compat/tensorflow_stub/io/gfile.py +1011 -0
  126. tensorbored/compat/tensorflow_stub/pywrap_tensorflow.py +285 -0
  127. tensorbored/compat/tensorflow_stub/tensor_shape.py +1035 -0
  128. tensorbored/context.py +129 -0
  129. tensorbored/data/__init__.py +0 -0
  130. tensorbored/data/grpc_provider.py +365 -0
  131. tensorbored/data/ingester.py +46 -0
  132. tensorbored/data/proto/__init__.py +0 -0
  133. tensorbored/data/proto/data_provider_pb2.py +517 -0
  134. tensorbored/data/proto/data_provider_pb2_grpc.py +374 -0
  135. tensorbored/data/provider.py +1365 -0
  136. tensorbored/data/server_ingester.py +301 -0
  137. tensorbored/data_compat.py +159 -0
  138. tensorbored/dataclass_compat.py +224 -0
  139. tensorbored/default.py +124 -0
  140. tensorbored/errors.py +130 -0
  141. tensorbored/lazy.py +99 -0
  142. tensorbored/main.py +48 -0
  143. tensorbored/main_lib.py +62 -0
  144. tensorbored/manager.py +487 -0
  145. tensorbored/notebook.py +441 -0
  146. tensorbored/plugin_util.py +266 -0
  147. tensorbored/plugins/__init__.py +0 -0
  148. tensorbored/plugins/audio/__init__.py +0 -0
  149. tensorbored/plugins/audio/audio_plugin.py +229 -0
  150. tensorbored/plugins/audio/metadata.py +69 -0
  151. tensorbored/plugins/audio/plugin_data_pb2.py +37 -0
  152. tensorbored/plugins/audio/summary.py +230 -0
  153. tensorbored/plugins/audio/summary_v2.py +124 -0
  154. tensorbored/plugins/base_plugin.py +367 -0
  155. tensorbored/plugins/core/__init__.py +0 -0
  156. tensorbored/plugins/core/core_plugin.py +981 -0
  157. tensorbored/plugins/custom_scalar/__init__.py +0 -0
  158. tensorbored/plugins/custom_scalar/custom_scalars_plugin.py +320 -0
  159. tensorbored/plugins/custom_scalar/layout_pb2.py +85 -0
  160. tensorbored/plugins/custom_scalar/metadata.py +35 -0
  161. tensorbored/plugins/custom_scalar/summary.py +79 -0
  162. tensorbored/plugins/debugger_v2/__init__.py +0 -0
  163. tensorbored/plugins/debugger_v2/debug_data_multiplexer.py +631 -0
  164. tensorbored/plugins/debugger_v2/debug_data_provider.py +634 -0
  165. tensorbored/plugins/debugger_v2/debugger_v2_plugin.py +504 -0
  166. tensorbored/plugins/distribution/__init__.py +0 -0
  167. tensorbored/plugins/distribution/compressor.py +158 -0
  168. tensorbored/plugins/distribution/distributions_plugin.py +116 -0
  169. tensorbored/plugins/distribution/metadata.py +19 -0
  170. tensorbored/plugins/graph/__init__.py +0 -0
  171. tensorbored/plugins/graph/graph_util.py +129 -0
  172. tensorbored/plugins/graph/graphs_plugin.py +336 -0
  173. tensorbored/plugins/graph/keras_util.py +328 -0
  174. tensorbored/plugins/graph/metadata.py +42 -0
  175. tensorbored/plugins/histogram/__init__.py +0 -0
  176. tensorbored/plugins/histogram/histograms_plugin.py +144 -0
  177. tensorbored/plugins/histogram/metadata.py +63 -0
  178. tensorbored/plugins/histogram/plugin_data_pb2.py +34 -0
  179. tensorbored/plugins/histogram/summary.py +234 -0
  180. tensorbored/plugins/histogram/summary_v2.py +292 -0
  181. tensorbored/plugins/hparams/__init__.py +14 -0
  182. tensorbored/plugins/hparams/_keras.py +93 -0
  183. tensorbored/plugins/hparams/api.py +130 -0
  184. tensorbored/plugins/hparams/api_pb2.py +208 -0
  185. tensorbored/plugins/hparams/backend_context.py +606 -0
  186. tensorbored/plugins/hparams/download_data.py +158 -0
  187. tensorbored/plugins/hparams/error.py +26 -0
  188. tensorbored/plugins/hparams/get_experiment.py +71 -0
  189. tensorbored/plugins/hparams/hparams_plugin.py +206 -0
  190. tensorbored/plugins/hparams/hparams_util_pb2.py +69 -0
  191. tensorbored/plugins/hparams/json_format_compat.py +38 -0
  192. tensorbored/plugins/hparams/list_metric_evals.py +57 -0
  193. tensorbored/plugins/hparams/list_session_groups.py +1040 -0
  194. tensorbored/plugins/hparams/metadata.py +125 -0
  195. tensorbored/plugins/hparams/metrics.py +41 -0
  196. tensorbored/plugins/hparams/plugin_data_pb2.py +69 -0
  197. tensorbored/plugins/hparams/summary.py +205 -0
  198. tensorbored/plugins/hparams/summary_v2.py +597 -0
  199. tensorbored/plugins/image/__init__.py +0 -0
  200. tensorbored/plugins/image/images_plugin.py +232 -0
  201. tensorbored/plugins/image/metadata.py +65 -0
  202. tensorbored/plugins/image/plugin_data_pb2.py +34 -0
  203. tensorbored/plugins/image/summary.py +159 -0
  204. tensorbored/plugins/image/summary_v2.py +130 -0
  205. tensorbored/plugins/mesh/__init__.py +14 -0
  206. tensorbored/plugins/mesh/mesh_plugin.py +292 -0
  207. tensorbored/plugins/mesh/metadata.py +152 -0
  208. tensorbored/plugins/mesh/plugin_data_pb2.py +37 -0
  209. tensorbored/plugins/mesh/summary.py +251 -0
  210. tensorbored/plugins/mesh/summary_v2.py +214 -0
  211. tensorbored/plugins/metrics/__init__.py +0 -0
  212. tensorbored/plugins/metrics/metadata.py +17 -0
  213. tensorbored/plugins/metrics/metrics_plugin.py +623 -0
  214. tensorbored/plugins/pr_curve/__init__.py +0 -0
  215. tensorbored/plugins/pr_curve/metadata.py +75 -0
  216. tensorbored/plugins/pr_curve/plugin_data_pb2.py +34 -0
  217. tensorbored/plugins/pr_curve/pr_curves_plugin.py +241 -0
  218. tensorbored/plugins/pr_curve/summary.py +574 -0
  219. tensorbored/plugins/profile_redirect/__init__.py +0 -0
  220. tensorbored/plugins/profile_redirect/profile_redirect_plugin.py +49 -0
  221. tensorbored/plugins/projector/__init__.py +67 -0
  222. tensorbored/plugins/projector/metadata.py +26 -0
  223. tensorbored/plugins/projector/projector_config_pb2.py +54 -0
  224. tensorbored/plugins/projector/projector_plugin.py +795 -0
  225. tensorbored/plugins/projector/tf_projector_plugin/index.js +32 -0
  226. tensorbored/plugins/projector/tf_projector_plugin/projector_binary.html +524 -0
  227. tensorbored/plugins/projector/tf_projector_plugin/projector_binary.js +15536 -0
  228. tensorbored/plugins/scalar/__init__.py +0 -0
  229. tensorbored/plugins/scalar/metadata.py +60 -0
  230. tensorbored/plugins/scalar/plugin_data_pb2.py +34 -0
  231. tensorbored/plugins/scalar/scalars_plugin.py +181 -0
  232. tensorbored/plugins/scalar/summary.py +109 -0
  233. tensorbored/plugins/scalar/summary_v2.py +124 -0
  234. tensorbored/plugins/text/__init__.py +0 -0
  235. tensorbored/plugins/text/metadata.py +62 -0
  236. tensorbored/plugins/text/plugin_data_pb2.py +34 -0
  237. tensorbored/plugins/text/summary.py +114 -0
  238. tensorbored/plugins/text/summary_v2.py +124 -0
  239. tensorbored/plugins/text/text_plugin.py +288 -0
  240. tensorbored/plugins/wit_redirect/__init__.py +0 -0
  241. tensorbored/plugins/wit_redirect/wit_redirect_plugin.py +49 -0
  242. tensorbored/program.py +910 -0
  243. tensorbored/summary/__init__.py +35 -0
  244. tensorbored/summary/_output.py +124 -0
  245. tensorbored/summary/_tf/__init__.py +14 -0
  246. tensorbored/summary/_tf/summary/__init__.py +178 -0
  247. tensorbored/summary/_writer.py +105 -0
  248. tensorbored/summary/v1.py +51 -0
  249. tensorbored/summary/v2.py +25 -0
  250. tensorbored/summary/writer/__init__.py +13 -0
  251. tensorbored/summary/writer/event_file_writer.py +291 -0
  252. tensorbored/summary/writer/record_writer.py +50 -0
  253. tensorbored/util/__init__.py +0 -0
  254. tensorbored/util/encoder.py +116 -0
  255. tensorbored/util/grpc_util.py +311 -0
  256. tensorbored/util/img_mime_type_detector.py +40 -0
  257. tensorbored/util/io_util.py +20 -0
  258. tensorbored/util/lazy_tensor_creator.py +110 -0
  259. tensorbored/util/op_evaluator.py +104 -0
  260. tensorbored/util/platform_util.py +20 -0
  261. tensorbored/util/tb_logging.py +24 -0
  262. tensorbored/util/tensor_util.py +617 -0
  263. tensorbored/util/timing.py +122 -0
  264. tensorbored/version.py +21 -0
  265. tensorbored/webfiles.zip +0 -0
  266. tensorbored-2.21.0rc1769983804.dist-info/METADATA +49 -0
  267. tensorbored-2.21.0rc1769983804.dist-info/RECORD +271 -0
  268. tensorbored-2.21.0rc1769983804.dist-info/WHEEL +5 -0
  269. tensorbored-2.21.0rc1769983804.dist-info/entry_points.txt +6 -0
  270. tensorbored-2.21.0rc1769983804.dist-info/licenses/LICENSE +739 -0
  271. tensorbored-2.21.0rc1769983804.dist-info/top_level.txt +1 -0
@@ -0,0 +1,292 @@
1
+ # Copyright 2015 The TensorFlow Authors. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+
16
+ """Functionality for loading events from a record file."""
17
+
18
+ import contextlib
19
+
20
+ from tensorbored import data_compat
21
+ from tensorbored import dataclass_compat
22
+ from tensorbored.compat import tf
23
+ from tensorbored.compat.proto import event_pb2
24
+ from tensorbored.util import platform_util
25
+ from tensorbored.util import tb_logging
26
+
27
+ logger = tb_logging.get_logger()
28
+
29
+
30
+ @contextlib.contextmanager
31
+ def _nullcontext():
32
+ """Pre-Python-3.7-compatible standin for contextlib.nullcontext."""
33
+ yield
34
+
35
+
36
+ # Might as well make this a singleton.
37
+ _NULLCONTEXT = _nullcontext()
38
+
39
+
40
+ def _silence_deprecation_warnings():
41
+ """Context manager that best-effort silences TF deprecation warnings."""
42
+ try:
43
+ # Learn this one weird trick to make TF deprecation warnings go away.
44
+ from tensorflow.python.util import deprecation
45
+
46
+ return deprecation.silence()
47
+ except (ImportError, AttributeError):
48
+ return _NULLCONTEXT
49
+
50
+
51
+ def _make_tf_record_iterator(file_path):
52
+ """Returns an iterator over TF records for the given tfrecord file."""
53
+ # If we don't have TF at all, use the stub implementation.
54
+ if tf.__version__ == "stub":
55
+ # TODO(#1711): Reshape stub implementation to fit tf_record_iterator API
56
+ # rather than needlessly emulating the old PyRecordReader_New API.
57
+ logger.debug("Opening a stub record reader pointing at %s", file_path)
58
+ return _PyRecordReaderIterator(
59
+ tf.pywrap_tensorflow.PyRecordReader_New, file_path
60
+ )
61
+ # If PyRecordReader exists, use it, otherwise use tf_record_iterator().
62
+ # Check old first, then new, since tf_record_iterator existed previously but
63
+ # only gained the semantics we need at the time PyRecordReader was removed.
64
+ #
65
+ # TODO(#1711): Eventually remove PyRecordReader fallback once we can drop
66
+ # support for TF 2.1 and prior, and find a non-deprecated replacement for
67
+ # tf.compat.v1.io.tf_record_iterator.
68
+ try:
69
+ from tensorflow.python import pywrap_tensorflow
70
+
71
+ py_record_reader_new = pywrap_tensorflow.PyRecordReader_New
72
+ except (ImportError, AttributeError):
73
+ py_record_reader_new = None
74
+ if py_record_reader_new:
75
+ logger.debug("Opening a PyRecordReader pointing at %s", file_path)
76
+ return _PyRecordReaderIterator(py_record_reader_new, file_path)
77
+ else:
78
+ logger.debug("Opening a tf_record_iterator pointing at %s", file_path)
79
+ # TODO(#1711): Find non-deprecated replacement for tf_record_iterator.
80
+ with _silence_deprecation_warnings():
81
+ return tf.compat.v1.io.tf_record_iterator(file_path)
82
+
83
+
84
+ class _PyRecordReaderIterator:
85
+ """Python iterator for TF Records based on PyRecordReader."""
86
+
87
+ def __init__(self, py_record_reader_new, file_path):
88
+ """Constructs a _PyRecordReaderIterator for the given file path.
89
+
90
+ Args:
91
+ py_record_reader_new: pywrap_tensorflow.PyRecordReader_New
92
+ file_path: file path of the tfrecord file to read
93
+ """
94
+ with tf.compat.v1.errors.raise_exception_on_not_ok_status() as status:
95
+ self._reader = py_record_reader_new(
96
+ tf.compat.as_bytes(file_path), 0, tf.compat.as_bytes(""), status
97
+ )
98
+ if not self._reader:
99
+ raise IOError(
100
+ "Failed to open a record reader pointing to %s" % file_path
101
+ )
102
+
103
+ def __iter__(self):
104
+ return self
105
+
106
+ def __next__(self):
107
+ try:
108
+ self._reader.GetNext()
109
+ except tf.errors.OutOfRangeError as e:
110
+ raise StopIteration
111
+ return self._reader.record()
112
+
113
+ next = __next__ # for python2 compatibility
114
+
115
+
116
+ class RawEventFileLoader:
117
+ """An iterator that yields Event protos as serialized bytestrings."""
118
+
119
+ def __init__(self, file_path, detect_file_replacement=False):
120
+ """Constructs a RawEventFileLoader for the given file path.
121
+
122
+ Args:
123
+ file_path: the event file path to read from
124
+ detect_file_replacement: if True, when Load() is called, the loader
125
+ will make a stat() call to check the size of the file. If it sees
126
+ that the file has grown, it will reopen the file entirely (while
127
+ preserving the current offset) before attempting to read from it.
128
+ Otherwise, Load() will simply poll at EOF for new data.
129
+ """
130
+ if file_path is None:
131
+ raise ValueError("A file path is required")
132
+ self._file_path = platform_util.readahead_file_path(file_path)
133
+ self._detect_file_replacement = detect_file_replacement
134
+ self._file_size = None
135
+ self._iterator = _make_tf_record_iterator(self._file_path)
136
+ if self._detect_file_replacement and not hasattr(
137
+ self._iterator, "reopen"
138
+ ):
139
+ logger.warning(
140
+ "File replacement detection requested, but not enabled because "
141
+ "TF record iterator impl does not support reopening. This "
142
+ "functionality requires TensorFlow 2.9+"
143
+ )
144
+ self._detect_file_replacement = False
145
+
146
+ def Load(self):
147
+ """Loads all new events from disk as raw serialized proto bytestrings.
148
+
149
+ Calling Load multiple times in a row will not 'drop' events as long as the
150
+ return value is not iterated over.
151
+
152
+ Yields:
153
+ All event proto bytestrings in the file that have not been yielded yet.
154
+ """
155
+ logger.debug("Loading events from %s", self._file_path)
156
+ if self._detect_file_replacement:
157
+ has_increased = self.CheckForIncreasedFileSize()
158
+ # Only act on the file size information if we got a concrete result.
159
+ if has_increased is not None:
160
+ if has_increased:
161
+ logger.debug(
162
+ "Reopening %s since file size has changed",
163
+ self._file_path,
164
+ )
165
+ self._iterator.close()
166
+ self._iterator.reopen()
167
+ else:
168
+ logger.debug(
169
+ "Skipping attempt to poll %s since file size has not "
170
+ "changed (still %d)",
171
+ self._file_path,
172
+ self._file_size,
173
+ )
174
+ return
175
+ while True:
176
+ try:
177
+ yield next(self._iterator)
178
+ except StopIteration:
179
+ logger.debug("End of file in %s", self._file_path)
180
+ break
181
+ except tf.errors.DataLossError as e:
182
+ # We swallow partial read exceptions; if the record was truncated
183
+ # and a later update completes it, retrying can then resume from
184
+ # the same point in the file since the iterator holds the offset.
185
+ logger.debug("Truncated record in %s (%s)", self._file_path, e)
186
+ break
187
+ logger.debug("No more events in %s", self._file_path)
188
+
189
+ def CheckForIncreasedFileSize(self):
190
+ """Stats the file to get its updated size, returning True if it grew.
191
+
192
+ If the stat call fails or reports a smaller size than was previously
193
+ seen, then any previously cached size is left unchanged.
194
+
195
+ Returns:
196
+ boolean or None: True if the file size increased; False if it was
197
+ the same or decreased; or None if neither case could be detected
198
+ (either because the previous size had not been recorded yet, or
199
+ because the stat call for the current size failed).
200
+ """
201
+ previous_size = self._file_size
202
+ try:
203
+ self._file_size = tf.io.gfile.stat(self._file_path).length
204
+ except tf.errors.OpError as e:
205
+ logger.error("Failed to stat %s: %s", self._file_path, e)
206
+ return None
207
+ logger.debug(
208
+ "Stat on %s got size %d, previous size %s",
209
+ self._file_path,
210
+ self._file_size,
211
+ previous_size,
212
+ )
213
+ if previous_size is None:
214
+ return None
215
+ if self._file_size > previous_size:
216
+ return True
217
+ if self._file_size < previous_size:
218
+ logger.warning(
219
+ "File %s shrank from previous size %d to size %d",
220
+ self._file_path,
221
+ previous_size,
222
+ self._file_size,
223
+ )
224
+ # In case this was transient, preserve the previously cached size,
225
+ # to avoid reporting a spurious increase next time. If the file was
226
+ # actually truncated, we can't recover anyway, so just ignore it.
227
+ self._file_size = previous_size
228
+ return False
229
+
230
+
231
+ class LegacyEventFileLoader(RawEventFileLoader):
232
+ """An iterator that yields parsed Event protos."""
233
+
234
+ def Load(self):
235
+ """Loads all new events from disk.
236
+
237
+ Calling Load multiple times in a row will not 'drop' events as long as the
238
+ return value is not iterated over.
239
+
240
+ Yields:
241
+ All events in the file that have not been yielded yet.
242
+ """
243
+ for record in super().Load():
244
+ yield event_pb2.Event.FromString(record)
245
+
246
+
247
+ class EventFileLoader(LegacyEventFileLoader):
248
+ """An iterator that passes events through read-time compat layers.
249
+
250
+ Specifically, this includes `data_compat` and `dataclass_compat`.
251
+ """
252
+
253
+ def __init__(self, *args, **kwargs):
254
+ super().__init__(*args, **kwargs)
255
+ # Track initial metadata for each tag, for `dataclass_compat`.
256
+ # This is meant to be tracked per run, not per event file, so
257
+ # there is a potential failure case when the second event file
258
+ # in a single run has no summary metadata. This only occurs when
259
+ # all of the following hold: (a) the events were written with
260
+ # the TensorFlow 1.x (not 2.x) writer, (b) the summaries were
261
+ # created by `tensorboard.summary.v1` ops and so do not undergo
262
+ # `data_compat` transformation, and (c) the file writer was
263
+ # reopened by calling `.reopen()` on it, which creates a new
264
+ # file but does not clear the tag cache. This is considered
265
+ # sufficiently improbable that we don't take extra mitigations.
266
+ self._initial_metadata = {} # from tag name to `SummaryMetadata`
267
+
268
+ def Load(self):
269
+ for event in super().Load():
270
+ event = data_compat.migrate_event(event)
271
+ events = dataclass_compat.migrate_event(
272
+ event, self._initial_metadata
273
+ )
274
+ for event in events:
275
+ yield event
276
+
277
+
278
+ class TimestampedEventFileLoader(EventFileLoader):
279
+ """An iterator that yields (UNIX timestamp float, Event proto) pairs."""
280
+
281
+ def Load(self):
282
+ """Loads all new events and their wall time values from disk.
283
+
284
+ Calling Load multiple times in a row will not 'drop' events as long as the
285
+ return value is not iterated over.
286
+
287
+ Yields:
288
+ Pairs of (UNIX timestamp float, Event proto) for all events in the file
289
+ that have not been yielded yet.
290
+ """
291
+ for event in super().Load():
292
+ yield (event.wall_time, event)