Package: mistool
About this packagemisToolis the contraction ofmissing,miscellaneousandtool(s).
This package contains some modules that could be useful for Python
developments.If you want more informations and examples than thereafter, just take
a look at the docstrings.I beg your pardon for my english...English is not my native language, so be nice if you notice misunderstandings, misspellings or grammatical errors in my documents and codes.What's new in this version1.2.2-beta?¨html and ¨latex basic frames have been added to be used withterm_use.withframe.What's new in this version1.2.1-beta?The functionbetweeninstring_usehas a new optional argumentkeepsepsso as to keep or not the separators.What's new in this version1.2.0-beta?The moduledate_usehas been changed todatetime_use: see the presentation above to know how to work now with dates insidemisTool.What's new in this version1.1.1-beta?In the modulepython_use, the new classMKOrderedDictallows to define kinds of ordered dictionaries accepting several times the same key but at different "places".Warning !Here are some important changes.In the modulepython_use, the classOrderedRecuDictbecomesRecuOrderedDict.In the modulestring_use, the functionascii_itbecomesasciify.The moduleos_useChanging the working directory for commandsWithos_use.cd, you have a context which changes temporarily the directory where launching terminal like commands. When the context is closed, the working directory goes back to the one just before the call ofos_use.cd.Let's see an example. We suppose that we have the following directory with the absolute path/Users/projetmbc/basic_dirin a Unix system.+ basic_dir
    * latex_1.tex
    * latex_2.tex
    * python_1.py
    * python_2.py
    * python_3.py
    * python_4.py
    * text_1.txt
    * text_2.txt
    * text_3.txt
    + empty_dir
    + sub_dir
        * code_A.py
        * code_B.py
        * slide_A.pdf
        * slide_B.pdf
        + sub_sub_dir
            * doc.pdfThe following code first goes inside/Users/projetmbc/basic_dirand then it moves to/Users/projetmbc/basic_dir/sub_dir. Withsubprocess.call("ls"), we simply use the Unix commandlsso as to list files and folders inside the current working directory.>>>importsubprocess>>>frommistool.os_useimportcd>>>withcd("/Users/projetmbc/basic_dir"):...subprocess.call("ls")empty_dirpython_1.pypython_4.pytext_2.txtlatex_1.texpython_2.pysub_dirtext_3.txtlatex_2.texpython_3.pytext_1.txt>>>withcd("/Users/projetmbc/basic_dir/sub_dir"):...subprocess.call("ls")code_A.pyslide_A.pdfsub_sub_dircode_B.pyslide_B.pdfLaunching commands like in a terminalThe aim of the functionos_use.runthisis to simplify  a lot the launching of subprocesses(just use commands as you were inside your terminal). Let's consider the basic following Python script with absolute path/Users/projetmbc/script.py.print("Everything is ok.")To launch this program, we just have to use the single string Unix commandpython3 /Users/projetmbc/script.pylike in the following lines. You can see that by default nothing is printed, so you have to useshowoutput = Trueif
