<commit_before>import albow
from albow.dialogs import Dialog
import mceutils
from config import config
import pygame
from albow.translate import _
import sys
import os
import logging
import traceback
import directories

class OptionsPanel(Dialog):
    anchor = 'wh'

    def __init__(self, mcedit):
        Dialog.__init__(self)

        self.mcedit = mcedit

        self.langs = {}
        self.sgnal = {}
        self.portableVar = albow.AttrRef(self, 'portableLabelText')
        self.saveOldPortable = self.portableVar.get()

        self.saveOldConfig = {
            config.controls.autobrake:                 config.controls.autobrake.get(),
            config.controls.swapAxes:                  config.controls.swapAxes.get(),
            config.controls.cameraAccel:               config.controls.cameraAccel.get(),
            config.controls.cameraDrag:                config.controls.cameraDrag.get(),
            config.controls.cameraMaxSpeed:            config.controls.cameraMaxSpeed.get(),
            config.controls.cameraBrakingSpeed:        config.controls.cameraBrakingSpeed.get(),
            config.controls.mouseSpeed:                config.controls.mouseSpeed.get(),
            config.settings.undoLimit:                 config.settings.undoLimit.get(),
            config.settings.maxCopies:                 config.settings.maxCopies.get(),
            config.controls.invertMousePitch:          config.controls.invertMousePitch.get(),
            config.settings.spaceHeight:               config.settings.spaceHeight.get(),
            albow.AttrRef(self, 'blockBuffer'):        albow.AttrRef(self, 'blockBuffer').get(),
            config.settings.setWindowPlacement:        config.settings.setWindowPlacement.get(),
            config.settings.rotateBlockBrush:          config.settings.rotateBlockBrush.get(),
            config.settings.shouldResizeAlert:         config.settings.shouldResizeAlert.get(),
            config.settings.superSecretSettings:       config.settings.superSecretSettings.get(),
            config.settings.longDistanceMode:          config.settings.longDistanceMode.get(),
            config.settings.flyMode:                   config.settings.flyMode.get(),
            config.settings.langCode:                  config.settings.langCode.get()
        }

    def initComponents(self):
        """Initilize the window components. Call this after translation hs been loaded."""
        autoBrakeRow = mceutils.CheckBoxLabel("Autobrake",
                                              ref=config.controls.autobrake,
                                              tooltipText="Apply brake when not pressing movement keys")

        swapAxesRow = mceutils.CheckBoxLabel("Swap Axes Looking Down",
                                             ref=config.controls.swapAxes,
                                             tooltipText="Change the direction of the Forward and Backward keys when looking down")

        cameraAccelRow = mceutils.FloatInputRow("Camera Acceleration: ",
                                                ref=config.controls.cameraAccel, width=100, min=5.0)

        cameraDragRow = mceutils.FloatInputRow("Camera Drag: ",
                                               ref=config.controls.cameraDrag, width=100, min=1.0)

        cameraMaxSpeedRow = mceutils.FloatInputRow("Camera Max Speed: ",
                                                   ref=config.controls.cameraMaxSpeed, width=100, min=1.0)

        cameraBrakeSpeedRow = mceutils.FloatInputRow("Camera Braking Speed: ",
                                                     ref=config.controls.cameraBrakingSpeed, width=100,
                                                     min=1.0)

        mouseSpeedRow = mceutils.FloatInputRow("Mouse Speed: ",
                                               ref=config.controls.mouseSpeed, width=100, min=0.1,
                                               max=20.0)

        undoLimitRow = mceutils.IntInputRow("Undo Limit: ",
                                            ref=config.settings.undoLimit, width=100, min=0)

        maxCopiesRow = mceutils.IntInputRow("Copy Stack Size: ",
                                            ref=config.settings.maxCopies, width=100, min=0,
                                            tooltipText="Maximum number of copied objects.")

        # FONT SIZE
#        fontProportion = mceutils.IntInputRow("Fonts Proportion (%): ",
#                                            ref=config.settings.fontProportion, width=100, min=0,
#                                            tooltipText="Fonts sizing proportion. The number is a percentage.")
#        albow.resource.font_proportion = config.settings.fontProportion.get()

        invertRow = mceutils.CheckBoxLabel("Invert Mouse",
                                           ref=config.controls.invertMousePitch,
                                           tooltipText="Reverse the up and down motion of the mouse.")

        spaceHeightRow = mceutils.IntInputRow(_("Low Detail Height"),
                                              ref=config.settings.spaceHeight,
                                              tooltipText="When you are this far above the top of the world, move fast and use low-detail mode.")

        blockBufferRow = mceutils.IntInputRow("Block Buffer (MB):",
                                              ref=albow.AttrRef(self, 'blockBuffer'), min=1,
                                              tooltipText="Amount of memory used for temporary storage.  When more than this is needed, the disk is used instead.")

        setWindowPlacementRow = mceutils.CheckBoxLabel("Set Window Placement",
                                                       ref=config.settings.setWindowPlacement,
                                                       tooltipText="Try to save and restore the window position.")

        rotateBlockBrushRow = mceutils.CheckBoxLabel("Rotate block with brush",
                                                        ref=config.settings.rotateBlockBrush,
                                                        tooltipText="When rotating your brush, also rotate the orientation of the block your brushing with")

        windowSizeRow = mceutils.CheckBoxLabel("Window Resize Alert",
                                               ref=config.settings.shouldResizeAlert,
                                               tooltipText="Reminds you that the cursor won't work correctly after resizing the window.")

        superSecretSettingsRow = mceutils.CheckBoxLabel("Super Secret Settings",
                                                ref=config.settings.superSecretSettings,
                                                tooltipText="Weird stuff happen!")

        longDistanceRow = mceutils.CheckBoxLabel("Long-Distance Mode",
                                                 ref=config.settings.longDistanceMode,
                                                 tooltipText="Always target the farthest block under the cursor, even in mouselook mode.")

        flyModeRow = mceutils.CheckBoxLabel("Fly Mode",
                                            ref=config.settings.flyMode,
                                            tooltipText="Moving forward and Backward will not change your altitude in Fly Mode.")

        lng = config.settings.langCode.get()

        langs = sorted(self.getLanguageChoices().items())

        langNames = [k for k, v in langs]

        self.languageButton = mceutils.ChoiceButton(langNames, choose=self.changeLanguage)
        if self.sgnal[lng] in self.languageButton.choices:
            self.languageButton.selectedChoice = self.sgnal[lng]

        langButtonRow = albow.Row((albow.Label("Language", tooltipText="Choose your language."), self.languageButton))

        staticCommandsNudgeRow = mceutils.CheckBoxLabel("Static Coords While Nudging",
                                            ref=config.settings.staticCommandsNudge,
                                            tooltipText="Change static coordinates in command blocks while nudging.")

        moveSpawnerPosNudgeRow = mceutils.CheckBoxLabel("Change Spawners While Nudging",
                                            ref=config.settings.moveSpawnerPosNudge,
                                            tooltipText="Change the position of the mobs in spawners while nudging.")

        self.goPortableButton = goPortableButton = albow.Button("Change", action=self.togglePortable)

        goPortableButton.tooltipText = self.portableButtonTooltip()
        goPortableRow = albow.Row(
            (albow.ValueDisplay(ref=self.portableVar, width=250, align='r'), goPortableButton))

# Disabled Crash Reporting Option
#       reportRow = mceutils.CheckBoxLabel("Report Errors",
#                                          ref=config.settings.reportCrashes,
#                                          tooltipText="Automatically report errors to the developer.")

        inputs = (
            spaceHeightRow,
            cameraAccelRow,
            cameraDragRow,
            cameraMaxSpeedRow,
            cameraBrakeSpeedRow,
            blockBufferRow,
            mouseSpeedRow,
            undoLimitRow,
            maxCopiesRow,
#            fontProportion, # FONT SIZE
        )

        options = (
                    longDistanceRow,
                    flyModeRow,
                    autoBrakeRow,
                    swapAxesRow,
                    invertRow,
                    superSecretSettingsRow,
                    staticCommandsNudgeRow,
                    moveSpawnerPosNudgeRow,
                    rotateBlockBrushRow,
                    langButtonRow,
                    ) + (
                        ((sys.platform == "win32" and pygame.version.vernum == (1, 9, 1)) and (windowSizeRow,) or ())
                    ) + (
                        (sys.platform == "win32") and (setWindowPlacementRow,) or ()
                    ) + (
                        (not sys.platform == "darwin") and (goPortableRow,) or ()
                    )

        rightcol = albow.Column(options, align='r')
        leftcol = albow.Column(inputs, align='r')

        optionsColumn = albow.Column((albow.Label("Options"),
                                      albow.Row((leftcol, rightcol), align="t")))

        settingsRow = albow.Row((optionsColumn,))

        buttonsRow = albow.Row((albow.Button("OK", action=self.dismiss), albow.Button("Cancel", action=self.cancel)))

        resetToDefaultRow = albow.Row((albow.Button("Reset to default", action=self.resetDefault),))

        optionsColumn = albow.Column((settingsRow, buttonsRow, resetToDefaultRow))
        optionsColumn.key_down = self.key_down

        self.add(optionsColumn)
        self.shrink_wrap()

    @property
    def blockBuffer(self):
        return config.settings.blockBuffer.get() / 1048576

    @blockBuffer.setter
    def blockBuffer(self, val):
        config.settings.blockBuffer.set(int(val * 1048576))

    def getLanguageChoices(self, current=None):
        files = os.listdir(albow.translate.langPath)
        langs = {}
        sgnal = {}
        for file in files:
            name, ext = os.path.splitext(file)
            if ext == ".trn" and len(name) == 5 and name[2] == "_":
                langName = albow.translate.getLangName(file)
                langs[langName] = name
                sgnal[name] = langName
        if "English (US)" not in langs.keys():
            langs[u"English (US)"] = "en_US"
            sgnal["en_US"] = u"English (US)"
        self.langs = langs
        self.sgnal = sgnal
        logging.debug("Detected languages: %s"%self.langs)
        return langs

    def changeLanguage(self):
        langName = self.languageButton.selectedChoice
        if langName not in self.langs:
            lng = "en_US"
        else:
            lng = self.langs[langName]
        config.settings.langCode.set(lng)

    @staticmethod
    def portableButtonTooltip():
        return (
        "Click to make your MCEdit install self-contained by moving the settings and schematics into the program folder",
        "Click to make your MCEdit install persistent by moving the settings and schematics into your Documents folder")[
            directories.portable]

    @property
    def portableLabelText(self):
        return (_("Install Mode: Portable"), _("Install Mode: Fixed"))[1 - directories.portable]

    def togglePortable(self):
        if sys.platform == "darwin":
            return False
        textChoices = [
            _("This will make your MCEdit \"portable\" by moving your settings and schematics into the same folder as {0}. Continue?").format(
                (sys.platform == "darwin" and _("the MCEdit application") or _("MCEditData"))),
            _("This will move your settings and schematics to your Documents folder. Continue?"),
        ]
        if sys.platform == "darwin":
            textChoices[
                1] = _("This will move your schematics to your Documents folder and your settings to your Preferences folder. Continue?")

        alertText = textChoices[directories.portable]
        if albow.ask(alertText) == "OK":
            try:
                [directories.goPortable, directories.goFixed][directories.portable]()
            except Exception, e:
                traceback.print_exc()
                albow.alert(_(u"Error while moving files: {0}").format(repr(e)))

        self.goPortableButton.tooltipText = self.portableButtonTooltip()
        return True

    def dismiss(self, *args, **kwargs):
        """Used to change the language."""
        lng = config.settings.langCode.get()
        try:
            o, n, sc = albow.translate.setLang(lng)
        except:
            o, n, sc = albow.translate.setLang(self.langs[lng])
        if not sc and n != "en_US":
            albow.alert(_("{} is not a valid language").format("%s [%s]" % (self.sgnal[n], n)))
            if o == n:
                o = "en_US"
            config.settings.langCode.set(o)
            albow.translate.setLang(o)
        elif o != n:
            editor = self.mcedit.editor
            if editor and editor.unsavedEdits:
                result = albow.ask("You must restart MCEdit to see language changes", ["Save and Restart", "Restart", "Later"])
            else:
                result = albow.ask("You must restart MCEdit to see language changes", ["Restart", "Later"])
            if result == "Save and Restart":
                editor.saveFile()
                self.mcedit.restart()
            elif result == "Restart":
                self.mcedit.restart()
            elif result == "Later":
                pass

        for key in self.saveOldConfig.keys():
            self.saveOldConfig[key] = key.get()

        config.save()
        Dialog.dismiss(self, *args, **kwargs)

    def cancel(self, *args, **kwargs):
        Changes = False
        for key in self.saveOldConfig.keys():
            if key.get() != self.saveOldConfig[key]:
                Changes = True
        oldLanguage = self.saveOldConfig[config.settings.langCode]
        if config.settings.langCode.get() != oldLanguage:
            Changes = True
        newPortable = self.portableVar.get()
        if newPortable != self.saveOldPortable:
            Changes = True
        if not Changes:
            Dialog.dismiss(self, *args, **kwargs)
            return

        result = albow.ask("Do you want to save your changes?", ["Save", "Don't Save", "Cancel"])
        if result == "Cancel":
            return
        if result == "Save":
            self.dismiss(*args, **kwargs)
            return

        if config.settings.langCode.get() != oldLanguage:
            self.languageButton.selectedChoice = self.sgnal[oldLanguage]
            self.changeLanguage()

        if newPortable != self.saveOldPortable:
            self.portableVar.set(newPortable)
            self.togglePortable()

        for key in self.saveOldConfig.keys():
            key.set(self.saveOldConfig[key])

        config.save()
        Dialog.dismiss(self, *args, **kwargs)

    def resetDefault(self):
        for key in self.saveOldConfig.keys():
            if "AttrRef" in str(key):
                key.set(config.settings.blockBuffer.default / 1048576)
            elif "lang" not in str(key):
                key.set(key.default)

        if config.settings.langCode.get() != "en_US":
            config.settings.langCode.set("en_US")
            self.changeLanguage()
        if "Fixed" not in self.portableVar.get():
            self.portableVar.set("Install Mode: Fixed")
            self.togglePortable()

        config.save()

    def dispatch_key(self, name, evt):
        if name == "key_down":
            keyname = self.get_root().getKey(evt)
            if keyname == 'Escape':
                self.cancel()
