diff --git a/pycinema/Core.py b/pycinema/Core.py index 581f1526..40b1b7e0 100644 --- a/pycinema/Core.py +++ b/pycinema/Core.py @@ -8,6 +8,7 @@ import io import logging as log import os +import glob import importlib.resources CORE_NAN_VALUES = ['NaN', 'NAN', 'nan'] @@ -62,7 +63,7 @@ def getModulePath(): return str(os.path.dirname(resource_path)) except FileNotFoundError: - raise FileNotFoundError(f"Resource '{resource}' not found in package '{package}'") + raise FileNotFoundError(f"Resource 'Core.py' not found in package 'pycinema'") except Exception as e: raise Exception(f"An error occurred: {e}") @@ -107,8 +108,8 @@ def getPathForScript(name): else: if os.path.isfile(possible_script + ".py"): scriptpath = possible_script + ".py" - else: - log.debug("script directory does not exist: \'" + scriptdir + "\'") + else: + log.debug("script directory does not exist: \'" + scriptdir + "\'") return scriptpath @@ -120,6 +121,9 @@ def getPathForScript(name): def getColumnIndexFromTable(table, colname): ID = -1 + if len(table) < 1: + return ID + colnames = table[0] if colname in colnames: ID = colnames.index(colname) @@ -162,9 +166,9 @@ def getColumnFromTable(table, colname, autocast=False, nan_remove=False, nan_rep i += 1 # TODO: create a separate function call to determine column type - if autocast: - if (any(isNumber(item) for item in cleaned_column) and not (isinstance(cleaned_column, np.ndarray) and np.issubdtype(cleaned_column.dtype, np.floating))): - cleaned_column = np.array(cleaned_column, dtype=float) + if autocast and not isinstance(cleaned_column, np.ndarray): + if any(isNumber(item) for item in cleaned_column): + cleaned_column = np.array(cleaned_column, dtype=float) return cleaned_column @@ -173,28 +177,28 @@ def getColumnFromTable(table, colname, autocast=False, nan_remove=False, nan_rep def getTableExtent(table): try: nRows = len(table) - if nRows < 1: + if nRows < 2: return (0,0) nCols = len(table[1]) for i in range(2,nRows): if len(table[i]) != nCols: return (nRows,-1) return (nRows,nCols) - except: + except (TypeError, IndexError, KeyError, AttributeError): return (-1,-1) ################################################################################ # Image Class ################################################################################ class Image(): - image_id_counter = -1 + image_id_counter = 0 def __init__(self, channels=None, meta=None): self.meta = meta or {} self.channels = channels or {} if 'id' not in self.meta: self.meta['id'] = Image.image_id_counter - Image.image_id_counter += -1 + Image.image_id_counter += 1 def __str__(self): result = '{ PyCinemaImage:\n' @@ -302,7 +306,7 @@ def set(self, value, update=True, propagate_back=False): try: np.testing.assert_equal(self._value,value) return - except: + except Exception: pass # if self._value == value: # return @@ -387,7 +391,11 @@ def trigger(eventName, data): for listener in Filter._listeners[eventName]: listener(data) - def __init__(self, inputs={}, outputs={}): + def __init__(self, inputs=None, outputs=None): + if inputs is None: + inputs = {} + if outputs is None: + outputs = {} if Filter._debug: print('created',self) cls = self.__class__.__name__ diff --git a/pycinema/filters/CSVReader.py b/pycinema/filters/CSVReader.py index ff5115c8..cfea45e6 100644 --- a/pycinema/filters/CSVReader.py +++ b/pycinema/filters/CSVReader.py @@ -46,7 +46,7 @@ def _update(self): rows = csv.reader(csvfile, delimiter=',') for row in rows: table.append(row) - except: + except (IOError, OSError, PermissionError, csv.Error): log.error("Unable to open file: '" + csvPath + "'") self.outputs.table.set([[]]) return 0 diff --git a/pycinema/filters/Calculator.py b/pycinema/filters/Calculator.py index 329b1b19..539e285c 100644 --- a/pycinema/filters/Calculator.py +++ b/pycinema/filters/Calculator.py @@ -2,6 +2,7 @@ import copy import numpy as np +from asteval import Interpreter class Calculator(Filter): @@ -33,14 +34,18 @@ def _update(self): if isNumber(oTable[1][c]): variables[oTable[0][c]] = np.array([float(row[c]) for row in oTable[1:]]) - variables['__result'] = '' - expression = self.inputs.expression.get().strip() if expression=='': expression = '0' - exec('__result = '+expression,variables) - result = variables['__result'] + aeval = Interpreter() + aeval.symtable.update(variables) + + result = aeval(expression) + + if aeval.error: + err = aeval.error[0] + raise RuntimeError(err.get_error()) if type(result) not in [list, np.ndarray]: result = [result for i in range(0,extent[0]-1)] diff --git a/pycinema/filters/CinemaDatabaseReader.py b/pycinema/filters/CinemaDatabaseReader.py index 316be260..ea6d232e 100644 --- a/pycinema/filters/CinemaDatabaseReader.py +++ b/pycinema/filters/CinemaDatabaseReader.py @@ -39,7 +39,7 @@ def _update(self): rows = csv.reader(csvfile, delimiter=',') for row in rows: table.append(row) - except: + except (IOError, OSError, PermissionError, csv.Error): log.error(" Unable to open data.csv") self.outputs.table.set([[]]) return 0 diff --git a/pycinema/filters/ColorMapping.py b/pycinema/filters/ColorMapping.py index 813cf0ea..c8e31448 100644 --- a/pycinema/filters/ColorMapping.py +++ b/pycinema/filters/ColorMapping.py @@ -36,7 +36,7 @@ def updateWidgets(self): for widgets in self.widgets: widgets['c'].setEnabled(len(images)>0 and len(images[0].channels)>0) - if len(images)<1 or self.channel_model==None: + if len(images)<1 or self.channel_model is None: return else: iChannel = self.inputs.channel.get() diff --git a/pycinema/filters/DepthCompositing.py b/pycinema/filters/DepthCompositing.py index 622a46fd..b4b2acde 100644 --- a/pycinema/filters/DepthCompositing.py +++ b/pycinema/filters/DepthCompositing.py @@ -44,7 +44,7 @@ def toList(self,data): return [data] def getKeys(self,image,compose): - if compose[0]==None: + if compose[0] is None: return image.meta.keys() ignore = [compose[0]] + ['^id','^file','^camera','^resolution','_range'] return [p for p in image.meta.keys() if not any([re.search(i, p, re.IGNORECASE) for i in ignore])] @@ -145,7 +145,7 @@ def _update(self): try: for i in imagesA: i.getChannel(depthChannel) - except: + except Exception: self.outputs.images.set(imagesA) return 1 @@ -158,7 +158,7 @@ def _update(self): for key, images in imagesMap.items(): result = images[0].copy() - if metaCompositing[0]!=None and 'composition_mask' not in result.channels: + if metaCompositing[0] is not None and 'composition_mask' not in result.channels: result.channels['composition_mask'] = numpy.full(result.shape[:2], metaCompositing[1][str(result.meta[metaCompositing[0]])], dtype=numpy.ubyte) for i in range(1,len(images)): result = self.compose(result,images[i],depthChannel) diff --git a/pycinema/filters/ImageAnnotation.py b/pycinema/filters/ImageAnnotation.py index 66a0de36..b25b92a7 100644 --- a/pycinema/filters/ImageAnnotation.py +++ b/pycinema/filters/ImageAnnotation.py @@ -42,7 +42,7 @@ def __get_font(self, size): except IOError: continue - if font==None: + if font is None: print('unable to detect font') return font diff --git a/pycinema/filters/ImageReader.py b/pycinema/filters/ImageReader.py index 2fd48ac4..61295c55 100644 --- a/pycinema/filters/ImageReader.py +++ b/pycinema/filters/ImageReader.py @@ -61,7 +61,7 @@ def _update(self): file = h5py.File(path, 'r') for (g,v) in [('channels',image.channels), ('meta',image.meta)]: group = file.get(g) - if group==None: + if group is None: raise ValueError('h5 file not formatted correctly') for k in group.keys(): data = numpy.atleast_1d(numpy.squeeze(numpy.array(group.get(k)))) diff --git a/pycinema/filters/MLTFReader.py b/pycinema/filters/MLTFReader.py index 9ccefdc1..ac90105e 100644 --- a/pycinema/filters/MLTFReader.py +++ b/pycinema/filters/MLTFReader.py @@ -63,7 +63,7 @@ def _update(self): models[int(row[0])] = model #check if training configuration exists, if not give error - except: + except (IOError, OSError, PermissionError, csv.Error, ValueError, IndexError): log.error('[ERROR] Unable to open ML Model Directory') self.outputs.models.set([]) return 0 diff --git a/pycinema/filters/ParallelCoordinates.py b/pycinema/filters/ParallelCoordinates.py index 08a4a2bd..ef3e7ed6 100644 --- a/pycinema/filters/ParallelCoordinates.py +++ b/pycinema/filters/ParallelCoordinates.py @@ -150,6 +150,8 @@ def __init__(self, parameter, filter): self.bar.hide() def snapToValueIdx(self,y): + if self.y1 == self.y0: + return 0 l = (y - self.y0) / (self.y1 - self.y0) l = max(min(l,1),0) return round(l*(self.n_values-1)) diff --git a/pycinema/filters/Python.py b/pycinema/filters/Python.py index f064e6a9..abc0fd7f 100644 --- a/pycinema/filters/Python.py +++ b/pycinema/filters/Python.py @@ -35,9 +35,8 @@ def _update(self): self.watcher.addPath(code) # fetch code - script_file = open(code, "r") - code = script_file.read() - script_file.close() + with open(code, "r") as script_file: + code = script_file.read() elif len(watched_files)>0: self.watcher.removePaths(watched_files) diff --git a/pycinema/filters/Shader.py b/pycinema/filters/Shader.py index 92f99758..2ed745e2 100644 --- a/pycinema/filters/Shader.py +++ b/pycinema/filters/Shader.py @@ -11,7 +11,15 @@ class Shader(Filter): quad = None fbo = None - def __init__(self, inputs={}, outputs={}, textures=[], varyings=['uv'], quad=True): + def __init__(self, inputs=None, outputs=None, textures=None, varyings=None, quad=True): + if inputs is None: + inputs = {} + if outputs is None: + outputs = {} + if textures is None: + textures = [] + if varyings is None: + varyings = ['uv'] # program self.program = Shader.ctx.program( @@ -34,8 +42,8 @@ def __init__(self, inputs={}, outputs={}, textures=[], varyings=['uv'], quad=Tru super().__init__(inputs, outputs) def initFramebuffer(self,res,components=[1],dtypes=['f1']): - if Shader.fbo==None or Shader.fbo.size!=res: - if Shader.fbo!=None: + if Shader.fbo is None or Shader.fbo.size!=res: + if Shader.fbo is not None: Shader.fbo.release() if len(components)==1 and dtypes[0]=='f1': Shader.fbo = Shader.ctx.simple_framebuffer(res) @@ -110,5 +118,5 @@ def releaseTextures(self): 1.0, 1.0 ]).astype('f4').tobytes() ) -except: +except Exception: log.warning("Unable to setup OpenGL context.") diff --git a/pycinema/filters/ShaderFXAA.py b/pycinema/filters/ShaderFXAA.py index b43ca698..49826eaf 100644 --- a/pycinema/filters/ShaderFXAA.py +++ b/pycinema/filters/ShaderFXAA.py @@ -152,7 +152,7 @@ def _update(self): try: for image in images: results.append( self.render(image) ) - except: + except Exception: self.outputs.images.set(images) return 1 diff --git a/pycinema/filters/ShaderIBS.py b/pycinema/filters/ShaderIBS.py index 83bd3b4c..30182c57 100644 --- a/pycinema/filters/ShaderIBS.py +++ b/pycinema/filters/ShaderIBS.py @@ -181,18 +181,22 @@ def _update(self): images = self.inputs.images.get() # set uniforms - self.program['radius'].value = float(self.inputs.radius.get()) - self.program['samples'].value = int(self.inputs.samples.get()) - self.program['diff_area'].value = float(self.inputs.diff.get()) - self.program['silhouette'].value = float(self.inputs.silhouette.get()*500) - self.program['ambient'].value = float(self.inputs.ambient.get()) - self.program['luminance'].value = float(self.inputs.luminance.get()) + try: + self.program['radius'].value = float(self.inputs.radius.get()) + self.program['samples'].value = int(self.inputs.samples.get()) + self.program['diff_area'].value = float(self.inputs.diff.get()) + self.program['silhouette'].value = float(self.inputs.silhouette.get()*500) + self.program['ambient'].value = float(self.inputs.ambient.get()) + self.program['luminance'].value = float(self.inputs.luminance.get()) + except (ValueError, TypeError): + self.outputs.images.set(images) + return 1 # render images try: for image in images: results.append( self.render(image) ) - except: + except Exception: self.outputs.images.set(images) return 1 diff --git a/pycinema/filters/ShaderLineAO.py b/pycinema/filters/ShaderLineAO.py index c35d1e1a..227bd087 100644 --- a/pycinema/filters/ShaderLineAO.py +++ b/pycinema/filters/ShaderLineAO.py @@ -277,7 +277,7 @@ def _update(self): try: for image in images: results.append( self.render(image) ) - except: + except Exception: self.outputs.images.set(images) return 1 diff --git a/pycinema/filters/ShaderPBR.py b/pycinema/filters/ShaderPBR.py index 0b34d2f3..6ddbac88 100644 --- a/pycinema/filters/ShaderPBR.py +++ b/pycinema/filters/ShaderPBR.py @@ -252,16 +252,20 @@ def _update(self): images = self.inputs.images.get() # set uniforms - self.program['uAmbient'].value = float(self.inputs.ambient.get()) - self.program['uDiffuse'].value = float(self.inputs.diffuse.get()) - self.program['uRoughness'].value = float(self.inputs.roughness.get()) - self.program['uMetallic'].value = float(self.inputs.metallic.get()) + try: + self.program['uAmbient'].value = float(self.inputs.ambient.get()) + self.program['uDiffuse'].value = float(self.inputs.diffuse.get()) + self.program['uRoughness'].value = float(self.inputs.roughness.get()) + self.program['uMetallic'].value = float(self.inputs.metallic.get()) + except (ValueError, TypeError): + self.outputs.images.set(images) + return 1 # render images try: for image in images: results.append( self.render(image) ) - except: + except Exception: self.outputs.images.set(images) return 1 diff --git a/pycinema/filters/ShaderPhong.py b/pycinema/filters/ShaderPhong.py index ac3b7550..5474aa73 100644 --- a/pycinema/filters/ShaderPhong.py +++ b/pycinema/filters/ShaderPhong.py @@ -114,16 +114,20 @@ def _update(self): images = self.inputs.images.get() # set uniforms - self.program['uAmbient'].value = float(self.inputs.ambient.get()) - self.program['uDiffuse'].value = float(self.inputs.diffuse.get()) - self.program['uSpecular'].value = float(self.inputs.specular.get()) - self.program['uExponent'].value = float(self.inputs.exponent.get()) + try: + self.program['uAmbient'].value = float(self.inputs.ambient.get()) + self.program['uDiffuse'].value = float(self.inputs.diffuse.get()) + self.program['uSpecular'].value = float(self.inputs.specular.get()) + self.program['uExponent'].value = float(self.inputs.exponent.get()) + except (ValueError, TypeError): + self.outputs.images.set(images) + return 1 # render images try: for image in images: results.append( self.render(image) ) - except: + except Exception: self.outputs.images.set(images) return 1 diff --git a/pycinema/filters/ShaderPointAO.py b/pycinema/filters/ShaderPointAO.py index a9fb8843..126fe031 100644 --- a/pycinema/filters/ShaderPointAO.py +++ b/pycinema/filters/ShaderPointAO.py @@ -283,7 +283,7 @@ def _update(self): try: for image in images: results.append( self.render(image) ) - except: + except Exception: self.outputs.images.set(images) return 1 diff --git a/pycinema/filters/ShaderSSAO.py b/pycinema/filters/ShaderSSAO.py index 4de5bd32..538b78b2 100644 --- a/pycinema/filters/ShaderSSAO.py +++ b/pycinema/filters/ShaderSSAO.py @@ -129,7 +129,7 @@ def _update(self): try: for image in images: results.append( self.render(image) ) - except: + except Exception: self.outputs.images.set(images) return 1 diff --git a/pycinema/filters/SqliteDatabaseReader.py b/pycinema/filters/SqliteDatabaseReader.py index f9367780..e397a8ea 100644 --- a/pycinema/filters/SqliteDatabaseReader.py +++ b/pycinema/filters/SqliteDatabaseReader.py @@ -38,22 +38,30 @@ def _update(self): conn = sqlite3.connect(dbPath) cursor = conn.cursor() - # capture the names of each column - cdata = cursor.execute(f'PRAGMA table_info({tname});').fetchall() - + # Validate table name exists (safe parameterized query) + cursor.execute( + "SELECT name FROM sqlite_master WHERE type='table' AND name=?", + (tname,) + ) + if not cursor.fetchone(): + log.error(f"Table '{tname}' does not exist in database") + self.outputs.table.set([[]]) + return 0 + + # Now safe to use validated table name with identifier quoting + cdata = cursor.execute(f'PRAGMA table_info("{tname}")').fetchall() cnames = [entry[1] for entry in cdata] table.append(cnames) - # capture row data - data = cursor.execute("SELECT * FROM " + tname + "").fetchall() #LIMIT 10 + # Use identifier quoting for table name + data = cursor.execute(f'SELECT * FROM "{tname}"').fetchall() for row in data: - # tuple output convert to list table.append(list(row)) cursor.close() except sqlite3.Error as error: - log.error(" Error while connecting to sqlite: " + error) + log.error(f" Error while connecting to sqlite: {str(error)}") self.outputs.table.set([[]]) return 0 finally: @@ -66,7 +74,7 @@ def _update(self): # add dbPath prefix to file column try: fileColumnIdx = [i for i, item in enumerate(table[0]) if re.search(self.inputs.file_column.get(), item, re.IGNORECASE)].pop() - except: + except (IndexError, re.error): log.error(" file column not found: '" + self.inputs.file_column.get() + "'") self.outputs.table.set([[]]) return 0 diff --git a/pycinema/filters/TableWriter.py b/pycinema/filters/TableWriter.py index 99adf75a..c3c7ffaa 100644 --- a/pycinema/filters/TableWriter.py +++ b/pycinema/filters/TableWriter.py @@ -18,8 +18,8 @@ def __init__(self): } ); - def writeCSV(self): - with open(self.inputs.path.get(), 'w') as csvfile: + def writeCSV(self, path): + with open(path, 'w') as csvfile: write = csv.writer(csvfile) write.writerows(self.inputs.table.get()) @@ -37,7 +37,7 @@ def _update(self): if not os.path.exists(directory): os.makedirs(directory) - self.writeCSV() + self.writeCSV(path) return 1 diff --git a/pycinema/filters/TextFileReader.py b/pycinema/filters/TextFileReader.py index 115dc942..6ee0a789 100644 --- a/pycinema/filters/TextFileReader.py +++ b/pycinema/filters/TextFileReader.py @@ -34,7 +34,7 @@ def _update(self): with open(p, 'r', encoding='utf-8') as textfile: file_contents = textfile.read() temptext = file_contents - except: + except (IOError, OSError, PermissionError, UnicodeDecodeError): log.error(" Unable to open file: '" + p + "'") self.outputs.text.set(temptext) diff --git a/pycinema/filters/ValueSource.py b/pycinema/filters/ValueSource.py index 4149ed72..6c299bf0 100644 --- a/pycinema/filters/ValueSource.py +++ b/pycinema/filters/ValueSource.py @@ -1,4 +1,5 @@ from pycinema import Filter +import ast class ValueSource(Filter): @@ -16,6 +17,6 @@ def __init__(self): def _update(self): value = self.inputs.value.get() if isinstance(value, str): - value = eval(value) + value = ast.literal_eval(value) self.outputs.value.set( value ) return 1 diff --git a/pycinema/filters/YamlFileReader.py b/pycinema/filters/YamlFileReader.py index 5812b896..4227fb7a 100644 --- a/pycinema/filters/YamlFileReader.py +++ b/pycinema/filters/YamlFileReader.py @@ -34,7 +34,7 @@ def _update(self): results = [] with open(p, 'r', encoding='utf-8') as textfile: data = yaml.safe_load(textfile) - except: + except (IOError, OSError, PermissionError, yaml.YAMLError): log.error(" Unable to open file: '" + p + "'") self.outputs.data.set(data) diff --git a/pycinema/ipy/ColorMappingWidgets.py b/pycinema/ipy/ColorMappingWidgets.py index c19f7cf2..46636c4b 100644 --- a/pycinema/ipy/ColorMappingWidgets.py +++ b/pycinema/ipy/ColorMappingWidgets.py @@ -109,7 +109,7 @@ def _update(self): # add widgets to container container = self.inputs.container.get() - if container!=None and len(container.children)==0: + if container is not None and len(container.children)==0: container.children = [ self.channelWidget, self.mapWidget, diff --git a/pycinema/ipy/ImageViewer.py b/pycinema/ipy/ImageViewer.py index f95d815c..eab78adc 100644 --- a/pycinema/ipy/ImageViewer.py +++ b/pycinema/ipy/ImageViewer.py @@ -23,7 +23,7 @@ def __init__(self): def _update(self): container = self.inputs.container.get() - if container==None: + if container is None: container = ipywidgets.HBox() IPython.display.display(container) diff --git a/pycinema/ipy/ParameterWidgets.py b/pycinema/ipy/ParameterWidgets.py index a0be9f8c..7d8ae076 100644 --- a/pycinema/ipy/ParameterWidgets.py +++ b/pycinema/ipy/ParameterWidgets.py @@ -170,7 +170,7 @@ def on_composite_change(change): self.widgets.append(wt) container = self.inputs.container.get() - if container!=None: + if container is not None: items = [] for i,wt in enumerate(self.widgets): items.append(wt['B']) diff --git a/pycinema/theater/TabFrame.py b/pycinema/theater/TabFrame.py index 67c9da38..a7655fb9 100644 --- a/pycinema/theater/TabFrame.py +++ b/pycinema/theater/TabFrame.py @@ -82,11 +82,11 @@ def fRenameTab(self): bar.__edit = None def insertTab(self,idx,splitFrame=None,name=None): - if splitFrame==None: + if splitFrame is None: splitFrame = pycinema.theater.SplitFrame() splitFrame.insertView(0,pycinema.theater.views.SelectionView()) - if name==None: + if name is None: name = "Layout %d"%self.tab_counter self.tab_counter += 1 diff --git a/pycinema/theater/Theater.py b/pycinema/theater/Theater.py index 170e81ac..e3c98cf1 100644 --- a/pycinema/theater/Theater.py +++ b/pycinema/theater/Theater.py @@ -142,10 +142,9 @@ def saveScript(self): if not script_file_name.endswith('.py'): script_file_name += '.py' try: - f = open(script_file_name, "w") - f.write(script) - f.close() - except: + with open(script_file_name, "w") as f: + f.write(script) + except (IOError, OSError, PermissionError): return return script @@ -177,7 +176,9 @@ def about(self, no_views=False): msgBox = QtWidgets.QMessageBox.about(self, "About", "pycinema v" + pycinema.__version__); return - def executeScript(self, script, args=[]): + def executeScript(self, script, args=None): + if args is None: + args = [] QtNodeEditorView.auto_layout = False QtNodeEditorView.auto_connect = False @@ -214,22 +215,23 @@ def call(): return QtCore.QTimer.singleShot(0, lambda: call()) - def loadScript(self, script_file_name=None, scriptkey=None, args=[]): + def loadScript(self, script_file_name=None, scriptkey=None, args=None): + if args is None: + args = [] if not script_file_name: script_file_name = QtWidgets.QFileDialog.getOpenFileName(self, "Load Script")[0] if script_file_name and len(script_file_name)>0: if os.path.isfile(script_file_name): try: - script_file = open(script_file_name, "r") - script = script_file.read() - script_file.close() + with open(script_file_name, "r") as script_file: + script = script_file.read() self.reset(True) if not scriptkey: self.setWindowTitle("Cinema:Theater (" + script_file_name + ")") else: self.setWindowTitle("Cinema:" + scriptkey) self.executeScript(script,args) - except: + except (IOError, OSError, PermissionError, UnicodeDecodeError): return else: print("CINEMA ERROR: script file \'" + script_file_name + "\' does not exist") @@ -238,7 +240,9 @@ class Theater(): instance = None - def __init__(self, args=[]): + def __init__(self, args=None): + if args is None: + args = [] # show UI app = QtWidgets.QApplication([]) diff --git a/pycinema/theater/node_editor/InputText.py b/pycinema/theater/node_editor/InputText.py index 15a3c03a..6f8bfc7f 100644 --- a/pycinema/theater/node_editor/InputText.py +++ b/pycinema/theater/node_editor/InputText.py @@ -76,7 +76,7 @@ def setValue(self,text): v = float(text) else: v = eval(text) - except: + except (ValueError, SyntaxError, NameError): v = None self.skip = True diff --git a/pycinema/theater/views/NodeEditorView.py b/pycinema/theater/views/NodeEditorView.py index eb9e79a1..c0bb93a4 100644 --- a/pycinema/theater/views/NodeEditorView.py +++ b/pycinema/theater/views/NodeEditorView.py @@ -11,7 +11,7 @@ use_pgv = True try: import pygraphviz as pgv -except: +except ImportError: use_pgv = False import igraph diff --git a/setup.py b/setup.py index 6ccd1af2..20d2dd65 100644 --- a/setup.py +++ b/setup.py @@ -41,7 +41,8 @@ "trame-vuetify", "trame-plotly", "pandas", - "pyyaml" + "pyyaml", + "asteval" ], extras_require={ "synema": ["synema", "scikit-image"]