FAQ | This is a LIVE service | Changelog

Skip to content
Snippets Groups Projects
thindown.py 13.2 KiB
Newer Older
#!/usr/bin/env python
#  (works on either Python 2 or Python 3)

# program to "thin down" the gradint .py for low memory environments
# by taking out some of the code that's unused on that platform

# This file is part of the source code of Gradint
# (c) Silas S. Brown.
Silas S. Brown's avatar
Silas S. Brown committed
#    This program 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.
#    This program 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.
Silas S. Brown's avatar
Silas S. Brown committed

Silas S. Brown's avatar
Silas S. Brown committed
import sys, re
Silas S. Brown's avatar
Silas S. Brown committed

Silas S. Brown's avatar
Silas S. Brown committed
tk_only = [ # we want these on WinCE but not S60:
# note: comments are stripped BEFORE checking against this list
Silas S. Brown's avatar
Silas S. Brown committed
"def words_exist():",
Silas S. Brown's avatar
Silas S. Brown committed
"def reviseCount(num):", # used only in Tk for now
Silas S. Brown's avatar
Silas S. Brown committed
"if mp3web:",
Silas S. Brown's avatar
Silas S. Brown committed
"class InputSourceManager(object):",
Silas S. Brown's avatar
Silas S. Brown committed
"class InputSource(object):",
"class MicInput(InputSource):",
"class PlayerInput(InputSource):",
Silas S. Brown's avatar
Silas S. Brown committed
"class ButtonScrollingMixin(object):",
"class RecorderControls(ButtonScrollingMixin):",
Silas S. Brown's avatar
Silas S. Brown committed
"def doRecWords():",
"if app:","elif app:",
"def addStatus(widget,status,mouseOnly=0):",
"def addButton(parent,text,command,packing=None,status=None):",
"def addLabel(row,label):",
"def CXVMenu(e):",
"def selectAll(e):",
"def selectAllButNumber(e):",
"def addTextBox(row,wide=0):",
Silas S. Brown's avatar
Silas S. Brown committed
"def addLabelledBox(row,wide=0,status=None):",
Silas S. Brown's avatar
Silas S. Brown committed
"def addRow(parent,wide=0):",
"def addRightRow(widerow):",
"def make_output_row(parent):",
"def select_userNumber(N,updateGUI=1):",
Silas S. Brown's avatar
Silas S. Brown committed
"def select_userNumber2(N):",
Silas S. Brown's avatar
Silas S. Brown committed
"def updateUserRow(fromMainMenu=0):","def get_userNames():",
"def set_userName(N,unicodeName):",
"def wrapped_set_userName(N,unicodeName):",
Silas S. Brown's avatar
Silas S. Brown committed
"def renameUser(i,radioButton,parent,cancel=0):",
"def deleteUser(i):",
Silas S. Brown's avatar
Silas S. Brown committed
"def addUserToFname(fname,userNo):",
Silas S. Brown's avatar
Silas S. Brown committed
"def setupScrollbar(parent,rowNo):",
Silas S. Brown's avatar
Silas S. Brown committed
"def focusButton(button):",
Silas S. Brown's avatar
Silas S. Brown committed
"def bindUpDown(o,alsoLeftRight=False):",
Silas S. Brown's avatar
Silas S. Brown committed
"class ExtraButton(object):",
"def make_extra_buttons_waiting_list():",
"def startTk():",
Silas S. Brown's avatar
Silas S. Brown committed
# "def guiVocabList(parsedVocab):", # now actually used on S60
Silas S. Brown's avatar
Silas S. Brown committed
"def synchronizeListbox(listbox,masterList):",
"if useTK:",
Silas S. Brown's avatar
Silas S. Brown committed
"if useTK and not tkSnack:",
Silas S. Brown's avatar
Silas S. Brown committed
"def openDirectory(dir,inGuiThread=0):",
Silas S. Brown's avatar
Silas S. Brown committed
"def gui_event_loop():",
Silas S. Brown's avatar
Silas S. Brown committed
"def makeButton(parent,text,command):",
Silas S. Brown's avatar
Silas S. Brown committed
"def vocabLinesWithLangs():",
"if Tk_might_display_wrong_hanzi:",
"def setup_samplesDir_ifNec(d=0):",
"def filename2unicode(f):",
"def unicode2filename(u):",
Silas S. Brown's avatar
Silas S. Brown committed
]