<commit_msg>Fixed a couple of bugs in option panel that made the install type unrecognized in other language than english and crashed MCEdit on abort changes.<commit_after>import albow
from albow.dialogs import Dialog
import mceutils
from config import config
import pygame
from albow.translate import _
import sys
import os
import logging
import traceback
import directories

class OptionsPanel(Dialog):
    anchor = 'wh'

    def __init__(self, mcedit):
        Dialog.__init__(self)

        self.mcedit = mcedit

        self.langs = {}
        self.sgnal = {}
        self.portableVar = albow.AttrRef(self, 'portableLabelText')
        self.saveOldPortable = self.portableVar.get()

        self.saveOldConfig = {
            config.controls.autobrake:                 config.controls.autobrake.get(),
            config.controls.swapAxes:                  config.controls.swapAxes.get(),
            config.controls.cameraAccel:               config.controls.cameraAccel.get(),
            config.controls.cameraDrag:                config.controls.cameraDrag.get(),
            config.controls.cameraMaxSpeed:            config.controls.cameraMaxSpeed.get(),
            config.controls.cameraBrakingSpeed:        config.controls.cameraBrakingSpeed.get(),
            config.controls.mouseSpeed:                config.controls.mouseSpeed.get(),
            config.settings.undoLimit:                 config.settings.undoLimit.get(),
            config.settings.maxCopies:                 config.settings.maxCopies.get(),
            config.controls.invertMousePitch:          config.controls.invertMousePitch.get(),
            config.settings.spaceHeight:               config.settings.spaceHeight.get(),
            albow.AttrRef(self, 'blockBuffer'):        albow.AttrRef(self, 'blockBuffer').get(),
            config.settings.setWindowPlacement:        config.settings.setWindowPlacement.get(),
            config.settings.rotateBlockBrush:          config.settings.rotateBlockBrush.get(),
            config.settings.shouldResizeAlert:         config.settings.shouldResizeAlert.get(),
            config.settings.superSecretSettings:       config.settings.superSecretSettings.get(),
            config.settings.longDistanceMode:          config.settings.longDistanceMode.get(),
            config.settings.flyMode:                   config.settings.flyMode.get(),
            config.settings.langCode:                  config.settings.langCode.get()
        }

    def initComponents(self):
        """Initilize the window components. Call this after translation hs been loaded."""
        autoBrakeRow = mceutils.CheckBoxLabel("Autobrake",
                                              ref=config.controls.autobrake,
                                              tooltipText="Apply brake when not pressing movement keys")

        swapAxesRow = mceutils.CheckBoxLabel("Swap Axes Looking Down",
                                             ref=config.controls.swapAxes,
                                             tooltipText="Change the direction of the Forward and Backward keys when looking down")

        cameraAccelRow = mceutils.FloatInputRow("Camera Acceleration: ",
                                                ref=config.controls.cameraAccel, width=100, min=5.0)

        cameraDragRow = mceutils.FloatInputRow("Camera Drag: ",
                                               ref=config.controls.cameraDrag, width=100, min=1.0)

        cameraMaxSpeedRow = mceutils.FloatInputRow("Camera Max Speed: ",
                                                   ref=config.controls.cameraMaxSpeed, width=100, min=1.0)

        cameraBrakeSpeedRow = mceutils.FloatInputRow("Camera Braking Speed: ",
                                                     ref=config.controls.cameraBrakingSpeed, width=100,
                                                     min=1.0)

        mouseSpeedRow = mceutils.FloatInputRow("Mouse Speed: ",
                                               ref=config.controls.mouseSpeed, width=100, min=0.1,
                                               max=20.0)

        undoLimitRow = mceutils.IntInputRow("Undo Limit: ",
                                            ref=config.settings.undoLimit, width=100, min=0)

        maxCopiesRow = mceutils.IntInputRow("Copy Stack Size: ",
                                            ref=config.settings.maxCopies, width=100, min=0,
                                            tooltipText="Maximum number of copied objects.")

        # FONT SIZE
#        fontProportion = mceutils.IntInputRow("Fonts Proportion (%): ",
#                                            ref=config.settings.fontProportion, width=100, min=0,
#                                            tooltipText="Fonts sizing proportion. The number is a percentage.")
#        albow.resource.font_proportion = config.settings.fontProportion.get()

        invertRow = mceutils.CheckBoxLabel("Invert Mouse",
                                           ref=config.controls.invertMousePitch,
                                           tooltipText="Reverse the up and down motion of the mouse.")

        spaceHeightRow = mceutils.IntInputRow(_("Low Detail Height"),
                                              ref=config.settings.spaceHeight,
                                              tooltipText="When you are this far above the top of the world, move fast and use low-detail mode.")

        blockBufferRow = mceutils.IntInputRow("Block Buffer (MB):",
                                              ref=albow.AttrRef(self, 'blockBuffer'), min=1,
                                              tooltipText="Amount of memory used for temporary storage.  When more than this is needed, the disk is used instead.")

        setWindowPlacementRow = mceutils.CheckBoxLabel("Set Window Placement",
                                                       ref=config.settings.setWindowPlacement,
                                                       tooltipText="Try to save and restore the window position.")

        rotateBlockBrushRow = mceutils.CheckBoxLabel("Rotate block with brush",
                                                        ref=config.settings.rotateBlockBrush,
                                                        tooltipText="When rotating your brush, also rotate the orientation of the block your brushing with")

        windowSizeRow = mceutils.CheckBoxLabel("Window Resize Alert",
                                               ref=config.settings.shouldResizeAlert,
                                               tooltipText="Reminds you that the cursor won't work correctly after resizing the window.")

        superSecretSettingsRow = mceutils.CheckBoxLabel("Super Secret Settings",
                                                ref=config.settings.superSecretSettings,
                                                tooltipText="Weird stuff happen!")

        longDistanceRow = mceutils.CheckBoxLabel("Long-Distance Mode",
                                                 ref=config.settings.longDistanceMode,
                                                 tooltipText="Always target the farthest block under the cursor, even in mouselook mode.")

        flyModeRow = mceutils.CheckBoxLabel("Fly Mode",
                                            ref=config.settings.flyMode,
                                            tooltipText="Moving forward and Backward will not change your altitude in Fly Mode.")

        lng = config.settings.langCode.get()

        langs = sorted(self.getLanguageChoices().items())

        langNames = [k for k, v in langs]

        self.languageButton = mceutils.ChoiceButton(langNames, choose=self.changeLanguage)
        if self.sgnal[lng] in self.languageButton.choices:
            self.languageButton.selectedChoice = self.sgnal[lng]

        langButtonRow = albow.Row((albow.Label("Language", tooltipText="Choose your language."), self.languageButton))

        staticCommandsNudgeRow = mceutils.CheckBoxLabel("Static Coords While Nudging",
                                            ref=config.settings.staticCommandsNudge,
                                            tooltipText="Change static coordinates in command blocks while nudging.")

        moveSpawnerPosNudgeRow = mceutils.CheckBoxLabel("Change Spawners While Nudging",
                                            ref=config.settings.moveSpawnerPosNudge,
                                            tooltipText="Change the position of the mobs in spawners while nudging.")

        self.goPortableButton = goPortableButton = albow.Button("Change", action=self.togglePortable)

        goPortableButton.tooltipText = self.portableButtonTooltip()
        goPortableRow = albow.Row(
            (albow.ValueDisplay(ref=self.portableVar, width=250, align='r'), goPortableButton))

