1+ import imp
12import os
23import sys
34from unittest import TestCase
1112
1213from traitlets .config .manager import BaseJSONConfigManager
1314from traitlets .tests .utils import check_help_all_output
15+ from jupyter_core import paths
1416
1517from notebook .serverextensions import toggle_serverextension_python
16- from notebook import nbextensions
18+ from notebook import nbextensions , serverextensions , extensions
1719from notebook .notebookapp import NotebookApp
1820from notebook .nbextensions import _get_config_dir
1921
@@ -33,8 +35,24 @@ def test_help_output():
3335 check_help_all_output ('notebook.serverextensions' , ['install' ])
3436 check_help_all_output ('notebook.serverextensions' , ['uninstall' ])
3537
38+ outer_file = __file__
3639
37- class TestInstallServerExtension (TestCase ):
40+ class MockExtensionModule (object ):
41+ __file__ = outer_file
42+
43+ @staticmethod
44+ def _jupyter_server_extension_paths ():
45+ return [{
46+ 'module' : '_mockdestination/index'
47+ }]
48+
49+ loaded = False
50+
51+ def load_jupyter_server_extension (self , app ):
52+ self .loaded = True
53+
54+
55+ class MockEnvTestCase (TestCase ):
3856
3957 def tempdir (self ):
4058 td = TemporaryDirectory ()
@@ -43,40 +61,55 @@ def tempdir(self):
4361
4462 def setUp (self ):
4563 self .tempdirs = []
64+ self ._mock_extensions = []
4665
4766 self .test_dir = self .tempdir ()
4867 self .data_dir = os .path .join (self .test_dir , 'data' )
4968 self .config_dir = os .path .join (self .test_dir , 'config' )
5069 self .system_data_dir = os .path .join (self .test_dir , 'system_data' )
70+ self .system_config_dir = os .path .join (self .test_dir , 'system_config' )
5171 self .system_path = [self .system_data_dir ]
72+ self .system_config_path = [self .system_config_dir ]
5273
53- self .patch_env = patch .dict ('os.environ' , {
74+ self .patches = []
75+ p = patch .dict ('os.environ' , {
5476 'JUPYTER_CONFIG_DIR' : self .config_dir ,
5577 'JUPYTER_DATA_DIR' : self .data_dir ,
5678 })
57- self .patch_env .start ()
58- self .patch_system_path = patch .object (nbextensions ,
59- 'SYSTEM_JUPYTER_PATH' , self .system_path )
60- self .patch_system_path .start ()
79+ self .patches .append (p )
80+ for mod in (paths , nbextensions ):
81+ p = patch .object (mod ,
82+ 'SYSTEM_JUPYTER_PATH' , self .system_path )
83+ self .patches .append (p )
84+ p = patch .object (mod ,
85+ 'ENV_JUPYTER_PATH' , [])
86+ self .patches .append (p )
87+ for mod in (paths , extensions ):
88+ p = patch .object (mod ,
89+ 'SYSTEM_CONFIG_PATH' , self .system_config_path )
90+ self .patches .append (p )
91+ p = patch .object (mod ,
92+ 'ENV_CONFIG_PATH' , [])
93+ self .patches .append (p )
94+ for p in self .patches :
95+ p .start ()
96+ self .addCleanup (p .stop )
97+ # verify our patches
98+ self .assertEqual (paths .jupyter_config_path (), [self .config_dir ] + self .system_config_path )
99+ self .assertEqual (extensions ._get_config_dir (user = False ), self .system_config_dir )
100+ self .assertEqual (paths .jupyter_path (), [self .data_dir ] + self .system_path )
61101
62102 def tearDown (self ):
63- self .patch_env . stop ()
64- self . patch_system_path . stop ( )
103+ for modulename in self ._mock_extensions :
104+ sys . modules . pop ( modulename )
65105
66- def _inject_mock_extension (self ):
67- outer_file = __file__
106+ def _inject_mock_extension (self , modulename = 'mockextension' ):
68107
69- class mock ():
70- __file__ = outer_file
108+ sys .modules [modulename ] = ext = MockExtensionModule ()
109+ self ._mock_extensions .append (modulename )
110+ return ext
71111
72- @staticmethod
73- def _jupyter_server_extension_paths ():
74- return [{
75- 'module' : '_mockdestination/index'
76- }]
77-
78- import sys
79- sys .modules ['mockextension' ] = mock
112+ class TestInstallServerExtension (MockEnvTestCase ):
80113
81114 def _get_config (self , user = True ):
82115 cm = BaseJSONConfigManager (config_dir = _get_config_dir (user ))
@@ -98,13 +131,37 @@ def test_disable(self):
98131 config = self ._get_config ()
99132 assert not config ['mockextension' ]
100133
134+ def test_merge_config (self ):
135+ # enabled at sys level
136+ mock_sys = self ._inject_mock_extension ('mockext_sys' )
137+ # enabled at sys, disabled at user
138+ mock_both = self ._inject_mock_extension ('mockext_both' )
139+ # enabled at user
140+ mock_user = self ._inject_mock_extension ('mockext_user' )
141+ # enabled at Python
142+ mock_py = self ._inject_mock_extension ('mockext_py' )
143+
144+ toggle_serverextension_python ('mockext_sys' , enabled = True , user = False )
145+ toggle_serverextension_python ('mockext_user' , enabled = True , user = True )
146+ toggle_serverextension_python ('mockext_both' , enabled = True , user = False )
147+ toggle_serverextension_python ('mockext_both' , enabled = False , user = True )
148+
149+ app = NotebookApp (nbserver_extensions = {'mockext_py' : True })
150+ app .init_server_extensions ()
151+
152+ assert mock_user .loaded
153+ assert mock_sys .loaded
154+ assert mock_py .loaded
155+ assert not mock_both .loaded
156+
101157
102- class TestOrderedServerExtension (TestCase ):
158+ class TestOrderedServerExtension (MockEnvTestCase ):
103159 """
104160 Test that Server Extensions are loaded _in order_
105161 """
106162
107163 def setUp (self ):
164+ super (TestOrderedServerExtension , self ).setUp ()
108165 mockextension1 = SimpleNamespace ()
109166 mockextension2 = SimpleNamespace ()
110167
@@ -124,6 +181,7 @@ def load_jupyter_server_extension(obj):
124181 sys .modules ['mockextension1' ] = mockextension1
125182
126183 def tearDown (self ):
184+ super (TestOrderedServerExtension , self ).tearDown ()
127185 del sys .modules ['mockextension2' ]
128186 del sys .modules ['mockextension1' ]
129187
0 commit comments