Silas S. Brown's avatar
Silas S. Brown committed
not_S60_or_android = [ # but may still need on winCE
Silas S. Brown's avatar
Silas S. Brown committed
"if winsound:",
"if winsound or mingw32:",
Silas S. Brown's avatar
Silas S. Brown committed
"class ESpeakSynth(Synth):","def espeak_volume_ok():",
'if winCEsound or ((winsound or mingw32) and not os.sep in tmpPrefix and not tmpPrefix.startswith("C:")):',
'def got_program(prog):', # as no non-winsound/unix
'if useTK and runInBackground and not (winsound or mingw32) and hasattr(os,"fork") and not "gradint_no_fork" in os.environ:',
'def maybe_warn_mp3():',
'elif (cygwin or ((winsound or mingw32) and winsound_also)) and os.sep in file:',
'elif (winsound and not (self.length>10 and wavPlayer)) or winCEsound:',
"elif wavPlayer.find('sndrec32')>=0:",
'elif wavPlayer:', # it'll take appuifw/android 1st
'if winsound or mingw32 or cygwin:',
'elif winsound or mingw32 or cygwin:',
'for s in synth_priorities.split():', # Ekho/eSpeak/MacOS/SAPI not available on S60/Android (well, not that we can yet call into)
'def import_recordings(destDir=None):', # TODO: document in advanced.txt that this option is non-functional on S60/Android?  (code WOULD work if suitably configured, but unlikely to be used and we need to save size)
"elif msvcrt:",
Silas S. Brown's avatar
Silas S. Brown committed
]

Silas S. Brown's avatar
Silas S. Brown committed
not_android = [
"if not app and not app==False and not appuifw and not android:",
"elif not android:",
"def fileExists(f):", # assume we got os.path
"def fileExists_stat(f):",
"def isDirectory(directory):",
"for p in [progressFile,progressFileBackup,pickledProgressFile]:", # this coherence check is not likely to be a problem on Android, and we could do with saving the space
Silas S. Brown's avatar
Silas S. Brown committed
"if need_say_where_put_progress:", # ditto
'def check_for_interrupts():','if emulated_interruptMain:','if emulated_interruptMain or winCEsound:','def handleInterrupt():', # no current way to do this on Android (unlike S60/WinCE)
r"if not '\xc4'.lower()=='\xc4':", # this workaround is not needed on Android
r"if not fileExists(configFiles[0]) and sys.argv and (os.sep in sys.argv[0] or (os.sep=='\\' and '/' in sys.argv[0])):", # that logic not likely to work on Android (but we do need the rest of that block)
"def guiVocabList(parsedVocab):", # not yet available on Android (unlike S60, TODO?)
]

riscos_only = [
Silas S. Brown's avatar
Silas S. Brown committed
"if riscos_sound:",
Silas S. Brown's avatar
Silas S. Brown committed
"elif riscos_sound:",
'if riscos_sound and hex(int(time.time())).find("0xFFFFFFFF")>=0 and not outputFile:',
"class OldRiscosSynth(Synth):",
Silas S. Brown's avatar
Silas S. Brown committed
'if not extsep==".":', # RISC OS
Silas S. Brown's avatar
Silas S. Brown committed
]

mac_only = [
Silas S. Brown's avatar
Silas S. Brown committed
'if macsound and __name__=="__main__":',
Silas S. Brown's avatar
Silas S. Brown committed
'if macsound and "_" in os.environ:',
Silas S. Brown's avatar
Silas S. Brown committed
"if macsound:","elif macsound:",
Silas S. Brown's avatar
Silas S. Brown committed
'if hasattr(app,"isBigPrint") and macsound:',
'elif macsound and got_program("afconvert"):',
Silas S. Brown's avatar
Silas S. Brown committed
]

