From a9c8165ff4c8d90016f1ff552e0d505a813c5037 Mon Sep 17 00:00:00 2001 From: Alan Rubin Date: Tue, 7 Apr 2020 13:24:00 +1000 Subject: [PATCH] Globals fix (#35) * replaced globals() with a dictionary * increment version * --version only outputs version number --- docs/conf.py | 2 +- enrich2/gui/configurator.py | 19 +++++++++++++++++-- enrich2/gui/create_root_dialog.py | 29 +++++++++++++++++++++++++---- enrich2/gui/create_seqlib_dialog.py | 24 ++++++++++++++++++++---- enrich2/main.py | 4 ++-- enrich2/selection.py | 19 +++++++++++++++++-- setup.py | 2 +- 7 files changed, 83 insertions(+), 16 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 53f60f9..949b789 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -53,7 +53,7 @@ # The short X.Y version. version = '1.3' # The full version, including alpha/beta/rc tags. -release = '1.3.0' +release = '1.3.1' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/enrich2/gui/configurator.py b/enrich2/gui/configurator.py index cdd1331..aee12d5 100644 --- a/enrich2/gui/configurator.py +++ b/enrich2/gui/configurator.py @@ -15,11 +15,27 @@ from ..experiment import Experiment from ..condition import Condition from ..selection import Selection +from ..barcode import BarcodeSeqLib +from ..barcodevariant import BcvSeqLib +from ..barcodeid import BcidSeqLib +from ..basic import BasicSeqLib +from ..idonly import IdOnlySeqLib from ..overlap import OverlapSeqLib from ..seqlib import SeqLib from ..storemanager import SCORING_METHODS, LOGR_METHODS +#: map class names to class definitions to avoid use of globals() +SEQLIB_CLASSES = { + "BarcodeSeqLib": BarcodeSeqLib, + "BcvSeqLib": BcvSeqLib, + "BcidSeqLib": BcidSeqLib, + "BasicSeqLib": BasicSeqLib, + "IdOnlySeqLib": IdOnlySeqLib, + "OverlapSeqLib": OverlapSeqLib, +} + + def write_json(d, handle): """ Write the contents of dictionary *d* to an open file *handle* in json format. @@ -358,8 +374,7 @@ def menu_open(self): elif is_selection(cfg): obj = Selection() elif is_seqlib(cfg): - sltype = seqlib_type(cfg) - obj = globals()[sltype]() + obj = SEQLIB_CLASSES[seqlib_type(cfg)]() else: tkMessageBox.showerror(None, "Unrecognized config format.") return diff --git a/enrich2/gui/create_root_dialog.py b/enrich2/gui/create_root_dialog.py index 0c5ff9c..c306d20 100644 --- a/enrich2/gui/create_root_dialog.py +++ b/enrich2/gui/create_root_dialog.py @@ -3,7 +3,28 @@ import ttk import tkSimpleDialog from .dialog_elements import FileEntry, StringEntry, DEFAULT_COLUMNS -from .create_seqlib_dialog import seqlib_label_text +from .create_seqlib_dialog import SEQLIB_LABEL_TEXT +from ..barcode import BarcodeSeqLib +from ..barcodevariant import BcvSeqLib +from ..barcodeid import BcidSeqLib +from ..basic import BasicSeqLib +from ..idonly import IdOnlySeqLib +from ..overlap import OverlapSeqLib +from ..selection import Selection +from ..experiment import Experiment + + +#: map class names to class definitions to avoid use of globals() +ELEMENT_CLASSES = { + "BarcodeSeqLib": BarcodeSeqLib, + "BcvSeqLib": BcvSeqLib, + "BcidSeqLib": BcidSeqLib, + "BasicSeqLib": BasicSeqLib, + "IdOnlySeqLib": IdOnlySeqLib, + "OverlapSeqLib": OverlapSeqLib, + "Selection": Selection, + "Experiment": Experiment, +} class CreateRootDialog(tkSimpleDialog.Dialog): @@ -60,10 +81,10 @@ def body(self, master): label = ttk.Label(element_types, text="SeqLib") label.grid(column=0, row=5, sticky="w") - for i, k in enumerate(seqlib_label_text.keys()): + for i, k in enumerate(SEQLIB_LABEL_TEXT.keys()): rb = ttk.Radiobutton( element_types, - text=seqlib_label_text[k], + text=SEQLIB_LABEL_TEXT[k], variable=self.element_tkstring, value=k, ) @@ -93,7 +114,7 @@ def apply(self): # create the object try: - self.element = globals()[self.element_tkstring.get()]() + self.element = ELEMENT_CLASSES[self.element_tkstring.get()]() except KeyError: raise KeyError( "Unrecognized element type '{}'".format(self.element_tkstring.get()) diff --git a/enrich2/gui/create_seqlib_dialog.py b/enrich2/gui/create_seqlib_dialog.py index c9beaa9..f741746 100644 --- a/enrich2/gui/create_seqlib_dialog.py +++ b/enrich2/gui/create_seqlib_dialog.py @@ -3,9 +3,15 @@ import ttk import tkSimpleDialog from collections import OrderedDict +from ..barcode import BarcodeSeqLib +from ..barcodevariant import BcvSeqLib +from ..barcodeid import BcidSeqLib +from ..basic import BasicSeqLib +from ..idonly import IdOnlySeqLib +from ..overlap import OverlapSeqLib -seqlib_label_text = OrderedDict( +SEQLIB_LABEL_TEXT = OrderedDict( [ ("BcvSeqLib", "Barcoded Variant"), ("BcidSeqLib", "Barcoded Identifier"), @@ -16,6 +22,16 @@ ] ) +#: map class names to class definitions to avoid use of globals() +SEQLIB_CLASSES = { + "BarcodeSeqLib": BarcodeSeqLib, + "BcvSeqLib": BcvSeqLib, + "BcidSeqLib": BcidSeqLib, + "BasicSeqLib": BasicSeqLib, + "IdOnlySeqLib": IdOnlySeqLib, + "OverlapSeqLib": OverlapSeqLib, +} + class CreateSeqLibDialog(tkSimpleDialog.Dialog): """ @@ -31,10 +47,10 @@ def body(self, master): message = ttk.Label(master, text="SeqLib type:") message.grid(column=0, row=0) - for i, k in enumerate(seqlib_label_text.keys()): + for i, k in enumerate(SEQLIB_LABEL_TEXT.keys()): rb = ttk.Radiobutton( master, - text=seqlib_label_text[k], + text=SEQLIB_LABEL_TEXT[k], variable=self.element_tkstring, value=k, ) @@ -57,6 +73,6 @@ def buttonbox(self): def apply(self): try: - self.element_type = globals()[self.element_tkstring.get()] + self.element_type = SEQLIB_CLASSES[self.element_tkstring.get()] except KeyError: raise KeyError("Unrecognized element type.") diff --git a/enrich2/main.py b/enrich2/main.py index 15740f5..b3359a8 100755 --- a/enrich2/main.py +++ b/enrich2/main.py @@ -40,7 +40,7 @@ __author__ = "Alan F Rubin" __copyright__ = "Copyright 2016-2020, Alan F Rubin" __license__ = "BSD-3-Clause" -__version__ = "1.3.0" +__version__ = "1.3.1" __maintainer__ = "Alan F Rubin" __email__ = "alan.rubin@wehi.edu.au" @@ -98,7 +98,7 @@ def main_cmd(): # add support for semantic version checking parser.add_argument( - "--version", action="version", version="%(prog)s {}".format(__version__) + "--version", action="version", version="{}".format(__version__) ) # add analysis options diff --git a/enrich2/selection.py b/enrich2/selection.py index f23a5e6..da6b4f0 100644 --- a/enrich2/selection.py +++ b/enrich2/selection.py @@ -1,6 +1,10 @@ from __future__ import print_function +from .barcode import BarcodeSeqLib from .barcodevariant import BcvSeqLib from .barcodeid import BcidSeqLib +from .basic import BasicSeqLib +from .idonly import IdOnlySeqLib +from .overlap import OverlapSeqLib from .config_check import seqlib_type from .storemanager import StoreManager import os @@ -25,6 +29,17 @@ from .dataframe import singleton_dataframe +#: map class names to class definitions to avoid use of globals() +SEQLIB_CLASSES = { + "BarcodeSeqLib": BarcodeSeqLib, + "BcvSeqLib": BcvSeqLib, + "BcidSeqLib": BcidSeqLib, + "BasicSeqLib": BasicSeqLib, + "IdOnlySeqLib": IdOnlySeqLib, + "OverlapSeqLib": OverlapSeqLib, +} + + def regression_apply(row, timepoints, weighted): """ :py:meth:`pandas.DataFrame.apply` apply function for calculating @@ -148,7 +163,7 @@ def configure(self, cfg, configure_children=True): if libtype is None: raise ValueError("Unrecognized SeqLib config") elif libtype in ("BcvSeqLib", "BcidSeqLib"): - lib = globals()[libtype]() + lib = SEQLIB_CLASSES[libtype]() # don't re-parse the barcode maps if possible mapfile = lib_cfg["barcodes"]["map file"] if mapfile in self.barcode_maps.keys(): @@ -160,7 +175,7 @@ def configure(self, cfg, configure_children=True): else: # requires that the SeqLib derived classes be imported into the # module namespace using "from x import y" style - lib = globals()[libtype]() + lib = SEQLIB_CLASSES[libtype]() lib.configure(lib_cfg) self.add_child(lib) diff --git a/setup.py b/setup.py index ced7d05..11662ad 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ setup( name="Enrich2", - version="1.3.0", + version="1.3.1", packages=find_packages(),