This module freezes the current installation of OpenTeacher with PyInstaller into an executable. For more on PyInstaller, see:
Type: | pyinstallerInterface |
Uses (at least one of): | |
Requires (at least one of): |
SourceSaverModule >
MetadataModule > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | #! /usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright 2012-2013, Marten de Vries
#
# This file is part of OpenTeacher.
#
# OpenTeacher is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# OpenTeacher is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with OpenTeacher. If not, see <http://www.gnu.org/licenses/>.
import platform
import tempfile
import atexit
import os
import shutil
import subprocess
class PyinstallerInterfaceModule:
"""This module freezes the current installation of OpenTeacher with
PyInstaller into an executable. For more on PyInstaller, see:
http://www.pyinstaller.org/
"""
def __init__(self, moduleManager, *args, **kwargs):
super().__init__(*args, **kwargs)
self._mm = moduleManager
self.type = "pyinstallerInterface"
self.requires = (
self._mm.mods(type="sourceSaver"),
self._mm.mods(type="metadata")
)
self._tempPaths = set()
atexit.register(self._cleanup)
@property
def _saveSource(self):
return self._modules.default("active", type="sourceSaver").saveSource
def build(self):
path = tempfile.mkdtemp()
self._tempPaths.add(path)
for iconName in ["icon.ico", "icon.icns"]:
shutil.copy(
self._mm.resourcePath(iconName),
os.path.join(path, iconName)
)
with open(os.path.join(path, "starter.py"), "w") as f:
f.write("""
import sys
import os
if not sys.frozen:
#import OT dependencies, so PyInstaller adds them to the build.
#not required at runtime though, so that's why the if statement
#above is here.
from xml.etree import ElementTree
from PyQt5 import QtCore, QtGui, QtWebEngine, QtWebEngineWidgets, QtNetwork, QtMultimedia, QtMultimediaWidgets, QtQml, QtOpenGL
import argparse
import atexit
import bisect
import chardet
import code
import collections
import contextlib
import csv
import docutils
import enchant
import html.parser
import Image
import itertools
import json
import latexcodec
import logging
import mimetypes
import platform
import runpy
import shutil
import sqlite3
import subprocess
import traceback
import urllib
import urllib.request
import urllib.error
import urwid
import uuid
import weakref
import webbrowser
import xml.dom.minidom
import zipfile
#windows only, so wrapped.
try:
import win32com
except ImportError:
pass
#filter the -psn argument passed by mac os x out.
sys.argv = [a for a in sys.argv if not a.startswith("-psn")]
sys.path.insert(0, os.path.join(os.path.dirname(sys.executable), 'source'))
sys.exit(__import__('openteacher').ModuleApplication().run())
""")
if platform.system() == "Darwin":
icon = "icon.icns"
else:
icon = "icon.ico"
#save so they can be restored later
cwd = os.getcwd()
os.chdir(path)
#run pyinstaller
subprocess.check_call([
"pyinstaller",
"--windowed",
"--name", self._metadata["name"].lower(),
"--icon", icon,
"starter.py",
])
#restore environment
os.chdir(cwd)
if platform.system() == "Darwin":
resultPath = os.path.join(path, "dist", self._metadata["name"] + ".app")
else:
resultPath = os.path.join(path, "dist", self._metadata["name"].lower())
#save source
sourcePath = self._saveSource()
#copy the source in
if platform.system() == "Darwin":
shutil.copytree(sourcePath, os.path.join(resultPath, "Contents/MacOS/source"))
else:
shutil.copytree(sourcePath, os.path.join(resultPath, "source"))
# self._copyInTesseractPortableExecutables(resultPath)# FIXME
return resultPath
def _copyInTesseractPortableExecutables(self, resultPath):
if platform.system() != "Windows":
return
#copy in the portable tesseract executables.
tesseractDir = os.path.join(os.getcwd(), "tesseract-portable")
for fileOrDir in os.listdir(tesseractDir):
source = os.path.join(tesseractDir, fileOrDir)
result = os.path.join(resultPath, fileOrDir)
copy = shutil.copy if os.path.isfile(source) else shutil.copytree
copy(source, result)
def _cleanup(self):
for path in self._tempPaths:
shutil.rmtree(path)
def enable(self):
self._modules = set(self._mm.mods(type="modules")).pop()
self._metadata = self._modules.default("active", type="metadata").metadata
self.active = True
def disable(self):
self.active = False
del self._modules
del self._metadata
def init(moduleManager):
return PyinstallerInterfaceModule(moduleManager)
|