Repository: deis/deis

Issue:
pip install deis failing on PyYAML
Running `pip install --upgrade deis` fails on my ubuntu 14.04 env with the following:

Command /usr/bin/python -c "import setuptools, tokenize;**file**='/tmp/pip_build_root/PyYAML/setup.py';exec(compile(getattr(tokenize, 'open', open)(**file**).read().replace('\r\n', '\n'), **file**, 'exec'))" install --record /tmp/pip-lSlZgy-record/install-record.txt --single-version-externally-managed --compile failed with error code 1 in /tmp/pip_build_root/PyYAML

This could be my environment as I don't use python normally.



Discussion:
You probably need to `sudo` the command if you're using the default system python, although that _ought_ to result in a more relevant error message. I wonder if that's it.

It's a lot simpler and safer to use a python `virtualenv` to do this. We have a script in master at [`tests/bin/build-deis-cli.sh`](https://github.com/deis/deis/blob/master/tests/bin/build-deis-cli.sh) that does this--we should make that the default in the client's `Makefile` as well, it might fix this error and is better practice anyway.

sorry, I am using sudo on the command and get the same error. The binary worked nicely.

I've installed `virtualenv` and just tried the script you mention and get similar error:

  Can't roll back PyYAML; was not uninstalled
Cleaning up...
Command /home/charles/CoreOS/deis-source/venv/bin/python -c "import setuptools, tokenize;**file**='/home/charles/CoreOS/deis-source/venv/build/PyYAML/setup.py';exec(compile(getattr(tokenize, 'open', open)(**file**).read().replace('\r\n', '\n'), **file**, 'exec'))" install --record /tmp/pip-62n1y1-record/install-record.txt --single-version-externally-managed --compile --install-headers /home/charles/CoreOS/deis-source/venv/include/site/python2.7 failed with error code 1 in /home/charles/CoreOS/deis-source/venv/build/PyYAML

There is a full dump in ~/.pip/pip.log, would that help?

@charlesmarshall do you have libyaml installed? Any log dump would help here.


Resolving patch:
diff --git a/client/deis.py b/client/deis.py
--- a/client/deis.py
+++ b/client/deis.py
@@ -68,7 +68,6 @@
 from docopt import DocoptExit
 import requests
 from termcolor import colored
-import yaml
 
 __version__ = '0.12.0-dev'
 
@@ -180,7 +179,7 @@ class Settings(dict):
     """
     Settings backed by a file in the user's home directory
 
-    On init, settings are loaded from ~/.deis/client.yaml
+    On init, settings are loaded from ~/.deis/client.json
     """
 
     def __init__(self):
@@ -188,10 +187,22 @@ def __init__(self):
         # Create the $HOME/.deis dir if it doesn't exist
         if not os.path.isdir(path):
             os.mkdir(path, 0700)
-        self._path = os.path.join(path, 'client.yaml')
+        self._path = os.path.join(path, 'client.json')
         if not os.path.exists(self._path):
+            settings = {}
+            # try once to convert the old settings file if it exists
+            # FIXME: this code can be removed in November 2014 or thereabouts, that's long enough.
+            old_path = os.path.join(path, 'client.yaml')
+            if os.path.exists(old_path):
+                try:
+                    with open(old_path, 'r') as f:
+                        txt = f.read().replace('{', '{"', 1).replace(':', '":', 1).replace("'", '"')
+                        settings = json.loads(txt)
+                        os.remove(old_path)
+                except:
+                    pass  # ignore errors, at least we tried to convert it
             with open(self._path, 'w') as f:
-                f.write(yaml.safe_dump({}))
+                json.dump(settings, f)
         # load initial settings
         self.load()
 
@@ -201,7 +212,7 @@ def load(self):
         """
         with open(self._path) as f:
             data = f.read()
-        settings = yaml.safe_load(data)
+        settings = json.loads(data)
         self.update(settings)
         return settings
 
@@ -209,7 +220,7 @@ def save(self):
         """
         Serialize and save settings to the filesystem
         """
-        data = yaml.safe_dump(dict(self))
+        data = json.dumps(dict(self))
         with open(self._path, 'w') as f:
             f.write(data)
         return data
diff --git a/client/setup.py b/client/setup.py
--- a/client/setup.py
+++ b/client/setup.py
@@ -57,9 +57,7 @@
       ],
       long_description=LONG_DESCRIPTION,
       install_requires=[
-          'docopt==0.6.2', 'python-dateutil==2.2',
-          'PyYAML==3.11', 'requests==2.3.0',
-          'termcolor==1.1.0'
+          'docopt==0.6.2', 'python-dateutil==2.2', 'requests==2.3.0', 'termcolor==1.1.0'
       ],
       zip_safe=True,
       **KWARGS)


Test patch:
diff --git a/tests/bin/build-deis-cli.sh b/tests/bin/build-deis-cli.sh
--- a/tests/bin/build-deis-cli.sh
+++ b/tests/bin/build-deis-cli.sh
@@ -4,5 +4,5 @@
 
 virtualenv --system-site-packages venv
 . venv/bin/activate
-pip install docopt==0.6.2 python-dateutil==2.2 PyYAML==3.11 requests==2.3.0 pyinstaller==2.1 termcolor==1.1.0
+pip install docopt==0.6.2 python-dateutil==2.2 requests==2.3.0 pyinstaller==2.1 termcolor==1.1.0
 make -C client/ client
diff --git a/tests/bin/test-integration.sh b/tests/bin/test-integration.sh
--- a/tests/bin/test-integration.sh
+++ b/tests/bin/test-integration.sh
@@ -31,7 +31,7 @@ set -e
 # Build updated Deis CLI and use it for testing
 virtualenv --system-site-packages venv
 . venv/bin/activate
-pip install docopt==0.6.2 python-dateutil==2.2 PyYAML==3.11 requests==2.3.0 pyinstaller==2.1 termcolor==1.1.0
+pip install docopt==0.6.2 python-dateutil==2.2 requests==2.3.0 pyinstaller==2.1 termcolor==1.1.0
 make -C client/ client
 chmod +x client/dist/deis
 export PATH=`pwd`/client/dist:$PATH