you want to see what the script launched prints.>>>frommistool.os_useimportPPath,runthis>>>pyfile=PPath("/Users/projetmbc/script.py")>>>runthis(cmd="python3{0}".format(ppath))>>>runthis(cmd="python3{0}".format(ppath),showoutput=True)Everythingisok.System used and environment's pathThe call toos_use.system()returns the name, in lower case, of the OS used : possible strings returned can be for example"windows","mac","linux"and also"java".os_use.pathenv()gives you the paths of executables known by your OS(this is indeed an alias foros.getenv('PATH')).Enhanced version of the classpathlib.PathThe classos_use.PPathadds several methods to the useful classpathlib.Path. Here are examples.Informations about one pathThe following code shows additional informations given by the classos_use.PPath.>>>frommistool.os_useimportPPath>>>path=PPath("dir/subdir/file.txt")>>>path.parentPPath('dir/subdir')>>>print(path.depth)2>>>print(path.ext)'txt'Another useful method namedis_protectedworks as explained below.If the path does not point to an existing file or folder, an OS error is raised.If the path is the one of a folder, the answer returned isTruefor a modifiable directory andFalseotherwise.Finally if the path points to a file, then that is its parent folder which is tested.There is also the methodis_emptywhich can give three different responses.If the path is the one of an empty directory,Falseis
returned.Trueis returned when the path corresponds to an non-empty folder.If the path doesn't point to an existing directory an OS error is raised.Changing one pathChanging or adding an extension is very easy with the methodwith_ext.>>>frommistool.os_useimportPPath>>>path_no_ext=PPath("dir/subdir")>>>path_no_ext.with_ext("ext")PPath('dir/subdir.ext')>>>path_ext=PPath("dir/subdir/file.txt")>>>path_ext.with_ext("ext")PPath('dir/subdir/file.ext')Obtaining a short version or a normalized one of a path needs no effort. Here is how to do that(~is a shortcut for the main OS user's folder).>>>frommistool.os_useimportPPath>>>path_too_long=PPath("~/dir_1/dir_2/dir_3/../../file.txt")>>>path_too_long.normpathPPath('/Users/projetmbc/dir_1/file.txt')>>>path_long=PPath("/Users/projetmbc/dir_1/dir_2/dir_3/../../file.txt")>>>path_long.shortpathPPath('~/dir_1/file.txt')Comparing pathsThe "common" folder of several paths is obtained by using the methodcommon_withor equivalently the magic operator&.>>>frommistool.os_useimportPPath>>>path=PPath("/Users/projetmbc/source/doc")>>>path_1=PPath("/Users/projetmbc/README")>>>path_2=PPath("/Users/projetmbc/source/misTool/os_use.py")>>>path_danger=PPath("/NoUser/projects")>>>path.common_with(path_1)# Same as ``path & path_1``PPath('/Users/projetmbc')>>>path.common_with(path_2)# Same as ``path & path_2``PPath('/Users/projetmbc/source')>>>path.common_with(path_danger)# No error raised !PPath('/')>>>path.common_with(path_1,path_2)# Same as ``path & path_1 & path_2``PPath('/Users/projetmbc')>>>path.common_with([path_1,path_2])# Same as ``path & [path_1, path_2]``PPath('/Users/projetmbc')The classos_use.PPathadds a magic method so as to usepath - anotherpathinstead ofpath.relative_to(anotherpath)where the methodrelative_tois implemented by the classpathlib.Path.>>>frommistool.os_useimportPPath>>>main=PPath("/Users/projetmbc")>>>path_1=PPath("/Users/projetmbc/README")>>>path_2=PPath("/Users/projetmbc/source/misTool/os_use.py")>>>path_1-mainPPath('README')>>>path_2-mainPPath('source/misTool/os_use.py')>>>path_2-path_1Traceback(mostrecentcalllast):[...]ValueError:'/Users/projetmbc/source/misTool/os_use.py'doesnotstartwith'/Users/projetmbc/README'If you need to know the depth of one path relatively to another, just call the methoddepth_in.>>>frommistool.os_useimportPPath>>>main=PPath("/Users/projetmbc")>>>path_1=PPath("/Users/projetmbc/README")>>>path_2=PPath("/Users/projetmbc/source/misTool/os_use.py")>>>path_pb=PPath("/NoUser/projects")>>>print(path_1.depth_in(main))0>>>print(path_2.depth_in(main))2>>>print(path_pb.depth_in(main))Traceback(mostrecentcalllast):[...]ValueError:'/NoUser/projects'doesnotstartwith'/Users/projetmbc'The special concept of "regpath"A "regpath" is a query mixing all the power of regexes and the Unix-glob special characters(there are also some additional query
features). We will use some "regpaths" in the incoming examples.See the docstring of the methodregpath2metafor complete informations about the "regpaths".Walk and seeThe methodseetriesto open the current path with a possible associated application. For example, an HTML file will be opened by your default browser.You can walk very easily inside a directory thanks to the methodwalkand the "regpaths"(see the previous section). For example, let's suppose that we have the following directory with absolute path/Users/projetmbc/basic_dirin a Unix system.+ basic_dir
    * latex_1.tex
    * latex_2.tex
    * python_1.py
    * python_2.py
    * python_3.py
    * python_4.py
    * text_1.txt
    * text_2.txt
    * text_3.txt
    + empty_dir
    + sub_dir
        * code_A.py
        * code_B.py
        * slide_A.pdf
        * slide_B.pdf
        + sub_sub_dir
            * doc.pdfHere are easy to understand examples where the regpath"*"is for a
