Repository: ipython/ipython

Issue:
nbconvert: commandline tests fail Win7x64 Py3.3
nbconvert: commandline tests fail Win7x64 Py3.3

Even though this is deep in my territory, pinging @ivanov for input before I get
started since this has to do with the traitlet lists via commandline.

```
**********************************************************************
IPython test group: IPython.nbconvert
........................................................EEEEE..SE

======================================================================
ERROR: Do explicit notebook names work?
----------------------------------------------------------------------
Traceback (most recent call last):
  File "E:\Python33\lib\site-packages\ipython-1.0.0_dev-py3.3.egg\IPython\nbconv
ert\tests\test_nbconvertapp.py", line 71, in test_explicit
    self.call('nbconvert --log-level=0 --to="python" --notebooks='
  File "E:\Python33\lib\site-packages\ipython-1.0.0_dev-py3.3.egg\IPython\nbconv
ert\tests\base.py", line 142, in call
    raise OSError(stderr)
OSError: [NbConvertApp] CRITICAL | Bad config encountered during initialization:

[NbConvertApp] CRITICAL | The 'notebooks' trait of a NbConvertApp instance must
be a list or None, but a value of class 'str' (i.e. '[notebook2.ipynb]') was spe
cified.


======================================================================
ERROR: Can explicit notebook names be used and then a matching search pattern?
----------------------------------------------------------------------
Traceback (most recent call last):
  File "E:\Python33\lib\site-packages\ipython-1.0.0_dev-py3.3.egg\IPython\nbconv
ert\tests\test_nbconvertapp.py", line 119, in test_explicit_glob
    self.call('nbconvert --log-level=0 --to="python" --notebooks='
  File "E:\Python33\lib\site-packages\ipython-1.0.0_dev-py3.3.egg\IPython\nbconv
ert\tests\base.py", line 142, in call
    raise OSError(stderr)
OSError: [NbConvertApp] CRITICAL | Bad config encountered during initialization:

[NbConvertApp] CRITICAL | The 'notebooks' trait of a NbConvertApp instance must
be a list or None, but a value of class 'str' (i.e. '[notebook1.ipynb,notebook2.
ipynb,*.ipynb]') was specified.


======================================================================
ERROR: Do search patterns work for notebook names?
----------------------------------------------------------------------
Traceback (most recent call last):
  File "E:\Python33\lib\site-packages\ipython-1.0.0_dev-py3.3.egg\IPython\nbconv
ert\tests\test_nbconvertapp.py", line 49, in test_glob
    self.call('nbconvert --to="python" --notebooks=\'["*.ipynb"]\' --log-level=0
')
  File "E:\Python33\lib\site-packages\ipython-1.0.0_dev-py3.3.egg\IPython\nbconv
ert\tests\base.py", line 142, in call
    raise OSError(stderr)
OSError: [NbConvertApp] CRITICAL | Bad config encountered during initialization:

[NbConvertApp] CRITICAL | The 'notebooks' trait of a NbConvertApp instance must
be a list or None, but a value of class 'str' (i.e. '[*.ipynb]') was specified.


======================================================================
ERROR: Can a search pattern be used along with matching explicit notebook names?

----------------------------------------------------------------------
Traceback (most recent call last):
  File "E:\Python33\lib\site-packages\ipython-1.0.0_dev-py3.3.egg\IPython\nbconv
ert\tests\test_nbconvertapp.py", line 108, in test_glob_explicit
    self.call('nbconvert --log-level=0 --to="python" --notebooks='
  File "E:\Python33\lib\site-packages\ipython-1.0.0_dev-py3.3.egg\IPython\nbconv
ert\tests\base.py", line 142, in call
    raise OSError(stderr)
OSError: [NbConvertApp] CRITICAL | Bad config encountered during initialization:

[NbConvertApp] CRITICAL | The 'notebooks' trait of a NbConvertApp instance must
be a list or None, but a value of class 'str' (i.e. '[*.ipynb,notebook1.ipynb,no
tebook2.ipynb]') was specified.


======================================================================
ERROR: Do search patterns work for subdirectory notebook names?
----------------------------------------------------------------------
Traceback (most recent call last):
  File "E:\Python33\lib\site-packages\ipython-1.0.0_dev-py3.3.egg\IPython\nbconv
ert\tests\test_nbconvertapp.py", line 61, in test_glob_subdir
    '\'["%s"]\'' % os.path.join('subdir', '*.ipynb'))
  File "E:\Python33\lib\site-packages\ipython-1.0.0_dev-py3.3.egg\IPython\nbconv
ert\tests\base.py", line 142, in call
    raise OSError(stderr)
OSError: [NbConvertApp] CRITICAL | Bad config encountered during initialization:

[NbConvertApp] CRITICAL | The 'notebooks' trait of a NbConvertApp instance must
be a list or None, but a value of class 'str' (i.e. '[subdir\\*.ipynb]') was spe
cified.


======================================================================
ERROR: Do export templates work?
----------------------------------------------------------------------
Traceback (most recent call last):
  File "E:\Python33\lib\site-packages\ipython-1.0.0_dev-py3.3.egg\IPython\nbconv
ert\tests\test_nbconvertapp.py", line 96, in test_template
    self.call('nbconvert --log-level=0 --to=slides --notebooks='
  File "E:\Python33\lib\site-packages\ipython-1.0.0_dev-py3.3.egg\IPython\nbconv
ert\tests\base.py", line 142, in call
    raise OSError(stderr)
OSError: [NbConvertApp] CRITICAL | Bad config encountered during initialization:

[NbConvertApp] CRITICAL | The 'notebooks' trait of a NbConvertApp instance must
be a list or None, but a value of class 'str' (i.e. '[notebook2.ipynb]') was spe
cified.


----------------------------------------------------------------------
Ran 65 tests in 8.289s

FAILED (SKIP=1, errors=6)
```



