Esempio n. 1
0
def _buildImg(col, latex, fname, model):
    # add header/footer & convert to utf8
    latex = (model["latexPre"] + "\n" + latex + "\n" + model["latexPost"])
    latex = latex.encode("utf8")
    # it's only really secure if run in a jail, but these are the most common
    tmplatex = latex.replace("\\includegraphics", "")
    for bad in ("\\write18", "\\readline", "\\input", "\\include", "\\catcode",
                "\\openout", "\\write", "\\loop", "\\def", "\\shipout"):
        # don't mind if the sequence is only part of a command
        bad_re = "\\" + bad + "[^a-zA-Z]"
        if re.search(bad_re, tmplatex):
            return _("""\
For security reasons, '%s' is not allowed on cards. You can still use \
it by placing the command in a different package, and importing that \
package in the LaTeX header instead.""") % bad
    # write into a temp file
    log = open(namedtmp("latex_log.txt"), "w")
    texpath = namedtmp("tmp.tex")
    texfile = file(texpath, "w")
    texfile.write(latex)
    texfile.close()
    mdir = col.media.dir()
    oldcwd = os.getcwd()
    png = namedtmp("tmp.png")
    try:
        # generate png
        os.chdir(tmpdir())
        for latexCmd in latexCmds:
            if call(latexCmd, stdout=log, stderr=log):
                return _errMsg(latexCmd[0], texpath)
        # add to media
        shutil.copyfile(png, os.path.join(mdir, fname))
        return
    finally:
        os.chdir(oldcwd)
Esempio n. 2
0
def _buildImg(deck, latex, fname, model):
    # add header/footer
    latex = (model.conf["latexPre"] + "\n" +
             latex + "\n" +
             model.conf["latexPost"])
    # write into a temp file
    log = open(namedtmp("latex_log.txt"), "w")
    texfile = file(namedtmp("tmp.tex"), "w")
    texfile.write(latex)
    texfile.close()
    # make sure we have a valid mediaDir
    mdir = deck.media.dir(create=True)
    oldcwd = os.getcwd()
    png = namedtmp("tmp.png")
    try:
        # generate dvi
        os.chdir(tmpdir())
        if call(latexCmd + ["tmp.tex"], stdout=log, stderr=log):
            return _errMsg("latex")
        # and png
        if call(latexDviPngCmd + ["tmp.dvi", "-o", "tmp.png"],
                stdout=log, stderr=log):
            return _errMsg("dvipng")
        # add to media
        shutil.copy2(png,
                     os.path.join(mdir, fname))
        return
    finally:
        os.chdir(oldcwd)
Esempio n. 3
0
def _buildImg(col, latex, fname, model):
    # add header/footer & convert to utf8
    latex = (model["latexPre"] + "\n" +
             latex + "\n" +
             model["latexPost"])
    latex = latex.encode("utf8")
    # it's only really secure if run in a jail, but these are the most common
    for bad in ("write18", "\\readline", "\\input", "\\include", "\\catcode",
                "\\openout", "\\write", "\\loop", "\\def", "\\shipout"):
        assert bad not in latex
    # write into a temp file
    log = open(namedtmp("latex_log.txt"), "w")
    texfile = file(namedtmp("tmp.tex"), "w")
    texfile.write(latex)
    texfile.close()
    mdir = col.media.dir()
    oldcwd = os.getcwd()
    png = namedtmp("tmp.png")
    try:
        # generate dvi
        os.chdir(tmpdir())
        if call(latexCmd + ["tmp.tex"], stdout=log, stderr=log):
            return _errMsg("latex")
        # and png
        if call(latexDviPngCmd + ["tmp.dvi", "-o", "tmp.png"],
                stdout=log, stderr=log):
            return _errMsg("dvipng")
        # add to media
        shutil.copy2(png,
                     os.path.join(mdir, fname))
        return
    finally:
        os.chdir(oldcwd)
Esempio n. 4
0
def _buildImg(deck, latex, fname, model):
    # add header/footer
    latex = (model.conf["latexPre"] + "\n" + latex + "\n" +
             model.conf["latexPost"])
    # write into a temp file
    log = open(namedtmp("latex_log.txt"), "w")
    texfile = file(namedtmp("tmp.tex"), "w")
    texfile.write(latex)
    texfile.close()
    # make sure we have a valid mediaDir
    mdir = deck.media.dir(create=True)
    oldcwd = os.getcwd()
    png = namedtmp("tmp.png")
    try:
        # generate dvi
        os.chdir(tmpdir())
        if call(latexCmd + ["tmp.tex"], stdout=log, stderr=log):
            return _errMsg("latex")
        # and png
        if call(latexDviPngCmd + ["tmp.dvi", "-o", "tmp.png"],
                stdout=log,
                stderr=log):
            return _errMsg("dvipng")
        # add to media
        shutil.copy2(png, os.path.join(mdir, fname))
        return
    finally:
        os.chdir(oldcwd)
Esempio n. 5
0
def _buildImg(col, latex, fname, model):
    # add header/footer & convert to utf8
    latex = (model["latexPre"] + "\n" +
             latex + "\n" +
             model["latexPost"])
    latex = latex.encode("utf8")
    # it's only really secure if run in a jail, but these are the most common
    for bad in ("write18", "\\readline", "\\input", "\\include", "\\catcode",
                "\\openout", "\\write", "\\loop", "\\def", "\\shipout"):
        assert bad not in latex
    # write into a temp file
    log = open(namedtmp("latex_log.txt"), "w")
    texfile = file(namedtmp("tmp.tex"), "w")
    texfile.write(latex)
    texfile.close()
    mdir = col.media.dir()
    oldcwd = os.getcwd()
    png = namedtmp("tmp.png")
    try:
        # generate dvi
        os.chdir(tmpdir())
        if call(latexCmd + ["tmp.tex"], stdout=log, stderr=log):
            return _errMsg("latex")
        # and png
        if call(latexDviPngCmd + ["tmp.dvi", "-o", "tmp.png"],
                stdout=log, stderr=log):
            return _errMsg("dvipng")
        # add to media
        shutil.copyfile(png, os.path.join(mdir, fname))
        return
    finally:
        os.chdir(oldcwd)