# Disabled Crash Reporting Option
#       reportRow = mceutils.CheckBoxLabel("Report Errors",
#                                          ref=config.settings.reportCrashes,
#                                          tooltipText="Automatically report errors to the developer.")

        inputs = (
            spaceHeightRow,
            cameraAccelRow,
            cameraDragRow,
            cameraMaxSpeedRow,
            cameraBrakeSpeedRow,
            blockBufferRow,
            mouseSpeedRow,
            undoLimitRow,
            maxCopiesRow,
#            fontProportion, # FONT SIZE
        )

        options = (
                    longDistanceRow,
                    flyModeRow,
                    autoBrakeRow,
                    swapAxesRow,
                    invertRow,
                    superSecretSettingsRow,
                    staticCommandsNudgeRow,
                    moveSpawnerPosNudgeRow,
                    rotateBlockBrushRow,
                    langButtonRow,
                    ) + (
                        ((sys.platform == "win32" and pygame.version.vernum == (1, 9, 1)) and (windowSizeRow,) or ())
                    ) + (
                        (sys.platform == "win32") and (setWindowPlacementRow,) or ()
                    ) + (
                        (not sys.platform == "darwin") and (goPortableRow,) or ()
                    )

        rightcol = albow.Column(options, align='r')
        leftcol = albow.Column(inputs, align='r')

        optionsColumn = albow.Column((albow.Label("Options"),
                                      albow.Row((leftcol, rightcol), align="t")))

        settingsRow = albow.Row((optionsColumn,))

        buttonsRow = albow.Row((albow.Button("OK", action=self.dismiss), albow.Button("Cancel", action=self.cancel)))

        resetToDefaultRow = albow.Row((albow.Button("Reset to default", action=self.resetDefault),))

        optionsColumn = albow.Column((settingsRow, buttonsRow, resetToDefaultRow))
        optionsColumn.key_down = self.key_down

        self.add(optionsColumn)
        self.shrink_wrap()

    @property
    def blockBuffer(self):
        return config.settings.blockBuffer.get() / 1048576

    @blockBuffer.setter
    def blockBuffer(self, val):
        config.settings.blockBuffer.set(int(val * 1048576))

    def getLanguageChoices(self, current=None):
        files = os.listdir(albow.translate.langPath)
        langs = {}
        sgnal = {}
        for file in files:
            name, ext = os.path.splitext(file)
            if ext == ".trn" and len(name) == 5 and name[2] == "_":
                langName = albow.translate.getLangName(file)
                langs[langName] = name
                sgnal[name] = langName
        if "English (US)" not in langs.keys():
            langs[u"English (US)"] = "en_US"
            sgnal["en_US"] = u"English (US)"
        self.langs = langs
        self.sgnal = sgnal
        logging.debug("Detected languages: %s"%self.langs)
        return langs

    def changeLanguage(self):
        langName = self.languageButton.selectedChoice
        if langName not in self.langs:
            lng = "en_US"
        else:
            lng = self.langs[langName]
        config.settings.langCode.set(lng)

    @staticmethod
    def portableButtonTooltip():
        return (
        "Click to make your MCEdit install self-contained by moving the settings and schematics into the program folder",
        "Click to make your MCEdit install persistent by moving the settings and schematics into your Documents folder")[
            directories.portable]

    @property
    def portableLabelText(self):
        return (_("Install Mode: Portable"), _("Install Mode: Fixed"))[1 - directories.portable]

    @portableLabelText.setter
    def portableLabelText(self, *args, **kwargs):
        pass

    def togglePortable(self):
        if sys.platform == "darwin":
            return False
        textChoices = [
            _("This will make your MCEdit \"portable\" by moving your settings and schematics into the same folder as {0}. Continue?").format(
                (sys.platform == "darwin" and _("the MCEdit application") or _("MCEditData"))),
            _("This will move your settings and schematics to your Documents folder. Continue?"),
        ]
        if sys.platform == "darwin":
            textChoices[
                1] = _("This will move your schematics to your Documents folder and your settings to your Preferences folder. Continue?")

        alertText = textChoices[directories.portable]
        if albow.ask(alertText) == "OK":
            try:
                [directories.goPortable, directories.goFixed][directories.portable]()
            except Exception, e:
                traceback.print_exc()
                albow.alert(_(u"Error while moving files: {0}").format(repr(e)))

        self.goPortableButton.tooltipText = self.portableButtonTooltip()
        return True

    def dismiss(self, *args, **kwargs):
        """Used to change the language."""
        lng = config.settings.langCode.get()
        try:
            o, n, sc = albow.translate.setLang(lng)
        except:
            o, n, sc = albow.translate.setLang(self.langs[lng])
        if not sc and n != "en_US":
            albow.alert(_("{} is not a valid language").format("%s [%s]" % (self.sgnal[n], n)))
            if o == n:
                o = "en_US"
            config.settings.langCode.set(o)
            albow.translate.setLang(o)
        elif o != n:
            editor = self.mcedit.editor
            if editor and editor.unsavedEdits:
                result = albow.ask("You must restart MCEdit to see language changes", ["Save and Restart", "Restart", "Later"])
            else:
                result = albow.ask("You must restart MCEdit to see language changes", ["Restart", "Later"])
            if result == "Save and Restart":
                editor.saveFile()
                self.mcedit.restart()
            elif result == "Restart":
                self.mcedit.restart()
            elif result == "Later":
                pass

        for key in self.saveOldConfig.keys():
            self.saveOldConfig[key] = key.get()

        config.save()
        Dialog.dismiss(self, *args, **kwargs)

    def cancel(self, *args, **kwargs):
        Changes = False
        for key in self.saveOldConfig.keys():
            if key.get() != self.saveOldConfig[key]:
                Changes = True
        oldLanguage = self.saveOldConfig[config.settings.langCode]
        if config.settings.langCode.get() != oldLanguage:
            Changes = True
        newPortable = _(self.portableVar.get())
        if newPortable != _(self.saveOldPortable):
            Changes = True
        if not Changes:
            Dialog.dismiss(self, *args, **kwargs)
            return

        result = albow.ask("Do you want to save your changes?", ["Save", "Don't Save", "Cancel"])
        if result == "Cancel":
            return
        if result == "Save":
            self.dismiss(*args, **kwargs)
            return

        if config.settings.langCode.get() != oldLanguage:
            self.languageButton.selectedChoice = self.sgnal[oldLanguage]
            self.changeLanguage()

        if _(newPortable) != _(self.saveOldPortable):
            self.portableVar.set(newPortable)
            self.togglePortable()

        for key in self.saveOldConfig.keys():
            key.set(self.saveOldConfig[key])

        config.save()
        Dialog.dismiss(self, *args, **kwargs)

    def resetDefault(self):
        for key in self.saveOldConfig.keys():
            if "AttrRef" in str(key):
                key.set(config.settings.blockBuffer.default / 1048576)
            elif "lang" not in str(key):
                key.set(key.default)

        if config.settings.langCode.get() != "en_US":
            config.settings.langCode.set("en_US")
            self.changeLanguage()
        if "Fixed" not in self.portableVar.get():
            self.portableVar.set("Install Mode: Fixed")
            self.togglePortable()

        config.save()

    def dispatch_key(self, name, evt):
        if name == "key_down":
            keyname = self.get_root().getKey(evt)
            if keyname == 'Escape':
                self.cancel()
<|endoftext|>


<commit_before>"""
Listen to serial, return most recent numeric values
Lots of help from here:
http://stackoverflow.com/questions/1093598/pyserial-how-to-read-last-line-sent-from-serial-device
"""
from threading import Thread
import time
import serial
import logging

import astropy.units as u
import astropy.coordinates as coords
from astropy.time import Time
import ephem

class Convert():
    """
        Convert convenience functions
    """

    def __init__(self):

        # Attach to the logger
        self.logger = Logger()

    def HA_to_Dec(self,J2000_coordinate, site):
        """
            HA to Dec
        """
        assert type(J2000_coordinate) == coords.FK5
        assert J2000_coordinate.equinox.value == 'J2000.000'

        ## Coordinate precessed to Jnow (as an astropy coordinate object)
        Jnow_coordinate = J2000_coordinate.precess_to(Time.now())

        ## Coordinate as a pyephem coordinate (J2000)
        RA_string, Dec_string = J2000_coordinate.to_string(precision=2, sep=':').split(' ')
        ephem_coordinate = ephem.FixedBody(RA_string, Dec_string, epoch=ephem.J2000)
        ephem_coordinate = ephem.readdb('Polaris,f|M|F7,{},{},2.02,2000'.format(RA_string, Dec_string))
        ephem_coordinate.compute(site)

        HourAngle = ephem_coordinate.ra - site.sidereal_time()

        self.logger.info('Astropy J2000: {}'.format(J2000_coordinate.to_string(precision=2, sep=':')))
        self.logger.info('pyephem Jnow:  {} {}'.format(ephem_coordinate.ra, ephem_coordinate.dec))
        self.logger.info('RA decimal = {:f}'.format(ephem_coordinate.ra))
        self.logger.info('LST decimal = {:f}'.format(site.sidereal_time()))
        self.logger.info('HA decimal = {:f}'.format(HourAngle))

        return HourAngle

class Logger():

    """
        Sets up the logger for our program
    """

    def __init__(self):

        self.logger = logging.getLogger('PanoptesLogger')
        self.logger.setLevel(logging.DEBUG)

        self.log_format = logging.Formatter(
            '%(asctime)23s %(levelname)8s: %(message)s')

        # Set up file output
        self.file_name = 'panoptes.log'
        self.log_fh = logging.FileHandler(self.file_name)
        self.log_fh.setLevel(logging.DEBUG)
        self.log_fh.setFormatter(self.log_format)
        self.logger.addHandler(self.log_fh)

    def debug(self, msg):
        """ Send a debug message """

        self.logger.debug(msg)

    def info(self, msg):
        """ Send an info message """

        self.logger.info(msg)

    def error(self, msg):
        """ Send an error message """

        self.logger.error(msg)

    def warning(self, msg):
        """ Send an warning message """

        self.logger.warning(msg)

    def critical(self, msg):
        """ Send an critical message """

        self.logger.critical(msg)

    def exception(self, msg):
        """ Send an exception message """

        self.logger.exception(msg)

last_received = ''

def receiving(ser):
    """
    A callback that is attached to a Thread for the SerialData class
    """

    global last_received
    buffer = ''
    while True:
        buffer = buffer + ser.read(ser.inWaiting()).decode()
        if '\n' in buffer:
            lines = buffer.split('\n')  # Guaranteed to have at least 2 entries
            last_received = lines[-2]
            # If the Arduino sends lots of empty lines, you'll lose the
            # last filled line, so you could make the above statement conditional
            # like so: if lines[-2]: last_received = lines[-2]
            buffer = lines[-1]