Discussion:
It seems like the input should be evaluated through the py interpreter, but it's not.  Why this fails on Windows and not *nix, I have no idea.

BTW:  I do have _pywin32_ installed

hmm, works here on python3... let's just try a simple way of passing a Configurabe list from the command line to python3:

make a new file called `testext.py` with these contents:

``` python

def load_ipython_extension(ip):
    print('X'*80)
    print("omg, extension loaded!")
    print('X'*80)

```

and then run `ipython3 --InteractiveShellApp.extensions='["testext"]'` (note that, yes, there are two different types of quoting going on there). 

report back here with the results, or try to fiddle with it and massage it until it accepts that list from the command line

quick thought - if the extension example works, it could be that you need to insert extra escapes for the path separators on windows....

WEIRD, so 
`ipython3 --InteractiveShellApp.extensions='["testext"]'` does **not** work
`ipython3 --InteractiveShellApp.extensions="['testext']"` does
`ipython3 --InteractiveShellApp.extensions=['testext']` does

This is what is used in nbconvert's tests

`--notebooks='["notebook1.ipynb","notebook2.ipynb","*.ipynb"]'` 

I'll open a PR that changes it...  We will let Travis test on *nix


Resolving patch:
diff --git a/IPython/nbconvert/nbconvertapp.py b/IPython/nbconvert/nbconvertapp.py
--- a/IPython/nbconvert/nbconvertapp.py
+++ b/IPython/nbconvert/nbconvertapp.py
@@ -59,7 +59,6 @@ def validate(self, obj, value):
 nbconvert_aliases.update({
     'to' : 'NbConvertApp.export_format',
     'template' : 'Exporter.template_file',
-    'notebooks' : 'NbConvertApp.notebooks',
     'writer' : 'NbConvertApp.writer_class',
     'post': 'NbConvertApp.post_processor_class',
     'output': 'NbConvertApp.output_base'


Test patch:
diff --git a/IPython/nbconvert/tests/base.py b/IPython/nbconvert/tests/base.py
--- a/IPython/nbconvert/tests/base.py
+++ b/IPython/nbconvert/tests/base.py
@@ -136,8 +136,20 @@ def _get_files_path(self):
         return path
 
 
-    def call(self, parameters, raise_on_error=True):
+    def call(self, parameters, ignore_return_code=False):
+        """
+        Execute a, IPython shell command, listening for both Errors and non-zero
+        return codes.
+
+        PARAMETERS:
+        -----------
+        parameters : str
+            List of parameters to pass to IPython.
+        ignore_return_code : optional bool (default False)
+            Throw an OSError if the return code 
+        """
+
         stdout, stderr, retcode = get_output_error_code(ipy_cmd + parameters)
-        if retcode != 0 and raise_on_error:
+        if not (retcode == 0 or ignore_return_code):
             raise OSError(stderr)
         return stdout, stderr
diff --git a/IPython/nbconvert/tests/test_nbconvertapp.py b/IPython/nbconvert/tests/test_nbconvertapp.py
--- a/IPython/nbconvert/tests/test_nbconvertapp.py
+++ b/IPython/nbconvert/tests/test_nbconvertapp.py
@@ -39,7 +39,7 @@ def test_notebook_help(self):
         Will help show if no notebooks are specified?
         """
         with self.create_temp_cwd():
-            out, err = self.call('nbconvert --log-level=0', raise_on_error=False)
+            out, err = self.call('nbconvert --log-level 0', ignore_return_code=True)
             assert "see '--help-all'" in out
 
 
@@ -48,7 +48,7 @@ def test_glob(self):
         Do search patterns work for notebook names?
         """
         with self.create_temp_cwd(['notebook*.ipynb']):
-            self.call('nbconvert --to="python" --notebooks=\'["*.ipynb"]\' --log-level=0')
+            self.call('nbconvert --to python *.ipynb --log-level 0')
             assert os.path.isfile('notebook1.py')
             assert os.path.isfile('notebook2.py')
 
@@ -59,8 +59,8 @@ def test_glob_subdir(self):
         """
         with self.create_temp_cwd():
             self.copy_files_to(['notebook*.ipynb'], 'subdir/')
-            self.call('nbconvert --to="python" --log-level=0 --notebooks='
-                      '\'["%s"]\'' % os.path.join('subdir', '*.ipynb'))
+            self.call('nbconvert --to python --log-level 0 ' + 
+                      os.path.join('subdir', '*.ipynb'))
             assert os.path.isfile('notebook1.py')
             assert os.path.isfile('notebook2.py')
 
@@ -70,8 +70,7 @@ def test_explicit(self):
         Do explicit notebook names work?
         """
         with self.create_temp_cwd(['notebook*.ipynb']):
-            self.call('nbconvert --log-level=0 --to="python" --notebooks='
-                      '\'["notebook2.ipynb"]\'')
+            self.call('nbconvert --log-level 0 --to python notebook2')
             assert not os.path.isfile('notebook1.py')
             assert os.path.isfile('notebook2.py')
 
@@ -84,8 +83,9 @@ def test_filename_spaces(self):
         """
         with self.create_temp_cwd(['notebook2.ipynb']):
             os.rename('notebook2.ipynb', 'notebook with spaces.ipynb')
-            o,e = self.call('nbconvert --log-level=0 --to="latex" "notebook with spaces"'
-                            ' --post="PDF" --PDFPostProcessor.verbose=True')
+            o,e = self.call('nbconvert --log-level 0 --to latex '
+                            '"notebook with spaces" --post PDF '
+                            '--PDFPostProcessor.verbose=True')
             assert os.path.isfile('notebook with spaces.tex')
             assert os.path.isdir('notebook with spaces_files')
             assert os.path.isfile('notebook with spaces.pdf')
@@ -97,8 +97,8 @@ def test_post_processor(self):
         Do post processors work?
         """
         with self.create_temp_cwd(['notebook1.ipynb']):
-            self.call('nbconvert --log-level=0 --to="latex" notebook1'
-                      ' --post="PDF" --PDFPostProcessor.verbose=True')
+            self.call('nbconvert --log-level 0 --to latex notebook1 '
+                      '--post PDF --PDFPostProcessor.verbose=True')
             assert os.path.isfile('notebook1.tex')
             assert os.path.isfile('notebook1.pdf')
 
@@ -109,8 +109,8 @@ def test_template(self):
         Do export templates work?
         """
         with self.create_temp_cwd(['notebook2.ipynb']):
-            self.call('nbconvert --log-level=0 --to=slides --notebooks='
-                      '\'["notebook2.ipynb"]\' --template=reveal')
+            self.call('nbconvert --log-level 0 --to slides '  
+                      'notebook2.ipynb --template reveal')
             assert os.path.isfile('notebook2.slides.html')
             with open('notebook2.slides.html') as f:
                 assert '/reveal.css' in f.read()
@@ -121,8 +121,8 @@ def test_glob_explicit(self):
         Can a search pattern be used along with matching explicit notebook names?
         """
         with self.create_temp_cwd(['notebook*.ipynb']):
-            self.call('nbconvert --log-level=0 --to="python" --notebooks='
-                      '\'["*.ipynb","notebook1.ipynb","notebook2.ipynb"]\'')
+            self.call('nbconvert --log-level 0 --to python '
+                      '*.ipynb notebook1.ipynb notebook2.ipynb')
             assert os.path.isfile('notebook1.py')
             assert os.path.isfile('notebook2.py')
 
@@ -132,8 +132,8 @@ def test_explicit_glob(self):
         Can explicit notebook names be used and then a matching search pattern?
         """
         with self.create_temp_cwd(['notebook*.ipynb']):
-            self.call('nbconvert --log-level=0 --to="python" --notebooks='
-                      '\'["notebook1.ipynb","notebook2.ipynb","*.ipynb"]\'')
+            self.call('nbconvert --log-level 0 --to=python '
+                      'notebook1.ipynb notebook2.ipynb *.ipynb')
             assert os.path.isfile('notebook1.py')
             assert os.path.isfile('notebook2.py')
 
@@ -143,7 +143,7 @@ def test_default_config(self):
         Does the default config work?
         """
         with self.create_temp_cwd(['notebook*.ipynb', 'ipython_nbconvert_config.py']):
-            self.call('nbconvert --log-level=0')
+            self.call('nbconvert --log-level 0')
             assert os.path.isfile('notebook1.py')
             assert not os.path.isfile('notebook2.py')
 
@@ -155,6 +155,6 @@ def test_override_config(self):
         with self.create_temp_cwd(['notebook*.ipynb',
                                    'ipython_nbconvert_config.py',
                                    'override.py']):
-            self.call('nbconvert --log-level=0 --config="override.py"')
+            self.call('nbconvert --log-level 0 --config="override.py"')
             assert not os.path.isfile('notebook1.py')
             assert os.path.isfile('notebook2.py')