Skip to content

Commit

Permalink
update tests with changes in extension manager
Browse files Browse the repository at this point in the history
  • Loading branch information
Zsailer committed Jul 23, 2020
1 parent 16daa58 commit 9353e2e
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 97 deletions.
3 changes: 1 addition & 2 deletions jupyter_server/extension/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -400,8 +400,7 @@ def _load_jupyter_server_extension(cls, serverapp):
extension_manager = serverapp.extension_manager
try:
# Get loaded extension from serverapp.
pkg = extension_manager.enabled_extensions[cls.name]
point = pkg.extension_points[cls.name]
point = extension_manager.extension_points[cls.name]
extension = point.app
except KeyError:
extension = cls()
Expand Down
28 changes: 19 additions & 9 deletions jupyter_server/extension/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
HasTraits,
Dict,
Unicode,
Instance,
default,
validate
)

Expand All @@ -23,6 +21,7 @@ class ExtensionPoint(HasTraits):
point defined by metadata and importable from a Python package.
"""
metadata = Dict()
_app = None

@validate('metadata')
def _valid_metadata(self, proposed):
Expand All @@ -43,10 +42,11 @@ def _valid_metadata(self, proposed):
"The submodule '{}' could not be found. Are you "
"sure the extension is installed?".format(self._module_name)
)
# Initialize the app object if it exists.
app = self.metadata.get("app")
if app:
metadata["app"] = app()
# If the metadata includes an ExtensionApp, create an instance.
try:
self._app = metadata.get("app")()
except TypeError:
pass
return metadata

@property
Expand All @@ -56,7 +56,7 @@ def linked(self):
@property
def app(self):
"""If the metadata includes an `app` field"""
return self.metadata.get("app")
return self._app

@property
def module_name(self):
Expand Down Expand Up @@ -129,7 +129,7 @@ class ExtensionPackage(HasTraits):
"""
name = Unicode(help="Name of the an importable Python package.")

# A dictionary that stores whether the extension point has been linked.
# Store extension points that have been linked.
_linked_points = {}

@validate("name")
Expand Down Expand Up @@ -186,7 +186,7 @@ class ExtensionManager(LoggingConfigurable):
m = ExtensionManager(jpserver_extensions=extensions)
"""
# The `enabled_extensions` attribute provides a dictionary
# with extension names mapped to their ExtensionPackage interface
# with extension (package) names mapped to their ExtensionPackage interface
# (see above). This manager simplifies the interaction between the
# ServerApp and the extensions being appended.
_enabled_extensions = {}
Expand All @@ -203,6 +203,16 @@ def enabled_extensions(self):
"""
return dict(sorted(self._enabled_extensions.items()))

@property
def extension_points(self):
extensions = self.enabled_extensions
return {
name: point
for value in extensions.values()
for name, point in value.extension_points.items()
}


def from_jpserver_extensions(self, jpserver_extensions):
"""Add extensions from 'jpserver_extensions'-like dictionary."""
for name, enabled in jpserver_extensions.items():
Expand Down
3 changes: 1 addition & 2 deletions tests/extension/mockextensions/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,4 @@ class MockExtensionApp(ExtensionAppJinjaMixin, ExtensionApp):
def initialize_handlers(self):
self.handlers.append(('/mock', MockExtensionHandler))
self.handlers.append(('/mock_template', MockExtensionTemplateHandler))
self.loaded = True

self.loaded = True
32 changes: 20 additions & 12 deletions tests/extension/test_app.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import pytest
from jupyter_server.serverapp import ServerApp

# Use ServerApps environment because it monkeypatches
# jupyter_core.paths and provides a config directory
# that's not cross contaminating the user config directory.
pytestmark = pytest.mark.usefixtures("environ")


@pytest.fixture
def server_config(request, template_dir):
Expand All @@ -21,14 +26,19 @@ def server_config(request, template_dir):


@pytest.fixture
def mock_extension(extension_manager):
return extension_manager.extension_points["mockextension"].app
def mock_extension(serverapp, extension_manager):
name = "tests.extension.mockextensions"
pkg = extension_manager.enabled_extensions[name]
point = pkg.extension_points["mockextension"]
app = point.app
return app