Esempio n. 6
0
def _buildImg(col, latex, fname, model):
    # add header/footer & convert to utf8
    latex = (model["latexPre"] + "\n" +
             latex + "\n" +
             model["latexPost"])
    latex = latex.encode("utf8")
    # it's only really secure if run in a jail, but these are the most common
    tmplatex = latex.replace("\\includegraphics", "")
    for bad in ("write18", "\\readline", "\\input", "\\include", "\\catcode",
                "\\openout", "\\write", "\\loop", "\\def", "\\shipout"):
        if bad in tmplatex:
            return _("""\
For security reasons, '%s' is not allowed on cards. You can still use \
it by placing the command in a different package, and importing that \
package in the LaTeX header instead.""") % bad
    # write into a temp file
    log = open(namedtmp("latex_log.txt"), "w")
    texpath = namedtmp("tmp.tex")
    texfile = file(texpath, "w")
    texfile.write(latex)
    texfile.close()
    mdir = col.media.dir()
    oldcwd = os.getcwd()
    png = namedtmp("tmp.png")
    try:
        # generate png
        os.chdir(tmpdir())
        for latexCmd in latexCmds:
            if call(latexCmd, stdout=log, stderr=log):
                return _errMsg(latexCmd[0], texpath)
        # add to media
        shutil.copyfile(png, os.path.join(mdir, fname))
        return
    finally:
        os.chdir(oldcwd)
Esempio n. 7
0
def _save_latex_image(
    col: anki.collection.Collection,
    extracted: ExtractedLatex,
    header: str,
    footer: str,
    svg: bool,
) -> str | None:
    # add header/footer
    latex = f"{header}\n{extracted.latex_body}\n{footer}"
    # it's only really secure if run in a jail, but these are the most common
    tmplatex = latex.replace("\\includegraphics", "")
    for bad in (
            "\\write18",
            "\\readline",
            "\\input",
            "\\include",
            "\\catcode",
            "\\openout",
            "\\write",
            "\\loop",
            "\\def",
            "\\shipout",
    ):
        # don't mind if the sequence is only part of a command
        bad_re = f"\\{bad}[^a-zA-Z]"
        if re.search(bad_re, tmplatex):
            return col.tr.media_for_security_reasons_is_not(val=bad)

    # commands to use
    if svg:
        latex_cmds = svgCommands
        ext = "svg"
    else:
        latex_cmds = pngCommands
        ext = "png"

    # write into a temp file
    log = open(namedtmp("latex_log.txt"), "w", encoding="utf8")
    texpath = namedtmp("tmp.tex")
    texfile = open(texpath, "w", encoding="utf8")
    texfile.write(latex)
    texfile.close()
    oldcwd = os.getcwd()
    png_or_svg = namedtmp(f"tmp.{ext}")
    try:
        # generate png/svg
        os.chdir(tmpdir())
        for latex_cmd in latex_cmds:
            if call(latex_cmd, stdout=log, stderr=log):
                return _err_msg(col, latex_cmd[0], texpath)
        # add to media
        with open(png_or_svg, "rb") as file:
            data = file.read()
        col.media.write_data(extracted.filename, data)
        os.unlink(png_or_svg)
        return None
    finally:
        os.chdir(oldcwd)
        log.close()
Esempio n. 8
0
 def _start_recording(self) -> None:
     driver = self.mw.pm.recording_driver()
     if driver is RecordingDriver.PyAudio:
         self._recorder = PyAudioRecorder(self.mw, namedtmp("rec.wav"))
     elif driver is RecordingDriver.QtAudioInput:
         self._recorder = QtAudioInputRecorder(namedtmp("rec.wav"), self.mw,
                                               self._parent)
     else:
         assert_exhaustive(driver)
     self._recorder.start(self._start_timer)
Esempio n. 9
0
    def _start_recording(self) -> None:
        if qtmajor > 5:
            self._recorder = QtAudioInputRecorder(namedtmp("rec.wav"), self.mw,
                                                  self._parent)
        else:
            from .qt5 import QtAudioInputRecorder as Qt5Recorder

            self._recorder = Qt5Recorder(namedtmp("rec.wav"), self.mw,
                                         self._parent)
        self._recorder.start(self._start_timer)
Esempio n. 10
0
File: sound.py Progetto: chan18/anki
    def _start_recording(self) -> None:
        if qtmajor > 5:
            if macos_helper and platform.machine() == "arm64":
                self._recorder = NativeMacRecorder(namedtmp("rec.wav"), )
            else:
                self._recorder = QtAudioInputRecorder(namedtmp("rec.wav"),
                                                      self.mw, self._parent)
        else:
            from aqt.qt.qt5_audio import QtAudioInputRecorder as Qt5Recorder

            self._recorder = Qt5Recorder(namedtmp("rec.wav"), self.mw,
                                         self._parent)
        self._recorder.start(self._start_timer)
Esempio n. 11
0
    def _processImage(self,
                      mime: QMimeData,
                      extended: bool = False) -> Optional[str]:
        if not mime.hasImage():
            return None
        im = QImage(mime.imageData())
        uname = namedtmp("paste")
        if self.editor.mw.pm.profile.get("pastePNG", False):
            ext = ".png"
            im.save(uname + ext, None, 50)
        else:
            ext = ".jpg"
            im.save(uname + ext, None, 80)

        # invalid image?
        path = uname + ext
        if not os.path.exists(path):
            return None

        with open(path, "rb") as file:
            data = file.read()
        fname = self.editor._addPastedImage(data, ext)
        if fname:
            return self.editor.fnameToLink(fname)
        return None
Esempio n. 12
0
    def downloadRemote(self):
        raise Exception()
        mdir = self.deck.dir(create=True)
        refs = {}
        for (question, answer) in self.deck.db.all(
            "select question, answer from cards"):
            for txt in (question, answer):
                for f in mediaFiles(txt, remote=True):
                    refs[f] = True

        failed = []
        passed = []
        for c, link in enumerate(refs.keys()):
            try:
                path = namedtmp(os.path.basename(link))
                url = urllib2.urlopen(link)
                open(path, "wb").write(url.read())
                newpath = copyToMedia(self.deck, path)
                passed.append([link, newpath])
            except:
                failed.append(link)
            #self.deck.updateProgress(label=_("Download %d...") % c)
        for (url, name) in passed:
            self.deck.db.execute(
                "update fields set value = replace(value, :url, :name)",
                url=url, name=name)
            #self.deck.updateProgress(label=_("Updating references..."))
        #self.deck.updateProgress(label=_("Updating cards..."))
        # rebuild entire q/a cache
        for m in self.deck.models:
            self.deck.updateCardsFromModel(m, dirty=True)
        return (passed, failed)
