Add zip_safe flag to par_binary. (#62)

* Add zip_safe flag to par_binary.

Currently a no-op.

* Regenerate documentation.
diff --git a/compiler/cli.py b/compiler/cli.py
index d450427..6efde2f 100644
--- a/compiler/cli.py
+++ b/compiler/cli.py
@@ -49,6 +49,16 @@
         '--stub_file',
         help='Read imports and interpreter path from the specified stub file',
         required=True)
+    # See
+    # http://setuptools.readthedocs.io/en/latest/setuptools.html#setting-the-zip-safe-flag
+    # for background and explanation.
+    parser.add_argument(
+        '--zip_safe',
+        help='Safe to import modules and access datafiles straight from zip ' +
+        'archive?  If False, all files will be extracted to a temporary ' +
+        'directory at the start of execution.',
+        type=bool,
+        default=True)
     return parser
 
 
diff --git a/compiler/cli_test.py b/compiler/cli_test.py
index 95a937b..7db41b4 100644
--- a/compiler/cli_test.py
+++ b/compiler/cli_test.py
@@ -28,6 +28,7 @@
             '--manifest_root=bazz',
             '--outputpar=baz',
             '--stub_file=quux',
+            '--zip_safe=False',
             'foo',
         ])
         self.assertEqual(args.manifest_file, 'bar')
diff --git a/docs/WORKSPACE b/docs/WORKSPACE
index da063f0..77a5e97 100644
--- a/docs/WORKSPACE
+++ b/docs/WORKSPACE
@@ -20,7 +20,7 @@
 git_repository(
     name = "io_bazel_skydoc",
     remote = "https://github.com/bazelbuild/skydoc.git",
-    commit = "e9be81cf5be41e4200749f5d8aa2db7955f8aacc",
+    commit = "b36d22cc4436a7a7933e36a111bfc00fd494b9fb",
 )
 
 load("@io_bazel_skydoc//skylark:skylark.bzl", "skydoc_repositories")
diff --git a/docs/debug.html b/docs/debug.html
index 80e4ccd..8096e6e 100644
--- a/docs/debug.html
+++ b/docs/debug.html
@@ -122,7 +122,7 @@
           <div class="mdl-mini-footer__left-section">
             <div class="mdl-logo">Bazel</div>
             <ul class="mdl-mini-footer__link-list">
-              <li><a href="http://bazel.io">Home</a></li>
+              <li><a href="https://bazel.build">Home</a></li>
               <li><a href="https://github.com/bazelbuild">GitHub</a></li>
             </ul>
           </div>
diff --git a/docs/index.html b/docs/index.html
index 983a856..f46d709 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -164,7 +164,7 @@
           <div class="mdl-mini-footer__left-section">
             <div class="mdl-logo">Bazel</div>
             <ul class="mdl-mini-footer__link-list">
-              <li><a href="http://bazel.io">Home</a></li>
+              <li><a href="https://bazel.build">Home</a></li>
               <li><a href="https://github.com/bazelbuild">GitHub</a></li>
             </ul>
           </div>
diff --git a/docs/subpar.html b/docs/subpar.html
index 1391574..1009446 100644
--- a/docs/subpar.html
+++ b/docs/subpar.html
@@ -140,7 +140,7 @@
 
           <h2 id="parfile">parfile</h2>
 
-          <pre>parfile(<a href="#parfile.name">name</a>, <a href="#parfile.src">src</a>, <a href="#parfile.compiler">compiler</a>, <a href="#parfile.default_python_version">default_python_version</a>, <a href="#parfile.imports">imports</a>, <a href="#parfile.main">main</a>)</pre>
+          <pre>parfile(<a href="#parfile.name">name</a>, <a href="#parfile.src">src</a>, <a href="#parfile.compiler">compiler</a>, <a href="#parfile.default_python_version">default_python_version</a>, <a href="#parfile.imports">imports</a>, <a href="#parfile.main">main</a>, <a href="#parfile.zip_safe">zip_safe</a>)</pre>
 
           <p>A self-contained, single-file Python program, with a .par file extension.</p>
 <p>You probably want to use par_binary() instead of this.</p>