non-recursive search contrary to the regpath"**".>>>frommistool.os_useimportPPath>>>folder=PPath("/Users/projetmbc/basic_dir")>>>forpinfolder.walk("dir::**"):...print("+",p)...+/Users/projetmbc/basic_dir/empty_dir+/Users/projetmbc/basic_dir/sub_dir+/Users/projetmbc/basic_dir/sub_dir/sub_sub_dir>>>forpinfolder.walk("file::**.py"):...print("+",p)...+/Users/projetmbc/basic_dir/python_1.py+/Users/projetmbc/basic_dir/python_2.py+/Users/projetmbc/basic_dir/python_3.py+/Users/projetmbc/basic_dir/python_4.py+/Users/projetmbc/basic_dir/sub_dir/code_A.py+/Users/projetmbc/basic_dir/sub_dir/code_B.py>>>forpinfolder.walk("file::*.py"):...print("+",p)...+/Users/projetmbc/basic_dir/python_1.py+/Users/projetmbc/basic_dir/python_2.py+/Users/projetmbc/basic_dir/python_3.py+/Users/projetmbc/basic_dir/python_4.pyCreateCreating files and folders is straight forward with the methodcreateeven if this needs to add several parent directories that don't yet exist. In the following example, we suppose that the current directory has absolute path/Users/projetmbc, and doesn't contain any subfolder.>>>frommistool.os_useimportPPath>>>path_1=PPath("test/README")>>>path_1.is_file()False>>>path_1.create("file")>>>path_1.is_file()True>>>path_2=PPath("test/README")>>>path_2.create("dir")Traceback(mostrecentcalllast):[...]ValueError:pathpointstoanexistingfile.RemoveIf you want to destroy a whole directory, or simply a file, given by itsPPath, just use the methodremove.Warning ! Because removing a file or a directory can be a dangerous thing, you can use the methodcan_be_removedwhich by default will raise an OS error if thePPathis one of an existing file or folder.The methodcleanallows to remove specific files and/or directories matching a regpath given as an argument.Move & copyBy default, the methodcopy_toallows you to copy a file or a directory into another location, whereas the methodmove_towill move a file or a directory to another place.The modulestring_useMulti-replacementsThe classstring_use.MultiReplacemakes possible to do multi-replacements recursively or not(by defaultmode = "norecu").>>>frommistool.string_useimportMultiReplace>>>frommistool.config.patternimportPATTERNS_WORDS>>>oldnew={...'W1':"Word #1",...'W2':"Word #2",...'W3':"W1 and W2"...}>>>mreplace=MultiReplace(...oldnew=oldnew,...mode="recu",...pattern=PATTERNS_WORDS['var']...)>>>print(mreplace("W1 and W2 = W3"))Word#1 and Word #2 = Word #1 and Word #2>>>mreplace.mode="norecu">>>mreplace.build()>>>print(mreplace("W1 and W2 = W3"))Word#1 and Word #2 = W1 and W2The code above show that cyclic definitions will raise aValueErrorexception.>>>frommistool.string_useimportMultiReplace>>>frommistool.config.patternimportPATTERNS_WORDS>>>oldnew={...'WRONG_1':"one small text and  WRONG_2",...'WRONG_2':"one small text, and then WRONG_3",...'WRONG_3':"with WRONG_1, there is one problem here"...}>>>mreplace=MultiReplace(...oldnew=oldnew,...mode="recu",...pattern=PATTERNS_WORDS["var"]...)Traceback(mostrecentcalllast):[...]ValueError:thefollowingvisciouscirclehasbeenfound.+WRONG_2-->WRONG_3-->WRONG_1-->WRONG_2Multi-splitsThe aim of the classstring_use.MultiSplitis to split a text on several semantic depths. Here is an example of use.>>>frommistool.string_useimportMultiSplit>>>msplit=MultiSplit(seps="|")>>>print(msplit("p_1 ; p_2 ; p_3 | r_1 ; r_2 | s"))['p_1 ; p_2 ; p_3 ',' r_1 ; r_2 ',' s']>>>msplit.seps=["|",";"]>>>msplit.strip=True>>>print(msplit("p_1 ; p_2 ; p_3 | r_1 ; r_2 | s"))[['p_1','p_2','p_3'],['r_1','r_2'],['s']]Before, between and afterThe functionstring_use.betweenlooks for two separators such as to return the text before, between and after the first matching of this separators. By default, separators are not kept but you can ask to the function to keep them.Noneis returned if no matching has been found. Just take a look at a concrete example.>>>frommistool.string_useimportbetween>>>text="f(x ; y) = x**2 + y**2">>>seps=["(",")"]>>>print(between(text,seps))['f',# Before'x ; y',# Between' = x**2 + y**2'# After]>>>print(between(text,seps,True))['f(',# Before'x ; y',# Between') = x**2 + y**2'# After]>>>seps=["{","}"]>>>print(between(text,seps))NoneJoin with a last special textYou can join several strings with a special final separator as the examples above show.>>>frommistool.string_useimportjoinand>>>texts=["1","2","3"]>>>print(joinand(texts))1,2and3>>>print(joinand(texts=texts,andtext="et"))1,2et3>>>print(joinand(texts=texts,sep=" + ",andtext="="))1+2=3Playing with cases of lettersThe functionstring_use.casegives more auto-formatting of strings(the last formatting looks strange but it is useful for an incoming project of the author ofmistool).>>>frommistool.string_useimportcase>>>text="onE eXamPLe">>>forkindin['lower','upper','sentence','title']:...print("{0}[{1}]".format(case(text,kind),kind))...oneexample[lower]ONEEXAMPLE[upper]Oneexample[sentence]OneExample[title]A camel case string can be "uncamelized" by the functionstring_use.camelto. Here is how to use it(you can change the separator by using the optional argumentsepwhich is"_"by default).>>>frommistool.string_useimportcamelto>>>text="OneSmallExampLE">>>forkindin['lower','upper','sentence','title']:...print("{0}[{1}]".format(camelto(text,kind),kind))...one_small_examp_l_e[lower]ONE_SMALL_EXAMP_L_E[upper]One_small_examp_l_e[sentence]One_Small_Examp_L_E[title]If you need to check the case of a string, just usestring_use.iscase(text, kind).Playing with ASCIIYou can check if a string is a pure ASCII one.>>>frommistool.string_useimportisascii>>>print(isascii("Vive la France !"))True>>>print(isascii("¡Viva España!"))FalseYou can also transform a string to a pure ASCII one(this will not always work but in case of failure you can contribute very easily to enhancestring_use.asciify).>>>frommistool.string_useimportasciify>>>print(asciify("¡Viva España!"))VivaEspana!>>>oldnew={'!':""}>>>print(asciify(text="¡Viva España!",oldnew=oldnew))VivaEspanaThe last example above shows how to be permissive : this means thatstring_use.asciifywill "asciify" the most characters as possible.>>>frommistool.string_useimportasciify>>>print(asciify(text="L'Odyssée de ∏",strict=False))L'Odyssee de ∏>>>print(asciify("L'Odyssée de ∏"))Traceback(mostrecentcalllast):[...]ValueError:ASCIIconversioncan't be made because of the character << ∏ >>.Youcanusethefunction``_ascii_report``soastoreportmorepreciselythisfealurewitheventuallyanasciialternative.Auto completionThe classstring_use.AutoCompletegives the auto-completion feature accessible without using any GUI package.>>>frommistool.string_useimportAutoComplete>>>myac=AutoComplete(...words=[..."article","artist","art",..."when","who","whendy",..."bar","barbie","barber","bar"...]...)>>>print(myac.matching("art"))['article','artist']>>>print(myac.matching(""))['art','article','artist','bar','barber','barbie','when','whendy','who']>>>print(myac.missing("art",'article'))icleIt is a convention in GUI applications to give auto-completion only for at least three characters. You can do that by using the optional argumentminsizewhich is1by default.The moduleterm_useAuto-numbering stepsFor terminal informations, it can be useful to number some important printed steps. This can be done easily with the classterm_use.Step.>>>frommistool.term_useimportStep>>>mysteps=Step()>>>i=0>>>whilei<=12:...ifi%2:...mysteps("Action #{0}".format(i))...i+=1...1)Action#12)Action#33)Action#54)Action#75)Action#96)Action#11The classterm_use.Stephas two optional arguments.startgives the first number which is1by default.textitis a function of two variables(n, t)returning the text containing the step numbernand the textt. By default,textit = lambda n, t: "{0}) {1}".format(n, t).FrameThe functionterm_use.withframeputs a text inside an ASCII frame(you can choose the alignment and use other kinds of frames if necessary as it is explained in the docstrings).>>>frommistool.term_useimportwithframe>>>text='''... One small... text... to do tests... '''.strip()>>>print(withframe(text))################ One small   ## text        ## to do tests ################ASCII tree views of one directoryFor our examples, we consider a folder with the following structure and the absolute path/Users/projetmbc/dir.+ dir
    * code_1.py
    * code_2.py
    * file_1.txt
    * file_2.txt
    + doc
        * code_A.py
        * code_B.py
        * slide_A.pdf
        * slide_B.pdf
        + licence
            * doc.pdf
    + emptydirThe preceding ASCII tree view was built easily using the following code(PPathis the class defined inos_useadded interm_usefor you comfort).>>>frommistool.term_useimportDirView,PPath>>>dir=PPath("/Users/projetmbc/dir")>>>dirview=DirView(...ppath=dir,...sorting="filefirst"...)>>>print(dirview.ascii)+dir*code_1.py*code_2.py*file_1.txt*file_2.txt+doc*code_A.py*code_B.py*slide_A.pdf*slide_B.pdf+licence*doc.pdf+emptydirUsing the "regpath" concept of the moduleos_use, we can filter folders and files shown as in the example above(we also use the argumentdisplayso as to customize the output).>>>frommistool.term_useimportDirView,PPath>>>dir=PPath("/Users/projetmbc/dir")>>>dirview=DirView(...ppath=dir,...regpath="file::**.py",...display="main short found"...)>>>print(dirview.ascii)+dir*code_1.py*code_2.py+doc*code_A.py*code_B.pyYou can also use the following property methods.dirview.treeis a graphical tree.dirview.tocgives a minimal tabulated tree.dirview.latexis for the LaTeX packagedirtree.The modulepython_useA multikeys dictionaryThe classMKOrderedDictallows to work easily with multikeys ordered dictionaries. Here is a complete example of use.>>>frommistool.python_useimportMKOrderedDict>>>onemkdict=MKOrderedDict()>>>onemkdict[(1,2,4)]="1st value">>>onemkdict["key"]="2nd value">>>onemkdict["key"]="3rd value">>>print(onemkdict)MKOrderedDict([((id=0,key=(1,2,4)),value='1st value'),((id=0,key='key'),value='2nd value'),((id=1,key='key'),value='3rd value')])>>>fork_id,valinonemkdict["key"]:...print(k_id,val)...02ndvalue13rdvalue>>>print(onemkdict.getitembyid(1,"key"))3rdvalue>>>for(k_id,key),valinonemkdict.items():...print((k_id,key),"===>",val)...(0,(1,2,4))===>1stvalue(0,'key')===>2ndvalue(1,'key')===>3rdvalue>>>forkey,valinonemkdict.items(noid=True):...print(key,"===>",val)...(1,2,4)===>1stvaluekey===>2ndvaluekey===>3rdvalue>>>"key"inonemkdictTrue>>>"kaaaay"inonemkdictFalse>>>onemkdict.setitembyid(0,"key","New 2nd value")>>>print(onemkdict)MKOrderedDict([((id=0,key=(1,2,4)),value='1st value'),((id=0,key='key'),value='New 2nd value'),((id=1,key='key'),value='3rd value')])A dictionary defined recursivelyThe classRecuOrderedDictallows to use a list of hashable keys, or just a single hashable key. Here is a complete example of use.>>>frommistool.python_useimportRecuOrderedDict>>>onerecudict=RecuOrderedDict()>>>onerecudict[[1,2,4]]="1st value">>>onerecudict[(1,2,4)]="2nd value">>>onerecudict["key"]="3rd value">>>print(onerecudict)RecuOrderedDict([(1,RecuOrderedDict([(2,RecuOrderedDict([(4,'1st value')]))])),((1,2,4),'2nd value'),('key','3rd value')])>>>[1,2,4]inonerecudictTrue>>>[2,4]inonerecudict[1]TrueList of single values of a dictionaryIf you need to list all the value of one dictionary, the functionpython_use.dictvaluesis made for you.>>>frommistool.python_useimportdictvalues>>>onedict={"a":1,"b":2,"c":1}>>>print(dictvalues(onedict))[1,2]>>>print(list(onedict.values()))[2,1,1]Easy quoted text with the least escaped quote symbolsWithpython_use.quoteyou can add without pain quotes around a text.>>>frommistool.python_useimportquote>>>print(quote('First example.'))'First example.'>>>print(quote("Same example."))'Same example.'>>>print(quote('One "small" example.'))'One "small" example.'>>>print(quote("Another kind of\"example\"."))'Another kind of "example".'>>>print(quote("An example a 'little' more\"problematic\"."))'An example a\'little\'more "problematic".'The moduledatetime_useSpecial classddatetimeThe classddatetimeis an enhanced version of the classdatetime.datetime: see the two sections below. It is very easy to build an instance ofddatetimethanks to the very cool functionbuild_ddatetime. The examples above show different ways to define a date.>>>frommistool.datetime_useimportbuild_ddatetime>>>build_ddatetime((2017,8,1))ddatetime(2017,8,1,0,0)>>>build_ddatetime(2017,8,1)ddatetime(2017,8,1,0,0)>>>build_ddatetime("2017-08-01")ddatetime(2017,8,1,0,0)>>>build_ddatetime("Friday 01 august 2017")ddatetime(2017,8,1,0,0)>>>build_ddatetime("Vendredi 1er août 2017",lang="fr_FR")ddatetime(2017,8,1,0,0)>>>build_ddatetime("Vendredi 1er août 2017")[...]ValueError:Unknownstringformat>>>build_ddatetime("Vendredi 1er août 2017","fr_FR")[...]TypeError:anintegerisrequired(gottypestr)Note that youmustdefine a special language usinglang = "fr_FR"as you can see in the two last commands in the preceding example.Next day having a fixed english nameIn some applications you want to know the next monday after a fixing date.>>>frommistool.datetime_useimportddatetime>>>onedate=ddatetime(2017,8,1)>>>print(onedate.strftime("%Y-%m-%dis a %A."))2017-08-01isaTuesday.>>>nextfriday=onedate.nextday(name="friday")>>>print("Next Friday:",nextfriday.strftime("%Y-%m-%d"))NextFriday:2017-08-04Translating a dateThanks to the classddatetime, it is easy to safely translate all the names in a date.>>>frommistool.datetime_useimportddatetime>>>onedate=ddatetime(2015,6,2)>>>oneformat="%A%d%B %Y">>>print(onedate.translate(strformat=oneformat))Tuesday02June2015>>>print(onedate.translate(strformat=oneformat,lang="fr_FR"))Mardi02juin2015Parsing a string to build a dateThe functionparsedateis an international version of the functiondateutil.parser.parse(translations need external contributions : the job is very easy to do !).>>>frommistool.datetime_useimportparsedate>>>parsedate("Friday 01 august 2017")ddatetime(2017,8,1,0,0)>>>parsedate(timestr="Vendredi 1er Août 2017",lang="fr_FR")ddatetime(2017,8,1,0,0)>>>parsedate(timestr="Montag, 11. April 2016",lang="de_DE")[...]ValueError:unsupportedlanguage''de_DE''The moduleurl_useLooking for dead or bad urlsFor the following example, we suppose that we have a working internet connection.>>>frommistool.url_useimportislinked>>>islinked("http://www.google.com")True>>>islinked("http://www.g-o-o-g-l-e.com")FalseEscaping special characters in urlsIt is safe to not use non-ASCII characters in a url. Here is one way to do that.>>>frommistool.url_useimportescape>>>print(escape("http://www.vivaespaña.com/camión/"))http://www.vivaespa%C3%B1a.com/cami%C3%B3n/The modulelatex_useEscaping the special LaTeX charactersThe functionlatex_use.escapewill escape all special characters for you regarding the text or math mode.>>>frommistool.latex_useimportescape>>>onetext="\OH/ & ...">>>print(escape(onetext))\textbackslash{}OH/\&...>>>print(escape(text=onetext,mode="math"))\backslash{}OH/\&...Easy LaTeX compilation(s)The classlatex_use.Buildcompiles a LaTeX file for you(for the moment only the PDF compilation is implemented). Let's consider the