Esempio n. 13
0
def getVerse(self):
    ''' Lookup verse from ESV web-service and set results in current note.
    self should be set to Editor
    '''
    #open ESV api connection and run query against reference
    esv = EsvSession()
    if not esv.query(self.note[REF_FIELD]):
        #query did not return successfully
        showInfo("No such passage: %s" % (self.note[REF_FIELD]))
        return

    #Retrive audio into a temporary folder
    path = namedtmp(os.path.basename(esv.esvMp3Link), True)
    urllib.urlretrieve(esv.esvMp3Link, path)

    #set note fields
    self.note[AUDIO_FIELD] = self._addMedia(path)
    self.note[TEXT_FIELD] = esv.esvText
    self.note[REF_FIELD] = esv.esvRef
    self.note[HINT_FIELD] = ",".join(esv.esvText.split()[:5]).replace(",", " ")

    #set 'y' for any additional card types that need to be generated
    for cardName in ADDTL_CARDS:
        self.note[cardName] = 'y'

    #reload note, makes things show up
    self.loadNote()
Esempio n. 14
0
    def _processImage(self,
                      mime: QMimeData,
                      extended: bool = False) -> str | None:
        if not mime.hasImage():
            return None
        im = QImage(mime.imageData())
        uname = namedtmp("paste")
        if self.editor.mw.col.get_config_bool(Config.Bool.PASTE_IMAGES_AS_PNG):
            ext = ".png"
            im.save(uname + ext, None, 50)
        else:
            ext = ".jpg"
            im.save(uname + ext, None, 80)

        # invalid image?
        path = uname + ext
        if not os.path.exists(path):
            return None

        with open(path, "rb") as file:
            data = file.read()
        fname = self.editor._addPastedImage(data, ext)
        if fname:
            return self.editor.fnameToLink(fname)
        return None
Esempio n. 15
0
def _buildImg(col, latex, fname, model):
    # add header/footer
    latex = (model["latexPre"] + "\n" +
             latex + "\n" +
             model["latexPost"])
    # it's only really secure if run in a jail, but these are the most common
    tmplatex = latex.replace("\\includegraphics", "")
    for bad in ("\\write18", "\\readline", "\\input", "\\include",
                "\\catcode", "\\openout", "\\write", "\\loop",
                "\\def", "\\shipout"):
        # don't mind if the sequence is only part of a command
        bad_re = "\\" + bad + "[^a-zA-Z]"
        if re.search(bad_re, tmplatex):
            return _("""\
For security reasons, '%s' is not allowed on cards. You can still use \
it by placing the command in a different package, and importing that \
package in the LaTeX header instead.""") % bad

    # commands to use?
    if model.get("latexsvg", False):
        latexCmds = svgCommands
        ext = "svg"
    else:
        latexCmds = pngCommands
        ext = "png"

    # write into a temp file
    log = open(namedtmp("latex_log.txt"), "w")
    texpath = namedtmp("tmp.tex")
    texfile = open(texpath, "w", encoding="utf8")
    texfile.write(latex)
    texfile.close()
    mdir = col.media.dir()
    oldcwd = os.getcwd()
    png = namedtmp("tmp.%s" % ext)
    try:
        # generate png
        os.chdir(tmpdir())
        for latexCmd in latexCmds:
            if call(latexCmd, stdout=log, stderr=log):
                return _errMsg(latexCmd[0], texpath)
        # add to media
        shutil.copyfile(png, os.path.join(mdir, fname))
        return
    finally:
        os.chdir(oldcwd)
        log.close()
Esempio n. 16
0
 def _processImage(self, mime):
     im = QImage(mime.imageData())
     name = namedtmp("paste-%d.png" % im.cacheKey())
     uname = unicode(name, sys.getfilesystemencoding())
     if im.hasAlphaChannel():
         im.save(uname)
     else:
         im.save(uname, None, 95)
     mime = QMimeData()
     mime.setHtml(self.editor._addMedia(uname))
     return mime
Esempio n. 17
0
    def _addDummyCollection(self, zip):
        path = namedtmp("dummy.anki2")
        c = Collection(path)
        n = c.newNote()
        n[_('Front')] = "This file requires a newer version of Anki."
        c.addNote(n)
        c.save()
        c.close()

        zip.write(path, "collection.anki2")
        os.unlink(path)
Esempio n. 18
0
def _errMsg(type):
    msg = (_("Error executing %s.") % type) + "<br>"
    try:
        log = open(namedtmp("latex_log.txt", rm=False)).read()
        if not log:
            raise Exception()
        msg += "<small><pre>" + cgi.escape(log) + "</pre></small>"
    except:
        msg += _("Have you installed latex and dvipng?")
        pass
    return msg
Esempio n. 19
0
    def _addDummyCollection(self, zip) -> None:
        path = namedtmp("dummy.anki2")
        c = Collection(path)
        n = c.newNote()
        n.fields[0] = "This file requires a newer version of Anki."
        c.addNote(n)
        c.save()
        c.close(downgrade=True)

        zip.write(path, "collection.anki2")
        os.unlink(path)
Esempio n. 20
0
def _errMsg(type):
    msg = (_("Error executing %s.") % type) + "<br>"
    try:
        log = open(namedtmp("latex_log.txt", rm=False)).read()
        if not log:
            raise Exception()
        msg += "<small><pre>" + cgi.escape(log) + "</pre></small>"
    except:
        msg += _("Have you installed latex and dvipng?")
        pass
    return msg
Esempio n. 21
0
 def _processImage(self, mime):
     im = QImage(mime.imageData())
     uname = namedtmp("paste-%d" % im.cacheKey())
     ext = ".jpg"
     im.save(uname+ext, None, 80)
     # invalid image?
     if not os.path.exists(uname+ext):
         return QMimeData()
     mime = QMimeData()
     mime.setHtml(self.editor._addMedia(uname+ext))
     return mime
Esempio n. 22
0
 def _processImage(self, mime):
     im = QImage(mime.imageData())
     name = namedtmp("paste-%d.png" % im.cacheKey())
     uname = unicode(name, sys.getfilesystemencoding())
     if im.hasAlphaChannel():
         im.save(uname)
     else:
         im.save(uname, None, 95)
     mime = QMimeData()
     mime.setHtml(self.editor._addMedia(uname))
     return mime