class SerialData(object):

    """
       Serial class
    """

    def __init__(self, init=50):

        # Attach to the logger
        self.logger = Logger()

        try:
            self.ser = serial.Serial(
                port='/dev/ttyACM0',
                baudrate=115200,
                bytesize=serial.EIGHTBITS,
                parity=serial.PARITY_NONE,
                stopbits=serial.STOPBITS_ONE,
                timeout=0.1,
                xonxoff=0,
                rtscts=0,
                interCharTimeout=None
            )
            time.sleep(2)

        except serial.serialutil.SerialException:
            self.ser = None
            self.logger.critical('Could not connect to serial port')
        else:
            Thread(target=receiving, args=(self.ser,)).start()

    def next(self):
        if not self.ser:
            return 0
        # return a float value or try a few times until we get one
        for i in range(40):
            raw_line = last_received
            try:
                return float(raw_line.strip())
            except ValueError:
                time.sleep(.005)
        return 0.

    def write(self,value):
        """
            For now just pass the value along to serial object
        """

        if not self.ser:
            return 0

        return self.ser.write(value)

    def read(self):
        """ Reads value """

        if not self.ser:
            return 0

        return self.ser.read()

    def __del__(self):
        if self.ser:
            self.ser.close()
<commit_msg>Make utils a base class. Simplify all<commit_after>
import time

from panoptes.utils import *

class PanoptesUtils():
    """
    Base class for all our utils functions. Currently provides:
        - self.logger   Logging methods
        - self.serial   Serial Port communication methods
        - self.convert  Convenience conversion methods
    """

    def __init__(self):
        """
        Sets up all utils
        """
        self.logger = Logger()
        self.serial = SerialData()
        self.convert = Convert()<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

from __future__ import unicode_literals

import io
import os
import sys
import json
import yaml
import fnmatch
import nbformat
import requests
import warnings
import entrypoints

from contextlib import contextmanager

from tenacity import retry, retry_if_exception_type, stop_after_attempt, wait_exponential

from . import __version__
from .log import logger
from .utils import chdir
from .exceptions import (
    PapermillException,
    PapermillRateLimitException,
    missing_dependency_generator,
    missing_environment_variable_generator,
)

try:
    from .s3 import S3
except ImportError:
    S3 = missing_dependency_generator("boto3", "s3")
try:
    from .adl import ADL
except ImportError:
    ADL = missing_dependency_generator("azure.datalake.store", "azure")
except KeyError as exc:
    if exc.args[0] == "APPDATA":
        ADL = missing_environment_variable_generator("azure.datalake.store", "APPDATA")
    else:
        raise
try:
    from .abs import AzureBlobStore
except ImportError:
    AzureBlobStore = missing_dependency_generator("azure.storage.blob", "azure")
try:
    from gcsfs import GCSFileSystem
except ImportError:
    GCSFileSystem = missing_dependency_generator("gcsfs", "gcs")

def fallback_gs_is_retriable(e):
    try:
        print(e.code)
        return e.code is None or e.code == 429
    except AttributeError:
        print(e)
        return False

try:
    # Default to gcsfs library's retry logic
    from gcsfs.utils import is_retriable as gs_is_retriable
except ImportError:
    gs_is_retriable = fallback_gs_is_retriable

try:
    FileNotFoundError
except NameError:
    FileNotFoundError = IOError

class PapermillIO(object):
    '''
    The holder which houses any io system registered with the system.
    This object is used in a singleton manner to save and load particular
    named Handler objects for reference externally.
    '''

    def __init__(self):
        self.reset()

    def read(self, path, extensions=['.ipynb', '.json']):
        if path == '-':
            return sys.stdin.read()

        if not fnmatch.fnmatch(os.path.basename(path), '*.*'):
            warnings.warn(
                "the file is not specified with any extension : " + os.path.basename(path)
            )
        elif not any(fnmatch.fnmatch(os.path.basename(path), '*' + ext) for ext in extensions):
            warnings.warn(
                "The specified input file ({}) does not end in one of {}".format(path, extensions)
            )
        # Handle https://github.com/nteract/papermill/issues/317
        notebook_metadata = self.get_handler(path).read(path)
        if isinstance(notebook_metadata, (bytes, bytearray)):
            return notebook_metadata.decode('utf-8')
        return notebook_metadata

    def write(self, buf, path, extensions=['.ipynb', '.json']):
        if path == '-':
            try:
                # Python 3
                return sys.stdout.buffer.write(buf.encode('utf-8'))
            except AttributeError:
                # Python 2: add explicit utf-8 encoding
                # https://github.com/nteract/papermill/issues/420
                return sys.stdout.write(buf.encode('utf-8'))

        # Usually no return object here
        if not fnmatch.fnmatch(os.path.basename(path), '*.*'):
            warnings.warn(
                "the file is not specified with any extension : " + os.path.basename(path)
            )
        elif not any(fnmatch.fnmatch(os.path.basename(path), '*' + ext) for ext in extensions):
            warnings.warn(
                "The specified input file ({}) does not end in one of {}".format(path, extensions)
            )
        return self.get_handler(path).write(buf, path)

    def listdir(self, path):
        return self.get_handler(path).listdir(path)

    def pretty_path(self, path):
        return self.get_handler(path).pretty_path(path)

    def reset(self):
        self._handlers = []

    def register(self, scheme, handler):
        # Keep these ordered as LIFO
        self._handlers.insert(0, (scheme, handler))

    def register_entry_points(self):
        # Load handlers provided by other packages
        for entrypoint in entrypoints.get_group_all("papermill.io"):
            self.register(entrypoint.name, entrypoint.load())

    def get_handler(self, path):
        local_handler = None
        for scheme, handler in self._handlers:
            if scheme == 'local':
                local_handler = handler

            if path.startswith(scheme):
                return handler

        if local_handler is None:
            raise PapermillException(
                "Could not find a registered schema handler for: {}".format(path)
            )

        return local_handler

class HttpHandler(object):
    @classmethod
    def read(cls, path):
        return requests.get(path, headers={'Accept': 'application/json'}).text

    @classmethod
    def listdir(cls, path):
        raise PapermillException('listdir is not supported by HttpHandler')

    @classmethod
    def write(cls, buf, path):
        result = requests.put(path, json=json.loads(buf))
        result.raise_for_status()

    @classmethod
    def pretty_path(cls, path):
        return path

class LocalHandler(object):
    def __init__(self):
        self._cwd = None

    def read(self, path):
        try:
            with chdir(self._cwd):
                with io.open(path, 'r', encoding="utf-8") as f:
                    return f.read()
        except IOError as e:
            try:
                # Check if path could be a notebook passed in as a
                # string
                json.loads(path)
                return path
            except ValueError:
                # Propagate the IOError
                raise e

    def listdir(self, path):
        with chdir(self._cwd):
            return [os.path.join(path, fn) for fn in os.listdir(path)]

    def write(self, buf, path):
        with chdir(self._cwd):
            dirname = os.path.dirname(path)
            if dirname and not os.path.exists(dirname):
                raise FileNotFoundError("output folder {} doesn't exist.".format(dirname))
            with io.open(path, 'w', encoding="utf-8") as f:
                f.write(buf)

    def pretty_path(self, path):
        return path

    def cwd(self, new_path):
        '''Sets the cwd during reads and writes'''
        old_cwd = self._cwd
        self._cwd = new_path
        return old_cwd

class S3Handler(object):
    @classmethod
    def read(cls, path):
        return "\n".join(S3().read(path))

    @classmethod
    def listdir(cls, path):
        return S3().listdir(path)

    @classmethod
    def write(cls, buf, path):
        return S3().cp_string(buf, path)

    @classmethod
    def pretty_path(cls, path):
        return path

class ADLHandler(object):
    def __init__(self):
        self._client = None

    def _get_client(self):
        if self._client is None:
            self._client = ADL()
        return self._client

    def read(self, path):
        lines = self._get_client().read(path)
        return "\n".join(lines)

    def listdir(self, path):
        return self._get_client().listdir(path)

    def write(self, buf, path):
        return self._get_client().write(buf, path)

    def pretty_path(self, path):
        return path

class ABSHandler(object):
    def __init__(self):
        self._client = None

    def _get_client(self):
        if self._client is None:
            self._client = AzureBlobStore()
        return self._client

    def read(self, path):
        lines = self._get_client().read(path)
        return "\n".join(lines)

    def listdir(self, path):
        return self._get_client().listdir(path)

    def write(self, buf, path):
        return self._get_client().write(buf, path)

    def pretty_path(self, path):
        return path

class GCSHandler(object):
    RATE_LIMIT_RETRIES = 3
    RETRY_DELAY = 1
    RETRY_MULTIPLIER = 1
    RETRY_MAX_DELAY = 4

    def __init__(self):
        self._client = None

    def _get_client(self):
        if self._client is None:
            self._client = GCSFileSystem()
        return self._client

    def read(self, path):
        with self._get_client().open(path) as f:
            return f.read()

    def listdir(self, path):
        return self._get_client().ls(path)

    def write(self, buf, path):
        # Wrapped so we can mock retry options during testing
        @retry(
            retry=retry_if_exception_type(PapermillRateLimitException),
            stop=stop_after_attempt(self.RATE_LIMIT_RETRIES),
            wait=wait_exponential(
                multiplier=self.RETRY_MULTIPLIER, min=self.RETRY_DELAY, max=self.RETRY_MAX_DELAY
            ),
            reraise=True,
        )
        def retry_write():
            try:
                with self._get_client().open(path, 'w') as f:
                    return f.write(buf)
            except Exception as e:
                try:
                    message = e.message
                except AttributeError:
                    message = "Generic exception {} raised".format(type(e))
                if gs_is_retriable(e):
                    raise PapermillRateLimitException(message)
                # Reraise the original exception without retries
                raise

        return retry_write()

    def pretty_path(self, path):
        return path

# Hack to make YAML loader not auto-convert datetimes
# https://stackoverflow.com/a/52312810
NoDatesSafeLoader = yaml.SafeLoader
NoDatesSafeLoader.yaml_implicit_resolvers = {
    k: [r for r in v if r[0] != 'tag:yaml.org,2002:timestamp'] for
    k, v in NoDatesSafeLoader.yaml_implicit_resolvers.items()
}

# Instantiate a PapermillIO instance and register Handlers.
papermill_io = PapermillIO()
papermill_io.register("local", LocalHandler())
papermill_io.register("s3://", S3Handler)
papermill_io.register("adl://", ADLHandler())
papermill_io.register("abs://", ABSHandler())
papermill_io.register("http://", HttpHandler)
papermill_io.register("https://", HttpHandler)
papermill_io.register("gs://", GCSHandler())
papermill_io.register_entry_points()

def read_yaml_file(path):
    """Reads a YAML file from the location specified at 'path'."""
    return yaml.load(papermill_io.read(path, ['.json', '.yaml', '.yml']), Loader=NoDatesSafeLoader)