desktop_only = [ # Don't want these on either WinCE or S60:
Silas S. Brown's avatar
Silas S. Brown committed
'if hasattr(app,"isBigPrint") and winsound:',
Silas S. Brown's avatar
Silas S. Brown committed
"if unix:","elif unix:",
Silas S. Brown's avatar
Silas S. Brown committed
"def disable_lid(restore):",
'if unix and isDirectory("/dev/snd") and got_program("arecord"):',
Silas S. Brown's avatar
Silas S. Brown committed
"if unix and (';' in cmd or '<' in cmd):",
'elif wavPlayer=="sox":',
'elif wavPlayer=="aplay" and ((not fileType=="mp3") or madplay_path or gotSox):',
Silas S. Brown's avatar
Silas S. Brown committed
"def simplified_header(fname):",
Silas S. Brown's avatar
Silas S. Brown committed
"def win2cygwin(path):","elif cygwin:",
Silas S. Brown's avatar
Silas S. Brown committed
"if paranoid_file_management:",
"elif unix and not macsound:",
Silas S. Brown's avatar
Silas S. Brown committed
"elif unix and hasattr(os,\"popen\"):",
Silas S. Brown's avatar
Silas S. Brown committed
"def wavToMp3(directory):",
"def makeMp3Zips(baseDir,outDir,zipNo=0,direc=None):",
Silas S. Brown's avatar
Silas S. Brown committed
"def check_for_slacking():",
Silas S. Brown's avatar
Silas S. Brown committed
"def checkAge(fname,message):",
"def downloadLAME():",
"def decode_mp3(file):",
"class Mp3FileCache(object):",
"class OSXSynth_Say(Synth):",
Silas S. Brown's avatar
Silas S. Brown committed
"def aiff2wav(fname):", # (used only on Mac)
Silas S. Brown's avatar
Silas S. Brown committed
"class OSXSynth_OSAScript(Synth):",
"class PttsSynth(Synth):",
"def sapi_sox_bug_workaround(wavdata):",
"class FliteSynth(Synth):",
"def espeak_stdout_works():", # called only if unix
# (keep ESpeakSynth for WinCE)
"class EkhoSynth(Synth):",
"class FestivalSynth(Synth):",
"class GeneralSynth(Synth):", # (needs os.system, so not S60/WinCE)
"class GeneralFileSynth(Synth):", # (ditto)
"class ShellEvent(Event):",
# And the following are desktop only because they need sox:
"if gotSox and unix:",
Silas S. Brown's avatar
Silas S. Brown committed
"class SoundCollector(object):","if soundCollector:",
Silas S. Brown's avatar
Silas S. Brown committed
"def oggenc():",
Silas S. Brown's avatar
Silas S. Brown committed
"def outfile_writeBytes(o,bytes):",
"def outfile_close(o):",
"def outfile_writeFile(o,handle,filename):",
Silas S. Brown's avatar
Silas S. Brown committed
"class ShSoundCollector(object):",
Silas S. Brown's avatar
Silas S. Brown committed
"def outfile_write_error():",
"def lame_quiet():",
"def beepCmd(soxParams,fname):",
"def collector_time():",
"def collector_sleep(s):",
Silas S. Brown's avatar
Silas S. Brown committed
"def dd_command(offset,length):",
"def lame_endian_parameters():",
"if outputFile:",
"def setSoundCollector(sc):",
"def getAmplify(directory):",
"def doAmplify(directory,fileList,factor):",
Silas S. Brown's avatar
Silas S. Brown committed
"def gui_outputTo_end(openDir=True):",
Silas S. Brown's avatar
Silas S. Brown committed
"def gui_outputTo_start():",
Silas S. Brown's avatar
Silas S. Brown committed
"def warn_sox_decode():",
Silas S. Brown's avatar
Silas S. Brown committed
'if disable_once_per_day==1:',
'if once_per_day&2 and not hasattr(sys,"_gradint_innerImport"):',
Silas S. Brown's avatar
Silas S. Brown committed
'if once_per_day&1 and fileExists(progressFile) and time.localtime(os.stat(progressFile).st_mtime)[:3]==time.localtime()[:3]:',
Silas S. Brown's avatar
Silas S. Brown committed
'def optimise_partial_playing(ce):',
'def optimise_partial_playing_list(ceList):',
Silas S. Brown's avatar
Silas S. Brown committed
]
Silas S. Brown's avatar
Silas S. Brown committed

winCE_only = [
"if use_unicode_filenames:",
Silas S. Brown's avatar
Silas S. Brown committed
"if winCEsound:",'elif winCEsound:',
'if winCEsound and __name__=="__main__":',
'elif winCEsound and fileType=="mp3":',
Silas S. Brown's avatar
Silas S. Brown committed
"if WMstandard:",
Silas S. Brown's avatar
Silas S. Brown committed
]

Silas S. Brown's avatar
Silas S. Brown committed
not_winCE = [
"if not winCEsound:",
]

