Repository: pydoit/doit

Issue:
'get_var' fails while the multiprocess execution if any task uses delayed creation.
@schettino72 , hey! :)

So, i found strange behaviour while trying to implement some stuff.

```.py
#! /usr/bin/doit -f
# -*- coding: utf-8 -*-

from doit import get_var
from doit import create_after

get_var( 'A', None )


def task_foo() :
  return {
    'actions': [ 'echo foo' ],
    'task_dep': [ 'bar' ],
  }
  
@create_after( executed = 'baz' )
def task_bar() :
  for i in range( 10 ) :
    yield {
      'name': 'bar_{}'.format( i ),
      'actions': [ 'echo bar_{}'.format( i ) ]
    }
    
def task_baz() :
  for i in range( 10 ) :
    yield {
      'name': 'baz_{}'.format( i ),
      'actions': [ 'echo baz_{}'.format( i ) ]
    }
```

This code works fine while being executed in single-process mode. But it fails in multi process mode.

```
/root>GetVar.py -n 2
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/py3.4/lib/multiprocessing/spawn.py", line 106, in spawn_main
    exitcode = _main(fd)
  File "/py3.4/lib/multiprocessing/spawn.py", line 116, in _main
    self = pickle.load(from_parent)
  File "/root/GetVar.py", line 7, in <module>
    get_var( 'A', None )
  File "/py3.4/lib/site-packages/doit/doit_cmd.py", line 35, in get_var
    return _CMDLINE_VARS.get(name, default)
AttributeError: 'NoneType' object has no attribute 'get'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/py3.4/lib/multiprocessing/spawn.py", line 106, in spawn_main
    exitcode = _main(fd)
  File "/py3.4/lib/multiprocessing/spawn.py", line 116, in _main
    self = pickle.load(from_parent)
  File "/root/GetVar.py", line 7, in <module>
    get_var( 'A', None )
  File "/py3.4/lib/site-packages/doit/doit_cmd.py", line 35, in get_var
    return _CMDLINE_VARS.get(name, default)
AttributeError: 'NoneType' object has no attribute 'get'
```

But if i remove the `create_after` decorator, all became works fine even in multi process mode. So, i found it ambiguous. I had seen no notifications in docs about such behaviour.

Can you confirm this is the doit error or not?
Currently i use the last (0.30.0) version of doit.

Discussion:

Patch:
diff --git a/doit/doit_cmd.py b/doit/doit_cmd.py
index e1be34d..ce6ed15 100644
--- a/doit/doit_cmd.py
+++ b/doit/doit_cmd.py
@@ -32,6 +32,8 @@ def reset_vars():
     _CMDLINE_VARS = {}
 
 def get_var(name, default=None):
+    if _CMDLINE_VARS is None:
+        return None
     return _CMDLINE_VARS.get(name, default)
 
 def set_var(name, value):


Test patch:
diff --git a/tests/test_doit_cmd.py b/tests/test_doit_cmd.py
index 90d51a2..84c740a 100644
--- a/tests/test_doit_cmd.py
+++ b/tests/test_doit_cmd.py
@@ -45,6 +45,17 @@ class TestRun(object):
         cmd_main(['x=1', 'y=abc'])
         assert '1' == doit_cmd.get_var('x')
         assert 'abc' == doit_cmd.get_var('y')
+        assert None is doit_cmd.get_var('z')
+
+    def test_cmdline_novars(self, monkeypatch):
+        mock_run = Mock()
+        monkeypatch.setattr(Run, "execute", mock_run)
+        cmd_main(['x=1'])
+
+        # Simulate the variable below not being initialized by a subprocess on
+        # Windows. See https://github.com/pydoit/doit/issues/164.
+        doit_cmd._CMDLINE_VARS = None
+        assert None is doit_cmd.get_var('x')
 
     def test_cmdline_vars_not_opts(self, monkeypatch):
         mock_run = Mock()