def test_initialize(mock_extension, template_dir):
def test_initialize(serverapp, mock_extension, template_dir):
# Check that settings and handlers were added to the mock extension.
assert isinstance(mock_extension.serverapp, ServerApp)
assert len(mock_extension.handlers) > 0
assert mock_extension.loaded
assert mock_extension.template_paths == [str(template_dir)]


Expand All @@ -46,22 +56,20 @@ def test_instance_creation_with_argv(
serverapp,
trait_name,
trait_value,
extension_manager
mock_extension,
):
extension = extension_manager.extension_points['mockextension'].app
assert getattr(extension, trait_name) == trait_value
assert getattr(mock_extension, trait_name) == trait_value


def test_extensionapp_load_config_file(
extension_environ,
config_file,
extension_manager,
mock_extension,
serverapp,
):
extension = extension_manager.extension_points['mockextension'].app
# Assert default config_file_paths is the same in the app and extension.
assert extension.config_file_paths == serverapp.config_file_paths
assert extension.config_dir == serverapp.config_dir
assert extension.config_file_name == 'jupyter_mockextension_config'
assert mock_extension.config_file_paths == serverapp.config_file_paths
assert mock_extension.config_dir == serverapp.config_dir
assert mock_extension.config_file_name == 'jupyter_mockextension_config'
# Assert that the trait is updated by config file
assert extension.mock_trait == 'config from file'
assert mock_extension.mock_trait == 'config from file'
15 changes: 4 additions & 11 deletions tests/extension/test_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,11 @@ def test_extension_package_notfound_error():


def test_extension_manager_api():
# Import mock extension metadata
from .mockextensions import _jupyter_server_extension_paths

# Testing the first path (which is an extension app).
metadata_list = _jupyter_server_extension_paths()

jpserver_extensions = {
"tests.extension.mockextensions": True
}
manager = ExtensionManager(jpserver_extensions=jpserver_extensions)
assert len(manager.extensions) == 1
assert len(manager.extension_points) == len(metadata_list)
assert "mockextension" in manager.extension_points
assert "tests.extension.mockextensions.mock1" in manager.extension_points
manager = ExtensionManager()
manager.from_jpserver_extensions(jpserver_extensions)
assert len(manager.enabled_extensions) == 1
assert "tests.extension.mockextensions" in manager.enabled_extensions

62 changes: 1 addition & 61 deletions tests/extension/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,65 +1,5 @@
import pytest
from jupyter_server.extension.utils import (
list_extensions_in_configd,
configd_enabled,
validate_extension
)

# Use ServerApps environment because it monkeypatches
# jupyter_core.paths and provides a config directory
# that's not cross contaminating the user config directory.
pytestmark = pytest.mark.usefixtures("environ")


@pytest.fixture
def configd(env_config_path):
"""A pathlib.Path object that acts like a jupyter_server_config.d folder."""
configd = env_config_path.joinpath('jupyter_server_config.d')
configd.mkdir()
return configd


ext1_json_config = """\
{
"ServerApp": {
"jpserver_extensions": {
"ext1_config": true
}
}
}
"""

@pytest.fixture
def ext1_config(configd):
config = configd.joinpath("ext1_config.json")
config.write_text(ext1_json_config)


ext2_json_config = """\
{
"ServerApp": {
"jpserver_extensions": {
"ext2_config": false
}
}
}
"""


@pytest.fixture
def ext2_config(configd):
config = configd.joinpath("ext2_config.json")
config.write_text(ext2_json_config)


def test_list_extension_from_configd(ext1_config, ext2_config):
extensions = list_extensions_in_configd()
assert "ext2_config" in extensions
assert "ext1_config" in extensions


def test_config_enabled(ext1_config):
assert configd_enabled("ext1_config")
from jupyter_server.extension.utils import validate_extension


def test_validate_extension():
Expand Down

0 comments on commit 9353e2e

Please sign in to comment.