Skip to content

Commit

Permalink
Make import tensorboard as tb possible
Browse files Browse the repository at this point in the history
This change introduces a lazy loader that will allow us to provide some of the
conviences TensorFlow has. For example:

    import tensorboard as tb
    tb.summary.scalar('foo', tensor)

Only the hourglass summary module has been made available in this namespace,
since that's probably the only thing where we're 100% positive we want this
functionality.
  • Loading branch information
jart committed Nov 30, 2017
1 parent 17b7851 commit 092527b
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 5 deletions.
19 changes: 18 additions & 1 deletion tensorboard/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -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"],
Expand Down Expand Up @@ -309,7 +320,7 @@ py_test(
srcs = ["summary_test.py"],
srcs_version = "PY2AND3",
deps = [
":summary",
":lib",
"//tensorboard:expect_tensorflow_installed",
],
)
Expand All @@ -326,3 +337,9 @@ py_library(
"//tensorboard:expect_tensorflow_installed",
],
)

py_library(
name = "lazy",
srcs = ["lazy.py"],
srcs_version = "PY2AND3",
)
17 changes: 17 additions & 0 deletions tensorboard/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
54 changes: 54 additions & 0 deletions tensorboard/lazy.py
Original file line number Diff line number Diff line change
@@ -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)
9 changes: 5 additions & 4 deletions tensorboard/summary_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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([
Expand All @@ -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
Expand Down

0 comments on commit 092527b

Please sign in to comment.