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,441 @@
1
+ # Copyright 2019 The TensorFlow Authors. All Rights Reserved.
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+ # ==============================================================================
14
+ """Utilities for using TensorBoard in notebook contexts, like Colab.
15
+
16
+ These APIs are experimental and subject to change.
17
+ """
18
+
19
+ import datetime
20
+ import errno
21
+ import html
22
+ import json
23
+ import os
24
+ import random
25
+ import shlex
26
+ import textwrap
27
+ import time
28
+
29
+ from tensorbored import manager
30
+
31
+ # Return values for `_get_context` (see that function's docs for
32
+ # details).
33
+ _CONTEXT_COLAB = "_CONTEXT_COLAB"
34
+ _CONTEXT_IPYTHON = "_CONTEXT_IPYTHON"
35
+ _CONTEXT_NONE = "_CONTEXT_NONE"
36
+
37
+
38
+ def _get_context():
39
+ """Determine the most specific context that we're in.
40
+
41
+ Returns:
42
+ _CONTEXT_COLAB: If in Colab with an IPython notebook context.
43
+ _CONTEXT_IPYTHON: If not in Colab, but we are in an IPython notebook
44
+ context (e.g., from running `jupyter notebook` at the command
45
+ line).
46
+ _CONTEXT_NONE: Otherwise (e.g., by running a Python script at the
47
+ command-line or using the `ipython` interactive shell).
48
+ """
49
+ # In Colab, the `google.colab` module is available, but the shell
50
+ # returned by `IPython.get_ipython` does not have a `get_trait`
51
+ # method.
52
+ try:
53
+ import google.colab # noqa: F401
54
+ import IPython
55
+ except ImportError:
56
+ pass
57
+ else:
58
+ if IPython.get_ipython() is not None:
59
+ # We'll assume that we're in a Colab notebook context.
60
+ return _CONTEXT_COLAB
61
+
62
+ # In an IPython command line shell or Jupyter notebook, we can
63
+ # directly query whether we're in a notebook context.
64
+ try:
65
+ import IPython
66
+ except ImportError:
67
+ pass
68
+ else:
69
+ ipython = IPython.get_ipython()
70
+ if ipython is not None and ipython.has_trait("kernel"):
71
+ return _CONTEXT_IPYTHON
72
+
73
+ # Otherwise, we're not in a known notebook context.
74
+ return _CONTEXT_NONE
75
+
76
+
77
+ def load_ipython_extension(ipython):
78
+ """Deprecated: use `%load_ext tensorbored` instead.
79
+
80
+ Raises:
81
+ RuntimeError: Always.
82
+ """
83
+ raise RuntimeError(
84
+ "Use '%load_ext tensorbored' instead of '%load_ext tensorbored.notebook'."
85
+ )
86
+
87
+
88
+ def _load_ipython_extension(ipython):
89
+ """Load the TensorBoard notebook extension.
90
+
91
+ Intended to be called from `%load_ext tensorbored`. Do not invoke this
92
+ directly.
93
+
94
+ Args:
95
+ ipython: An `IPython.InteractiveShell` instance.
96
+ """
97
+ _register_magics(ipython)
98
+
99
+
100
+ def _register_magics(ipython):
101
+ """Register IPython line/cell magics.
102
+
103
+ Args:
104
+ ipython: An `InteractiveShell` instance.
105
+ """
106
+ ipython.register_magic_function(
107
+ _start_magic,
108
+ magic_kind="line",
109
+ magic_name="tensorbored",
110
+ )
111
+
112
+
113
+ def _start_magic(line):
114
+ """Implementation of the `%tensorbored` line magic."""
115
+ return start(line)
116
+
117
+
118
+ def start(args_string):
119
+ """Launch and display a TensorBoard instance as if at the command line.
120
+
121
+ Args:
122
+ args_string: Command-line arguments to TensorBoard, to be
123
+ interpreted by `shlex.split`: e.g., "--logdir ./logs --port 0".
124
+ Shell metacharacters are not supported: e.g., "--logdir 2>&1" will
125
+ point the logdir at the literal directory named "2>&1".
126
+ """
127
+ context = _get_context()
128
+ try:
129
+ import IPython
130
+ import IPython.display
131
+ except ImportError:
132
+ IPython = None
133
+
134
+ if context == _CONTEXT_NONE:
135
+ handle = None
136
+ print("Launching TensorBoard...")
137
+ else:
138
+ handle = IPython.display.display(
139
+ IPython.display.Pretty("Launching TensorBoard..."),
140
+ display_id=True,
141
+ )
142
+
143
+ def print_or_update(message):
144
+ if handle is None:
145
+ print(message)
146
+ else:
147
+ handle.update(IPython.display.Pretty(message))
148
+
149
+ parsed_args = shlex.split(args_string, comments=True, posix=True)
150
+ start_result = manager.start(parsed_args)
151
+
152
+ if isinstance(start_result, manager.StartLaunched):
153
+ _display(
154
+ port=start_result.info.port,
155
+ print_message=False,
156
+ display_handle=handle,
157
+ )
158
+
159
+ elif isinstance(start_result, manager.StartReused):
160
+ template = (
161
+ "Reusing TensorBoard on port {port} (pid {pid}), started {delta} ago. "
162
+ "(Use '!kill {pid}' to kill it.)"
163
+ )
164
+ message = template.format(
165
+ port=start_result.info.port,
166
+ pid=start_result.info.pid,
167
+ delta=_time_delta_from_info(start_result.info),
168
+ )
169
+ print_or_update(message)
170
+ _display(
171
+ port=start_result.info.port,
172
+ print_message=False,
173
+ display_handle=None,
174
+ )
175
+
176
+ elif isinstance(start_result, manager.StartFailed):
177
+
178
+ def format_stream(name, value):
179
+ if value == "":
180
+ return ""
181
+ elif value is None:
182
+ return "\n<could not read %s>" % name
183
+ else:
184
+ return "\nContents of %s:\n%s" % (name, value.strip())
185
+
186
+ message = (
187
+ "ERROR: Failed to launch TensorBoard (exited with %d).%s%s"
188
+ % (
189
+ start_result.exit_code,
190
+ format_stream("stderr", start_result.stderr),
191
+ format_stream("stdout", start_result.stdout),
192
+ )
193
+ )
194
+ print_or_update(message)
195
+
196
+ elif isinstance(start_result, manager.StartExecFailed):
197
+ the_tensorboard_binary = (
198
+ "%r (set by the `TENSORBOARD_BINARY` environment variable)"
199
+ % (start_result.explicit_binary,)
200
+ if start_result.explicit_binary is not None
201
+ else "`tensorbored`"
202
+ )
203
+ if start_result.os_error.errno == errno.ENOENT:
204
+ message = (
205
+ "ERROR: Could not find %s. Please ensure that your PATH contains "
206
+ "an executable `tensorbored` program, or explicitly specify the path "
207
+ "to a TensorBoard binary by setting the `TENSORBOARD_BINARY` "
208
+ "environment variable." % (the_tensorboard_binary,)
209
+ )
210
+ else:
211
+ message = "ERROR: Failed to start %s: %s" % (
212
+ the_tensorboard_binary,
213
+ start_result.os_error,
214
+ )
215
+ print_or_update(textwrap.fill(message))
216
+
217
+ elif isinstance(start_result, manager.StartTimedOut):
218
+ message = (
219
+ "ERROR: Timed out waiting for TensorBoard to start. "
220
+ "It may still be running as pid %d." % start_result.pid
221
+ )
222
+ print_or_update(message)
223
+
224
+ else:
225
+ raise TypeError(
226
+ "Unexpected result from `manager.start`: %r.\n"
227
+ "This is a TensorBoard bug; please report it." % start_result
228
+ )
229
+
230
+
231
+ def _time_delta_from_info(info):
232
+ """Format the elapsed time for the given TensorBoardInfo.
233
+
234
+ Args:
235
+ info: A TensorBoardInfo value.
236
+
237
+ Returns:
238
+ A human-readable string describing the time since the server
239
+ described by `info` started: e.g., "2 days, 0:48:58".
240
+ """
241
+ delta_seconds = int(time.time()) - info.start_time
242
+ return str(datetime.timedelta(seconds=delta_seconds))
243
+
244
+
245
+ def display(port=None, height=None):
246
+ """Display a TensorBoard instance already running on this machine.
247
+
248
+ Args:
249
+ port: The port on which the TensorBoard server is listening, as an
250
+ `int`, or `None` to automatically select the most recently
251
+ launched TensorBoard.
252
+ height: The height of the frame into which to render the TensorBoard
253
+ UI, as an `int` number of pixels, or `None` to use a default value
254
+ (currently 800).
255
+ """
256
+ _display(port=port, height=height, print_message=True, display_handle=None)
257
+
258
+
259
+ def _display(port=None, height=None, print_message=False, display_handle=None):
260
+ """Internal version of `display`.
261
+
262
+ Args:
263
+ port: As with `display`.
264
+ height: As with `display`.
265
+ print_message: True to print which TensorBoard instance was selected
266
+ for display (if applicable), or False otherwise.
267
+ display_handle: If not None, an IPython display handle into which to
268
+ render TensorBoard.
269
+ """
270
+ if height is None:
271
+ height = 800
272
+
273
+ if port is None:
274
+ infos = manager.get_all()
275
+ if not infos:
276
+ raise ValueError(
277
+ "Can't display TensorBoard: no known instances running."
278
+ )
279
+ else:
280
+ info = max(manager.get_all(), key=lambda x: x.start_time)
281
+ port = info.port
282
+ else:
283
+ infos = [i for i in manager.get_all() if i.port == port]
284
+ info = max(infos, key=lambda x: x.start_time) if infos else None
285
+
286
+ if print_message:
287
+ if info is not None:
288
+ message = (
289
+ "Selecting TensorBoard with {data_source} "
290
+ "(started {delta} ago; port {port}, pid {pid})."
291
+ ).format(
292
+ data_source=manager.data_source_from_info(info),
293
+ delta=_time_delta_from_info(info),
294
+ port=info.port,
295
+ pid=info.pid,
296
+ )
297
+ print(message)
298
+ else:
299
+ # The user explicitly provided a port, and we don't have any
300
+ # additional information. There's nothing useful to say.
301
+ pass
302
+
303
+ fn = {
304
+ _CONTEXT_COLAB: _display_colab,
305
+ _CONTEXT_IPYTHON: _display_ipython,
306
+ _CONTEXT_NONE: _display_cli,
307
+ }[_get_context()]
308
+ return fn(port=port, height=height, display_handle=display_handle)
309
+
310
+
311
+ def _display_colab(port, height, display_handle):
312
+ """Display a TensorBoard instance in a Colab output frame.
313
+
314
+ The Colab VM is not directly exposed to the network, so the Colab
315
+ runtime provides a service worker tunnel to proxy requests from the
316
+ end user's browser through to servers running on the Colab VM: the
317
+ output frame may issue requests to https://localhost:<port> (HTTPS
318
+ only), which will be forwarded to the specified port on the VM.
319
+
320
+ It does not suffice to create an `iframe` and let the service worker
321
+ redirect its traffic (`<iframe src="https://localhost:6006">`),
322
+ because for security reasons service workers cannot intercept iframe
323
+ traffic. Instead, we manually fetch the TensorBoard index page with an
324
+ XHR in the output frame, and inject the raw HTML into `document.body`.
325
+
326
+ By default, the TensorBoard web app requests resources against
327
+ relative paths, like `./data/logdir`. Within the output frame, these
328
+ requests must instead hit `https://localhost:<port>/data/logdir`. To
329
+ redirect them, we change the document base URI, which transparently
330
+ affects all requests (XHRs and resources alike).
331
+ """
332
+ import IPython.display
333
+
334
+ shell = """
335
+ (async () => {
336
+ const url = new URL(await google.colab.kernel.proxyPort(%PORT%, {'cache': true}));
337
+ url.searchParams.set('tensorboardColab', 'true');
338
+ const iframe = document.createElement('iframe');
339
+ iframe.src = url;
340
+ iframe.setAttribute('width', '100%');
341
+ iframe.setAttribute('height', '%HEIGHT%');
342
+ iframe.setAttribute('frameborder', 0);
343
+ document.body.appendChild(iframe);
344
+ })();
345
+ """
346
+ replacements = [
347
+ ("%PORT%", "%d" % port),
348
+ ("%HEIGHT%", "%d" % height),
349
+ ]
350
+ for k, v in replacements:
351
+ shell = shell.replace(k, v)
352
+ script = IPython.display.Javascript(shell)
353
+
354
+ if display_handle:
355
+ display_handle.update(script)
356
+ else:
357
+ IPython.display.display(script)
358
+
359
+
360
+ def _display_ipython(port, height, display_handle):
361
+ import IPython.display
362
+
363
+ frame_id = "tensorbored-frame-{:08x}".format(random.getrandbits(64))
364
+ shell = """
365
+ <iframe id="%HTML_ID%" width="100%" height="%HEIGHT%" frameborder="0">
366
+ </iframe>
367
+ <script>
368
+ (function() {
369
+ const frame = document.getElementById(%JSON_ID%);
370
+ const url = new URL(%URL%, window.location);
371
+ const port = %PORT%;
372
+ if (port) {
373
+ url.port = port;
374
+ }
375
+ frame.src = url;
376
+ })();
377
+ </script>
378
+ """
379
+ proxy_url = os.environ.get("TENSORBOARD_PROXY_URL")
380
+ if proxy_url is not None:
381
+ # Allow %PORT% in $TENSORBOARD_PROXY_URL
382
+ proxy_url = proxy_url.replace("%PORT%", "%d" % port)
383
+ replacements = [
384
+ ("%HTML_ID%", html.escape(frame_id, quote=True)),
385
+ ("%JSON_ID%", json.dumps(frame_id)),
386
+ ("%HEIGHT%", "%d" % height),
387
+ ("%PORT%", "0"),
388
+ ("%URL%", json.dumps(proxy_url)),
389
+ ]
390
+ else:
391
+ replacements = [
392
+ ("%HTML_ID%", html.escape(frame_id, quote=True)),
393
+ ("%JSON_ID%", json.dumps(frame_id)),
394
+ ("%HEIGHT%", "%d" % height),
395
+ ("%PORT%", "%d" % port),
396
+ ("%URL%", json.dumps("/")),
397
+ ]
398
+
399
+ for k, v in replacements:
400
+ shell = shell.replace(k, v)
401
+ iframe = IPython.display.HTML(shell)
402
+ if display_handle:
403
+ display_handle.update(iframe)
404
+ else:
405
+ IPython.display.display(iframe)
406
+
407
+
408
+ def _display_cli(port, height, display_handle):
409
+ del height # unused
410
+ del display_handle # unused
411
+ message = "Please visit http://localhost:%d in a web browser." % port
412
+ print(message)
413
+
414
+
415
+ def list():
416
+ """Print a listing of known running TensorBoard instances.
417
+
418
+ TensorBoard instances that were killed uncleanly (e.g., with SIGKILL
419
+ or SIGQUIT) may appear in this list even if they are no longer
420
+ running. Conversely, this list may be missing some entries if your
421
+ operating system's temporary directory has been cleared since a
422
+ still-running TensorBoard instance started.
423
+ """
424
+ infos = manager.get_all()
425
+ if not infos:
426
+ print("No known TensorBoard instances running.")
427
+ return
428
+
429
+ print("Known TensorBoard instances:")
430
+ for info in infos:
431
+ template = (
432
+ " - port {port}: {data_source} (started {delta} ago; pid {pid})"
433
+ )
434
+ print(
435
+ template.format(
436
+ port=info.port,
437
+ data_source=manager.data_source_from_info(info),
438
+ delta=_time_delta_from_info(info),
439
+ pid=info.pid,
440
+ )
441
+ )
@@ -0,0 +1,266 @@
1
+ # Copyright 2017 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
+ """Provides utilities that may be especially useful to plugins."""
16
+
17
+ from google.protobuf import json_format
18
+ from importlib import metadata
19
+ from packaging import version
20
+ import threading
21
+
22
+ from tensorbored._vendor.bleach.sanitizer import Cleaner
23
+ import markdown
24
+
25
+ from tensorbored import context as _context
26
+ from tensorbored.backend import experiment_id as _experiment_id
27
+ from tensorbored.util import tb_logging
28
+
29
+ logger = tb_logging.get_logger()
30
+
31
+ _ALLOWED_ATTRIBUTES = {
32
+ "a": ["href", "title"],
33
+ "img": ["src", "title", "alt"],
34
+ }
35
+
36
+ _ALLOWED_TAGS = [
37
+ "ul",
38
+ "ol",
39
+ "li",
40
+ "p",
41
+ "pre",
42
+ "code",
43
+ "blockquote",
44
+ "h1",
45
+ "h2",
46
+ "h3",
47
+ "h4",
48
+ "h5",
49
+ "h6",
50
+ "hr",
51
+ "br",
52
+ "strong",
53
+ "em",
54
+ "a",
55
+ "img",
56
+ "table",
57
+ "thead",
58
+ "tbody",
59
+ "td",
60
+ "tr",
61
+ "th",
62
+ ]
63
+
64
+
65
+ # Cache Markdown converter to avoid expensive initialization at each
66
+ # call to `markdown_to_safe_html`. Cache a different instance per thread.
67
+ class _MarkdownStore(threading.local):
68
+ def __init__(self):
69
+ self.markdown = markdown.Markdown(
70
+ extensions=[
71
+ "markdown.extensions.tables",
72
+ "markdown.extensions.fenced_code",
73
+ ]
74
+ )
75
+
76
+
77
+ _MARKDOWN_STORE = _MarkdownStore()
78
+
79
+
80
+ # Cache Cleaner to avoid expensive initialization at each call to `clean`.
81
+ # Cache a different instance per thread.
82
+ class _CleanerStore(threading.local):
83
+ def __init__(self):
84
+ self.cleaner = Cleaner(
85
+ tags=_ALLOWED_TAGS, attributes=_ALLOWED_ATTRIBUTES
86
+ )
87
+
88
+
89
+ _CLEANER_STORE = _CleanerStore()
90
+
91
+
92
+ def safe_html(unsafe_string):
93
+ """Return the input as a str, sanitized for insertion into the DOM.
94
+
95
+ Arguments:
96
+ unsafe_string: A Unicode string or UTF-8--encoded bytestring
97
+ possibly containing unsafe HTML markup.
98
+
99
+ Returns:
100
+ A string containing safe HTML.
101
+ """
102
+ total_null_bytes = 0
103
+ if isinstance(unsafe_string, bytes):
104
+ unsafe_string = unsafe_string.decode("utf-8")
105
+ return _CLEANER_STORE.cleaner.clean(unsafe_string)
106
+
107
+
108
+ def markdown_to_safe_html(markdown_string):
109
+ """Convert Markdown to HTML that's safe to splice into the DOM.
110
+
111
+ Arguments:
112
+ markdown_string: A Unicode string or UTF-8--encoded bytestring
113
+ containing Markdown source. Markdown tables are supported.
114
+
115
+ Returns:
116
+ A string containing safe HTML.
117
+ """
118
+ return markdowns_to_safe_html([markdown_string], lambda xs: xs[0])
119
+
120
+
121
+ def markdowns_to_safe_html(markdown_strings, combine):
122
+ """Convert multiple Markdown documents to one safe HTML document.
123
+
124
+ One could also achieve this by calling `markdown_to_safe_html`
125
+ multiple times and combining the results. Compared to that approach,
126
+ this function may be faster, because HTML sanitization (which can be
127
+ expensive) is performed only once rather than once per input. It may
128
+ also be less precise: if one of the input documents has unsafe HTML
129
+ that is sanitized away, that sanitization might affect other
130
+ documents, even if those documents are safe.
131
+
132
+ Args:
133
+ markdown_strings: List of Markdown source strings to convert, as
134
+ Unicode strings or UTF-8--encoded bytestrings. Markdown tables
135
+ are supported.
136
+ combine: Callback function that takes a list of unsafe HTML
137
+ strings of the same shape as `markdown_strings` and combines
138
+ them into a single unsafe HTML string, which will be sanitized
139
+ and returned.
140
+
141
+ Returns:
142
+ A string containing safe HTML.
143
+ """
144
+ unsafe_htmls = []
145
+ total_null_bytes = 0
146
+
147
+ for source in markdown_strings:
148
+ # Convert to utf-8 whenever we have a binary input.
149
+ if isinstance(source, bytes):
150
+ source_decoded = source.decode("utf-8")
151
+ # Remove null bytes and warn if there were any, since it probably means
152
+ # we were given a bad encoding.
153
+ source = source_decoded.replace("\x00", "")
154
+ total_null_bytes += len(source_decoded) - len(source)
155
+ unsafe_html = _MARKDOWN_STORE.markdown.convert(source)
156
+ unsafe_htmls.append(unsafe_html)
157
+
158
+ unsafe_combined = combine(unsafe_htmls)
159
+ sanitized_combined = _CLEANER_STORE.cleaner.clean(unsafe_combined)
160
+
161
+ warning = ""
162
+ if total_null_bytes:
163
+ warning = (
164
+ "<!-- WARNING: discarded %d null bytes in markdown string "
165
+ "after UTF-8 decoding -->\n"
166
+ ) % total_null_bytes
167
+
168
+ return warning + sanitized_combined
169
+
170
+
171
+ def context(environ):
172
+ """Get a TensorBoard `RequestContext` from a WSGI environment.
173
+
174
+ Returns:
175
+ A `RequestContext` value.
176
+ """
177
+ return _context.from_environ(environ)
178
+
179
+
180
+ def experiment_id(environ):
181
+ """Determine the experiment ID associated with a WSGI request.
182
+
183
+ Each request to TensorBoard has an associated experiment ID, which is
184
+ always a string and may be empty. This experiment ID should be passed
185
+ to data providers.
186
+
187
+ Args:
188
+ environ: A WSGI environment `dict`. For a Werkzeug request, this is
189
+ `request.environ`.
190
+
191
+ Returns:
192
+ A experiment ID, as a possibly-empty `str`.
193
+ """
194
+ return environ.get(_experiment_id.WSGI_ENVIRON_KEY, "")
195
+
196
+
197
+ def proto_to_json(proto):
198
+ """Utility method to convert proto to JSON, accounting for different version support.
199
+
200
+ Args:
201
+ proto: The proto to convert to JSON.
202
+ """
203
+ # Fallback for internal usage, since non third-party code doesn't really
204
+ # have the concept of "versions" in a monorepo. The package version chosen
205
+ # below is the minimum value to choose the non-deprecated kwarg to
206
+ # `MessageToJson`.
207
+ try:
208
+ current_version = metadata.version("protobuf")
209
+ except metadata.PackageNotFoundError:
210
+ current_version = "5.0.0"
211
+ if version.parse(current_version) >= version.parse("5.0.0"):
212
+ return json_format.MessageToJson(
213
+ proto,
214
+ always_print_fields_with_no_presence=True,
215
+ )
216
+ return json_format.MessageToJson(
217
+ proto,
218
+ including_default_value_fields=True,
219
+ )
220
+
221
+
222
+ class _MetadataVersionChecker:
223
+ """TensorBoard-internal utility for warning when data is too new.
224
+
225
+ Specify a maximum known `version` number as stored in summary
226
+ metadata, and automatically reject and warn on data from newer
227
+ versions. This keeps a (single) bit of internal state to handle
228
+ logging a warning to the user at most once.
229
+
230
+ This should only be used by plugins bundled with TensorBoard, since
231
+ it may instruct users to upgrade their copy of TensorBoard.
232
+ """
233
+
234
+ def __init__(self, data_kind, latest_known_version):
235
+ """Initialize a `_MetadataVersionChecker`.
236
+
237
+ Args:
238
+ data_kind: A human-readable description of the kind of data
239
+ being read, like "scalar" or "histogram" or "PR curve".
240
+ latest_known_version: Highest tolerated value of `version`,
241
+ like `0`.
242
+ """
243
+ self._data_kind = data_kind
244
+ self._latest_known_version = latest_known_version
245
+ self._warned = False
246
+
247
+ def ok(self, version, run, tag):
248
+ """Test whether `version` is permitted, else complain."""
249
+ if 0 <= version <= self._latest_known_version:
250
+ return True
251
+ self._maybe_warn(version, run, tag)
252
+ return False
253
+
254
+ def _maybe_warn(self, version, run, tag):
255
+ if self._warned:
256
+ return
257
+ self._warned = True
258
+ logger.warning(
259
+ "Some %s data is too new to be read by this version of TensorBoard. "
260
+ "Upgrading TensorBoard may fix this. "
261
+ "(sample: run %r, tag %r, data version %r)",
262
+ self._data_kind,
263
+ run,
264
+ tag,
265
+ version,
266
+ )
File without changes
File without changes