Esempio n. 23
0
    def _addDummyCollection(self, zip):
        path = namedtmp("dummy.anki2")
        c = Collection(path)
        n = c.newNote()
        n[_('Front')] = "This file requires a newer version of Anki."
        c.addNote(n)
        c.save()
        c.close()

        zip.write(path, "collection.anki2")
        os.unlink(path)
Esempio n. 24
0
File: latex.py Progetto: v-limc/anki
def _errMsg(col: anki.collection.Collection, type: str, texpath: str) -> Any:
    msg = f"{col.tr.media_error_executing(val=type)}<br>"
    msg += f"{col.tr.media_generated_file(val=texpath)}<br>"
    try:
        with open(namedtmp("latex_log.txt", rm=False)) as f:
            log = f.read()
        if not log:
            raise Exception()
        msg += f"<small><pre>{html.escape(log)}</pre></small>"
    except:
        msg += col.tr.media_have_you_installed_latex_and_dvipngdvisvgm()
    return msg
Esempio n. 25
0
File: latex.py Progetto: ZX1209/anki
def _errMsg(type: str, texpath: str) -> Any:
    msg = (_("Error executing %s.") % type) + "<br>"
    msg += (_("Generated file: %s") % texpath) + "<br>"
    try:
        with open(namedtmp("latex_log.txt", rm=False)) as f:
            log = f.read()
        if not log:
            raise Exception()
        msg += "<small><pre>" + html.escape(log) + "</pre></small>"
    except:
        msg += _("Have you installed latex and dvipng/dvisvgm?")
    return msg
Esempio n. 26
0
def _errMsg(type, texpath):
    msg = (_("Error executing %s.") % type) + "<br>"
    msg += (_("Generated file: %s") % texpath) + "<br>"
    try:
        with open(namedtmp("latex_log.txt", rm=False)) as f:
            log = f.read()
        if not log:
            raise Exception()
        msg += "<small><pre>" + html.escape(log) + "</pre></small>"
    except:
        msg += _("Have you installed latex and dvipng/dvisvgm?")
    return msg
Esempio n. 27
0
def _errMsg(col: anki.collection.Collection, type: str, texpath: str) -> Any:
    msg = col.tr(TR.MEDIA_ERROR_EXECUTING, val=type) + "<br>"
    msg += col.tr(TR.MEDIA_GENERATED_FILE, val=texpath) + "<br>"
    try:
        with open(namedtmp("latex_log.txt", rm=False)) as f:
            log = f.read()
        if not log:
            raise Exception()
        msg += "<small><pre>" + html.escape(log) + "</pre></small>"
    except:
        msg += col.tr(TR.MEDIA_HAVE_YOU_INSTALLED_LATEX_AND_DVIPNGDVISVGM)
    return msg
Esempio n. 28
0
def export_audio(output_folder, field_names, model_ids, cards_per_batch,
                 num_batches, num_loops, include_separator):
    "Save all audio files into one large audio file"
    audio_files = get_card_audio(cards_per_batch * num_batches, field_names,
                                 model_ids)

    # get files on machine
    audio_files = [
        os.path.join(mw.col.media.dir(), field) for field in audio_files
    ]

    for batch_id in range(num_batches):
        audio_files_in_batch = audio_files[batch_id *
                                           cards_per_batch:(batch_id + 1) *
                                           cards_per_batch]
        output_file = os.path.join(output_folder, "batch%d.mp3" % batch_id)
        audio_list_tmp_file = namedtmp("studyahead_audio_list.txt")

        separator_audio = os.path.join(mw.pm.addonFolder(), 'Studyahead_Audio',
                                       'file_separator.mp3')
        with codecs.open(audio_list_tmp_file, "w", "utf-8") as f:
            for i, audio_file in enumerate(audio_files_in_batch):
                for j in range(num_loops):
                    f.write("file '%s'\n" % os.path.relpath(
                        audio_file,
                        os.path.dirname(audio_list_tmp_file)).replace(
                            "\\", "/"))
                if i < len(audio_files_in_batch) and include_separator:
                    f.write("file '%s'\n" % os.path.relpath(
                        separator_audio,
                        os.path.dirname(audio_list_tmp_file)).replace(
                            "\\", "/"))

        output_command = [
            "ffmpeg", "-y", "-f", "concat", "-safe", "0", "-i",
            audio_list_tmp_file.replace("\\", "/"), "-vcodec", "copy",
            output_file
        ]
        with open(namedtmp("studyahead_audio_log.txt"), "w") as log:
            call(output_command, wait=True, stdout=log, stderr=log)
Esempio n. 29
0
 def browser(self):
     # dump to a temporary file
     path = namedtmp("report.png")
     p = self.form.web.page()
     oldsize = p.viewportSize()
     p.setViewportSize(p.mainFrame().contentsSize())
     image = QImage(p.viewportSize(), QImage.Format_ARGB32)
     painter = QPainter(image)
     p.mainFrame().render(painter)
     painter.end()
     image.save(path, "png")
     p.setViewportSize(oldsize)
     openFolder(path)
Esempio n. 30
0
File: stats.py Progetto: ChYi/ankiqt
 def browser(self):
     # dump to a temporary file
     path = namedtmp("report.png")
     p = self.form.web.page()
     oldsize = p.viewportSize()
     p.setViewportSize(p.mainFrame().contentsSize())
     image = QImage(p.viewportSize(), QImage.Format_ARGB32)
     painter = QPainter(image)
     p.mainFrame().render(painter)
     painter.end()
     image.save(path, "png")
     p.setViewportSize(oldsize)
     openFolder(path)
Esempio n. 31
0
def _buildImg(col, latex, fname, model):
    # add header/footer & convert to utf8
    latex = (model["latexPre"] + "\n" +
             latex + "\n" +
             model["latexPost"])
    latex = latex.encode("utf8")
    # it's only really secure if run in a jail, but these are the most common
    for bad in ("write18", "\\readline", "\\input", "\\include", "\\catcode",
                "\\openout", "\\write", "\\loop", "\\def", "\\shipout"):
        if bad in latex:
            return _("""\
For security reasons, '%s' is not allowed on cards. You can still use \
it by placing the command in a different package, and importing that \
package in the LaTeX header instead.""") % bad
    # write into a temp file
    log = open(namedtmp("latex_log.txt"), "w")
    texpath = namedtmp("tmp.tex")
    texfile = file(texpath, "w")
    texfile.write(latex)
    texfile.close()
    mdir = col.media.dir()
    oldcwd = os.getcwd()
    png = namedtmp("tmp.png")
    try:
        # generate dvi
        os.chdir(tmpdir())
        if call(latexCmd + ["tmp.tex"], stdout=log, stderr=log):
            return _errMsg("latex", texpath)
        # and png
        if call(latexDviPngCmd + ["tmp.dvi", "-o", "tmp.png"],
                stdout=log, stderr=log):
            return _errMsg("dvipng", texpath)
        # add to media
        shutil.copyfile(png, os.path.join(mdir, fname))
        return
    finally:
        os.chdir(oldcwd)
