Skip to content
This repository was archived by the owner on Aug 11, 2020. It is now read-only.

Commit 03d4a7a

Browse files
committed
change zip_to_tmp to take a list of files, skip a list of ignore_files, and use the full directory basename for the zip file; change jobs create to handle a list of extra files along with the workspace files; change run to implement init, conda, pipenv, req options
1 parent 325038f commit 03d4a7a

File tree

1 file changed

+105
-51
lines changed

1 file changed

+105
-51
lines changed

paperspace/jobs.py

Lines changed: 105 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,29 @@
1515
from .login import apikey
1616
from .method import *
1717

18-
def zip_to_tmp(obj_name):
18+
def zip_to_tmp(files, ignore_files=[]):
19+
file = files[0]
1920
zipname = os.path.join(tempfile.gettempdir(),
20-
os.path.basename(obj_name)) + '.zip'
21+
os.path.basename(os.path.abspath(os.path.expanduser(file)))) + '.zip'
2122
outZipFile = zipfile.ZipFile(zipname, 'w', zipfile.ZIP_DEFLATED)
22-
23-
if os.path.isdir(obj_name):
24-
for dirpath, dirnames, filenames in os.walk(obj_name):
25-
for filename in dirnames + filenames:
26-
filepath = os.path.join(dirpath, filename)
27-
basename = os.path.basename(filepath)
28-
if ('/.git/' not in filepath
29-
and basename not in ['.git', '.gitignore']):
30-
arcname = os.path.relpath(filepath, obj_name)
31-
outZipFile.write(filepath, arcname)
32-
else:
33-
outZipFile.write(obj_name, os.path.basename(obj_name))
34-
35-
outZipFile.close()
23+
files_added = set()
24+
with outZipFile:
25+
for file in files:
26+
if os.path.isdir(file):
27+
for dirpath, dirnames, filenames in os.walk(file):
28+
dirnames[:] = [d for d in dirnames if d not in ignore_files]
29+
for filename in filenames:
30+
if filename not in ignore_files:
31+
filepath = os.path.join(dirpath, filename)
32+
arcname = os.path.relpath(filepath, file)
33+
if arcname not in files_added:
34+
outZipFile.write(filepath, arcname)
35+
files_added.add(arcname)
36+
else:
37+
arcname = os.path.basename(file)
38+
if arcname not in files_added:
39+
outZipFile.write(file, arcname)
40+
files_added.add(arcname)
3641
return zipname
3742

3843

@@ -47,7 +52,9 @@ def method(category, method, params):
4752
elif not config.PAPERSPACE_API_KEY:
4853
config.PAPERSPACE_API_KEY = apikey()
4954
params.pop('tail', None)
50-
params.pop('no_logging', None)
55+
no_logging = params.pop('no_logging', None)
56+
workspace_files = params.pop('extraFiles', [])
57+
ignore_files = params.pop('ignoreFiles', [])
5158

5259
if method in ['artifactsGet', 'artifactsList', 'getJob', 'getJobs',
5360
'getLogs']:
@@ -68,19 +75,39 @@ def method(category, method, params):
6875

6976
files = None
7077
if method == 'createJob' and 'workspace' in params:
71-
workspace = params['workspace']
72-
workspace_file = None
73-
if workspace and workspace != 'none':
74-
workspace_path = os.path.expanduser(workspace)
75-
if os.path.exists(workspace_path):
76-
if (not workspace_path.endswith('.zip')
77-
and not workspace_path.endswith('.gz')):
78-
workspace_file = zip_to_tmp(workspace_path)
79-
else:
80-
workspace_file = workspace_path
78+
79+
workspace = params.get('workspace', None)
80+
ignore_files.extend(['.git', '.gitignore'])
81+
if workspace:
82+
if workspace != 'none':
83+
workspace_files.insert(0, workspace)
84+
del params['workspace']
85+
86+
if workspace_files:
87+
workspace_file = None
88+
for file in workspace_files:
89+
file_path = os.path.expanduser(file)
90+
if not os.path.exists(file_path):
91+
message = format('error: file or directory not found: %s' % file_path)
92+
print(message)
93+
if no_logging:
94+
return { 'error': True, 'message': message }
95+
sys.exit(1)
96+
elif file_path == '/':
97+
message = 'error: cannot zip root directory'
98+
print(message)
99+
if no_logging:
100+
return { 'error': True, 'message': message }
101+
sys.exit(1)
102+
103+
if len(workspace_files) == 1 and (file_path.endswith('.zip') or file_path.endswith('.gz')):
104+
workspace_file = file_path
105+
106+
if not workspace_file:
107+
workspace_file = zip_to_tmp(workspace_files, ignore_files)
108+
81109
files = {'file': open(workspace_file, 'rb')}
82110
params['workspaceFileName'] = os.path.basename(workspace_file)
83-
del params['workspace']
84111