Silas S. Brown's avatar
Silas S. Brown committed
S60_only = [
Silas S. Brown's avatar
Silas S. Brown committed
'if sys.platform.find("ymbian")>-1:',
Silas S. Brown's avatar
Silas S. Brown committed
"class S60Synth(Synth):",
Silas S. Brown's avatar
Silas S. Brown committed
"if appuifw:","elif appuifw:",
Silas S. Brown's avatar
Silas S. Brown committed
"def s60_recordWord():",
"def s60_recordFile(language):",
"def s60_addVocab():",
"def s60_changeLang():",
"def s60_runLesson():",
"def s60_viewVocab():",
"def s60_main_menu():",
]

Silas S. Brown's avatar
Silas S. Brown committed
android_only = [
"if android:",
"elif android:",
"class AndroidSynth(Synth):",
Silas S. Brown's avatar
Silas S. Brown committed
"def android_recordWord():",
"def android_recordFile(language):",
"def android_main_menu():",
"def android_addVocab():",
"def android_changeLang():",
]

android_or_S60 = [
"def droidOrS60RecWord(recFunc,inputFunc):",
Silas S. Brown's avatar
Silas S. Brown committed
]

Silas S. Brown's avatar
Silas S. Brown committed
if "s60" in sys.argv: # S60 version
  version = "S60"
Silas S. Brown's avatar
Silas S. Brown committed
  to_omit = tk_only + desktop_only + winCE_only + not_S60_or_android + android_only + riscos_only + mac_only
Silas S. Brown's avatar
Silas S. Brown committed
elif "android" in sys.argv: # Android version
  version = "Android"
Silas S. Brown's avatar
Silas S. Brown committed
  to_omit = tk_only + desktop_only + winCE_only + S60_only + not_S60_or_android + not_android + riscos_only + mac_only
Silas S. Brown's avatar
Silas S. Brown committed
elif "wince" in sys.argv: # Windows Mobile version
Silas S. Brown's avatar
Silas S. Brown committed
  version = "WinCE"
Silas S. Brown's avatar
Silas S. Brown committed
  to_omit = desktop_only + S60_only + android_only + android_or_S60 + not_winCE + riscos_only + mac_only
Silas S. Brown's avatar
Silas S. Brown committed
elif "core" in sys.argv: # experimental "core code only" for 'minimal embedded porting' starting point (no UI, no synth, limited file I/O; you'll probably have to load up the event data yourself)
  version = "core"
  to_omit = tk_only + not_S60_or_android + not_android + riscos_only + mac_only + desktop_only + winCE_only + S60_only + android_only + android_or_S60 + [
"def main():",
"def rest_of_main():",
'if __name__=="__main__":',
"def transliterates_differently(text,lang):",
"def primitive_synthloop():",
"def appendVocabFileInRightLanguages():",
'def delOrReplace(L2toDel,L1toDel,newL2,newL1,action="delete"):',
"def generalCheck(text,language,pauseOnError=0):",
"def localise(s):",
"def singular(number,s):",
"def readText(l):",
"def asUnicode(x):",
"def updateSettingsFile(fname,newVals):",
"def clearScreen():",
"def startBrowser(url):",'def getYN(msg,defaultIfEof="n"):',"def waitOnMessage(msg):",
"def interrupt_instructions():",
"def parseSynthVocab(fname,forGUI=0):",
"def scanSamples_inner(directory,retVal,doLimit):",
"def getLsDic(directory):",
"def check_has_variants(directory,ls):",
"def exec_in_a_func(x):",
"def scanSamples(directory=None):",
"def synth_from_partials(text,lang,voice=None,isStart=1):",
"def partials_langname(lang):",
"if partialsDirectory and isDirectory(partialsDirectory):",
'for zipToCheck in ["yali-voice","yali-lower","cameron-voice"]:',
'def stripPuncEtc(text):',
'def can_be_synthesized(fname,dirBase=None,lang=None):',
'def synthcache_lookup(fname,dirBase=None,printErrors=0,justQueryCache=0,lang=None):',
'def textof(fname):',
'if synthCache and transTbl in synthCache_contents:',
'if synthCache:',
'class Partials_Synth(Synth):',
'def abspath_from_start(p):',
'class SynthEvent(Event):',
'def pinyin_uColon_to_V(pinyin):',
'def synth_event(language,text,is_prompt=0):',
'def get_synth_if_possible(language,warn=1,to_transliterate=False):',
'if wavPlayer_override or (unix and not macsound and not (oss_sound_device=="/dev/sound/dsp" or oss_sound_device=="/dev/dsp")):',
'def fix_compatibility(utext):',
'def read_chinese_number(num):',
'def preprocess_chinese_numbers(utext,isCant=0):',
'def intor0(v):',
'def fix_pinyin(pinyin,en_words):',
'def fix_commas(text):',
'def shell_escape(text):',
'class SimpleZhTransliterator(object):',
'def sort_out_pinyin_3rd_tones(pinyin):',
'def ensure_unicode(text):',
'def unzip_and_delete(f,specificFiles="",ignore_fail=0):',
'class Synth(object):',
'def quickGuess(letters,lettersPerSec):',"def changeToDirOf(file,winsound_also=0):",'if app or appuifw or android:',
'def subst_some_synth_for_synthcache(events):',
'def decide_subst_synth(cache_fname):',
'if winsound or winCEsound or mingw32 or riscos_sound or not hasattr(os,"tempnam") or android:',
'if len(sys.argv)>1:',
'def readSettings(f):',
'def exc_info(inGradint=True):',
'if not fileExists(configFiles[0]):',
'def u8strip(d):']
Silas S. Brown's avatar
Silas S. Brown committed
else: assert 0, "Unrecognised version on command line"

