diff --git a/tensorboard/BUILD b/tensorboard/BUILD index 503851d889..233b6937ce 100644 --- a/tensorboard/BUILD +++ b/tensorboard/BUILD @@ -28,6 +28,17 @@ py_binary( ], ) +py_library( + name = "lib", + srcs = ["__init__.py"], + srcs_version = "PY2AND3", + visibility = ["//visibility:public"], + deps = [ + ":lazy", + ":summary", + ], +) + py_library( name = "program", srcs = ["program.py"], @@ -309,7 +320,7 @@ py_test( srcs = ["summary_test.py"], srcs_version = "PY2AND3", deps = [ - ":summary", + ":lib", "//tensorboard:expect_tensorflow_installed", ], ) @@ -326,3 +337,9 @@ py_library( "//tensorboard:expect_tensorflow_installed", ], ) + +py_library( + name = "lazy", + srcs = ["lazy.py"], + srcs_version = "PY2AND3", +) diff --git a/tensorboard/__init__.py b/tensorboard/__init__.py index 85c94f4b6b..e17d41a4da 100644 --- a/tensorboard/__init__.py +++ b/tensorboard/__init__.py @@ -12,3 +12,20 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== +"""TensorBoard is a webapp for understanding TensorFlow runs and graphs. +""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorboard import lazy + +pkg = lambda i: i # helps google sync process +mod = lambda i: lazy.LazyLoader(i[i.rindex('.') + 1:], globals(), i) + +summary = mod(pkg('tensorboard.summary')) + +del lazy +del mod +del pkg diff --git a/tensorboard/lazy.py b/tensorboard/lazy.py new file mode 100644 index 0000000000..d1099b0636 --- /dev/null +++ b/tensorboard/lazy.py @@ -0,0 +1,54 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""TensorBoard is a webapp for understanding TensorFlow runs and graphs. +""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import importlib +import types + + +class LazyLoader(types.ModuleType): + """Lazily import a module, mainly to avoid pulling in large dependencies.""" + + # The lint error here is incorrect. + def __init__(self, local_name, parent_module_globals, name): # pylint: disable=super-on-old-class + self._local_name = local_name + self._parent_module_globals = parent_module_globals + + super(LazyLoader, self).__init__(name) + + def _load(self): + # Import the target module and insert it into the parent's namespace + module = importlib.import_module(self.__name__) + self._parent_module_globals[self._local_name] = module + + # Update this object's dict so that if someone keeps a reference to the + # LazyLoader, lookups are efficient (__getattr__ is only called on lookups + # that fail). + self.__dict__.update(module.__dict__) + + return module + + def __getattr__(self, item): + module = self._load() + return getattr(module, item) + + def __dir__(self): + module = self._load() + return dir(module) diff --git a/tensorboard/summary_test.py b/tensorboard/summary_test.py index 861d9272fc..8a303132ab 100644 --- a/tensorboard/summary_test.py +++ b/tensorboard/summary_test.py @@ -18,14 +18,15 @@ public entry point for end users, so we should be as careful as possible to ensure that we export the right things. """ + from __future__ import absolute_import from __future__ import division from __future__ import print_function import collections +import tensorboard as tb import tensorflow as tf -from tensorboard import summary STANDARD_PLUGINS = frozenset([ @@ -43,15 +44,15 @@ class SummaryExportsTest(tf.test.TestCase): def test_each_plugin_has_an_export(self): for plugin in STANDARD_PLUGINS: - self.assertIsInstance(getattr(summary, plugin), collections.Callable) + self.assertIsInstance(getattr(tb.summary, plugin), collections.Callable) def test_plugins_export_pb_functions(self): for plugin in STANDARD_PLUGINS: self.assertIsInstance( - getattr(summary, '%s_pb' % plugin), collections.Callable) + getattr(tb.summary, '%s_pb' % plugin), collections.Callable) def test_all_exports_correspond_to_plugins(self): - exports = [name for name in dir(summary) if not name.startswith('_')] + exports = [name for name in dir(tb.summary) if not name.startswith('_')] futures = frozenset(('absolute_import', 'division', 'print_function')) bad_exports = [ name for name in exports