55import tarfile
66import tempfile
77from collections import namedtuple
8+ from copy import deepcopy
89from pathlib import Path
910from typing import Dict , Any , List
1011
1415from nbformat .notebooknode import NotebookNode
1516
1617from .iotypes import CWLFilePathInput , CWLBooleanInput , CWLIntInput , CWLStringInput , CWLFilePathOutput , \
17- CWLDumpableFile , CWLDumpableBinaryFile
18+ CWLDumpableFile , CWLDumpableBinaryFile , CWLDumpable
1819from .requirements_manager import RequirementsManager
1920
2021with open (os .sep .join ([os .path .abspath (os .path .dirname (__file__ )), 'templates' , 'template.dockerfile' ])) as f :
@@ -64,6 +65,7 @@ class AnnotatedVariablesExtractor(ast.NodeTransformer):
6465 dumpable_mapper = {
6566 (CWLDumpableFile .__name__ ,): "with open('{var_name}', 'w') as f:\n \t f.write({var_name})" ,
6667 (CWLDumpableBinaryFile .__name__ ,): "with open('{var_name}', 'wb') as f:\n \t f.write({var_name})" ,
68+ (CWLDumpable .__name__ , CWLDumpable .dump .__name__ ): None ,
6769 }
6870
6971 def __init__ (self , * args , ** kwargs ):
@@ -82,6 +84,8 @@ def __get_annotation__(self, type_annotation):
8284 annotation = self .__get_annotation__ (ann_expr .value )
8385 elif isinstance (type_annotation , ast .Subscript ):
8486 annotation = (type_annotation .value .id , * self .__get_annotation__ (type_annotation .slice .value ))
87+ elif isinstance (type_annotation , ast .Call ):
88+ annotation = (type_annotation .func .value .id , type_annotation .func .attr )
8589 return annotation
8690
8791 def visit_AnnAssign (self , node ):
@@ -94,18 +98,53 @@ def visit_AnnAssign(self, node):
9498 )
9599 return None
96100 elif annotation in self .dumpable_mapper :
97- dump_tree = ast .parse (self .dumpable_mapper [annotation ].format (var_name = node .target .id ))
98- self .to_dump .append (dump_tree .body )
99- self .extracted_variables .append (_VariableNameTypePair (
100- node .target .id , None , None , None , False , True , node .target .id )
101- )
102- # removing type annotation
103- return ast .Assign (
104- col_offset = node .col_offset ,
105- lineno = node .lineno ,
106- targets = [node .target ],
107- value = node .value
108- )
101+ dumper = self .dumpable_mapper [annotation ]
102+ if dumper is not None :
103+ dump_tree = ast .parse (dumper .format (var_name = node .target .id ))
104+ self .to_dump .append (dump_tree .body )
105+ self .extracted_variables .append (_VariableNameTypePair (
106+ node .target .id , None , None , None , False , True , node .target .id )
107+ )
108+ # removing type annotation
109+ return ast .Assign (
110+ col_offset = node .col_offset ,
111+ lineno = node .lineno ,
112+ targets = [node .target ],
113+ value = node .value
114+ )
115+ else :
116+ load_ctx = ast .Load ()
117+ func_name = deepcopy (node .annotation .args [0 ].value )
118+ func_name .ctx = load_ctx
119+ ast .fix_missing_locations (func_name )
120+
121+ new_dump_node = ast .Expr (
122+ col_offset = 0 , lineno = 0 ,
123+ value = ast .Call (
124+ args = node .annotation .args [1 :],
125+ col_offset = 0 ,
126+ func = ast .Attribute (
127+ attr = node .annotation .args [0 ].attr ,
128+ col_offset = 0 ,
129+ ctx = load_ctx ,
130+ lineno = 0 ,
131+ value = func_name ,
132+ ),
133+ keywords = node .annotation .keywords
134+ )
135+ )
136+ ast .fix_missing_locations (new_dump_node )
137+ self .to_dump .append ([new_dump_node ])
138+ self .extracted_variables .append (_VariableNameTypePair (
139+ node .target .id , None , None , None , False , True , node .annotation .args [1 ].s )
140+ )
141+ # removing type annotation
142+ return ast .Assign (
143+ col_offset = node .col_offset ,
144+ lineno = node .lineno ,
145+ targets = [node .target ],
146+ value = node .value
147+ )
109148 elif (isinstance (node .annotation , ast .Name ) and node .annotation .id in self .output_type_mapper ) or \
110149 (isinstance (node .annotation , ast .Str ) and node .annotation .s in self .output_type_mapper ):
111150 self .extracted_variables .append (_VariableNameTypePair (
0 commit comments