Silas S. Brown's avatar
Silas S. Brown committed
revertToIndent = lastIndentLevel = indentLevel = -1
Silas S. Brown's avatar
Silas S. Brown committed
lCount = -1 ; inTripleQuotes=0 ; orig = []
for l in sys.stdin:
Silas S. Brown's avatar
Silas S. Brown committed
  orig.append(l)
Silas S. Brown's avatar
Silas S. Brown committed
  lCount += 1
  if lCount==2: print ("\n# NOTE: this version has been automatically TRIMMED for "+version+" (some non-"+version+" code taken out)\n")
Silas S. Brown's avatar
Silas S. Brown committed
  l=l.rstrip()
  assert not "\t" in l, "can't cope with tabs"
Silas S. Brown's avatar
Silas S. Brown committed
  lastIndentLevel,indentLevel = indentLevel,-1
Silas S. Brown's avatar
Silas S. Brown committed
  for i in range(len(l)):
    if not l[i]==" ":
      indentLevel = i ; break
Silas S. Brown's avatar
Silas S. Brown committed
  was_inTripleQuotes = inTripleQuotes
Silas S. Brown's avatar
Silas S. Brown committed
  if (len(l.split('"""'))%2) == 0: inTripleQuotes = not inTripleQuotes
Silas S. Brown's avatar
Silas S. Brown committed
  if indentLevel<0 or indentLevel==len(l) or (revertToIndent>=0 and (indentLevel>revertToIndent or was_inTripleQuotes)): continue
Silas S. Brown's avatar
Silas S. Brown committed
  justRevertedI,revertToIndent = revertToIndent,-1
Silas S. Brown's avatar
Silas S. Brown committed
  code0 = (l+"#")[:l.find("#")].rstrip()
  code = code0.lstrip()
  if (code in to_omit or (':' in code and code[:code.index(':')+1] in to_omit)) and not was_inTripleQuotes:
    if ':' in code and code[:code.index(':')+1] in to_omit: code = code[:code.index(':')+1]
Silas S. Brown's avatar
Silas S. Brown committed
    if code.startswith("def "): code=re.sub(r"\([^)][^)][^)]+\)",r"(*_)",code)
Silas S. Brown's avatar
Silas S. Brown committed
    if code.startswith("elif "): pass # can always remove those lines completely, even if will be followed by an 'else' (and will never be the only thing in its block)
Silas S. Brown's avatar
Silas S. Brown committed
    else:
Silas S. Brown's avatar
Silas S. Brown committed
      if code.startswith("if "): code="if 0:"
      print (" "*indentLevel+code+" pass # trimmed")
Silas S. Brown's avatar
Silas S. Brown committed
    revertToIndent = indentLevel
Silas S. Brown's avatar
Silas S. Brown committed
  elif not code:
    if "#    " in l or lCount < 2: print (l) # keep start and GPL comments
  elif ('"' in code and '"' in l[len(code):]) or ("'" in code and "'" in l[len(code):]): print (l) # perhaps # was in a string, keep it
  else: print (code0)
Silas S. Brown's avatar
Silas S. Brown committed
orig = "".join(orig)
Silas S. Brown's avatar
Silas S. Brown committed
for o in to_omit:
Silas S. Brown's avatar
Silas S. Brown committed
  if not o in orig: sys.stderr.write("Warning: line not matched: "+o)