Skip to content
This repository was archived by the owner on Jan 8, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion compiler/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,13 @@ def make_command_line_parser():
help='Path to add to sys.path, may be repeated to provide multiple roots.',
action='append',
default=[],
dest='import_roots')
dest='import_roots'),
parser.add_argument(
'--no_remove',
help='Keep extracted files after program finishes if --zip_safe is ' +
'enabled.',
type=bool_from_string,
required=True)
return parser


Expand Down Expand Up @@ -170,5 +176,6 @@ def main(argv):
manifest_root=args.manifest_root,
timestamp=args.timestamp,
zip_safe=args.zip_safe,
no_remove=args.no_remove,
)
par.create()
2 changes: 2 additions & 0 deletions compiler/cli_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def test_make_command_line_parser(self):
'--output_par=baz',
'--stub_file=quux',
'--zip_safe=False',
'--no_remove=False',
'--import_root=root1',
'--import_root=root2',
'foo',
Expand All @@ -58,6 +59,7 @@ def test_make_command_line_parser_for_interprerter(self):
'--output_par=baz',
'--stub_file=quux',
'--zip_safe=False',
'--no_remove=False',
'--interpreter=foobar',
'foo',
])
Expand Down
6 changes: 5 additions & 1 deletion compiler/python_archive.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@
_boilerplate_template = """\
# Boilerplate added by subpar/compiler/python_archive.py
from %(runtime_package)s import support as _
_.setup(import_roots=%(import_roots)s, zip_safe=%(zip_safe)s)
_.setup(import_roots=%(import_roots)s, zip_safe=%(zip_safe)s,
no_remove=%(no_remove)s)
del _
# End boilerplate
"""
Expand Down Expand Up @@ -102,6 +103,7 @@ def __init__(self,
output_filename,
timestamp,
zip_safe,
no_remove,
):
self.main_filename = main_filename

Expand All @@ -114,6 +116,7 @@ def __init__(self,
t = datetime.utcfromtimestamp(timestamp)
self.timestamp_tuple = t.timetuple()[0:6]
self.zip_safe = zip_safe
self.no_remove = no_remove

self.compression = zipfile.ZIP_DEFLATED

Expand Down Expand Up @@ -172,6 +175,7 @@ def generate_boilerplate(self, import_roots):
'runtime_package': _runtime_package,
'import_roots': str(import_roots),
'zip_safe': self.zip_safe,
'no_remove': self.no_remove,
}
return boilerplate_contents.encode('ascii').decode('ascii')

Expand Down
2 changes: 2 additions & 0 deletions compiler/python_archive_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ def setUp(self):
self.date_time_tuple = (1980, 1, 1, 0, 0, 0)
self.timestamp = 315532800
self.zip_safe = True
self.no_remove = False

def _construct(self, manifest_filename=None):
return python_archive.PythonArchive(
Expand All @@ -62,6 +63,7 @@ def _construct(self, manifest_filename=None):
output_filename=self.output_filename,
timestamp=self.timestamp,
zip_safe=self.zip_safe,
no_remove=self.no_remove,
)

def test_create_manifest_not_found(self):
Expand Down
20 changes: 18 additions & 2 deletions docs/subpar.html
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ <h3 id="par_test_args">Attributes</h3>