Esempio n. 32
0
 def _processImage(self, mime):
     im = QImage(mime.imageData())
     uname = namedtmp("paste-%d" % im.cacheKey())
     if self.editor.mw.pm.profile.get("pastePNG", False):
         ext = ".png"
         im.save(uname+ext, None, 50)
     else:
         ext = ".jpg"
         im.save(uname+ext, None, 80)
     # invalid image?
     if not os.path.exists(uname+ext):
         return QMimeData()
     mime = QMimeData()
     mime.setHtml(self.editor._addMedia(uname+ext))
     return mime
Esempio n. 33
0
 def _processImage(self, mime):
     im = QImage(mime.imageData())
     uname = namedtmp("paste-%d" % im.cacheKey())
     if self.editor.mw.pm.profile.get("pastePNG", False):
         ext = ".png"
         im.save(uname+ext, None, 50)
     else:
         ext = ".jpg"
         im.save(uname+ext, None, 80)
     # invalid image?
     if not os.path.exists(uname+ext):
         return QMimeData()
     mime = QMimeData()
     mime.setHtml(self.editor._addMedia(uname+ext))
     return mime
Esempio n. 34
0
    def _processImage(self, mime):
        im = QImage(mime.imageData())
        uname = namedtmp("paste")
        if self.editor.mw.pm.profile.get("pastePNG", False):
            ext = ".png"
            im.save(uname+ext, None, 50)
        else:
            ext = ".jpg"
            im.save(uname+ext, None, 80)

        # invalid image?
        path = uname+ext
        if not os.path.exists(path):
            return

        data = open(path, "rb").read()
        return self.editor._addPastedImage(data, ext)
Esempio n. 35
0
def SaveImageToMedia(imageData, editor):
    im = QImage.fromData(imageData)
    uname = namedtmp("pasteHTML-%d" % im.cacheKey())

    if editor.mw.pm.profile.get("pastePNG", False):
        ext = ".png"
        im.save(uname + ext, None, 50)
    else:
        ext = ".jpg"
        im.save(uname + ext, None, 80)

    # invalid image?
    if not os.path.exists(uname + ext):
        return ""

    fname = editor.mw.col.media.addFile(uname + ext)
    return fname
Esempio n. 36
0
def _errMsg(type, texpath):
    """An error message, in html, concerning LaTeX compilation.

    This message contains LaTeX outputs if it exists, or a message
    asking whether the program latex and dvipng/dvisvgm are installed.

    Keyword arguments
    type -- the (begin of the) executed command 
    texpath -- the path to the (temporary) file which was compiled
    """
    msg = (_("Error executing %s.") % type) + "<br>"
    msg += (_("Generated file: %s") % texpath) + "<br>"
    try:
        log = open(namedtmp("latex_log.txt", rm=False)).read()
        if not log:
            raise Exception()
        msg += "<small><pre>" + cgi.escape(log) + "</pre></small>"
    except:
        msg += _("Have you installed latex and dvipng/dvisvgm?")
        pass
    return msg
Esempio n. 37
0
    def _processImage(self, mime):
        if not mime.hasImage():
            return
        im = QImage(mime.imageData())
        uname = namedtmp("paste")
        if self.editor.mw.pm.profile.get("pastePNG", False):
            ext = ".png"
            im.save(uname+ext, None, 50)
        else:
            ext = ".jpg"
            im.save(uname+ext, None, 80)

        # invalid image?
        path = uname+ext
        if not os.path.exists(path):
            return

        data = open(path, "rb").read()
        fname = self.editor._addPastedImage(data, ext)
        if fname:
            return self.editor.fnameToLink(fname)
Esempio n. 38
0
def testWrap():
    from anki.schedv2 import Scheduler
    path = namedtmp("humpty_dumpty_tmp.anki2")
    dummy_col = Collection(path)
    v2_sched = Scheduler(dummy_col)

    try:
        run_test.reset()
        v2_sched.moveToV1()
        assert run_test.state == 1, "The addon HumptyDumpty was not patched correctly. Error code 1"

        run_test.reset()
        v2_sched.moveToV2()
        assert run_test.state == 2, "The addon HumptyDumpty was not patched correctly. Error code 2"

        run_test.setTestState(run_test.STATE_FINISHED)  #for pref menu
        # print("HumptyDumpty was patched correctly.")

    finally:
        dummy_col.close()
        del dummy_col
Esempio n. 39
0
    def _processImage(self, mime):
        im = QImage(mime.imageData())
        uname = namedtmp("paste")
        if self.editor.mw.pm.profile.get("pastePNG", False):
            ext = ".png"
            im.save(uname + ext, None, 50)
        else:
            ext = ".jpg"
            im.save(uname + ext, None, 80)

        # invalid image?
        path = uname + ext
        if not os.path.exists(path):
            return

        # hash and rename
        csum = checksum(open(path, "rb").read())
        newpath = "{}-{}{}".format(uname, csum, ext)
        os.rename(path, newpath)

        # add to media and return resulting html link
        return self.editor._addMedia(newpath)
Esempio n. 40
0
File: editor.py Progetto: hans/anki
    def _processImage(self, mime):
        im = QImage(mime.imageData())
        uname = namedtmp("paste")
        if self.editor.mw.pm.profile.get("pastePNG", False):
            ext = ".png"
            im.save(uname+ext, None, 50)
        else:
            ext = ".jpg"
            im.save(uname+ext, None, 80)

        # invalid image?
        path = uname+ext
        if not os.path.exists(path):
            return

        # hash and rename
        csum = checksum(open(path, "rb").read())
        newpath = "{}-{}{}".format(uname, csum, ext)
        os.rename(path, newpath)

        # add to media and return resulting html link
        return self.editor._addMedia(newpath)
Esempio n. 41
0
#Just a fix to an Anki add-on by unknown autor  -1125592690
#Usage:
#download the original (contains pictures) add-on and then replace file c:\Users\<your win login>\Documents\Anki\addons\showdogs.py with this one