def write_ipynb(nb, path):
    """Saves a notebook object to the specified path.
    Args:
        nb_node (nbformat.NotebookNode): Notebook object to save.
        notebook_path (str): Path to save the notebook object to.
    """
    papermill_io.write(nbformat.writes(nb), path)

def load_notebook_node(notebook_path):
    """Returns a notebook object with papermill metadata loaded from the specified path.

    Args:
        notebook_path (str): Path to the notebook file.

    Returns:
        nbformat.NotebookNode

    """
    nb = nbformat.reads(papermill_io.read(notebook_path), as_version=4)

    if not hasattr(nb.metadata, 'papermill'):
        nb.metadata['papermill'] = {
            'parameters': dict(),
            'environment_variables': dict(),
            'version': __version__,
        }

    for cell in nb.cells:
        if not hasattr(cell.metadata, 'tags'):
            cell.metadata['tags'] = []  # Create tags attr if one doesn't exist.

        if not hasattr(cell.metadata, 'papermill'):
            cell.metadata['papermill'] = dict()
    return nb

def list_notebook_files(path):
    """Returns a list of all the notebook files in a directory."""
    return [p for p in papermill_io.listdir(path) if p.endswith('.ipynb')]

def get_pretty_path(path):
    return papermill_io.pretty_path(path)

@contextmanager
def local_file_io_cwd(path=None):
    try:
        local_handler = papermill_io.get_handler("local")
    except PapermillException:
        logger.warning("No local file handler detected")
    else:
        try:
            old_cwd = local_handler.cwd(path or os.getcwd())
        except AttributeError:
            logger.warning("Local file handler does not support cwd assignment")
        else:
            try:
                yield
            finally:
                local_handler.cwd(old_cwd)
<commit_msg>Inherit new class from SafeLoader<commit_after># -*- coding: utf-8 -*-

from __future__ import unicode_literals

import io
import os
import sys
import json
import yaml
import fnmatch
import nbformat
import requests
import warnings
import entrypoints

from contextlib import contextmanager

from tenacity import retry, retry_if_exception_type, stop_after_attempt, wait_exponential

from . import __version__
from .log import logger
from .utils import chdir
from .exceptions import (
    PapermillException,
    PapermillRateLimitException,
    missing_dependency_generator,
    missing_environment_variable_generator,
)

try:
    from .s3 import S3
except ImportError:
    S3 = missing_dependency_generator("boto3", "s3")
try:
    from .adl import ADL
except ImportError:
    ADL = missing_dependency_generator("azure.datalake.store", "azure")
except KeyError as exc:
    if exc.args[0] == "APPDATA":
        ADL = missing_environment_variable_generator("azure.datalake.store", "APPDATA")
    else:
        raise
try:
    from .abs import AzureBlobStore
except ImportError:
    AzureBlobStore = missing_dependency_generator("azure.storage.blob", "azure")
try:
    from gcsfs import GCSFileSystem
except ImportError:
    GCSFileSystem = missing_dependency_generator("gcsfs", "gcs")

def fallback_gs_is_retriable(e):
    try:
        print(e.code)
        return e.code is None or e.code == 429
    except AttributeError:
        print(e)
        return False

try:
    # Default to gcsfs library's retry logic
    from gcsfs.utils import is_retriable as gs_is_retriable
except ImportError:
    gs_is_retriable = fallback_gs_is_retriable

try:
    FileNotFoundError
except NameError:
    FileNotFoundError = IOError

class PapermillIO(object):
    '''
    The holder which houses any io system registered with the system.
    This object is used in a singleton manner to save and load particular
    named Handler objects for reference externally.
    '''

    def __init__(self):
        self.reset()

    def read(self, path, extensions=['.ipynb', '.json']):
        if path == '-':
            return sys.stdin.read()

        if not fnmatch.fnmatch(os.path.basename(path), '*.*'):
            warnings.warn(
                "the file is not specified with any extension : " + os.path.basename(path)
            )
        elif not any(fnmatch.fnmatch(os.path.basename(path), '*' + ext) for ext in extensions):
            warnings.warn(
                "The specified input file ({}) does not end in one of {}".format(path, extensions)
            )
        # Handle https://github.com/nteract/papermill/issues/317
        notebook_metadata = self.get_handler(path).read(path)
        if isinstance(notebook_metadata, (bytes, bytearray)):
            return notebook_metadata.decode('utf-8')
        return notebook_metadata

    def write(self, buf, path, extensions=['.ipynb', '.json']):
        if path == '-':
            try:
                # Python 3
                return sys.stdout.buffer.write(buf.encode('utf-8'))
            except AttributeError:
                # Python 2: add explicit utf-8 encoding
                # https://github.com/nteract/papermill/issues/420
                return sys.stdout.write(buf.encode('utf-8'))

        # Usually no return object here
        if not fnmatch.fnmatch(os.path.basename(path), '*.*'):
            warnings.warn(
                "the file is not specified with any extension : " + os.path.basename(path)
            )
        elif not any(fnmatch.fnmatch(os.path.basename(path), '*' + ext) for ext in extensions):
            warnings.warn(
                "The specified input file ({}) does not end in one of {}".format(path, extensions)
            )
        return self.get_handler(path).write(buf, path)

    def listdir(self, path):
        return self.get_handler(path).listdir(path)

    def pretty_path(self, path):
        return self.get_handler(path).pretty_path(path)

    def reset(self):
        self._handlers = []

    def register(self, scheme, handler):
        # Keep these ordered as LIFO
        self._handlers.insert(0, (scheme, handler))

    def register_entry_points(self):
        # Load handlers provided by other packages
        for entrypoint in entrypoints.get_group_all("papermill.io"):
            self.register(entrypoint.name, entrypoint.load())

    def get_handler(self, path):
        local_handler = None
        for scheme, handler in self._handlers:
            if scheme == 'local':
                local_handler = handler

            if path.startswith(scheme):
                return handler

        if local_handler is None:
            raise PapermillException(
                "Could not find a registered schema handler for: {}".format(path)
            )

        return local_handler

class HttpHandler(object):
    @classmethod
    def read(cls, path):
        return requests.get(path, headers={'Accept': 'application/json'}).text

    @classmethod
    def listdir(cls, path):
        raise PapermillException('listdir is not supported by HttpHandler')

    @classmethod
    def write(cls, buf, path):
        result = requests.put(path, json=json.loads(buf))
        result.raise_for_status()

    @classmethod
    def pretty_path(cls, path):
        return path

class LocalHandler(object):
    def __init__(self):
        self._cwd = None

    def read(self, path):
        try:
            with chdir(self._cwd):
                with io.open(path, 'r', encoding="utf-8") as f:
                    return f.read()
        except IOError as e:
            try:
                # Check if path could be a notebook passed in as a
                # string
                json.loads(path)
                return path
            except ValueError:
                # Propagate the IOError
                raise e

    def listdir(self, path):
        with chdir(self._cwd):
            return [os.path.join(path, fn) for fn in os.listdir(path)]

    def write(self, buf, path):
        with chdir(self._cwd):
            dirname = os.path.dirname(path)
            if dirname and not os.path.exists(dirname):
                raise FileNotFoundError("output folder {} doesn't exist.".format(dirname))
            with io.open(path, 'w', encoding="utf-8") as f:
                f.write(buf)

    def pretty_path(self, path):
        return path

    def cwd(self, new_path):
        '''Sets the cwd during reads and writes'''
        old_cwd = self._cwd
        self._cwd = new_path
        return old_cwd

class S3Handler(object):
    @classmethod
    def read(cls, path):
        return "\n".join(S3().read(path))

    @classmethod
    def listdir(cls, path):
        return S3().listdir(path)

    @classmethod
    def write(cls, buf, path):
        return S3().cp_string(buf, path)

    @classmethod
    def pretty_path(cls, path):
        return path

class ADLHandler(object):
    def __init__(self):
        self._client = None

    def _get_client(self):
        if self._client is None:
            self._client = ADL()
        return self._client

    def read(self, path):
        lines = self._get_client().read(path)
        return "\n".join(lines)

    def listdir(self, path):
        return self._get_client().listdir(path)

    def write(self, buf, path):
        return self._get_client().write(buf, path)

    def pretty_path(self, path):
        return path

class ABSHandler(object):
    def __init__(self):
        self._client = None

    def _get_client(self):
        if self._client is None:
            self._client = AzureBlobStore()
        return self._client

    def read(self, path):
        lines = self._get_client().read(path)
        return "\n".join(lines)

    def listdir(self, path):
        return self._get_client().listdir(path)

    def write(self, buf, path):
        return self._get_client().write(buf, path)

    def pretty_path(self, path):
        return path

class GCSHandler(object):
    RATE_LIMIT_RETRIES = 3
    RETRY_DELAY = 1
    RETRY_MULTIPLIER = 1
    RETRY_MAX_DELAY = 4

    def __init__(self):
        self._client = None

    def _get_client(self):
        if self._client is None:
            self._client = GCSFileSystem()
        return self._client

    def read(self, path):
        with self._get_client().open(path) as f:
            return f.read()

    def listdir(self, path):
        return self._get_client().ls(path)

    def write(self, buf, path):
        # Wrapped so we can mock retry options during testing
        @retry(
            retry=retry_if_exception_type(PapermillRateLimitException),
            stop=stop_after_attempt(self.RATE_LIMIT_RETRIES),
            wait=wait_exponential(
                multiplier=self.RETRY_MULTIPLIER, min=self.RETRY_DELAY, max=self.RETRY_MAX_DELAY
            ),
            reraise=True,
        )
        def retry_write():
            try:
                with self._get_client().open(path, 'w') as f:
                    return f.write(buf)
            except Exception as e:
                try:
                    message = e.message
                except AttributeError:
                    message = "Generic exception {} raised".format(type(e))
                if gs_is_retriable(e):
                    raise PapermillRateLimitException(message)
                # Reraise the original exception without retries
                raise

        return retry_write()

    def pretty_path(self, path):
        return path

# Hack to make YAML loader not auto-convert datetimes
# https://stackoverflow.com/a/52312810
class NoDatesSafeLoader(yaml.SafeLoader):
    yaml_implicit_resolvers = {
        k: [r for r in v if r[0] != 'tag:yaml.org,2002:timestamp'] for
        k, v in yaml.SafeLoader.yaml_implicit_resolvers.items()
    }

# Instantiate a PapermillIO instance and register Handlers.
papermill_io = PapermillIO()
papermill_io.register("local", LocalHandler())
papermill_io.register("s3://", S3Handler)
papermill_io.register("adl://", ADLHandler())
papermill_io.register("abs://", ABSHandler())
papermill_io.register("http://", HttpHandler)
papermill_io.register("https://", HttpHandler)
papermill_io.register("gs://", GCSHandler())
papermill_io.register_entry_points()