<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.compiler_args">compiler_args</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>
<pre>parfile(<a href="#parfile.name">name</a>, <a href="#parfile.src">src</a>, <a href="#parfile.compiler">compiler</a>, <a href="#parfile.compiler_args">compiler_args</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.no_remove">no_remove</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>
Expand Down Expand Up @@ -223,6 +223,14 @@ <h3 id="parfile_args">Attributes</h3>
<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.no_remove">
<td><code>no_remove</code></td>
<td>
<p><code>Boolean; Optional; Default is False</code></p>
<p>Whether to keep the extracted temporary directory after the
program finishes, if zip_safe is enabled.</p>
</td>
</tr>
<tr id="parfile.zip_safe">
<td><code>zip_safe</code></td>
<td>
Expand All @@ -239,7 +247,7 @@ <h3 id="parfile_args">Attributes</h3>

<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.compiler_args">compiler_args</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>
<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.compiler_args">compiler_args</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.no_remove">no_remove</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>
Expand Down Expand Up @@ -306,6 +314,14 @@ <h3 id="parfile_test_args">Attributes</h3>
<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.no_remove">
<td><code>no_remove</code></td>
<td>
<p><code>Boolean; Optional; Default is False</code></p>
<p>Whether to keep the extracted temporary directory after the
program finishes, if zip_safe is enabled.</p>
</td>
</tr>
<tr id="parfile_test.zip_safe">
<td><code>zip_safe</code></td>
<td>
Expand Down
20 changes: 18 additions & 2 deletions docs/subpar.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ specifically need to test a module's behaviour when used in a .par binary.
## parfile

<pre>
parfile(<a href="#parfile.name">name</a>, <a href="#parfile.src">src</a>, <a href="#parfile.compiler">compiler</a>, <a href="#parfile.compiler_args">compiler_args</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>)
parfile(<a href="#parfile.name">name</a>, <a href="#parfile.src">src</a>, <a href="#parfile.compiler">compiler</a>, <a href="#parfile.compiler_args">compiler_args</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.no_remove">no_remove</a>, <a href="#parfile.zip_safe">zip_safe</a>)
</pre>

A self-contained, single-file Python program, with a .par file extension.
Expand Down Expand Up @@ -182,6 +182,14 @@ the application.</p>
<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.no_remove">
<td><code>no_remove</code></td>
<td>
<p><code>Boolean; Optional; Default is False</code></p>
<p>Whether to keep the extracted temporary directory after the
program finishes, if zip_safe is enabled.</p>
</td>
</tr>
<tr id="parfile.zip_safe">
<td><code>zip_safe</code></td>
<td>
Expand All @@ -198,7 +206,7 @@ par file executes.</p>
## 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.compiler_args">compiler_args</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>)
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.compiler_args">compiler_args</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.no_remove">no_remove</a>, <a href="#parfile_test.zip_safe">zip_safe</a>)
</pre>

Identical to par_binary, but the rule is marked as being a test.
Expand Down Expand Up @@ -269,6 +277,14 @@ the application.</p>
<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.no_remove">
<td><code>no_remove</code></td>
<td>
<p><code>Boolean; Optional; Default is False</code></p>
<p>Whether to keep the extracted temporary directory after the
program finishes, if zip_safe is enabled.</p>
</td>
</tr>
<tr id="parfile_test.zip_safe">
<td><code>zip_safe</code></td>
<td>
Expand Down
13 changes: 7 additions & 6 deletions runtime/support.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ def _find_archive():
return archive_path


def _extract_files(archive_path):
def _extract_files(archive_path, no_remove):
"""Extract the contents of this .par file to disk.

This creates a temporary directory, and registers an atexit
Expand All @@ -107,9 +107,10 @@ def _extract_files(archive_path):
"""
extract_dir = tempfile.mkdtemp()

def _extract_files_cleanup():
shutil.rmtree(extract_dir, ignore_errors=True)
atexit.register(_extract_files_cleanup)
if not no_remove:
def _extract_files_cleanup():
shutil.rmtree(extract_dir, ignore_errors=True)
atexit.register(_extract_files_cleanup)
_log('# extracting %s to %s' % (archive_path, extract_dir))

zip_file = zipfile.ZipFile(archive_path, mode='r')
Expand Down Expand Up @@ -282,7 +283,7 @@ def _initialize_import_path(import_roots, import_prefix):
_log('# adding %s to sys.path' % full_roots)


def setup(import_roots, zip_safe):
def setup(import_roots, zip_safe, no_remove):
"""Initialize subpar run-time support

Args:
Expand All @@ -309,7 +310,7 @@ def setup(import_roots, zip_safe):

# Extract files to disk if necessary
if not zip_safe:
extract_dir = _extract_files(archive_path)
extract_dir = _extract_files(archive_path, no_remove)
# sys.path[0] is the name of the executing .par file. Point
# it to the extract directory instead, so that Python searches
# there for imports.
Expand Down
7 changes: 4 additions & 3 deletions runtime/support_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def test__find_archive(self):

def test__extract_files(self):
# Extract zipfile
extract_path = support._extract_files(self.zipfile_name)
extract_path = support._extract_files(self.zipfile_name, False)

# Check results
self.assertTrue(os.path.isdir(extract_path))
Expand Down Expand Up @@ -140,7 +140,7 @@ def test_setup(self):
mock_sys_path[0] = self.zipfile_name
sys.path = mock_sys_path
success = support.setup(import_roots=['some_root', 'another_root'],
zip_safe=True)
zip_safe=True, no_remove=False)
self.assertTrue(success)
finally:
sys.path = old_sys_path
Expand All @@ -165,7 +165,8 @@ def test_setup__extract(self):
mock_sys_path = list(sys.path)
mock_sys_path[0] = self.zipfile_name
sys.path = mock_sys_path
success = support.setup(import_roots=['some_root'], zip_safe=False)
success = support.setup(import_roots=['some_root'], zip_safe=False,
no_remove=False)
self.assertTrue(success)
finally:
sys.path = old_sys_path
Expand Down
11 changes: 11 additions & 0 deletions subpar.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ def _parfile_impl(ctx):
]

zip_safe = ctx.attr.zip_safe
no_remove = ctx.attr.no_remove

# Assemble command line for .par compiler
args = ctx.attr.compiler_args + [
Expand All @@ -84,6 +85,8 @@ def _parfile_impl(ctx):
ctx.attr.src.files_to_run.executable.path,
"--zip_safe",
str(zip_safe),
'--no_remove',
str(no_remove),
]
for import_root in import_roots:
args.extend(['--import_root', import_root])
Expand Down Expand Up @@ -136,6 +139,7 @@ parfile_attrs = {
),
"compiler_args": attr.string_list(default = []),
"zip_safe": attr.bool(default = True),
"no_remove": attr.bool(default = False),
}

# Rule to create a parfile given a py_binary() as input
Expand Down Expand Up @@ -171,6 +175,9 @@ Args:
extracted to a temporary directory on disk each time the
par file executes.

no_remove: Whether to keep the extracted temporary directory after the
program finishes, if zip_safe is enabled.

TODO(b/27502830): A directory foo.par.runfiles is also created. This
is a bug, don't use or depend on it.
"""
Expand Down Expand Up @@ -204,6 +211,7 @@ def par_binary(name, **kwargs):
compiler = kwargs.pop("compiler", None)
compiler_args = kwargs.pop("compiler_args", [])
zip_safe = kwargs.pop("zip_safe", True)
no_remove = kwargs.pop('no_remove', False)
native.py_binary(name = name, **kwargs)

main = kwargs.get("main", name + ".py")
Expand All @@ -222,6 +230,7 @@ def par_binary(name, **kwargs):
testonly = testonly,
visibility = visibility,
zip_safe = zip_safe,
no_remove=no_remove,
)

def par_test(name, **kwargs):
Expand All @@ -232,6 +241,7 @@ def par_test(name, **kwargs):
"""
compiler = kwargs.pop("compiler", None)
zip_safe = kwargs.pop("zip_safe", True)
no_remove = kwargs.pop('no_remove', False)
native.py_test(name = name, **kwargs)

main = kwargs.get("main", name + ".py")
Expand All @@ -249,4 +259,5 @@ def par_test(name, **kwargs):
testonly = testonly,
visibility = visibility,
zip_safe = zip_safe,
no_remove=no_remove,
)
1 change: 1 addition & 0 deletions tests/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ par_binary(
main = "package_extract/extract.py",
srcs_version = "PY2AND3",
zip_safe = False,
no_remove = False,
)

par_binary(
Expand Down