from aqt import mw
from aqt.utils import showInfo
from aqt.qt import *
from anki.hooks import wrap

import os
import random
import logging
from anki.utils import  namedtmp

LOGFILE = namedtmp('showdogs.log')

logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(lineno)d: %(message)s', filename=LOGFILE, datefmt='%d.%m.%Y %H:%M:%S%p)')
logger = logging.getLogger()

mw.showdogs = {}
mw.showdogs['card_count'] = 0
mw.showdogs['interval'] = 9

def showDog():
    mw.showdogs['card_count'] = mw.showdogs['card_count'] + 1
    if mw.showdogs['card_count'] % mw.showdogs['interval'] != 0:
        return

    dialog = QDialog(mw)
    layout = QVBoxLayout(dialog)
    dialog.setLayout(layout)
Esempio n. 42
0
def _save_latex_image(
    col: anki.collection.Collection,
    extracted: ExtractedLatex,
    header: str,
    footer: str,
    svg: bool,
) -> Optional[str]:
    # add header/footer
    latex = header + "\n" + extracted.latex_body + "\n" + footer
    # it's only really secure if run in a jail, but these are the most common
    tmplatex = latex.replace("\\includegraphics", "")
    for bad in (
            "\\write18",
            "\\readline",
            "\\input",
            "\\include",
            "\\catcode",
            "\\openout",
            "\\write",
            "\\loop",
            "\\def",
            "\\shipout",
    ):
        # don't mind if the sequence is only part of a command
        bad_re = "\\" + bad + "[^a-zA-Z]"
        if re.search(bad_re, tmplatex):
            return (_("""\
For security reasons, '%s' is not allowed on cards. You can still use \
it by placing the command in a different package, and importing that \
package in the LaTeX header instead.""") % bad)

    # commands to use
    if svg:
        latexCmds = svgCommands
        ext = "svg"
    else:
        latexCmds = pngCommands
        ext = "png"

    # write into a temp file
    log = open(namedtmp("latex_log.txt"), "w")
    texpath = namedtmp("tmp.tex")
    texfile = open(texpath, "w", encoding="utf8")
    texfile.write(latex)
    texfile.close()
    oldcwd = os.getcwd()
    png_or_svg = namedtmp("tmp.%s" % ext)
    try:
        # generate png/svg
        os.chdir(tmpdir())
        for latexCmd in latexCmds:
            if call(latexCmd, stdout=log, stderr=log):
                return _errMsg(latexCmd[0], texpath)
        # add to media
        with open(png_or_svg, "rb") as file:
            data = file.read()
        col.media.write_data(extracted.filename, data)
        os.unlink(png_or_svg)
        return None
    finally:
        os.chdir(oldcwd)
        log.close()
Esempio n. 43
0
class EditorWebView(AnkiWebView):
    def __init__(self, parent, editor):
        AnkiWebView.__init__(self)
        self.editor = editor
        self.errtxt = _("An error occured while opening %s")
        self.strip = self.editor.mw.pm.profile['stripHTML']

    def keyPressEvent(self, evt):
        if evt.matches(QKeySequence.Paste):
            self.onPaste()
            return evt.accept()
        elif evt.matches(QKeySequence.Copy):
            self.onCopy()
            return evt.accept()
        elif evt.matches(QKeySequence.Cut):
            self.onCut()
            return evt.accept()
        QWebView.keyPressEvent(self, evt)

    def onCut(self):
        self.triggerPageAction(QWebPage.Cut)
        self._flagAnkiText()

    def onCopy(self):
        self.triggerPageAction(QWebPage.Copy)
        self._flagAnkiText()

    def onPaste(self):
        mime = self.prepareClip()
        self.triggerPageAction(QWebPage.Paste)
        self.restoreClip(mime)

    def mouseReleaseEvent(self, evt):
        if not isMac and not isWin and evt.button() == Qt.MidButton:
            # middle click on x11; munge the clipboard before standard
            # handling
            mime = self.prepareClip(mode=QClipboard.Selection)
            AnkiWebView.mouseReleaseEvent(self, evt)
            self.restoreClip(mime, mode=QClipboard.Selection)
        else:
            AnkiWebView.mouseReleaseEvent(self, evt)

    def focusInEvent(self, evt):
        window = False
        if evt.reason() in (Qt.ActiveWindowFocusReason, Qt.PopupFocusReason):
            # editor area got focus again; need to tell js not to adjust cursor
            self.eval("mouseDown++;")
            window = True
        AnkiWebView.focusInEvent(self, evt)
        if evt.reason() == Qt.TabFocusReason:
            self.eval("focusField(0);")
        elif evt.reason() == Qt.BacktabFocusReason:
            n = len(self.editor.note.fields) - 1
            self.eval("focusField(%d);" % n)
        elif window:
            self.eval("mouseDown--;")

    def dropEvent(self, evt):
        oldmime = evt.mimeData()
        # coming from this program?
        if evt.source():
            if oldmime.hasHtml():
                mime = QMimeData()
                mime.setHtml(_filterHTML(oldmime.html()))
            else:
                # old qt on linux won't give us html when dragging an image;
                # in that case just do the default action (which is to ignore
                # the drag)
                return AnkiWebView.dropEvent(self, evt)
        else:
            mime = self._processMime(oldmime)
        # create a new event with the new mime data and run it
        new = QDropEvent(evt.pos(), evt.possibleActions(), mime,
                         evt.mouseButtons(), evt.keyboardModifiers())
        evt.accept()
        QWebView.dropEvent(self, new)
        # tell the drop target to take focus so the drop contents are saved
        self.eval("dropTarget.focus();")
        self.setFocus()

    def prepareClip(self, mode=QClipboard.Clipboard):
        clip = self.editor.mw.app.clipboard()
        mime = clip.mimeData(mode=mode)
        if mime.hasHtml() and mime.html().startswith("<!--anki-->"):
            # pasting from another field, filter extraneous webkit formatting
            html = mime.html()[11:]
            html = _filterHTML(html)
            mime.setHtml(html)
            return
        self.saveClip(mode=mode)
        mime = self._processMime(mime)
        clip.setMimeData(mime, mode=mode)

    def restoreClip(self, mime, mode=QClipboard.Clipboard):
        if not mime:
            return
        clip = self.editor.mw.app.clipboard()
        clip.setMimeData(mime, mode=mode)

    def saveClip(self, mode):
        # we don't own the clipboard object, so we need to copy it
        mime = self.editor.mw.app.clipboard().mimeData(mode=mode)
        n = QMimeData()
        if mime.hasText():
            n.setText(mime.text())
        if mime.hasHtml():
            n.setHtml(mime.html())
        if mime.hasUrls():
            n.setUrls(mime.urls())
        if mime.hasImage():
            n.setImageData(mime.imageData())
        return n

    def _processMime(self, mime):
        # print "html=%s image=%s urls=%s txt=%s" % (
        #     mime.hasHtml(), mime.hasImage(), mime.hasUrls(), mime.hasText())
        # print "html", mime.html()
        # print "urls", mime.urls()
        # print "text", mime.text()
        if mime.hasImage():
            return self._processImage(mime)
        elif mime.hasUrls():
            return self._processUrls(mime)
        elif mime.hasText() and (self.strip or not mime.hasHtml()):
            return self._processText(mime)
        elif mime.hasHtml():
            return self._processHtml(mime)
        else:
            # nothing
            return QMimeData()

    def _processUrls(self, mime):
        url = mime.urls()[0].toString()
        link = self._localizedMediaLink(url)
        mime = QMimeData()
        mime.setHtml(link)
        return mime

    def _localizedMediaLink(self, url):
        l = url.lower()
        for suffix in pics + audio:
            if l.endswith(suffix):
                return self._retrieveURL(url)
        # not a supported type; return link verbatim
        return url

    def _processText(self, mime):
        txt = unicode(mime.text())
        l = txt.lower()
        html = None
        # if the user is pasting an image or sound link, convert it to local
        if l.startswith("http://") or l.startswith("https://") or l.startswith(
                "file://"):
            txt = txt.split("\r\n")[0]
            html = self._localizedMediaLink(txt)
            if html == txt:
                # wasn't of a supported media type; don't change
                html = None
        new = QMimeData()
        if html:
            new.setHtml(html)
        else:
            new.setText(mime.text())
        return new

    def _processHtml(self, mime):
        html = mime.html()
        if self.strip:
            html = stripHTML(html)
        else:
            html = _filterHTML(html)
        mime = QMimeData()
        mime.setHtml(html)
        return mime

    def _processImage(self, mime):
        im = QImage(mime.imageData())
        uname = namedtmp("paste-%d" % im.cacheKey())
        if self.editor.mw.pm.profile.get("pastePNG", False):
            ext = ".png"
            im.save(uname + ext, None, 50)
        else:
            ext = ".jpg"
            im.save(uname + ext, None, 80)
        # invalid image?
        if not os.path.exists(uname + ext):
            return QMimeData()
        mime = QMimeData()
        mime.setHtml(self.editor._addMedia(uname + ext))
        return mime

    def _retrieveURL(self, url):
        # is it media?
        ext = url.split(".")[-1].lower()
        if ext not in pics and ext not in audio:
            return
        # fetch it into a temporary folder
        self.editor.mw.progress.start(immediate=True)
        try:
            req = urllib2.Request(
                url, None, {'User-Agent': 'Mozilla/5.0 (compatible; Anki)'})
            filecontents = urllib2.urlopen(req).read()
        except urllib2.URLError, e:
            showWarning(self.errtxt % e)
            return
        path = namedtmp(os.path.basename(url))
        file = open(path, "wb")
        file.write(filecontents)
        file.close()
        self.editor.mw.progress.finish()
        return self.editor._addMedia(path)