@@ -202,13 +202,23 @@
 <p>See <a href="http://www.bazel.io/docs/be/python.html#py_binary.main">py_binary.main</a></p>
       </td>
     </tr>
+    <tr id="parfile.zip_safe">
+      <td><code>zip_safe</code></td>
+      <td>
+        <p><code>Boolean; Optional; Default is True</code></p>
+        <p>Whether to import Python code and read datafiles directly
+from the zip archive.  Otherwise, if False, all files are
+extracted to a temporary directory on disk each time the
+par file executes.</p>
+      </td>
+    </tr>
   </tbody>
 </table>
           <hr>
 
           <h2 id="parfile_test">parfile_test</h2>
 
-          <pre>parfile_test(<a href="#parfile_test.name">name</a>, <a href="#parfile_test.src">src</a>, <a href="#parfile_test.compiler">compiler</a>, <a href="#parfile_test.default_python_version">default_python_version</a>, <a href="#parfile_test.imports">imports</a>, <a href="#parfile_test.main">main</a>)</pre>
+          <pre>parfile_test(<a href="#parfile_test.name">name</a>, <a href="#parfile_test.src">src</a>, <a href="#parfile_test.compiler">compiler</a>, <a href="#parfile_test.default_python_version">default_python_version</a>, <a href="#parfile_test.imports">imports</a>, <a href="#parfile_test.main">main</a>, <a href="#parfile_test.zip_safe">zip_safe</a>)</pre>
 
           <p>Identical to par_binary, but the rule is marked as being a test.</p>
 <p>You probably want to use par_test() instead of this.</p>
@@ -268,6 +278,16 @@
 <p>See <a href="http://www.bazel.io/docs/be/python.html#py_binary.main">py_binary.main</a></p>
       </td>
     </tr>
+    <tr id="parfile_test.zip_safe">
+      <td><code>zip_safe</code></td>
+      <td>
+        <p><code>Boolean; Optional; Default is True</code></p>
+        <p>Whether to import Python code and read datafiles directly
+from the zip archive.  Otherwise, if False, all files are
+extracted to a temporary directory on disk each time the
+par file executes.</p>
+      </td>
+    </tr>
   </tbody>
 </table>
 
@@ -278,7 +298,7 @@
           <div class="mdl-mini-footer__left-section">
             <div class="mdl-logo">Bazel</div>
             <ul class="mdl-mini-footer__link-list">
-              <li><a href="http://bazel.io">Home</a></li>
+              <li><a href="https://bazel.build">Home</a></li>
               <li><a href="https://github.com/bazelbuild">GitHub</a></li>
             </ul>
           </div>
diff --git a/docs/subpar.md b/docs/subpar.md
index 99e8116..1d71527 100644
--- a/docs/subpar.md
+++ b/docs/subpar.md
@@ -94,7 +94,7 @@
 ## parfile
 
 <pre>
-parfile(<a href="#parfile.name">name</a>, <a href="#parfile.src">src</a>, <a href="#parfile.compiler">compiler</a>, <a href="#parfile.default_python_version">default_python_version</a>, <a href="#parfile.imports">imports</a>, <a href="#parfile.main">main</a>)
+parfile(<a href="#parfile.name">name</a>, <a href="#parfile.src">src</a>, <a href="#parfile.compiler">compiler</a>, <a href="#parfile.default_python_version">default_python_version</a>, <a href="#parfile.imports">imports</a>, <a href="#parfile.main">main</a>, <a href="#parfile.zip_safe">zip_safe</a>)
 </pre>
 
 A self-contained, single-file Python program, with a .par file extension.
@@ -161,13 +161,23 @@
 <p>See <a href="http://www.bazel.io/docs/be/python.html#py_binary.main">py_binary.main</a></p>
       </td>
     </tr>
+    <tr id="parfile.zip_safe">
+      <td><code>zip_safe</code></td>
+      <td>
+        <p><code>Boolean; Optional; Default is True</code></p>
+        <p>Whether to import Python code and read datafiles directly
+from the zip archive.  Otherwise, if False, all files are
+extracted to a temporary directory on disk each time the
+par file executes.</p>
+      </td>
+    </tr>
   </tbody>
 </table>
 <a name="parfile_test"></a>
 ## parfile_test
 
 <pre>