85112
try:
86113
r = requests.request(http_method, config.CONFIG_HOST + path,
@@ -219,7 +246,7 @@ def waitfor(params):
219246
time.sleep(5)
220247

221248

222-
def create(params, no_logging=False):
249+
def create(params, no_logging=False, extra_files=[]):
223250
no_logging = no_logging or params.get('no_logging', False)
224251
job = method('jobs', 'createJob', params)
225252
if no_logging:
@@ -329,7 +356,6 @@ def artifactsGet(params, no_logging=False):
329356

330357

331358
# TO DO:
332-
# deal with invalid directories, e.g. root for workspace
333359
# detect running interactively
334360
# stream file uploads/downloads
335361

@@ -373,10 +399,6 @@ def run(params={}, no_logging=False):
373399
src = src.replace('paperspace.login', '_paperspace_null_func')
374400
src = src.replace('paperspace.logout', '_paperspace_null_func')
375401

376-
# XXX TEST CODE
377-
#print(src)
378-
#sys.exit(0)
379-
380402
src_path = os.path.join(tempfile.gettempdir(), src_file)
381403
with open(src_path, "w") as file:
382404
file.write(src)
@@ -390,25 +412,58 @@ def run(params={}, no_logging=False):
390412
params['machineType'] = 'P5000'
391413
if 'container' not in params:
392414
params['container'] = 'paperspace/tensorflow-python'
393-
if 'command' not in params:
394-
# TODO validate python version; handle no version, specific version
395-
python_ver = params['python'] if 'python' in params else str(sys.version_info[0])
396-
params['command'] = 'python' + python_ver + ' ' + src_file
397-
if 'workspace' not in params or run_this:
398-
params['workspace'] = src_path
399415

400-
# XXX TEST CODE
401-
#print(params)
416+
python_ver = params.pop('python', str(sys.version_info[0])) # defaults locally running version
417+
# TODO validate python version; handle no version, specific version
402418

403-
params.pop('python', None)
404-
params.pop('conda', None)
405-
params.pop('init', None)
406-
params.pop('req', None)
407-
params.pop('pipenv', None)
419+
if 'command' not in params:
420+
params['command'] = 'python' + python_ver + ' ' + src_file
408421

409-
# XXX TEST CODE
410-
#print('edited', params)
411-
#return {}
422+
params['extraFiles'] = []
423+
if 'workspace' not in params:
424+
params['workspace'] = src_path
425+
else:
426+
params['extraFiles'].append(src_path)
427+
428+
if 'ignoreFiles' in params:
429+
if isinstance(params['ignoreFiles'], str):
430+
params['ignoreFiles'] = params['ignoreFiles'].split(',')
431+
432+
req = params.pop('req', None)
433+
if req:
434+
if not isinstance(req, str):
435+
req = 'requirements.txt'
436+
if os.path.exists(req):
437+
params['extraFiles'].append(req)
438+
params['command'] = 'pip' + python_ver + ' install -r ' + os.path.basename(req) + '\n' + params['command']
439+
440+
pipenv = params.pop('pipenv', None)
441+
if pipenv:
442+
if isinstance(pipenv, str):
443+
pipenv = pipenv.split(',')
444+
elif isinstance(pipenv, bool):
445+
pipenv = ['Pipfile', 'Pipfile.lock']
446+
for pipfile in pipenv:
447+
if os.path.exists(pipfile):
448+
params['extraFiles'].append(pipfile)
449+
uses_python_ver = ''
450+
if python_ver.startswith('3'):
451+
uses_python_ver == '--three '
452+
elif python_ver.startswith('2'):
453+
uses_python_ver == '--two '
454+
params['command'] = 'pipenv ' + uses_python_ver + 'install\npipenv graph\n' + params['command']
455+
456+
conda = params.pop('conda', None)
457+
if conda:
458+
params['command'] = 'conda -env ' + conda + '\n' + params['command']
459+
460+
init = params.pop('init', None)
461+
if init:
462+
if not isinstance(init, str):
463+
init = 'init.sh'
464+
if os.path.exists(init):
465+
params['extraFiles'].append(init)
466+
params['command'] = '. ' + os.path.basename(init) + '\n' + params['command']
412467

413468
res = create(params, no_logging)
414469
if run_this:
@@ -419,5 +474,4 @@ def run(params={}, no_logging=False):
419474
# TO DO:
420475
# automatic install of imported dependencies
421476
# allow return results
422-
# combine local workspace with source
423477
# detect/use python environment

0 commit comments

Comments
 (0)