following LaTeX file with the absolute path/Users/projetmbc/latex/file.tex.\documentclass[11pt, oneside]{article}\begin{document}\section{One little test}One basic formula :$E=mc^2$.\end{document}In the following code, we call to the classterm_use.DirViewso as to show the new files made by LaTeX(the ellipsis[...]indicates some lines not reproduced here).>>>frommistool.latex_useimportBuild,PPath>>>frommistool.term_useimportDirView>>>latexdir=PPath("/Users/projetmbc/latex/file.tex")>>>print(DirView(latexdir.parent).ascii)+latex*file.tex>>>builder=Build(latexdir)>>>builder.pdf()# -- Start of compilation Nb.1 -- #ThisispdfTeX,Version3.14159265-2.6-1.40.15(TeXLive2014)(preloadedformat=pdflatex)restricted\write18enabled.enteringextendedmode[...]Outputwrittenonfile.pdf(1page,36666bytes).Transcriptwrittenonfile.log.# -- End of compilation Nb.1 -- #>>>print(DirView(latexdir.parent).ascii)+latex*file.aux*file.log*file.pdf*file.texThe PDF file has been build by LaTeX but there are also temporary ones. If you need several compilations, so as to build a table of content for example, just use the attribut-argumentrepeat, and if you don't want to see the LaTeX ouput, just set the attribut-argumentshowinfostoFalse.Removing the temporary files produced by LaTeXWe keep the same LaTeX example file. The functionlatex_use.cleancleans all unuseful temporary files when the compilation has been done.>>>frommistool.latex_useimportclean,PPath>>>frommistool.term_useimportDirView>>>latexdir=PPath("/Users/projetmbc/latex")>>>print(DirView(latexdir.parent).ascii)+latex*file.aux*file.log*file.pdf*file.synctex.gz*file.tex>>>clean(ppath=latexdir,showinfos=True)*Cleaningfor"/Users/projetmbc/latex/file.tex">>>print(DirView(latexdir.parent).ascii)+latex*file.pdf*file.texAutomatic installation of personal LaTeX packagesLet's suppose that we have package namedlyxamstored in a folder having the absolute path/Users/projetmbc/latex/lyxamand whose structure is the following one.+ lyxam
    + change_log
        + 2012
            * 02.txt
            * 03.txt
            * 04.txt
            * 10.txt
        * todo.txt
    * lyxam.sty
    + config
        * settings.tex
        + lang
            * en.tex
            * fr.tex
            + special
                * fr.config
            + standard
                * en.config
                * fr.config
        + style
            * apmep.tex
            * default.texTo install this package locally in your LaTeX distribution, just do like in the code above.>>>frommistool.latex_useimportinstall,PPath>>>package=PPath("/Users/projetmbc/latex/lyxam")>>>install(package)Startinginstallationofthepackagelocally.*Deletionoftheold<<lyxam>>packageinthelocalLaTeXdirectory.*Creationofanew<<lyxam>>packageinthelocalLaTeXdirectory.+Addingthenewfile<<lyxam.sty>>+Addingthenewfile<<change_log/todo.txt>>+Addingthenewfile<<change_log/2012/02.txt>>+Addingthenewfile<<change_log/2012/03.txt>>+Addingthenewfile<<change_log/2012/04.txt>>+Addingthenewfile<<change_log/2012/10.txt>>+Addingthenewfile<<config/settings.tex>>+Addingthenewfile<<config/lang/en.tex>>+Addingthenewfile<<config/lang/fr.tex>>+Addingthenewfile<<config/lang/special/fr.config>>+Addingthenewfile<<config/lang/standard/en.config>>+Addingthenewfile<<config/lang/standard/fr.config>>+Addingthenewfile<<config/style/apmep.tex>>+Addingthenewfile<<config/style/default.tex>>*RefreshingthelistofLaTeXpackages.Using the concept of "regpath" of the moduleos_use, you can for example choose to not install all theTXTfiles.>>>frommistool.latex_useimportinstall,PPath>>>package=PPath("/Users/projetmbc/latex/lyxam")>>>install(ppath=package,regpath="file not::**.txt")Startinginstallationofthepackagelocally.*Deletionoftheold<<lyxam>>packageinthelocalLaTeXdirectory.*Creationofanew<<lyxam>>packageinthelocalLaTeXdirectory.+Addingthenewfile<<lyxam.sty>>+Addingthenewfile<<config/settings.tex>>+Addingthenewfile<<config/lang/en.tex>>+Addingthenewfile<<config/lang/fr.tex>>+Addingthenewfile<<config/lang/special/fr.config>>+Addingthenewfile<<config/lang/standard/en.config>>+Addingthenewfile<<config/lang/standard/fr.config>>+Addingthenewfile<<config/style/apmep.tex>>+Addingthenewfile<<config/style/default.tex>>*RefreshingthelistofLaTeXpackages.Remove a personal LaTeX packagesJust useremove(name)wherenameis the name of a local LaTeX package.