-parfile_test(<a href="#parfile_test.name">name</a>, <a href="#parfile_test.src">src</a>, <a href="#parfile_test.compiler">compiler</a>, <a href="#parfile_test.default_python_version">default_python_version</a>, <a href="#parfile_test.imports">imports</a>, <a href="#parfile_test.main">main</a>)
+parfile_test(<a href="#parfile_test.name">name</a>, <a href="#parfile_test.src">src</a>, <a href="#parfile_test.compiler">compiler</a>, <a href="#parfile_test.default_python_version">default_python_version</a>, <a href="#parfile_test.imports">imports</a>, <a href="#parfile_test.main">main</a>, <a href="#parfile_test.zip_safe">zip_safe</a>)
 </pre>
 
 Identical to par_binary, but the rule is marked as being a test.
@@ -231,5 +241,15 @@
 <p>See <a href="http://www.bazel.io/docs/be/python.html#py_binary.main">py_binary.main</a></p>
       </td>
     </tr>
+    <tr id="parfile_test.zip_safe">
+      <td><code>zip_safe</code></td>
+      <td>
+        <p><code>Boolean; Optional; Default is True</code></p>
+        <p>Whether to import Python code and read datafiles directly
+from the zip archive.  Otherwise, if False, all files are
+extracted to a temporary directory on disk each time the
+par file executes.</p>
+      </td>
+    </tr>
   </tbody>
 </table>
diff --git a/subpar.bzl b/subpar.bzl
index da57852..7c33e9b 100644
--- a/subpar.bzl
+++ b/subpar.bzl
@@ -69,11 +69,14 @@
         ctx.attr.src.files_to_run.runfiles_manifest,
         ]
 
+    zip_safe = ctx.attr.zip_safe
+
     # Assemble command line for .par compiler
     args = [
         '--manifest_file', sources_file.path,
         '--outputpar', ctx.outputs.executable.path,
         '--stub_file', stub_file,
+        '--zip_safe', str(zip_safe),
         main_py_file.path,
     ]
     ctx.action(
@@ -118,6 +121,7 @@
         executable = True,
         cfg = "host",
     ),
+    "zip_safe": attr.bool(default=True),
 }
 
 # Rule to create a parfile given a py_binary() as input
@@ -125,6 +129,7 @@
     attrs = parfile_attrs,
     executable = True,
     implementation = _parfile_impl,
+    test = False,
 )
 """A self-contained, single-file Python program, with a .par file extension.
 
@@ -147,9 +152,13 @@
 
   compiler: Internal use only.
 
+  zip_safe: Whether to import Python code and read datafiles directly
+            from the zip archive.  Otherwise, if False, all files are
+            extracted to a temporary directory on disk each time the
+            par file executes.
+
 TODO(b/27502830): A directory foo.par.runfiles is also created. This
 is a bug, don't use or depend on it.
-
 """
 
 parfile_test = rule(
@@ -184,9 +193,10 @@
     default_python_version = kwargs.get('default_python_version', 'PY2')
     visibility = kwargs.get('visibility')
     testonly = kwargs.get('testonly', False)
+    zip_safe = kwargs.get('zip_safe', True)
     parfile(name=name + '.par', src=name, main=main, imports=imports,
             default_python_version=default_python_version, visibility=visibility,
-            testonly=testonly)
+            testonly=testonly, zip_safe=zip_safe)
 
 def par_test(name, **kwargs):
     """An executable Python test.
@@ -199,7 +209,10 @@
     imports = kwargs.get('imports')
     default_python_version = kwargs.get('default_python_version', 'PY2')
     visibility = kwargs.get('visibility')
+    testonly = kwargs.get('testonly', True)
+    zip_safe = kwargs.get('zip_safe', True)
     parfile_test(
         name=name + '.par', src=name, main=main, imports=imports,
         default_python_version=default_python_version, visibility=visibility,
+        testonly=testonly, zip_safe=zip_safe,
     )