Esempio n. 44
0
File: editor.py Progetto: empec/anki
        # is it media?
        ext = url.split(".")[-1].lower()
        if ext not in pics and ext not in audio:
            return
        # fetch it into a temporary folder
        self.editor.mw.progress.start(immediate=True)
        try:
            req = urllib2.Request(url, None, {
                'User-Agent': 'Mozilla/5.0 (compatible; Anki)'})
            filecontents = urllib2.urlopen(req).read()
        except urllib2.URLError, e:
            showWarning(self.errtxt % e)
            return
        finally:
            self.editor.mw.progress.finish()
        path = namedtmp(os.path.basename(urllib2.unquote(url)))
        file = open(path, "wb")
        file.write(filecontents)
        file.close()
        return self.editor._addMedia(path)

    def _flagAnkiText(self):
        # add a comment in the clipboard html so we can tell text is copied
        # from us and doesn't need to be stripped
        clip = self.editor.mw.app.clipboard()
        mime = clip.mimeData()
        if not mime.hasHtml():
            return
        html = mime.html()
        mime.setHtml("<!--anki-->" + mime.html())
Esempio n. 45
0
        # fetch it into a temporary folder
        self.editor.mw.progress.start(immediate=True,
                                      parent=self.editor.parentWindow)
        try:
            req = urllib2.Request(
                url, None, {'User-Agent': 'Mozilla/5.0 (compatible; Anki)'})
            filecontents = urllib2.urlopen(req).read()
        except urllib2.URLError, e:
            showWarning(self.errtxt % e)
            return
        finally:
            self.editor.mw.progress.finish()
        path = unicode(urllib2.unquote(url.encode("utf8")), "utf8")
        for badChar in "#%\"":
            path = path.replace(badChar, "")
        path = namedtmp(os.path.basename(path))
        file = open(path, "wb")
        file.write(filecontents)
        file.close()
        return self.editor._addMedia(path)

    def _flagAnkiText(self):
        # add a comment in the clipboard html so we can tell text is copied
        # from us and doesn't need to be stripped
        clip = self.editor.mw.app.clipboard()
        mime = clip.mimeData()
        if not mime.hasHtml():
            return
        html = mime.html()
        mime.setHtml("<!--anki-->" + mime.html())