def read_yaml_file(path):
    """Reads a YAML file from the location specified at 'path'."""
    return yaml.load(papermill_io.read(path, ['.json', '.yaml', '.yml']), Loader=NoDatesSafeLoader)

def write_ipynb(nb, path):
    """Saves a notebook object to the specified path.
    Args:
        nb_node (nbformat.NotebookNode): Notebook object to save.
        notebook_path (str): Path to save the notebook object to.
    """
    papermill_io.write(nbformat.writes(nb), path)

def load_notebook_node(notebook_path):
    """Returns a notebook object with papermill metadata loaded from the specified path.

    Args:
        notebook_path (str): Path to the notebook file.

    Returns:
        nbformat.NotebookNode

    """
    nb = nbformat.reads(papermill_io.read(notebook_path), as_version=4)

    if not hasattr(nb.metadata, 'papermill'):
        nb.metadata['papermill'] = {
            'parameters': dict(),
            'environment_variables': dict(),
            'version': __version__,
        }

    for cell in nb.cells:
        if not hasattr(cell.metadata, 'tags'):
            cell.metadata['tags'] = []  # Create tags attr if one doesn't exist.

        if not hasattr(cell.metadata, 'papermill'):
            cell.metadata['papermill'] = dict()
    return nb

def list_notebook_files(path):
    """Returns a list of all the notebook files in a directory."""
    return [p for p in papermill_io.listdir(path) if p.endswith('.ipynb')]

def get_pretty_path(path):
    return papermill_io.pretty_path(path)

@contextmanager
def local_file_io_cwd(path=None):
    try:
        local_handler = papermill_io.get_handler("local")
    except PapermillException:
        logger.warning("No local file handler detected")
    else:
        try:
            old_cwd = local_handler.cwd(path or os.getcwd())
        except AttributeError:
            logger.warning("Local file handler does not support cwd assignment")
        else:
            try:
                yield
            finally:
                local_handler.cwd(old_cwd)
<|endoftext|>


<commit_before>#!/usr/bin/env python
import os, sys
from optparse import OptionParser
from hydeengine import Generator, Initializer, Server

#import cProfile

PROG_ROOT = os.path.dirname(os.path.abspath( __file__ ))

def main(argv):
    parser = OptionParser()
    parser.add_option("-s", "--sitepath",
                        dest = "site_path", help = "Change the path of the site folder.")
    parser.add_option("-i", "--init", action = 'store_true',
                        dest = "init", default = False, help = "Create a new hyde site.")
    parser.add_option("-f", "--force", action = 'store_true',
                        dest = "force_init", default = False, help = "")
    parser.add_option("-t", "--template",
                        dest = "template", help = "Choose which template you want to use.")
    parser.add_option("-g", "--generate", action = "store_true",
                        dest = "generate", default = False, help = "Generate the source for your hyde site.")
    parser.add_option("-d", "--deploy_to",
                        dest = "deploy_to", help = "Change the path of the deploy folder.")
    parser.add_option("-w", "--webserve", action = "store_true",
                        dest = "webserve", default = False, help = "Start an instance of the CherryPy webserver.")

    (options, args) = parser.parse_args()

    if len(args):
        parser.error("Unexpected arguments encountered.")

    if not options.site_path:
        options.site_path = os.getcwdu()

    if options.deploy_to:
        options.deploy_to = os.path.abspath(options.deploy_to)

    if options.init:
        initializer = Initializer(options.site_path)
        initializer.initialize(PROG_ROOT,
                    options.template, options.force_init)
    if options.generate:
        generator = Generator(options.site_path)
        generator.generate(options.deploy_to)
    if options.webserve:
        server = Server(options.site_path)
        server.serve(options.deploy_to)

    if argv == []:
        print parser.format_option_help()

if __name__ == "__main__":
    main(sys.argv[1:])
    # cProfile.run('main(sys.argv[1:])', filename='hyde.cprof')
    # import pstats
    # stats = pstats.Stats('hyde.cprof')
    # stats.strip_dirs().sort_stats('time').print_stats(20)<commit_msg>Added version number<commit_after>#!/usr/bin/env python
import os, sys
from optparse import OptionParser
from hydeengine import Generator, Initializer, Server

#import cProfile

PROG_ROOT = os.path.dirname(os.path.abspath( __file__ ))

def main(argv):
    parser = OptionParser(usage="%prog [-f] [-q]", version="%prog 0.1a")
    parser.add_option("-s", "--sitepath",
                        dest = "site_path", help = "Change the path of the site folder.")
    parser.add_option("-i", "--init", action = 'store_true',
                        dest = "init", default = False, help = "Create a new hyde site.")
    parser.add_option("-f", "--force", action = 'store_true',
                        dest = "force_init", default = False, help = "")
    parser.add_option("-t", "--template",
                        dest = "template", help = "Choose which template you want to use.")
    parser.add_option("-g", "--generate", action = "store_true",
                        dest = "generate", default = False, help = "Generate the source for your hyde site.")
    parser.add_option("-d", "--deploy_to",
                        dest = "deploy_to", help = "Change the path of the deploy folder.")
    parser.add_option("-w", "--webserve", action = "store_true",
                        dest = "webserve", default = False, help = "Start an instance of the CherryPy webserver.")

    (options, args) = parser.parse_args()

    if len(args):
        parser.error("Unexpected arguments encountered.")

    if not options.site_path:
        options.site_path = os.getcwdu()

    if options.deploy_to:
        options.deploy_to = os.path.abspath(options.deploy_to)

    if options.init:
        initializer = Initializer(options.site_path)
        initializer.initialize(PROG_ROOT,
                    options.template, options.force_init)
    if options.generate:
        generator = Generator(options.site_path)
        generator.generate(options.deploy_to)
    if options.webserve:
        server = Server(options.site_path)
        server.serve(options.deploy_to)

    if argv == []:
        print parser.format_option_help()

if __name__ == "__main__":
    main(sys.argv[1:])
    # cProfile.run('main(sys.argv[1:])', filename='hyde.cprof')
    # import pstats
    # stats = pstats.Stats('hyde.cprof')
    # stats.strip_dirs().sort_stats('time').print_stats(20)<|endoftext|>


<commit_before>"""Daily Climatology"""

# third party
import pandas as pd
from pandas.io.sql import read_sql
import matplotlib.dates as mdates
from pyiem.exceptions import NoDataFound
from pyiem.reference import TWITTER_RESOLUTION_INCH
from pyiem.util import get_autoplot_context, get_dbconn
from pyiem.plot.use_agg import plt
from pyiem.plot import fitbox

PDICT = {
    "por": "Period of Record (por) Climatology",
    "1951": "1951-present Climatology",
    "ncei81": "NCEI 1981-2010 Climatology",
    "custom": "Custom Climatology (pick years)",
}
PDICT2 = {
    "0": "No Smoothing Applied",
    "7": "Seven Day Centered Smooth",
    "14": "Fourteen Day Centered Smooth",
}

def get_description():
    """ Return a dict describing how to call this plotter """
    desc = dict()
    desc["data"] = True
    desc[
        "description"
    ] = """This application plots daily climatology for
    a location or two of your choice.  You can pick which climatology to use
    and effectively build a difference plot when picking the same station,
    but using a different climatology.
    """
    desc["arguments"] = [
        dict(
            type="station",
            name="station1",
            default="IATDSM",
            label="Select First Station:",
            network="IACLIMATE",
        ),
        dict(
            type="select",
            name="c1",
            label="Climatology Source for First Station:",
            default="1951",
            options=PDICT,
        ),
        dict(
            type="station",
            name="station2",
            default="IATDSM",
            optional=True,
            label="Select Second Station (Optional):",
            network="IACLIMATE",
        ),
        dict(
            type="select",
            name="c2",
            label="Climatology Source for Second Station:",
            default="1951",
            options=PDICT,
        ),
        dict(
            type="select",
            name="s",
            label="For difference plot, should smoother be applied:",
            default="0",
            options=PDICT2,
        ),
        dict(
            type="year",
            min=1880,
            name="sy1",
            default=1991,
            label="Inclusive Start Year for First Station Period of Years:",
        ),
        dict(
            type="year",
            min=1880,
            name="ey1",
            default=2020,
            label="Inclusive End Year for First Station Period of Years:",
        ),
        dict(
            type="year",
            min=1880,
            name="sy2",
            default=1981,
            label="Inclusive Start Year for Second Station Period of Years:",
        ),
        dict(
            type="year",
            min=1880,
            name="ey2",
            default=2010,
            label="Inclusive End Year for Second Station Period of Years:",
        ),
    ]
    return desc

def pick_climate(ctx, idx):
    """Figure out what we need to use."""
    climo = ctx.get(f"c{idx}", "1951")
    cltable = "climate"
    clstation = ctx.get(f"station{idx}")
    if climo == "1951":
        cltable = "climate51"
        clstation = ctx.get(f"station{idx}")
    elif climo == "ncei81":
        cltable = "ncdc_climate81"
        if clstation in ctx[f"_nt{idx}"].sts:
            clstation = ctx[f"_nt{idx}"].sts[clstation]["ncdc81"]
    return cltable, clstation

