Skip to content

Commit

Permalink
fix(api): Remove crs from scripts in api/resources
Browse files Browse the repository at this point in the history
If a wheel is built on Windows, there's a good chance there will be carriage returns in the scripts
in api/resources, which break the container initialization scripts. To avoid editing the files in
question in the repo, add a step during the wheel build that unzips the wheel, removes carriage
returns, and rezips it.

Closes #2305
  • Loading branch information
sfoster1 committed Sep 18, 2018
1 parent 1e3b27e commit 3da3fcb
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 0 deletions.
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ Individual projects may have additional instructions, so be sure to check out th
Your computer will need the following tools installed to be able to develop with the Opentrons platform:

* macOS 10.11+, Linux, or Windows 10
* On Windows, please configure your git client to `autocrlf=input` if you intend to make API server changes and push them to the robot.
* Python 3.6 ([pyenv](https://github.com/pyenv/pyenv) is optional, but recommended for macOS / Linux. If `pyenv` is not available for your system or you do not want to use it, you can set the environment variable `OT_PYTHON` to the full path to the Python 3.6 executable)

```shell
Expand Down
1 change: 1 addition & 0 deletions api/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ dev:
.PHONY: wheel
wheel: clean
$(python) setup.py bdist_wheel
$(python) remove_cr_in_zip.py -v dist/
shx rm -rf build
shx ls dist

Expand Down
118 changes: 118 additions & 0 deletions api/remove_cr_in_zip.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
"""
Edit an opentrons wheel to remove any carriage returns from files in resources
If there are crs in the scripts in resources/, the robot will not be able to
boot because those files are sourced directly during the boot process. While
the crs may be rewritten when they are committed and pushed to github, if a
windows dev does a push-api from their local checkout there's a good chance
the crs will still be present.
This script therefore opens the specified wheel, unzips it to a tempdir,
removes any carriage returns found in /resources, and rezips it to the
original filename.
"""

import zipfile
import tempfile
import os
import sys
import re


def _write_files(outzip, contentsdir, verbose=False):
for dirpath, dirnames, filenames in os.walk(contentsdir):
for fn in filenames:
fn_abs = os.path.join(dirpath, fn)
zip_path = os.path.relpath(fn_abs, contentsdir)
outzip.write(fn_abs, zip_path)


def _edit_files(indir, verbose=False):
to_edit = []
print(os.listdir(os.path.join(indir, 'opentrons')))
for root, _2, filenames in os.walk(os.path.join(indir,
'opentrons',
'resources')):
to_edit.extend([os.path.join(root, fn) for fn in filenames])
if verbose:
print("File edit list: {}".format(to_edit))
for fn in to_edit:
# We don’t need to edit python files
if verbose:
sys.stdout.write("Checking {}: ".format(fn))
if fn.endswith('.py') or fn.endswith('.pyc'):
if verbose:
print("Skipped (is python file)")
continue
# Or python files that don’t look like python files
try:
first = open(fn).readline()
except UnicodeDecodeError: # (or binary files)
print("Skipped (is most likely binary)")
continue
else:
if first.startswith('#!') and 'python' in first:
if verbose:
print("Skipped (is shebanged python file)")
continue
contents = open(fn, 'rb').read()
new = re.sub(b'\r\n', b'\n', contents)
if verbose:
if len(contents)-len(new) > 0:
print("Edited (found {} <cr>)"
.format(len(contents)-len(new)))
else:
print("Nothing to do")
open(fn, 'wb').write(new)


def rewrite_egg(infile, outfile, verbose=False):
""" Rewrite any <cr> in the resources/ subdirectory of the specified egg.
filelike should be an open filelike object holding the egg.
"""
with tempfile.TemporaryDirectory() as tempdir:
with zipfile.ZipFile(infile, 'r') as inzip:
if verbose:
print("Extracting {} to {}".format(inzip, tempdir))
inzip.extractall(tempdir)
print("Editing files in {}".format(tempdir))
_edit_files(tempdir, verbose)
with zipfile.ZipFile(outfile, 'w') as outzip:
if verbose:
print("Zipping {} to {}".format(tempdir, outzip))
_write_files(outzip, tempdir, verbose)


if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser(
description='Create a new opentrons egg without <cr> in shell scripts')
parser.add_argument(
'in_whl', metavar='INWHL', type=str,
help='The wheel file, or directory containing the egg file, to read')
parser.add_argument(
'out_whl', metavar='OUTWHL', type=str,
help='The wheel file to write. If not specified, execute in place',
nargs='?',
default=None)
parser.add_argument('-v', '--verbose', help='Print extra status messages',
action='store_true')
args = parser.parse_args()
if os.path.isdir(args.in_whl):
files = os.listdir(args.in_whl)
for f in files:
if re.match('opentrons-.*.whl', f):
in_whl = os.path.join(args.in_whl, f)
break
else:
raise OSError("Couldn't find anything that looked like a wheel in {}"
.format(args.in_whl))
else:
in_whl = args.in_whl
if None is args.out_whl:
out_whl = in_whl
else:
out_whl = args.out_whl

rewrite_egg(in_whl, out_whl, args.verbose)

0 comments on commit 3da3fcb

Please sign in to comment.