Esempio n. 46
0
class EditorWebView(AnkiWebView):
    def __init__(self, parent, editor):
        AnkiWebView.__init__(self, parent)
        self.editor = editor
        self.errtxt = _("An error occured while opening %s")
        self.strip = self.editor.mw.config['stripHTML']

    def keyPressEvent(self, evt):
        self._curKey = True
        self.origClip = None
        shiftPaste = (evt.modifiers()
                      == (Qt.ShiftModifier | Qt.ControlModifier)
                      and evt.key() == Qt.Key_V)
        if evt.matches(QKeySequence.Paste) or shiftPaste:
            self.prepareClip(shiftPaste)
        if shiftPaste:
            self.triggerPageAction(QWebPage.Paste)
        QWebView.keyPressEvent(self, evt)
        if self.origClip:
            self.restoreClip()

    def contextMenuEvent(self, evt):
        # adjust in case the user is going to paste
        self.prepareClip()
        QWebView.contextMenuEvent(self, evt)
        self.restoreClip()

    def dropEvent(self, evt):
        oldmime = evt.mimeData()
        # coming from this program?
        if evt.source():
            # if they're copying just an image, we need to turn it into html
            # again
            txt = ""
            mime = QMimeData()
            if not oldmime.hasHtml() and oldmime.hasUrls():
                # qt gives it to us twice
                txt += '<img src="%s">' % os.path.basename(
                    oldmime.urls()[0].toString())
                mime.setHtml(txt)
            else:
                mime.setHtml(oldmime.html())
        else:
            mime = self._processMime(oldmime)
        # create a new event with the new mime data
        new = QDropEvent(evt.pos(), evt.possibleActions(), mime,
                         evt.mouseButtons(), evt.keyboardModifiers())
        evt.accept()
        QWebView.dropEvent(self, new)

    def prepareClip(self, keep=False):
        clip = self.editor.mw.app.clipboard()
        mime = clip.mimeData()
        self.saveClip()
        if keep:
            new = QMimeData()
            if mime.hasHtml():
                new.setHtml(mime.html())
            else:
                new.setText(mime.text())
            mime = new
        else:
            mime = self._processMime(mime)
        clip.setMimeData(mime)

    def restoreClip(self):
        clip = self.editor.mw.app.clipboard()
        clip.setMimeData(self.origClip)

    def saveClip(self):
        # we don't own the clipboard object, so we need to copy it
        mime = self.editor.mw.app.clipboard().mimeData()
        n = QMimeData()
        if mime.hasText():
            n.setText(mime.text())
        if mime.hasHtml():
            n.setHtml(mime.html())
        if mime.hasUrls():
            n.setUrls(mime.urls())
        if mime.hasImage():
            n.setImageData(mime.imageData())
        self.origClip = n

    def _processMime(self, mime):
        # print "html=%s image=%s urls=%s txt=%s" % (
        #     mime.hasHtml(), mime.hasImage(), mime.hasUrls(), mime.hasText())
        # print "html", mime.html()
        # print "urls", mime.urls()
        # print "text", mime.text()
        if mime.hasUrls():
            return self._processUrls(mime)
        elif mime.hasImage():
            return self._processImage(mime)
        elif mime.hasText() and (self.strip or not mime.hasHtml()):
            return self._processText(mime)
        elif mime.hasHtml():
            return self._processHtml(mime)
        else:
            # nothing
            return QMimeData()

    def _processUrls(self, mime):
        links = []
        for url in mime.urls():
            url = url.toString()
            link = self._retrieveURL(url)
            if link:
                links.append(link)
        mime = QMimeData()
        mime.setHtml("".join(links))
        return mime

    def _processText(self, mime):
        txt = unicode(mime.text())
        l = txt.lower()
        html = None
        # firefox on linux just gives us a url for an image
        if "\n" in l and (l.startswith("http://") or l.startswith("file://")):
            txt = txt.split("\r\n")[0]
            html = self._retrieveURL(txt)
        new = QMimeData()
        if html:
            new.setHtml(html)
        else:
            new.setText(mime.text())
        return new

    def _processHtml(self, mime):
        html = mime.html()
        if self.strip:
            html = stripHTML(html)
        mime = QMimeData()
        mime.setHtml(html)
        return mime

    def _processImage(self, mime):
        im = QImage(mime.imageData())
        name = namedtmp("paste-%d.png" % im.cacheKey())
        uname = unicode(name, sys.getfilesystemencoding())
        if im.hasAlphaChannel():
            im.save(uname)
        else:
            im.save(uname, None, 95)
        mime = QMimeData()
        mime.setHtml(self.editor._addMedia(uname))
        return mime

    def _retrieveURL(self, url):
        # is it media?
        ext = name.split(".")[-1].lower()
        if ext not in pics and ext not in audio:
            return
        # fetch it into a temporary folder
        try:
            req = urllib2.Request(
                url, None, {'User-Agent': 'Mozilla/5.0 (compatible; Anki)'})
            filecontents = urllib2.urlopen(req).read()
        except urllib2.URLError, e:
            showWarning(self.errtxt % e)
            return
        path = namedtmp(os.path.basename(url))
        file = open(path, "wb")
        file.write(filecontents)
        file.close()
        return self.editor._addMedia(path)
Esempio n. 47
0
        # fetch it into a temporary folder
        self.editor.mw.progress.start(
            immediate=True, parent=self.editor.parentWindow)
        try:
            req = urllib2.Request(url, None, {
                'User-Agent': 'Mozilla/5.0 (compatible; Anki)'})
            filecontents = urllib2.urlopen(req).read()
        except urllib2.URLError, e:
            showWarning(self.errtxt % e)
            return
        finally:
            self.editor.mw.progress.finish()
        path = unicode(urllib2.unquote(url.encode("utf8")), "utf8")
        path = path.replace("#", "")
        path = path.replace("%", "")
        path = namedtmp(os.path.basename(path))
        file = open(path, "wb")
        file.write(filecontents)
        file.close()
        return self.editor._addMedia(path)

    def _flagAnkiText(self):
        # add a comment in the clipboard html so we can tell text is copied
        # from us and doesn't need to be stripped
        clip = self.editor.mw.app.clipboard()
        mime = clip.mimeData()
        if not mime.hasHtml():
            return
        html = mime.html()
        mime.setHtml("<!--anki-->" + mime.html())
Esempio n. 48
0
#Just a fix to an Anki add-on by unknown autor  -1125592690
#Usage:
#download the original (contains pictures) add-on and then replace file c:\Users\<your win login>\Documents\Anki\addons\showdogs.py with this one

from aqt import mw
from aqt.utils import showInfo
from aqt.qt import *
from anki.hooks import wrap

import os
import random
import logging
from anki.utils import namedtmp

LOGFILE = namedtmp('showdogs.log')

logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s %(levelname)s %(lineno)d: %(message)s',
                    filename=LOGFILE,
                    datefmt='%d.%m.%Y %H:%M:%S%p)')
logger = logging.getLogger()

mw.showdogs = {}
mw.showdogs['card_count'] = 0
mw.showdogs['interval'] = 9


def showDog():
    mw.showdogs['card_count'] = mw.showdogs['card_count'] + 1
    if mw.showdogs['card_count'] % mw.showdogs['interval'] != 0:
        return