def plotter(fdict):
    """ Go """
    ctx = get_autoplot_context(fdict, get_description())
    station1 = ctx["station1"]
    station2 = ctx.get("station2")
    c1 = ctx["c1"]
    c2 = ctx.get("c2")

    dbconn = get_dbconn("coop")
    cltable1, clstation1 = pick_climate(ctx, "1")
    cltable2, clstation2 = pick_climate(ctx, "2")

    if c1 == "custom":
        df = read_sql(
            "SELECT sday, station, avg(high) as high, avg(low) as low "
            f"from alldata_{station1[:2]} WHERE "
            "station = %s and sday != '0229' and year >= %s and year <= %s "
            "and high is not null and "
            "low is not null GROUP by sday, station ORDER by sday ASC",
            dbconn,
            params=(station1, ctx["sy1"], ctx["ey1"]),
            index_col=None,
        )
        df["valid"] = pd.to_datetime(df["sday"] + "2000", format="%m%d%Y")
        df = df.set_index("valid")
    else:
        df = read_sql(
            f"SELECT valid, station, high, low from {cltable1} WHERE "
            "station = %s and valid != '2000-02-29' ORDER by valid ASC",
            dbconn,
            params=(clstation1,),
            index_col="valid",
        )
    if df.empty:
        raise NoDataFound("Failed to find data for station1")
    if station2:
        if c2 == "custom":
            df2 = read_sql(
                "SELECT sday, station, avg(high) as high, avg(low) as low "
                f"from alldata_{station2[:2]} WHERE "
                "station = %s and sday != '0229' and year >= %s and "
                "year <= %s and high is not null and "
                "low is not null GROUP by sday, station ORDER by sday ASC",
                dbconn,
                params=(station2, ctx["sy2"], ctx["ey2"]),
                index_col=None,
            )
            df2["valid"] = pd.to_datetime(
                df2["sday"] + "2000", format="%m%d%Y"
            )
            df2 = df2.set_index("valid")

        else:
            df2 = read_sql(
                f"SELECT valid, station, high, low from {cltable2} WHERE "
                "station = %s and valid != '2000-02-29' ORDER by valid ASC",
                dbconn,
                params=(clstation2,),
                index_col="valid",
            )
        if df2.empty:
            raise NoDataFound("Failed to find data for station2")
        df["station2"] = station2
        df["high2"] = df2["high"]
        df["low2"] = df2["low"]

    fig = plt.figure(figsize=TWITTER_RESOLUTION_INCH)

    if station2 is not None:
        ax0 = fig.add_axes([0.05, 0.15, 0.43, 0.75])
        ax1 = fig.add_axes([0.55, 0.15, 0.43, 0.75])
    else:
        ax0 = fig.add_axes([0.05, 0.15, 0.8, 0.75])
        ax1 = None

    c1label = c1
    if c1 == "custom":
        c1label = "[%s-%s]" % (ctx["sy1"], ctx["ey1"])
    c2label = c2
    if c2 == "custom":
        c2label = "[%s-%s]" % (ctx["sy2"], ctx["ey2"])
    ax0.plot(
        df.index.values,
        df["high"],
        color="r",
        linestyle="-",
        label="High %s (%s)" % (station1, c1label),
    )
    ax0.plot(
        df.index.values,
        df["low"],
        color="b",
        label="Low %s (%s)" % (station1, c1label),
    )
    ax0.set_ylabel(r"Temperature $^\circ\mathrm{F}$")
    title = "[%s] %s %s Daily Averages" % (
        station1,
        ctx["_nt1"].sts[station1]["name"],
        PDICT[c1] if c1 != "custom" else c1label,
    )
    subtitle = None
    if station2 is not None:
        if station1 == station2:
            title = "[%s] %s %s vs %s" % (
                station1,
                ctx["_nt1"].sts[station1]["name"],
                PDICT[c1] if c1 != "custom" else c1label,
                PDICT[c2] if c2 != "custom" else c2label,
            )
            label = f"{c1label} - {c2label}"
        else:
            title = "Daily Climatology Comparison"
            subtitle = "[%s] %s %s vs [%s] %s %s" % (
                station1,
                ctx["_nt1"].sts[station1]["name"],
                PDICT[ctx["c1"]],
                station2,
                ctx["_nt2"].sts[station2]["name"],
                PDICT[ctx["c2"]],
            )
            label = "%s (%s) - %s (%s)" % (station1, c1, station2, c2)
        ax0.plot(
            df.index.values,
            df["high2"],
            color="brown",
            label="High %s (%s)" % (station2, c2label),
        )
        ax0.plot(
            df.index.values,
            df["low2"],
            color="green",
            label="Low %s (%s)" % (station2, c2label),
        )
        delta = df["high"] - df["high2"]
        if ctx["s"] != "0":
            ax1.text(
                0.01,
                0.99,
                "%s Day Smoother Applied" % (int(ctx["s"]),),
                transform=ax1.transAxes,
                va="top",
            )
            delta = delta.rolling(window=int(ctx["s"])).mean()
        ax1.plot(
            df.index.values,
            delta.values,
            color="r",
            label=f"High Diff {label}",
        )
        delta = df["low"] - df["low2"]
        if ctx["s"] != "0":
            delta = delta.rolling(window=int(ctx["s"])).mean()
        ax1.plot(df.index.values, delta, color="b", label=f"Low Diff {label}")
        ax1.set_ylabel(r"Temp Difference $^\circ\mathrm{F}$")
        ax1.legend(ncol=1, loc="center", bbox_to_anchor=(0.5, -0.1))
        ax1.grid(True)
        ax1.xaxis.set_major_locator(mdates.MonthLocator(interval=1))
        ax1.xaxis.set_major_formatter(mdates.DateFormatter("%b"))

    fitbox(fig, title, 0.05, 0.94, 0.95, 0.99)
    if subtitle is not None:
        fitbox(fig, subtitle, 0.05, 0.95, 0.905, 0.935)
    ax0.legend(fontsize=10, ncol=2, loc="center", bbox_to_anchor=(0.5, -0.1))
    ax0.grid()
    ax0.xaxis.set_major_locator(mdates.MonthLocator(interval=1))
    ax0.xaxis.set_major_formatter(mdates.DateFormatter("%b"))

    return fig, df

if __name__ == "__main__":
    plotter(
        dict(
            network1="IACLIMATE",
            station1="IA0112",
            c1="custom",
            network2="IACLIMATE",
            station2="IA0112",
            c2="por",
            s="0",
            sy1=1981,
            ey1=2010,
            sy2=1991,
            ey2=2020,
        )
    )
<commit_msg>add monthly average subplot<commit_after>"""Daily Climatology"""
# stdlib
import calendar

# third party
import pandas as pd
from pandas.io.sql import read_sql
import matplotlib.dates as mdates
from pyiem.exceptions import NoDataFound
from pyiem.reference import TWITTER_RESOLUTION_INCH
from pyiem.util import get_autoplot_context, get_dbconn
from pyiem.plot.use_agg import plt
from pyiem.plot import fitbox

PDICT = {
    "por": "Period of Record (por) Climatology",
    "1951": "1951-present Climatology",
    "ncei81": "NCEI 1981-2010 Climatology",
    "custom": "Custom Climatology (pick years)",
}
PDICT2 = {
    "0": "No Smoothing Applied",
    "7": "Seven Day Centered Smooth",
    "14": "Fourteen Day Centered Smooth",
}

def get_description():
    """ Return a dict describing how to call this plotter """
    desc = dict()
    desc["data"] = True
    desc[
        "description"
    ] = """This application plots daily climatology for
    a location or two of your choice.  You can pick which climatology to use
    and effectively build a difference plot when picking the same station,
    but using a different climatology.
    """
    desc["arguments"] = [
        dict(
            type="station",
            name="station1",
            default="IATDSM",
            label="Select First Station:",
            network="IACLIMATE",
        ),
        dict(
            type="select",
            name="c1",
            label="Climatology Source for First Station:",
            default="1951",
            options=PDICT,
        ),
        dict(
            type="station",
            name="station2",
            default="IATDSM",
            optional=True,
            label="Select Second Station (Optional):",
            network="IACLIMATE",
        ),
        dict(
            type="select",
            name="c2",
            label="Climatology Source for Second Station:",
            default="1951",
            options=PDICT,
        ),
        dict(
            type="select",
            name="s",
            label="For difference plot, should smoother be applied:",
            default="0",
            options=PDICT2,
        ),
        dict(
            type="year",
            min=1880,
            name="sy1",
            default=1991,
            label="Inclusive Start Year for First Station Period of Years:",
        ),
        dict(
            type="year",
            min=1880,
            name="ey1",
            default=2020,
            label="Inclusive End Year for First Station Period of Years:",
        ),
        dict(
            type="year",
            min=1880,
            name="sy2",
            default=1981,
            label="Inclusive Start Year for Second Station Period of Years:",
        ),
        dict(
            type="year",
            min=1880,
            name="ey2",
            default=2010,
            label="Inclusive End Year for Second Station Period of Years:",
        ),
    ]
    return desc

def pick_climate(ctx, idx):
    """Figure out what we need to use."""
    climo = ctx.get(f"c{idx}", "1951")
    cltable = "climate"
    clstation = ctx.get(f"station{idx}")
    if climo == "1951":
        cltable = "climate51"
        clstation = ctx.get(f"station{idx}")
    elif climo == "ncei81":
        cltable = "ncdc_climate81"
        if clstation in ctx[f"_nt{idx}"].sts:
            clstation = ctx[f"_nt{idx}"].sts[clstation]["ncdc81"]
    return cltable, clstation

