def test_reporting_errors_f_strings(source, line): """Test that we properly report error on f-string. """ with pytest.raises(SyntaxError) as e: parse(source) assert "backslash" in e.value.args[0] assert line == e.value.args[1][1]
def refresh_view(self, change): """ Refresh the compiled view object. This method will (re)compile the view for the given view text and update the 'compiled_view' attribute. If a compiled model is available and the view has a member named 'model', the model will be applied to the view. """ viewer = self.workbench.get_plugin('declaracad.viewer') doc = self.active_document try: ast = parse(doc.source, filename=doc.name) code = EnamlCompiler.compile(ast, doc.name) module = ModuleType('__main__') module.__file__ = doc.name namespace = module.__dict__ with enaml.imports(): exec_(code, namespace) assembly = namespace.get('Assembly', lambda: None)() viewer.parts = [assembly] if assembly else [] except Exception as e: errors = doc.errors[:] log.warning(traceback.format_exc()) tb = traceback.format_exc().strip().split("\n") print(tb[-3]) m = re.search(r'File "(.+)", line (\d+),', tb[-3]) if m: errors.append("{}:{}: {}".format(m.group(1), m.group(2), tb[-1])) doc.errors = errors viewer.parts = []
def parse_and_create(self, source, **kwargs): """ Parses and compiles the source. The source should have a component defined with the name 'MainView'. Arguments --------- source : str The enaml source file kwargs : dict The default attribute values to pass to the component. Returns ------- The component tree for the 'MainView' component. """ # Start the app instance first. app = MockApplication.instance() if app is None: app = MockApplication() self.app = app enaml_ast = parse(source) enaml_module = types.ModuleType('__tests__') ns = enaml_module.__dict__ code = EnamlCompiler.compile(enaml_ast, '__enaml_tests__') exec code in ns view = ns['MainView'] self.view = view(**kwargs) self.view.prepare() self.client_view = app.builder().root
def load_model(filename): """ Load a DeclaraCAD model from an enaml file. Ideally this should be used in a separate process but it's not required. Parameters ---------- filename: String Path to the enaml file to load Returns ------- result: List[occ.shape.Shape] A list of shapes that can be passed to the python-occ viewer. """ # Parse the enaml file with open(filename, 'rU') as f: ast = parse(f.read()) code = EnamlCompiler.compile(ast, filename) module = ModuleType(filename.rsplit('.', 1)[0]) module.__file__ = filename namespace = module.__dict__ with enaml.imports(): exec_(code, namespace) Assembly = namespace['Assembly'] return [Assembly()]
def compile_source(source, item, filename='<test>', namespace=None): """ Compile Enaml source code and return the target item. Parameters ---------- source : str The Enaml source code string to compile. item : str The name of the item in the resulting namespace to return. filename : str, optional The filename to use when compiling the code. The default is '<test>'. namespace : dict Namespace in which to execute the code Returns ------- result : object The named object from the resulting namespace. """ ast = parse(source, filename) code = EnamlCompiler.compile(ast, filename) namespace = namespace or {} exec_(code, namespace) return namespace[item]
def parse_and_create(self, source, **kwargs): """ Parses and compiles the source. The source should have a component defined with the name 'MainView'. Arguments --------- source : str The enaml source file kwargs : dict The default attribute values to pass to the component. """ enaml_ast = parse(source) enaml_module = types.ModuleType('__tests__') ns = enaml_module.__dict__ code = EnamlCompiler.compile(enaml_ast, '__enaml_tests__') toolkit = self.toolkit with toolkit: exec code in ns view = ns['MainView'] cmpnt = view(**kwargs) toolkit.app.initialize() self.app = toolkit.app.app_object() cmpnt.setup() return cmpnt
def compile_source(source, item, filename='<test>'): """ Compile Enaml source code and return the target item. Parameters ---------- source : str The Enaml source code string to compile. item : str The name of the item in the resulting namespace to return. filename : str, optional The filename to use when compiling the code. The default is '<test>'. Returns ------- result : object The named object from the resulting namespace. """ ast = parse(source, filename) code = EnamlCompiler.compile(ast, filename) namespace = {} exec code in namespace return namespace[item]
def test_func_return_annotation_parsing(): """Test that we parse properly functions with a return type annotation. """ src = "def f() -> int:\n pass" py_ast = ast.parse(src).body[0] enaml_ast = parse(src).body[0].ast.body[0] validate_ast(py_ast, enaml_ast, True)
def test_raise_exception(): """Test raising an exception. """ src = """raise Exception()""" py_ast = ast.parse(src).body[0] enaml_ast = parse(src).body[0].ast.body[0] validate_ast(py_ast, enaml_ast, True)
def test_invalid_walrus_operator(desc): """Test that we produce valid ast use of the := walrus operator. """ src = dedent(TEST_BAD_SOURCE[desc]).strip() print(src) with pytest.raises(SyntaxError): enaml_ast = parse(src).body[0].ast
def test_func_definition_parsing(signature): """Test parsing all possible function signatures. """ src = FUNC_TEMPLATE.format(signature) py_ast = ast.parse(src).body[0] enaml_ast = parse(src).body[0].ast.body[0] validate_ast(py_ast, enaml_ast, True)
def test_f_strings(desc): """Async function with await list comp statement """ src = TEST_SOURCE[desc].strip() print(src) # Ensure it's valid py_ast = ast.parse(src) enaml_ast = parse(src).body[0].ast validate_ast(py_ast.body[0], enaml_ast.body[0], True)
def test_async(desc): """Async function with await list comp statement. """ src = FUNC_TEMPLATE.format(dedent(TEST_SOURCE[desc])) # Ensure it's valid py_ast = ast.parse(src) enaml_ast = parse(src).body[0].ast validate_ast(py_ast.body[0], enaml_ast.body[0], True) validate_ast(py_ast.body[1], enaml_ast.body[1], True) validate_ast(py_ast.body[2], enaml_ast.body[2], True)
def test_f_strings(desc): """Test that we produce valid ast for f-strings. """ src = TEST_SOURCE[desc].strip() print(src) # Ensure it's valid py_ast = ast.parse(src) enaml_ast = parse(src).body[0].ast validate_ast(py_ast.body[0], enaml_ast.body[0], True)
def test_async(desc): """Async function with await list comp statement """ src = FUNC_TEMPLATE.format(dedent(TEST_SOURCE[desc])) # Ensure it's valid py_ast = ast.parse(src) enaml_ast = parse(src).body[0].ast validate_ast(py_ast.body[0], enaml_ast.body[0], True) validate_ast(py_ast.body[1], enaml_ast.body[1], True) validate_ast(py_ast.body[2], enaml_ast.body[2], True)
def test_walrus_operator(desc): """Test that we produce valid ast use of the := walrus operator. """ src = dedent(TEST_SOURCE[desc]).strip() print(src) # Ensure it's valid py_ast = ast.parse(src) enaml_ast = parse(src).body[0].ast validate_ast(py_ast.body[0], enaml_ast.body[0], True)
def main(): usage = 'usage: %prog [options] enaml_file [script arguments]' parser = optparse.OptionParser(usage=usage, description=__doc__) parser.allow_interspersed_args = False parser.add_option('-c', '--component', default='Main', help='The component to view') parser.add_option( '-t', '--toolkit', default='default', help='The GUI toolkit to use [default: qt or ETS_TOOLKIT].') options, args = parser.parse_args() toolkit = prepare_toolkit(options.toolkit) if len(args) == 0: print 'No .enaml file specified' sys.exit() else: enaml_file = args[0] script_argv = args[1:] with open(enaml_file, 'rU') as f: enaml_code = f.read() # Parse and compile the Enaml source into a code object ast = parse(enaml_code, filename=enaml_file) code = EnamlCompiler.compile(ast, enaml_file) # Create a proper module in which to execute the compiled code so # that exceptions get reported with better meaning module = types.ModuleType('__main__') module.__file__ = enaml_file ns = module.__dict__ # Put the directory of the Enaml file first in the path so relative # imports can work. sys.path.insert(0, os.path.abspath(os.path.dirname(enaml_file))) # Bung in the command line arguments. sys.argv = [enaml_file] + script_argv with imports(): exec code in ns requested = options.component if requested in ns: component = ns[requested] descr = 'Enaml-run "%s" view' % requested show_simple_view(component(), toolkit, descr) elif 'main' in ns: ns['main']() else: msg = "Could not find component '%s'" % options.component print msg
def main(): usage = 'usage: %prog [options] enaml_file [script arguments]' parser = optparse.OptionParser(usage=usage, description=__doc__) parser.allow_interspersed_args = False parser.add_option('-c', '--component', default='Main', help='The component to view') options, args = parser.parse_args() if len(args) == 0: print('No .enaml file specified') sys.exit() else: enaml_file = args[0] script_argv = args[1:] enaml_code = read_source(enaml_file) # Parse and compile the Enaml source into a code object ast = parse(enaml_code, filename=enaml_file) code = EnamlCompiler.compile(ast, enaml_file) # Create a proper module in which to execute the compiled code so # that exceptions get reported with better meaning module = types.ModuleType('__main__') module.__file__ = os.path.abspath(enaml_file) sys.modules['__main__'] = module ns = module.__dict__ # Put the directory of the Enaml file first in the path so relative # imports can work. sys.path.insert(0, os.path.abspath(os.path.dirname(enaml_file))) # Bung in the command line arguments. sys.argv = [enaml_file] + script_argv with imports(): exec_(code, ns) # Make sure ^C keeps working signal.signal(signal.SIGINT, signal.SIG_DFL) requested = options.component if requested in ns: from enaml.qt.qt_application import QtApplication app = QtApplication() window = ns[requested]() window.show() window.send_to_front() app.start() elif 'main' in ns: ns['main']() else: msg = "Could not find component '%s'" % options.component print(msg)
def main(): usage = 'usage: %prog [options] enaml_file [script arguments]' parser = optparse.OptionParser(usage=usage, description=__doc__) parser.allow_interspersed_args = False parser.add_option( '-c', '--component', default='Main', help='The component to view' ) options, args = parser.parse_args() if len(args) == 0: print('No .enaml file specified') sys.exit() else: enaml_file = args[0] script_argv = args[1:] enaml_code = read_source(enaml_file) # Parse and compile the Enaml source into a code object ast = parse(enaml_code, filename=enaml_file) code = EnamlCompiler.compile(ast, enaml_file) # Create a proper module in which to execute the compiled code so # that exceptions get reported with better meaning module = types.ModuleType('__main__') module.__file__ = os.path.abspath(enaml_file) sys.modules['__main__'] = module ns = module.__dict__ # Put the directory of the Enaml file first in the path so relative # imports can work. sys.path.insert(0, os.path.abspath(os.path.dirname(enaml_file))) # Bung in the command line arguments. sys.argv = [enaml_file] + script_argv with imports(): exec_(code, ns) # Make sure ^C keeps working signal.signal(signal.SIGINT, signal.SIG_DFL) requested = options.component if requested in ns: from enaml.qt.qt_application import QtApplication app = QtApplication() window = ns[requested]() window.show() window.send_to_front() app.start() elif 'main' in ns: ns['main']() else: msg = "Could not find component '%s'" % options.component print(msg)
def main(): usage = 'usage: %prog [options] enaml_file [script arguments]' parser = optparse.OptionParser(usage=usage, description=__doc__) parser.allow_interspersed_args = False parser.add_option('-c', '--component', default='Main', help='The component to view') parser.add_option('-t', '--toolkit', default='default', choices=['default', 'wx', 'qt'], help='The toolkit backend to use') options, args = parser.parse_args() # Preapare the toolkit toolkit = prepare_toolkit(options.toolkit) if len(args) == 0: print 'No .enaml file specified' sys.exit() else: enaml_file = args[0] script_argv = args[1:] with open(enaml_file) as f: enaml_code = f.read() # Parse and compile the Enaml source into a code object ast = parse(enaml_code, filename=enaml_file) code = EnamlCompiler.compile(ast, enaml_file) # Create a proper module in which to execute the compiled code so # that exceptions get reported with better meaning module = types.ModuleType('__main__') module.__file__ = enaml_file ns = module.__dict__ # Put the directory of the Enaml file first in the path so relative imports # can work. sys.path.insert(0, os.path.abspath(os.path.dirname(enaml_file))) # Bung in the command line arguments. sys.argv = [enaml_file] + script_argv with imports(): exec code in ns with toolkit: requested = options.component if requested in ns: component = ns[requested] window = component() window.show() elif 'main' in ns: ns['main']() else: msg = "Could not find component '%s'" % options.component print msg
def test_raise_exception_with_cause(): """Test that we parse properly functions with a return type annotation. """ src = dedent(""" try: a = ""/0 except Exception as e: raise Exception() from e """) py_ast = ast.parse(src).body[0] enaml_ast = parse(src).body[0].ast.body[0] validate_ast(py_ast, enaml_ast, True)
def test_reraise_exception(): """Test raising an exception. """ src = dedent(""" try: a = ""/0 except: raise """) py_ast = ast.parse(src).body[0] enaml_ast = parse(src).body[0].ast.body[0] validate_ast(py_ast, enaml_ast, True)
def __init__(self, text, code=None, filename=None): self.text = text if code: self.code = code else: try: self.code = EnamlCompiler.compile(parse(text), filename) except SyntaxError as synerr: raise NotPython( u"Couldn't parse '%s' as Enaml source: '%s' at line %d" % ( filename, synerr.msg, synerr.lineno ) )
def main(): usage = "usage: %prog [options] enaml_file [script arguments]" parser = optparse.OptionParser(usage=usage, description=__doc__) parser.allow_interspersed_args = False parser.add_option("-c", "--component", default="Main", help="The component to view") options, args = parser.parse_args() if len(args) == 0: print("No .enaml file specified") sys.exit() else: enaml_file = args[0] script_argv = args[1:] with open(enaml_file, "rU") as f: enaml_code = f.read() # Parse and compile the Enaml source into a code object ast = parse(enaml_code, filename=enaml_file) code = EnamlCompiler.compile(ast, enaml_file) # Create a proper module in which to execute the compiled code so # that exceptions get reported with better meaning module = types.ModuleType("__main__") module.__file__ = os.path.abspath(enaml_file) sys.modules["__main__"] = module ns = module.__dict__ # Put the directory of the Enaml file first in the path so relative # imports can work. sys.path.insert(0, os.path.abspath(os.path.dirname(enaml_file))) # Bung in the command line arguments. sys.argv = [enaml_file] + script_argv with imports(): exec(code, ns) requested = options.component if requested in ns: from enaml.qt.qt_application import QtApplication app = QtApplication() window = ns[requested]() window.show() window.send_to_front() app.start() elif "main" in ns: ns["main"]() else: msg = "Could not find component '%s'" % options.component print(msg)
def read_component(enaml_file, requested='Main'): """ Read a component from an .enaml file. Parameters ---------- enaml_file : str The name of the .enaml file. requested : str, optional The name of the MainWindow holding the root Container. Returns ------- factory : callable The factory for the MainWindow, usually a MainWindow EnamlDefinition. module : module The module object from the .enaml file itself. Keep this alive at least until after the component gets constructed. Raises ------ NameError if the requested component does not exist in the module. """ with open(enaml_file) as f: enaml_code = f.read() # Parse and compile the Enaml source into a code object ast = parse(enaml_code, filename=enaml_file) code = EnamlCompiler.compile(ast, enaml_file) # Create a proper module in which to execute the compiled code so # that exceptions get reported with better meaning module = types.ModuleType('__main__') module.__file__ = enaml_file ns = module.__dict__ old_path = sys.path[:] sys.path.insert(0, os.path.dirname(enaml_file)) with imports(): exec code in ns sys.path[:] = old_path if requested in ns: factory = ns[requested] else: msg = "Could not find component {0!r}".format(requested) raise NameError(msg) return factory, module
def __init__(self, text, statements, multiline): self.root_node = parse(neuter_encoding_declaration(text)) self.statements = set(multiline.get(l, l) for l in statements) self.multiline = multiline self.arcs = set() # A map from arc pairs to a pair of sentence fragments: # (startmsg, endmsg). # For an arc from line 17, they should be usable like: # "Line 17 {endmsg}, because {startmsg}" self.missing_arc_fragments = collections.defaultdict(list) self.block_stack = [] self.debug = bool(int(os.environ.get("COVERAGE_TRACK_ARCS", 0)))
def main(): usage = "usage: %prog [options] enaml_file [script arguments]" parser = optparse.OptionParser(usage=usage, description=__doc__) parser.allow_interspersed_args = False parser.add_option("-c", "--component", default="Main", help="The component to view") parser.add_option("-t", "--toolkit", default="default", help="The GUI toolkit to use [default: qt or ETS_TOOLKIT].") options, args = parser.parse_args() toolkit = prepare_toolkit(options.toolkit) if len(args) == 0: print "No .enaml file specified" sys.exit() else: enaml_file = args[0] script_argv = args[1:] with open(enaml_file) as f: enaml_code = f.read() # Parse and compile the Enaml source into a code object ast = parse(enaml_code, filename=enaml_file) code = EnamlCompiler.compile(ast, enaml_file) # Create a proper module in which to execute the compiled code so # that exceptions get reported with better meaning module = types.ModuleType("__main__") module.__file__ = enaml_file ns = module.__dict__ # Put the directory of the Enaml file first in the path so relative # imports can work. sys.path.insert(0, os.path.abspath(os.path.dirname(enaml_file))) # Bung in the command line arguments. sys.argv = [enaml_file] + script_argv with imports(): exec code in ns requested = options.component if requested in ns: component = ns[requested] descr = 'Enaml-run "%s" view' % requested show_simple_view(component(), toolkit, descr) elif "main" in ns: ns["main"]() else: msg = "Could not find component '%s'" % options.component print msg
def main(): usage = 'usage: %prog [options] enaml_file' parser = optparse.OptionParser(usage=usage, description=__doc__) parser.add_option('-c', '--component', default='Main', help='The component to view') parser.add_option('-t', '--toolkit', default='default', choices=['default', 'wx', 'qt'], help='The toolkit backend to use') options, args = parser.parse_args() if len(args) == 0: print 'No .enaml file specified' sys.exit() elif len(args) > 1: print 'Too many files specified' sys.exit() else: enaml_file = args[0] with open(enaml_file) as f: enaml_code = f.read() # Parse and compile the Enaml source into a code object ast = parse(enaml_code, filename=enaml_file) code = EnamlCompiler.compile(ast, enaml_file) # Create a proper module in which to execute the compiled code so # that exceptions get reported with better meaning module = types.ModuleType('__main__') module.__file__ = enaml_file ns = module.__dict__ with imports(): exec code in ns with toolkits[options.toolkit](): requested = options.component if requested in ns: component = ns[requested] window = component() window.show() elif 'main' in ns: ns['main']() else: msg = "Could not find component '%s'" % options.component print msg
def parse_and_create(self, source, **kwargs): """ Parses and compiles the source. The source should have a component defined with the name 'MainView'. Arguments --------- source : str The enaml source file kwargs : dict The default attribute values to pass to the component. Returns ------- The component tree for the 'MainView' component. """ enaml_ast = parse(source) enaml_module = types.ModuleType('__tests__') ns = enaml_module.__dict__ code = EnamlCompiler.compile(enaml_ast, '__enaml_tests__') exec code in ns View = ns['MainView'] # Start the app instance first. session_name = get_unique_session_identifier() view_factory = simple_session(session_name, 'test', View) self.app = TestingQtApplication.instance() if self.app is None: self.app = TestingQtApplication([]) self.app.add_factories([view_factory]) session_id = self.app.start_session(session_name) self.app.start() session = self.app._sessions[session_id] # retrieve the enaml server side root widget self.view = session.windows[0] # retrieve the enaml client side root widget self.client_view = self.app._qt_sessions[session_id]._windows[0]
def test_decl_async_func(): py_src = dedent(""" from enaml.core.declarative import d_func from enaml.widgets.api import Window, Label async def fetch(query): return query class MainWindow(Window): @d_func async def search(self, query): result = await fetch(query) return result """) enaml_src = dedent(""" from enaml.core.declarative import d_func from enaml.widgets.api import Window, Label async def fetch(query): return query enamldef MainWindow(Window): async func search(query): result = await fetch(query) return result enamldef CustomWindow(MainWindow): async search => (query): result = await fetch(query) return result """) py_ast = ast.parse(py_src) enaml_ast = parse(enaml_src) validate_ast(py_ast.body[3].body[0], enaml_ast.body[1].body[0].funcdef, True) # Check override syntax validate_ast(py_ast.body[3].body[0], enaml_ast.body[2].body[0].funcdef, True) # Make sure it compiles CustomWindow = compile_source(enaml_src, 'CustomWindow')
def parse_and_create(self, source, **kwargs): """ Parses and compiles the source. The source should have a component defined with the name 'MainView'. Arguments --------- source : str The enaml source file kwargs : dict The default attribute values to pass to the component. Returns ------- A tuple of the server and client component trees for the 'MainView' component. """ # This replicates what enaml.runner.main does enaml_ast = parse(source, filename='__enaml_tests__') code = EnamlCompiler.compile(enaml_ast, '__enaml_tests__') enaml_module = types.ModuleType('__tests__') ns = enaml_module.__dict__ with traits_enaml.imports(): six.exec_(code, ns, ns) View = ns['MainView'] enaml_view = View(**kwargs) enaml_view.initialize() if not enaml_view.proxy_is_active: enaml_view.activate_proxy() toolkit_view = enaml_view.proxy # We need to keep a reference to the enaml_module to ensure it does not # get collected. If no reference is kept, enaml operators will not be # able to resolve objects properly (eg. validator = IntValidator(...) # will fail) self.enaml_module = enaml_module return enaml_view, toolkit_view
def refresh_view(self): """ Refresh the compiled view object. This method will (re)compile the view for the given view text and update the 'compiled_view' attribute. If a compiled model is available and the view has a member named 'model', the model will be applied to the view. """ text = self.view_text filename = self.view_filename _fake_linecache(text, filename) try: if not text: self.compiled_view = None self._view_module = None else: ast = parse(text, filename=filename) code = EnamlCompiler.compile(ast, filename) module = ModuleType('__main__') module.__file__ = filename namespace = module.__dict__ with enaml.imports(): exec_(code, namespace) view = namespace.get(self.view_item, lambda: None)() if isinstance(view, Object) and 'model' in view.members(): view.model = self.compiled_model # trap any initialization errors and roll back the view old = self.compiled_view try: self.compiled_view = view except Exception: self.compiled_view = old if isinstance(old, Widget): old.show() raise self._view_module = module if old is not None and not old.is_destroyed: old.destroy() except Exception: self.traceback = traceback.format_exc() else: self.traceback = ''
def test_examples(enaml_qtbot, enaml_sleep, path, handler): """ Test the enaml examples. """ dir_path = os.path.abspath(os.path.split(os.path.dirname(__file__))[0]) enaml_file = os.path.join(dir_path, 'examples', os.path.normpath(path)) with open(enaml_file, 'r') as f: enaml_code = f.read() # Parse and compile the Enaml source into a code object ast = parse(enaml_code, filename=enaml_file) code = EnamlCompiler.compile(ast, enaml_file) # Create a proper module in which to execute the compiled code so # that exceptions get reported with better meaning try: module = types.ModuleType('enaml_test') module.__file__ = os.path.abspath(enaml_file) sys.modules['enaml_test'] = module ns = module.__dict__ # Put the directory of the Enaml file first in the path so relative # imports can work. sys.path.insert(0, os.path.abspath(os.path.dirname(enaml_file))) with imports(): exec(code, ns) window = ns['Main']() window.show() window.send_to_front() wait_for_window_displayed(enaml_qtbot, window) enaml_qtbot.wait(enaml_sleep*1000) if handler is not None: handler(enaml_qtbot, window) finally: # Make sure we clean up the sys modification before leaving sys.path.pop(0) del sys.modules['enaml_test']
def generate_cache(path): #: Read with open(path, 'rU') as f: enaml_code = f.read() #: Compile ast = parse(enaml_code, filename=path) code = EnamlCompiler.compile(ast, path) #: Generate cache with open('tmp.enamlc', 'wb') as f: f.write(MAGIC) f.write(struct.pack('i', int(os.path.getmtime(path)))) marshal.dump(code, f) with open('tmp.enamlc', 'rb') as f: data = f.read() #: Cleanup if os.path.exists('tmp.enamlc'): os.remove('tmp.enamlc') return data
def load_model(filename, source=None): """ Load a DeclaraCAD model from an enaml file, source, or a shape supported by the LoadShape node. Parameters ---------- filename: String Path to the enaml file to load source: String Source code to parse (optional) Returns ------- result: List[occ.shape.Shape] A list of shapes that can be passed to the python-occ viewer. """ # Parse the enaml file or load from source code if source or filename.endswith('.enaml'): # Parse and compile the code with open(filename, 'r') as f: source = f.read() ast = parse(source) code = EnamlCompiler.compile(ast, filename) module = ModuleType(filename.rsplit('.', 1)[0]) module.__file__ = filename namespace = module.__dict__ with enaml.imports(): exec(code, namespace) Assembly = namespace['Assembly'] return [Assembly()] elif os.path.exists(filename): # Try to load from filename with enaml.imports(): from .loader import LoadedPart return [LoadedPart(filename=filename)] else: return []
def load_model(filename, source=None): """ Load a DeclaraCAD model from an enaml file. Ideally this should be used in a separate process but it's not required. Parameters ---------- filename: String Path to the enaml file to load source: String Source code to parse (optional) Returns ------- result: List[occ.shape.Shape] A list of shapes that can be passed to the python-occ viewer. """ # Parse the enaml file or load from source code if not source and os.path.exists(filename): with open(filename, 'r') as f: source = f.read() if not source: raise EmptyFileError( f"No source code given or '{filename}' does not exist") # Parse and compile the code ast = parse(source) code = EnamlCompiler.compile(ast, filename) module = ModuleType(filename.rsplit('.', 1)[0]) module.__file__ = filename namespace = module.__dict__ with enaml.imports(): exec(code, namespace) Assembly = namespace['Assembly'] return [Assembly()]