def plotter(fdict):
    """ Go """
    ctx = get_autoplot_context(fdict, get_description())
    station1 = ctx["station1"]
    station2 = ctx.get("station2")
    c1 = ctx["c1"]
    c2 = ctx.get("c2")

    dbconn = get_dbconn("coop")
    cltable1, clstation1 = pick_climate(ctx, "1")
    cltable2, clstation2 = pick_climate(ctx, "2")

    if c1 == "custom":
        df = read_sql(
            "SELECT sday, station, avg(high) as high, avg(low) as low "
            f"from alldata_{station1[:2]} WHERE "
            "station = %s and sday != '0229' and year >= %s and year <= %s "
            "and high is not null and "
            "low is not null GROUP by sday, station ORDER by sday ASC",
            dbconn,
            params=(station1, ctx["sy1"], ctx["ey1"]),
            index_col=None,
        )
        df["valid"] = pd.to_datetime(df["sday"] + "2000", format="%m%d%Y")
        df = df.set_index("valid")
    else:
        df = read_sql(
            f"SELECT valid, station, high, low from {cltable1} WHERE "
            "station = %s and valid != '2000-02-29' ORDER by valid ASC",
            dbconn,
            params=(clstation1,),
            index_col="valid",
        )
    if df.empty:
        raise NoDataFound("Failed to find data for station1")
    if station2:
        if c2 == "custom":
            df2 = read_sql(
                "SELECT sday, station, avg(high) as high, avg(low) as low "
                f"from alldata_{station2[:2]} WHERE "
                "station = %s and sday != '0229' and year >= %s and "
                "year <= %s and high is not null and "
                "low is not null GROUP by sday, station ORDER by sday ASC",
                dbconn,
                params=(station2, ctx["sy2"], ctx["ey2"]),
                index_col=None,
            )
            df2["valid"] = pd.to_datetime(
                df2["sday"] + "2000", format="%m%d%Y"
            )
            df2 = df2.set_index("valid")

        else:
            df2 = read_sql(
                f"SELECT valid, station, high, low from {cltable2} WHERE "
                "station = %s and valid != '2000-02-29' ORDER by valid ASC",
                dbconn,
                params=(clstation2,),
                index_col="valid",
            )
        if df2.empty:
            raise NoDataFound("Failed to find data for station2")
        df["station2"] = station2
        df["high2"] = df2["high"]
        df["low2"] = df2["low"]
        df["highdiff"] = df["high"] - df["high2"]
        df["lowdiff"] = df["low"] - df["low2"]

    fig = plt.figure(figsize=TWITTER_RESOLUTION_INCH)

    if station2 is not None:
        ax0 = fig.add_axes([0.05, 0.15, 0.43, 0.75])
        ax1 = fig.add_axes([0.55, 0.55, 0.43, 0.35])
        ax2 = fig.add_axes([0.55, 0.07, 0.43, 0.35])
    else:
        ax0 = fig.add_axes([0.05, 0.15, 0.8, 0.75])
        ax1 = None

    c1label = c1
    if c1 == "custom":
        c1label = "[%s-%s]" % (ctx["sy1"], ctx["ey1"])
    c2label = c2
    if c2 == "custom":
        c2label = "[%s-%s]" % (ctx["sy2"], ctx["ey2"])
    ax0.plot(
        df.index.values,
        df["high"],
        color="r",
        linestyle="-",
        label="High %s (%s)" % (station1, c1label),
    )
    ax0.plot(
        df.index.values,
        df["low"],
        color="b",
        label="Low %s (%s)" % (station1, c1label),
    )
    ax0.set_ylabel(r"Temperature $^\circ\mathrm{F}$")
    title = "[%s] %s %s Daily Averages" % (
        station1,
        ctx["_nt1"].sts[station1]["name"],
        PDICT[c1] if c1 != "custom" else c1label,
    )
    subtitle = None
    if station2 is not None:
        if station1 == station2:
            title = "[%s] %s %s vs %s" % (
                station1,
                ctx["_nt1"].sts[station1]["name"],
                PDICT[c1] if c1 != "custom" else c1label,
                PDICT[c2] if c2 != "custom" else c2label,
            )
            label = f"{c1label} - {c2label}"
        else:
            title = "Daily Climatology Comparison"
            subtitle = "[%s] %s %s vs [%s] %s %s" % (
                station1,
                ctx["_nt1"].sts[station1]["name"],
                PDICT[ctx["c1"]],
                station2,
                ctx["_nt2"].sts[station2]["name"],
                PDICT[ctx["c2"]],
            )
            label = "%s (%s) - %s (%s)" % (station1, c1, station2, c2)
        ax0.plot(
            df.index.values,
            df["high2"],
            color="brown",
            label="High %s (%s)" % (station2, c2label),
        )
        ax0.plot(
            df.index.values,
            df["low2"],
            color="green",
            label="Low %s (%s)" % (station2, c2label),
        )
        delta = df["highdiff"]
        if ctx["s"] != "0":
            ax1.text(
                0.01,
                0.99,
                "** %s Day Smoother Applied" % (int(ctx["s"]),),
                transform=ax1.transAxes,
                va="top",
            )
            delta = delta.rolling(window=int(ctx["s"])).mean()
        ax1.plot(
            df.index.values,
            delta.values,
            color="r",
            label=f"High Diff {label}",
        )
        delta = df["lowdiff"]
        if ctx["s"] != "0":
            delta = delta.rolling(window=int(ctx["s"])).mean()
        ax1.plot(df.index.values, delta, color="b", label=f"Low Diff {label}")
        ax1.set_ylabel(r"Temp Difference $^\circ\mathrm{F}$")
        ax1.legend(ncol=1, loc="center", bbox_to_anchor=(0.5, -0.2))
        ax1.grid()
        ax1.xaxis.set_major_locator(mdates.MonthLocator(interval=1))
        ax1.xaxis.set_major_formatter(mdates.DateFormatter("%b"))

        # Compute monthly
        gdf = df.groupby(df.index.month).mean()
        ax2.text(
            0.01,
            1.0,
            "Monthly Average Difference",
            transform=ax2.transAxes,
            va="bottom",
        )
        ax2.bar(gdf.index.values - 0.2, gdf["highdiff"], width=0.4, color="r")
        ax2.bar(gdf.index.values + 0.2, gdf["lowdiff"], width=0.4, color="b")
        ax2.set_ylabel(r"Temp Difference $^\circ\mathrm{F}$")
        ax2.set_xticks(range(1, 13))
        ax2.set_xticklabels(calendar.month_abbr[1:])
        ax2.grid()

    fitbox(fig, title, 0.05, 0.94, 0.95, 0.99)
    if subtitle is not None:
        fitbox(fig, subtitle, 0.05, 0.95, 0.905, 0.935)
    ax0.legend(fontsize=10, ncol=2, loc="center", bbox_to_anchor=(0.5, -0.1))
    ax0.grid()
    ax0.xaxis.set_major_locator(mdates.MonthLocator(interval=1))
    ax0.xaxis.set_major_formatter(mdates.DateFormatter("%b"))

    return fig, df

if __name__ == "__main__":
    plotter(
        dict(
            network1="IACLIMATE",
            station1="IA0112",
            c1="custom",
            network2="IACLIMATE",
            station2="IA0112",
            c2="por",
            s="0",
            sy1=1981,
            ey1=2010,
            sy2=1991,
            ey2=2020,
        )
    )
<|endoftext|>


<commit_before><commit_msg>adjustment to finding the base url when a get of a changeset occurs first<commit_after><|endoftext|>


<commit_before># ----------------------------------------------------------------------------
# Copyright (c) 2015--, micronota development team.
#
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file COPYING.txt, distributed with this software.
# ----------------------------------------------------------------------------

from os.path import join
from tempfile import mktemp, mkdtemp
from unittest import TestCase, main
from sqlite3 import connect
import shutil

from micronota.bfillings.util import _get_data_dir
from micronota.db.uniref import (
    prepare_metadata, create_id_map, sort_uniref)

class UnirefTests(TestCase):
    def setUp(self):
        self.tmp_dir = mkdtemp()

        self.obs_db_fp = mktemp()
        self.exp_db_fp = _get_data_dir()('uniprokb.db')
        self.sprot = [2, _get_data_dir()('uniprot_sprot.xml.gz')]
        self.trembl = [2, _get_data_dir()('uniprot_trembl.xml.gz')]
        self.table_name = 'metadata'

        self.id_map_exp = _get_data_dir()('id_map.db')
        self.id_map_obs = mktemp()
        self.id_map = [4, _get_data_dir()('id_map.txt.gz')]
        self.id_map_table = 'id_map'

        self.uniref_fp = _get_data_dir()('uniref100.fasta.gz')
        self.uniref_res = [
            'uniref100_sprot_archaea.fasta',
            'uniref100_sprot_bacteria.fasta',
            'uniref100_sprot_viruses.fasta',
            'uniref100_sprot_other.fasta',
            'uniref100_trembl_archaea.fasta',
            'uniref100_trembl_bacteria.fasta',
            'uniref100_trembl_viruses.fasta',
            'uniref100_trembl_other.fasta',
            'uniref100__other.fasta']

    def test_prepare_metadata(self):
        n_sprot = prepare_metadata(self.sprot[1], self.obs_db_fp)
        self.assertEqual(n_sprot, self.sprot[0])
        n_trembl = prepare_metadata(self.trembl[1], self.obs_db_fp)
        self.assertEqual(n_trembl, self.trembl[0])

        with connect(self.obs_db_fp) as o, connect(self.exp_db_fp) as e:
            co = o.cursor()
            co.execute('SELECT * from %s' % self.table_name)
            ce = e.cursor()
            ce.execute('SELECT * from %s' % self.table_name)
            self.assertCountEqual(co.fetchall(), ce.fetchall())

    def test_create_id_map(self):
        n = create_id_map(self.id_map[1], self.id_map_obs)
        self.assertEqual(n, self.id_map[0])
        with connect(self.id_map_obs) as o, connect(self.id_map_exp) as e:
            co = o.cursor()
            co.execute('SELECT * from %s' % self.id_map_table)
            ce = e.cursor()
            ce.execute('SELECT * from %s' % self.id_map_table)
            self.assertCountEqual(co.fetchall(), ce.fetchall())

    def test_sort_uniref(self):
        sort_uniref(self.exp_db_fp, self.uniref_fp, self.tmp_dir)
        for fp in self.uniref_res:
            obs = join(self.tmp_dir, fp)
            exp = _get_data_dir()(fp)
            with open(obs) as o, open(exp) as e:
                self.assertEqual(o.read(), e.read())

    def tearDown(self):
        shutil.rmtree(self.tmp_dir)

if __name__ == '__main__':
    main()
<commit_msg>remove tmp files<commit_after># ----------------------------------------------------------------------------
# Copyright (c) 2015--, micronota development team.
#
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file COPYING.txt, distributed with this software.
# ----------------------------------------------------------------------------

from os.path import join
from os import remove
from tempfile import mktemp, mkdtemp
from unittest import TestCase, main
from sqlite3 import connect
import shutil

from micronota.bfillings.util import _get_data_dir
from micronota.db.uniref import (
    prepare_metadata, create_id_map, sort_uniref)

class UnirefTests(TestCase):
    def setUp(self):
        self.tmp_dir = mkdtemp()

        self.obs_db_fp = mktemp()
        self.exp_db_fp = _get_data_dir()('uniprokb.db')
        self.sprot = [2, _get_data_dir()('uniprot_sprot.xml.gz')]
        self.trembl = [2, _get_data_dir()('uniprot_trembl.xml.gz')]
        self.table_name = 'metadata'

        self.id_map_obs = mktemp()
        self.id_map_exp = _get_data_dir()('id_map.db')
        self.id_map = [4, _get_data_dir()('id_map.txt.gz')]
        self.id_map_table = 'id_map'

        self.uniref_fp = _get_data_dir()('uniref100.fasta.gz')
        self.uniref_res = [
            'uniref100_sprot_archaea.fasta',
            'uniref100_sprot_bacteria.fasta',
            'uniref100_sprot_viruses.fasta',
            'uniref100_sprot_other.fasta',
            'uniref100_trembl_archaea.fasta',
            'uniref100_trembl_bacteria.fasta',
            'uniref100_trembl_viruses.fasta',
            'uniref100_trembl_other.fasta',
            'uniref100__other.fasta']

    def test_prepare_metadata(self):
        n_sprot = prepare_metadata(self.sprot[1], self.obs_db_fp)
        self.assertEqual(n_sprot, self.sprot[0])
        n_trembl = prepare_metadata(self.trembl[1], self.obs_db_fp)
        self.assertEqual(n_trembl, self.trembl[0])

        with connect(self.obs_db_fp) as o, connect(self.exp_db_fp) as e:
            co = o.cursor()
            co.execute('SELECT * from %s' % self.table_name)
            ce = e.cursor()
            ce.execute('SELECT * from %s' % self.table_name)
            self.assertCountEqual(co.fetchall(), ce.fetchall())

    def test_create_id_map(self):
        n = create_id_map(self.id_map[1], self.id_map_obs)
        self.assertEqual(n, self.id_map[0])
        with connect(self.id_map_obs) as o, connect(self.id_map_exp) as e:
            co = o.cursor()
            co.execute('SELECT * from %s' % self.id_map_table)
            ce = e.cursor()
            ce.execute('SELECT * from %s' % self.id_map_table)
            self.assertCountEqual(co.fetchall(), ce.fetchall())

    def test_sort_uniref(self):
        sort_uniref(self.exp_db_fp, self.uniref_fp, self.tmp_dir)
        for fp in self.uniref_res:
            obs = join(self.tmp_dir, fp)
            exp = _get_data_dir()(fp)
            with open(obs) as o, open(exp) as e:
                self.assertEqual(o.read(), e.read())
            remove(obs)

    def tearDown(self):
        shutil.rmtree(self.tmp_dir)

if __name__ == '__main__':
    main()
<|endoftext|>