Flask-AutoIndex-0.6.6/0000777000000000000000000000000013640414351012614 5ustar 00000000000000Flask-AutoIndex-0.6.6/Flask_AutoIndex.egg-info/0000777000000000000000000000000013640414347017333 5ustar 00000000000000Flask-AutoIndex-0.6.6/Flask_AutoIndex.egg-info/PKG-INFO0000666000000000000000000000254113640414346020431 0ustar 00000000000000Metadata-Version: 1.1 Name: Flask-AutoIndex Version: 0.6.6 Summary: The mod_autoindex for Flask Home-page: https://flask-autoindex.readthedocs.io Author: RIGAUDIE David Author-email: UNKNOWN License: MIT Description: Flask-AutoIndex --------------- Flask-AutoIndex generates an index page for your `Flask`_ application automatically. The result is similar to the one produced by the Apache module `mod_autoindex`_, but the look is more awesome! .. _Flask: https://palletsprojects.com/p/flask/ .. _mod_autoindex: http://httpd.apache.org/docs/current/mod/mod_autoindex.html Links ````` * `Documentation `_ * `Code repository and issue tracker `_ Platform: any Classifier: Development Status :: 4 - Beta Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content Classifier: Topic :: Software Development :: Libraries :: Python Modules Flask-AutoIndex-0.6.6/Flask_AutoIndex.egg-info/SOURCES.txt0000666000000000000000000000565113640414346021225 0ustar 00000000000000MANIFEST.in README.md setup.cfg setup.py Flask_AutoIndex.egg-info/PKG-INFO Flask_AutoIndex.egg-info/SOURCES.txt Flask_AutoIndex.egg-info/dependency_links.txt Flask_AutoIndex.egg-info/entry_points.txt Flask_AutoIndex.egg-info/not-zip-safe Flask_AutoIndex.egg-info/requires.txt Flask_AutoIndex.egg-info/top_level.txt docs/conf.py docs/index.rst docs/_static/example.png docs/_static/flask-autoindex.png flask_autoindex/__init__.py flask_autoindex/entry.py flask_autoindex/icons.py flask_autoindex/run.py flask_autoindex/static/asc.gif flask_autoindex/static/autoindex.css flask_autoindex/static/desc.gif flask_autoindex/templates/__autoindex__/autoindex.html flask_autoindex/templates/__autoindex__/macros.html tests/__init__.py tests/blueprinttest/__init__.py tests/static/helloworld.txt tests/static/test.7z tests/static/test.ai tests/static/test.alz tests/static/test.app tests/static/test.applescript tests/static/test.asp tests/static/test.avi tests/static/test.bak tests/static/test.bat tests/static/test.bin tests/static/test.bmp tests/static/test.bup tests/static/test.c tests/static/test.cab tests/static/test.cer tests/static/test.cfg tests/static/test.cgi tests/static/test.com tests/static/test.conf tests/static/test.cpl tests/static/test.cpp tests/static/test.css tests/static/test.csv tests/static/test.cur tests/static/test.db tests/static/test.dll tests/static/test.dmg tests/static/test.doc tests/static/test.docx tests/static/test.eps tests/static/test.exe tests/static/test.fla tests/static/test.flv tests/static/test.gif tests/static/test.h tests/static/test.htm tests/static/test.html tests/static/test.hwp tests/static/test.ico tests/static/test.ics tests/static/test.ini tests/static/test.iso tests/static/test.jar tests/static/test.java tests/static/test.jpeg tests/static/test.jpg tests/static/test.js tests/static/test.json tests/static/test.jsp tests/static/test.less tests/static/test.log tests/static/test.markdown tests/static/test.md tests/static/test.mid tests/static/test.mov tests/static/test.mp3 tests/static/test.mp4 tests/static/test.mpa tests/static/test.mpeg tests/static/test.mpg tests/static/test.pdf tests/static/test.php tests/static/test.pkg tests/static/test.png tests/static/test.ppt tests/static/test.pptx tests/static/test.psd tests/static/test.py tests/static/test.rar tests/static/test.rb tests/static/test.rss tests/static/test.rtf tests/static/test.sh tests/static/test.smi tests/static/test.sql tests/static/test.svg tests/static/test.swf tests/static/test.sys tests/static/test.tar tests/static/test.tar.gz tests/static/test.tgz tests/static/test.tif tests/static/test.tmp tests/static/test.toast tests/static/test.torrent tests/static/test.ttf tests/static/test.txt tests/static/test.vb tests/static/test.vcd tests/static/test.vcf tests/static/test.wav tests/static/test.wmv tests/static/test.xhtml tests/static/test.xls tests/static/test.xlsx tests/static/test.xml tests/static/test.xsl tests/static/test.yml tests/static/test.zipFlask-AutoIndex-0.6.6/Flask_AutoIndex.egg-info/dependency_links.txt0000666000000000000000000000000113640414346023400 0ustar 00000000000000 Flask-AutoIndex-0.6.6/Flask_AutoIndex.egg-info/entry_points.txt0000666000000000000000000000006513640414346022631 0ustar 00000000000000[console_scripts] fai = flask_autoindex.run:app.run Flask-AutoIndex-0.6.6/Flask_AutoIndex.egg-info/not-zip-safe0000666000000000000000000000000213636375251021567 0ustar 00000000000000 Flask-AutoIndex-0.6.6/Flask_AutoIndex.egg-info/requires.txt0000666000000000000000000000005213640414346021727 0ustar 00000000000000Flask>=1.1 Flask-Silk>=0.2 future>=0.13.0 Flask-AutoIndex-0.6.6/Flask_AutoIndex.egg-info/top_level.txt0000666000000000000000000000002013640414346022054 0ustar 00000000000000flask_autoindex Flask-AutoIndex-0.6.6/MANIFEST.in0000666000000000000000000000047413636360215014363 0ustar 00000000000000include LICENSE recursive-include tests * recursive-exclude tests *.pyc recursive-include flask_autoindex/static * recursive-include flask_autoindex/templates * include docs/*.rst docs/conf.py recursive-include docs/_static * recursive-include docs/_themes *.py *.css *.css_t *.conf *.html LICENSE README.md Flask-AutoIndex-0.6.6/PKG-INFO0000666000000000000000000000254113640414351013713 0ustar 00000000000000Metadata-Version: 1.1 Name: Flask-AutoIndex Version: 0.6.6 Summary: The mod_autoindex for Flask Home-page: https://flask-autoindex.readthedocs.io Author: RIGAUDIE David Author-email: UNKNOWN License: MIT Description: Flask-AutoIndex --------------- Flask-AutoIndex generates an index page for your `Flask`_ application automatically. The result is similar to the one produced by the Apache module `mod_autoindex`_, but the look is more awesome! .. _Flask: https://palletsprojects.com/p/flask/ .. _mod_autoindex: http://httpd.apache.org/docs/current/mod/mod_autoindex.html Links ````` * `Documentation `_ * `Code repository and issue tracker `_ Platform: any Classifier: Development Status :: 4 - Beta Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content Classifier: Topic :: Software Development :: Libraries :: Python Modules Flask-AutoIndex-0.6.6/README.md0000666000000000000000000000172513640411476014105 0ustar 00000000000000[![Build Status](https://travis-ci.org/general03/flask-autoindex.svg?branch=master)](https://travis-ci.org/general03/flask-autoindex) [![Maintainability](https://api.codeclimate.com/v1/badges/869c538c7fe4f09a5e72/maintainability)](https://codeclimate.com/github/general03/flask-autoindex/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/869c538c7fe4f09a5e72/test_coverage)](https://codeclimate.com/github/general03/flask-autoindex/test_coverage) [![PyPI version](https://badge.fury.io/py/Flask-AutoIndex.svg)](https://badge.fury.io/py/Flask-AutoIndex) A mod_autoindex for Flask ## Requirements * Flask * Python >= 3.6 ## Install ``` pip install Flask-AutoIndex ``` ## Usage ``` import os.path from flask import Flask from flask_autoindex import AutoIndex app = Flask(__name__) AutoIndex(app, browse_root=os.path.curdir) if __name__ == '__main__': app.run() ``` `flask run` ## Test `python setup.py test`Flask-AutoIndex-0.6.6/docs/0000777000000000000000000000000013640414347013551 5ustar 00000000000000Flask-AutoIndex-0.6.6/docs/_static/0000777000000000000000000000000013640414347015177 5ustar 00000000000000Flask-AutoIndex-0.6.6/docs/_static/example.png0000666000000000000000000006012613640377364017354 0ustar 00000000000000PNG  IHDR}jS'tEXtSoftwareAdobe ImageReadyqe<_IDATx t[y4DYL 2-:eYr k]V ^[Z5&avP'6K*̚ mG("Lj#cb5d($<}^88AD[X$Ϸo}8PqZXh.w V=kn7Zn.__=1}g=t,+ʨf:3Xo}-7՚ 덿Jܤ~F³z?3HOh_!A)DVF볦=ƤT*|_ΜJK|%RSB359ϳdh+שw]۞|)Ϸ  s~-Wصѣz{ɷbۺ^w^fsm]=Ƃ\ !+!|d5PO vzG [FNI ef][+e>|tY 2O+|)ӧ'R.hsU`Cko+D>=L^_y>;2_{44`,4#m?=~X) S+O( ޏ@+yKSSh?wEi묝m-/=3O577 #!;QwCnyOc~WL49'?FAzϜ9f7'B1j?*/pG7V3;$y_18"#/IdE={7wQ_{T{{|?ܩ;O;ѣGE.>`yO{繗yRx}߰8}eQ~T+?a=v店1sw;+{ s靦Yum`Ia,{ighS ;-g{G|E7)[qC|N烆7'Bxj?ѣf^cz||J.y<`[-"&DJGP"7>g~Ǎgsu?#:yhH vEMsUޟ{c9dzgO }_Gfyg_<bCe+|FU\N#їo?z-ojaI!L,ww @w֙]@_>H!e0>>^SS3˨uuuh.5Z ܜ{g>|=Q~'a,$e/^wgfOϟ&MOk=u..?RXTӸ]>q7)}Pg `-Iv=I}|c1SO5ozgT zIO?|գI(D]"vcǒE`3I/kyonx5ƳT~iN,K|"ZKJد((ώ{㵟WGI6.{* (_BQfI~џݕP]ݺik̿ 캾 GӇ?ڵرRIJ:*Ϛ9ǘޭ OlIwa~pÏh֙b~[/IKa~w;>ow ~Rw7g~mXR.2DNz꒳hq{%Š)yp$&!~W&Uǐ)1U~*۰C? b0KOSWsԥ`qFv)Y!'Uo>;k,K7. %,~f(wLU"@+˃8<`].Byfw?F@*t> 2܌$n_5q?o U6YՋx-@u@gFG,^JdYpG]O.ǏN$u%oYTw> o_uMɼ4J*GQQtP_DQY*5JfY^pT|_;;u"})GՅOͶ6H.:NI?q?\Qcd6k Ӭ0q; *WolEWګ@@\R5ՀH(`y@&D7C2"Vns0[B)YzƫU$wwX20HF=Jڨ4Qmp3ʍo~u2յt4\U&ZK֬X[X.YG]ku6=K`EW[~CZbP,S˞,5+){ Kolb>tQ;XB^%"#`FuKK gjj7-e5c؎$bאfY8SܾXݤX{oow7|篮|Dbɫ Q#)_n{TąfF\9Iʛ H5z96]ڳ^j 3Bt )P&K9VX=l[ //݉r;6SzHE-o2~#g'ǪTWl۱dƯY[w}{a{h<wALn]pYP2̽bkԊ[%FTH?yfrW BXeT-/37G}pRAEKk[csD+"x$\2,pcVJ]Vc^kxG,D>f_&SOm۔!m>sgRt:d.C7uRTG){ 3N;Q,%Ă[A^a)DA9E.cK3qGtL[ha^SaM$XV[{<Ԧd:ѨGSS_#l?hmúJ: H9QTv᫒3jl#݋UvDPs5Ԗ7\Q]o _<'6?Շv߻oz6ʻZ[,>m_ޫ4f/ɽ< `UZ+(奬x!geו%,P$jE*wQ?bfZtRw<BydiRNi~:VOH ~ٕ"~] ].t* 3#t t]$8ό],g*m;  sk0ykUhA`Q|/`0 s`H^{L0XSsx˭crx-͡>R%ݤ|Zd{+ވK+HЊjtXy$;?w[W?S?9udMUuW7[lln}MB#@r9K-5x]qw( PcxbFTraaAݡV6(=p6*O~`˳,Zӛ<3"\v>3_eS3c?KS'=u7uǽ{Ӆ51\dH돔{{#%*6<_r8nArXicawc?b浆)O8*d9 B ZsWY~@\eɚ.ͦg毒K3/mڻs{붿nNjwx讪oYpiw|7V8}7ˆwwX20HF=yF= r_rLKm=9M%:B4oYeɚ$KRƪzѯַ޵=;fܡ̎kW?qe?&sפ5YlyDVCeJKgjh"Œ¶1.E^g#D+4bA\k:/Թ7oBnEXIXgWmV?uuu_WLبPiiWLM-h ߘZ#5Yʹ4 vM,q)ײd#nLM.3~?}?.Rfrs(fq}%W~GPXt0zȠz+?TdR-Yx 2fe } 6'и®(=)N\8a$. "Fk_)Xs){QaaQo2Pt,ƕCGa-t:t'7c$lG-oNUl::?.uKeS糩 ƒd`]uk.L'uiU*QɃ@o\ڙdۻH96k/-#Y.RP6/Hk'VaVb%s)^ \S&'HpRAu#֡ؔ\7WqdNdQ8\B [" M.oR}^l )b .=Υ'#3ť%.3eg wK.;gvagk$6ꙹkk񅛁X,fr?t.hN)qH eoW }ԎI2OʌEv AȪ'-*`311QN][?⤟M6}}6Ot*,D"*x#)eu4'.@`0FAssYeRU#u]Չԕ_m2Խΐ¿4CZK7eE饚ە;ICż殳mw4ZVɞo]~f:mZX¹+>bbDrig7)AxF=k $lEIo{Ur  Y骄po=_םv?x@#awVŻ{ DHYiR2`vT.ɯ/=9*K.K< sΥ-P.u;D.nETon*%BgXR+ldNaF4 {{-vˀ\!8Vuf{8Z"L2nܛWzA9BSJ3:i-\ y+!/(Ҕplw i4rؼ[;&=e,5ZQ56kF$u![Msu\=SGTU7zufKW1d~qW߯@&g_ 1Z;X1z6k S0qF#*>` -(Nj^MZfO9, \Nkܔ.ͦg毒K3/mڻs{붿nNjwx讪q cug6VpaC '+Ik/Ar8nE'\ekh9:dYNkܔKRƪzѯַ޵=;fܡ̎kW?qe?&sEtWZ8ȭ%* " >妮I&60T [c,}R6Z7&H"v iS^usp>Mt]VX.5#?zӄfLr\z22S$M_NqK\fpsԬ1=짓A@]mRMvݡ(߹4`eXN頶T[}p8݉>N:E;V\ҷƊw s.ΦegKRcl4+/ -}+8BJ'+{kghs7/:l5ϝOsfNYSUݸ͖-=[_Ǽ_}}Q.`ePcx#bP+t 13*?NԱežY3s)e35\֘>53 4uS'|Sǿ9y;y'=?>]Rо-b (#䎻q.u?b浆[8DfTD[hAQtUk檃O!sձ)].;M_%g_Z۴w^]Wmaݎ]U{7I@uf3B;bhDvimT6HͶ6B_W%Wɬ%-Yq(';2V_sd ;ΟNO q\5D³$WP݊p;oh3!:h !/uuuN29u8oiG9SS 3.a5cI^F1Ҽ4#ћձ8+zmw 42ӗIMSB uhv,77͏r)8K9jV`Z㊻CC{| F9!I@t:0vo^:^$9qMXcAKB6!sUs.ΦegKRcl4u}#ns>tѭf|8)c&wP?M0C̵-#5|#)XǢ#ECVz[ wS@2\zK_ҿ1'e.s-A 'e0;TF4Qrp{*6), $HG{QXa_ ׆,UG,/Gg`=}u"udjp uo9#k0f23$SK3؜j*zsbn/; =NBO6gbc.Z131rhU^`y8M4{5uԷzucpb҄|O/gG_=ljZ?G Uw>gO"UD~ a\U%*|fH0wWtčϺᱎE$h9!fW"zGs8b(3n ewDw.\?V#],8W@%yfttX \ ] Q ~`]a.bw ƚP 2BנE|mT؅,]+U%%ief3/ԅ@YnnRqpsLc:]qwHXrhOH:˷ ",H$&lvEX! IRVg7J //݉.]?z֊ [J=ȮM \6Mc-q''+<9.Mt}~qv6quK7H\9)LroEG!Ňj|P:6BUK_)'Bx,H,A鵅5XH$QrXx[ϕo*麗d8ȥ.1 0}\2Wt@~Ap "fD~*z.]Ɩf")JqOVFv)K:D"1^a˴t:QۜU(fM"  [FҐ.X.J=ϬjՉԕ_m2ԽΐL/͐g/cKBtu XnO/#vkiXDWDG\I#zXXIbq.2^S'|A5Q^ZN%,UՈDvՓ?Ϧ#qPU}{6TA䝎f;sM4!-NKA6ӝ0q/*olEWRw)3ˤ_kv8̥Ӽ].;M_%g_Z۴w^]Wmaݎ]U{7I@wLm6^k"ḻ*A*VO4iW FjSn|Ka~uΒp.7jm{m=wmΟ?whn;#f>O\z`b>zC!wSUd*\4qՂ$*tȖ&qAԢoZFk@$IĮ!kzx)]Wd),AG\$ ^%2d65eH24標n/GEK-&AB]v}-hqZk 13j9 Kw>Sb{-v7Q:.C`G:˼lF~8@ DWg [a9MgScsl|6uAxp\]R ;t:M!lBQzb6 Ah7 5I1Mnɐ[vdmQ*.XbD~7~nHKSO|rYBznBІ_8څ-bv5.:OFi_M|=Nvw*DV85򳥙#N+$Go.6H$b뇽qwڔR)I$47w7[r7/U#:k0ޞ:RCwp\5K\53)K3+L ^v{'Qev(6r{}Sig.?IooOk5VБVDʉפ󯎨BzH='ŬYNN;;EK=y(\ՉDvՓ?Ϧ#qPU}{66hoYҞ+{/G.~Wʬb̥;#yfVr(>tD:*+LNqYXk[__tJ'i&*',|^&7.:bY],@ ׏U.KUw.PIpV8W@%*tt`!<3|Tiy`5dWˤ]&S^`B Sg0O#Czg;[nw5dIv~~~0sȚ]nl=/h>hN7"EB@g )0٠M9䫍6`:4qC."\v>3_eS3c?KS'=u7uǽ{INZ]SK]sDA (#䎻xex]χyQbJ&dõ;$y!.GGܘ&\f6{\f\ғ]dқ;M9jӄ{['-C{rJLh`>p h4#j 0V*&LRZ=nѧciНԁv@!Rv'á"sUs.ΦegKRcl4+#&c=4_tEf|8)&wSM smˈ"av !Q5Mmp-><妻L $åǩ >nz{Ypv,[Nk߸OZ MHJ111Q})'En  K~?w*kx>;999>>NHCCo*Coe&丹}Cޘx"0FiPf*Y%1d"HcW $sWaP&UdT$4K,U.}mrjT ,+WEu^#P殰,?vT!r4f}уu 97[=fu Z_yLA)'n1e`FAAD=ֈEѨt&:LÑ7m42 [(gBVm$4c-T&g_) LSκ.u%qioOtVObͩeW})Ջܡ,G)y 76t|(%*:ֹ"7V8l V1 RF=QRkF5Xb$b-M%I[J)Uhi ʨh-C\S*v8E*W~/e7# jxkʱh U'8HLRߴ0[et޳-$?`uyk92\a|vE:}gյ?6lR~ y6k]Fc!voIGYJs@0Beڮ&*r"96ژݡzVPNޥ>x5zPxlW/>k]M }[$)An{WTTE$j9%TG-^ڂ G"LO\ZqwjWȦ:[Ӈo7XSy~:Ƃ7:8pݾX->3bb=NB>6&Av=h 'a6a^m`vSFhKevs vSF=ԖA/뤯l%aQ(sD^֡ 1}yر֒eztӗ/ɷv~ y:g|H3nUMYklEOx|::vfmH75(WE#*wk4Kޤ[ vCES2:2CȇO[lT%4P07hVntjFn=iٗ )n-'5PEG,:FFFƲlhTtlق(571Zj; @wwt]$8ό]@w\:bd2966dt#{F#Rݱcǚ5k R:~H/P~~nnN]*lv~~z8ޣ#p Qť[UUe0K֭۹sӧO:(]}Y/`Az󚚚Ν[v>GzTq94dw"027d946n ɷOqξηg%C7PNElg?NF\75l>梂hNWZ"^!3̍{^ARm gT~|1rWsUQ塭N hMzU**T,Kx t |{w'JNOO_tŋVԘn_t̨/2A[UΌ(Grqs9}&// 9I^Ubf@k I7iI Bs,eĨu|:wiP3Dl]tIA23nuo3yd½Lz갮mg-LXTЩQyZ+ H!Q52{DWWUǎnMze(UkupV-: w}b_.b鵅LrYsJMsdKG 5?ӕ{'w/3{#jo MZ}Dw+RuR}Dx> 9|@}G>"pSvD[Fֻ5W4K4'XG&swH>6;uOMxuix_"ƻɷO؏a'yOL`.~stoe_B ij yL3#tV/RxCu|D[__e-NZ^` ~?3@G@w.p].t* 3#jt]$8WX:t~>Le2{*Ttwرf$=}*oɺK6u]<@<V1{tҡN"Tzziݺu;w<}S /+,H/}^SSS[[ܹs^*8U")F Yo)v;+;T_UGRC3=*x6x#:!lGNFJR,_m&)f]0} :"WEE[L*hx vN |{w'JNOO_tŋVԘn_tj@W/sX}@]>$~rRE2]Q=|xDm=. 9 g!{4)ӵQ'6"DWT QR^P)|f%Z%3gP:%l /lYxzm|t2оw#2)ldڽ=Z_K92e6LK#i6qwU !tDo:/2_PSGMhYNݗ@K;+C-st^+%oXvEX\r$SUuIMK[>6{mFF&lML]"%Ef )I<6.KnimrGBh ^i =(JrÑETH':)KK,N`ŦGdW Vg~{:^*˭p;oqc3FyL&bg?$7!=o&;`8*wY#?5+98@tp]GuAnRޮTEpP]X(Dܺ/UG֮8 PXA9_׫])\VD"BvMLrީ|\wF6=?kydւFQFk 9ܭ/ɷGZo~h6HCfbn/qw-Ic#]a׃ ڨ=Ngޕv̵N|9iSjOt{Uuք0˨/oT]*2~e NՋcjJlgX#[>"]Y;Зn9{foW"x#=K[rp## R0ޭhȼAnJٱ/pnv*P0wOĬ v}hcSٳmڽv78Lս4߼ (NMl=uIQǷH4*[l1He: 5=F ] z @%yfttX \ K'ɱL&{5!@%t#'w{׬YC&(SMm6^"ḻ*A:[=Ѩ])yZ& qʹ(:\*2[OGsΝ,+Of)+nb/JusE]#XK@nZ\.yò{r\b]^r皱=şzy$_QB)\ـwxG>9.v@f조ɥ4iU;4l*vr h =4tLM-loLR-*אfRs MξrtU&/D娛.fb_kGZN!j]1-3[;x^ s)o_t{Fn*ukao\/{|BD]B_l?4YΛl =M|=,l}~ClFH渣78t`&NE@&tdJݲn1\buיaVV&IvMjXTp'ɖfⳳVS)춦OnόS[C5JsSOŏoIJ2F63=Zg)y:Mu6r_M 3>^t{D%T7M ta‚N smˈ">I\3fk#)"`#/jمT\fMG7N# 6yMKu]eۺG2G6d$u=ɳzgӷ !um',w\>"뷑,RSgb߁fcb!-|\z듑$оFvu}[|K^=N"8I}l3:zZ10ۋ2] .#_eW9=TM̚+"Yt- b./[E/Xzm!\ +xmzPS)mpտ{O_;v쳏|<9uڵ\pߗշS~W3Ie~&555<ȹsp/(ݽ<=?j\:NS5ɿųMMM`uSQ.x#bP+t 13*?NԱ^^YnZX]rޒڢ߶j}#35l{fg2T&onڸ~{_ne;i9 b"'.~x]χ a6PD[hAQtUk檃O!sձ6\FkOn ݺh]Ѩ^!Az}]6<^{Kc W7r|k֬ҋ)զ6qwU !tTzpݮµ61^mmmD7EJYM [Lz!j=UE;.jDTJw)ǽ0y5c{?'Hb$s$}^]S'>a7DothH;C^'d9w"0&Eoـӫb ޘ*C}h =*Hljj7-e5c,KjrKX2,sDlMיoyu֊ngg1\įSm=Mn16}OQCHȺ+_hу=dBXi牋T^|ݵE:[Asφ[[= &|QcAL| ➬ t g{tDĽFn( EʂDAs"[RGZR1S^ pLYu'.VJ}BjOXW/|Do#Y¥/< i=Uܯv' ij y({fcDwyv ii-.00w>w.mgY-;Cr-20Iim-tѥ%(\x"D/፧x)=Ơ@u!y ! @BF51MT*:eztfvwfK=Db۝o|˥9FfV@Cl^'15oGFsdLUy7Yd+i2+/e~2i]|}JzRq v8cVz>$z^>X6e[V0T5I{5M;g}}Ν;WN/< sωgOV9kumܾU63*+|u~˵76>* 7V-R36wޫ,--a0Dk~eʵK= acZ}\-jO\J}gO8+`&vsyG Won2x =&bo @pGx@ Ļt1iL-\9 @w.t~c?XL#9(wf}H{ːGiwA؏4}yao>~^^="ӧN ~®Ovy'g= $ ~"Cm}֏O#aĻcL*6j#:Kaa*'"1̖^m+m>T[uG S"MT<8)l%:RCdjh25[֩/Us'3 SJ֡ ۔}&SHfhj!Uw*kӃJ4 QbXP"dGҿi' Y+k/ roMDxoZk8hdrkd>q-]$z|pͨv]^b/lD%+*"rT<T^&Iv69iBAt*M* E59!1*6"U @QBGuSJMh_Y/(zzŒK-H '<ɖGEMze*G ɲ7N~s9+nȜ+_>/:(ڬ|odnؒdz.ɧu*/d 1 \3Üw ] ܿ'<}9|3]~IUfAfiAbjtzڢTR<9LU7'Zd2feNx:W 9vB-ڱz=k?KذjX`!Pf-ZCwiA.mJ&3!f Aw{:6"M70dqO'v5wE, alDHݳ(DW#;Wvy44$_<)bQf33Nn"t,,M4\޺>u4vg)01¿"jY-! K$**;ߴY7W2?aǕ32urr`uzFdvIO2m'(L#6EⲕhNݲ!{Ԫas%C }t'\xN#&4CJv##bM ,u!%uENP@M=UQG=_%$cR&ϳ-4X쩨2/'lUk)?)+.٦py{>biQe1hK-Nnm,M˞"6T꫑@)/p.w7k/vCwyG~!w̪/a?~׎ 5Yx Owm#S3CnD`[ol^/+2wwm}^p c?D10NtwQ_oʥeūݣRw{{H[=! }\*?P[M=l[?{.LCBjF:w3u{@@w flask-autoindex_resized iG'0IDATxq"օuÉ`U"0MD`8#V af6YnoX[-G[[[QEQEQ_,((EQEQ((EQEQE((XEQEQ,((EQEQE(("`QEQEQ,((EQEQ((EQEQE((XEQEQ,((EQEQ'KjSocɏ1sEQEQ"4%SO5f^7yZ< sEQEQOjqRgkMO!nATa,{&{4{8(N^S1c&Y =:').~bF_EQUrcRS=MKa*{u={xsZ`x1,(`=e?{wC@Wן`q|ŦO59Ɓt9sSK #sT5pSKu#E `1d0pU>ߕ~&q-W{*2Հ37SH;A:*4qt EUq3`C((;772``|[03n@Q)[t~\T|1^W5|Lah ZJ. oJ!/1(&2.eՏЂ6*m}`!eF؈zڰX!'% :vmC3F" n^ onтNR/mw/b܏A% [>""H*kQ˙c?[zZ>CB+V)sj!Ϥ_A`z.^zI;14Vcu@ajkz'!r~ < 1ݙ; h|8$ɺ4N`-jeSQNQtjo _Y^bA1S\=+;Rgt!Ҧe@I^WL'f+ fg')f5j 9FL4uZlJFxWG~iB?8o "#D;':6K ;SCu蛅負No뮟ٹ6m#HW?>!(yy^`:u3 X:g),{ පeUW[T,ϚޠW9>EaI}M:@,hWtu»Ա{V`UܭE:XUy!m=蜥t e>[ʒ=xɱCZtm*)qA :;Ukƿz7chAH+M\=%|6&$0}*/{R ^9k叶~.ߔmy˙j RuRy FmuyCOQ2Gb=|E6T;#({1দ(괥pׁ߉5݃ LF`K^>,`mXU̓6P^"LQHJ!_%E;d`6qxX>8]xN]8n>;*@;jK Rj. Jcb3\jW ={40bG#9lT6EgՠE&0,Yr=z5k_Byv>;V}*lnC#)ՎG?dS_AՔ ڍ|p+ C`akpi'#M XU,^YjR1'~7%+3G3dJr[ͬ2][$؉f| ?{#|ېU96Jѕ8C 25(Z:-kZX>{o0Ol c;@\?2.S|6 gà DoWKz`3Saj;RWn,*}P,l%1KήK\hc<,!ct9$1–e5E7rF_(' Q.=+&֐;7 :ߖw|`:: 4ތ qհ[4)H\7t+j^lnM:p>|n(ʼz!~YpDKcklX~i,tvg@ZPQ=m՘_cSW Xnzy‰ZMmuj `Z"J10˕~X4b5wZ}pw#8C/;]gcu[|LśVķE8Mw95t , c,`SjWps%uZ膸jRh54s e'S3 J uP$] _%Hc?N OEX~yRꞖkŮ[v;I[^'>U3}ѣ/_؎br]g(o1*os-+bnt#tl:Dt7zqc L\ejI} NG;G3 L 5yy1&S@KY:дTGYW%awڕH̆@@8v(%x6sͤA#]4Pxn빱>@ĐZ8njO*V eݫ/}@oFl۫6#Oum@}IYl}2icp4N!Q:U';VkW೐V^>n-pMmMx9G=V]h+ ڻ+??,\@GX/q6\5văq ƨ5z#,Yq^% ϶{K :;^LymSh޽U֭t_TvNIͪ@%:WhdH YVцG*WO9KYsZԦ]W.Я%akZon:K O{qpPWiZڤCo^r  N $b`)*SXekE YՊ7qm<8E5r^A5K_yl 9΃eP~ SkO`5`46FMZ*PuyhhV $~hcq %CEӀ+=~˗ל7_V`!Yf~^4X>]ch%>:Q@ԣeߗ)ӞW:,[gtHȊ:ӏd*w4Wi?X>VocGh3VZ̶8V LjBCÕH#p`/4xky}9o9Q@ʗ8+1zDps{zC+ oS!@sK:ՎuhXr?ǖ5-onZ[gK+CU[=KhWգMi^|cݿlZoX\5RL[g7xn=ep_!֣kڴ\^}$DZ7oS~2(gtX} e5r|0I m* ͰDGQgD~?TT)Ve~G+Q2bղᧈ xiJZ-h)g~4Ku&GF,)M=r鵭pvum꺔IݼWޣFup!n^ѧ]6II%ub:QmvJyzwxgHGm龌XR)-{Můw>Q;vW9e˖1=ʏP;UvffO-X(#~S&Nyc`d@[{'C1Fd1 DPe[a "+G) I>5`gqx_ɒT4۹̸ XOԾ X8K7:a!5L86ajI?4guoc"#`PX*Qih,!`EUW;rjG\{^8 [9aݭxSZu|)ite2Hu]`E6D[ >E݉`j`Ŭ|f0SC962)d vpq f1El\a$U"n0$= 4#ls1ʴ),U1zw{xy<ɁcB̴H؆+t _]4).C8ro6VNz҃Mk:`,WQ6혽#ŗ1Khms`{يA=V3_ u蓘ؑTTۢ{LJr?JM:7plPk=m't[O~./~XquzpuGp Bh`'8ogY~q{7%f$OK~Nm`i#»2ewh+|ZS&xB1VJ O6|RuU,Ē qɴY!OT2 :WԺ#'޾-o{%؃ |b3 @# M Vئ$ukwY21Qu:P@^:JbYvoO[ 9;*-%ٟǿf<[kybf-K Z/-|>+ (v1b|O;ɼ\ek*5zM® N)k)VWζ1+X!1%zh丹$TcqB#/ܷ݃U 94}5EeO,YWTUiEmqvp<թJ쫘1i4ֳ9ǨUcp+Oe R-$1JXI^Qg[M+yyp1ƹǀ[Ǻ؇G U6eÆm/u`%S`b;ɍuw{ tJNaMӅ{p=l70uב; ,(aޠn`(i?:2y* b೮/ z(r/f_!XdJq-5z0h6'fI=VP{J*wD 374iæ+~ v[ npB-S`%L"dEXm q=b9M i-YbZΟY뽞~'n}VohˇZO2z @V 5fD<\zCj9?eEO>"5fnt GlW\ͭsA#2XXDD}T骽U-ڭFQ 5IsB^{4辇p^E7W t`udzy 4u046+ۇWU-2 Nq|:w% S?-]n L+Q4M ]tIZ'ײuD7Hz+SRtWxHH!~Hύ+᳊zV} VvCO}[si)c8 8zОDj[.[ٴO)_XS,Ti}H4`[T0U( !kqm4\s\gADyy4sjh ~Q~R(A67}n"(ۑ|,;h}n_ƙ %=kWpLg yw?|& Z-Fjl=Gf*$:ixb)9~8anQ4MV"B,Q \ۜӲ4:5SU?M<%>) |weLT.n#tH'H[u.I_±Q}>T̊ZXVLϜ7П|K}>{fZH|I2"Y~6|VQZweּciulpO޻Z'㻛*o% 5@\ (cmT}p4J=#cߖcUM܎"WA=P^#ԛעFwVB!i( ֝Pep{rԇ~Ċ.{M%@~Mz6щ7(Y&3!,łժioZƴHP{@+Ӏen%"_G,e\'yd oِF}u-lv~6 >{u`KoѾX9`Ex9s{u)X\-@zG?.Wz D)ͱ^=ԓq2w+ZG'KRa‘AiC>"V]^%t@7L'`ŭWyKoLmiA<-dKA>˾Q8[,;ڗH?p$vMT%cj@֨`4*gg]td/lN=J:>+q-W%ElΠeۄڡHݡl.=8w儍uG?uNP꣤{ fVa@HbKHٱ=gu#pY7C8*]Ix +_Xi\y1nv8smQt'KyE]Y/Z% qLMI# `h!-ܯMQ& Mq W75#z4'1:٘UQ3Jϯʬ4q^$߸Dy>y\QL&)7ׯ94@Y=8i1t6;1gCbق%>Ωec?zp~*u?s^ :ʶ(O˴[kczkŀrNB5H% [Oο\}w% {P$L"JW*v7"Vs5RpUGUU y{ܬw};3!A=hAUh{\m g۩,Mh;#X/Lr:nNju] QE 6tQ@7gݒ }u{kX?G(.48L10+_v&枹[ hTP` {SR6_Ƃqu :rۙ)i_\ 8W \f|@N{^Ӎѳׁ :.jeV_ӈB ,N[tg4%%y6vᩅyq%!K,ݹ~]2rB*s US|"|ՔBgk,V,Xgg<_tyg~j}侚Nn\aNy]ꊙ~[~4[yX?I9bA=VpO T*W Z~rWl{vhPNS0Vr Y@,6p A[vXDdJ:~Je&X vbYӦ f,*7( Kza|.a,筼[ wӳ8^|h^vc XEQEQ,((EQEQE(("`QEQE((XEQEQ((EQEQE((XEQEQ,((EQEQE(("`QEQE((X((EQEQWڪIENDB`Flask-AutoIndex-0.6.6/docs/conf.py0000666000000000000000000000377513640411755015064 0ustar 00000000000000# Configuration file for the Sphinx documentation builder. # # This file only contains a selection of the most common options. For a full # list see the documentation: # https://www.sphinx-doc.org/en/master/usage/configuration.html # -- Path setup -------------------------------------------------------------- # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # # import os # import sys # sys.path.insert(0, os.path.abspath('.')) # -- Project information ----------------------------------------------------- project = 'Flask AutoIndex' copyright = '2020, David RIGAUDIE' author = 'David RIGAUDIE' # The full version, including alpha/beta/rc tags release = '0.6.6' # -- General configuration --------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ ] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # html_theme = 'alabaster' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # The master toctree document master_doc = 'index'Flask-AutoIndex-0.6.6/docs/index.rst0000666000000000000000000001553713640411105015412 0ustar 00000000000000Flask-AutoIndex ~~~~~~~~~~~~~~~ .. module:: flask_autoindex .. figure:: _static/flask-autoindex.png :alt: The Flask-AutoIndex logo Flask-AutoIndex generates an index page for your `Flask`_ application automatically. The result is similar to the one produced by the Apache module `mod_autoindex`_, but the look is more awesome! Look at this: .. figure:: _static/example.png :alt: The screenshot of index page generated by Flask-AutoIndex This module contains a pre-designed template and CSS file which provide a default style. You can also design your own style. .. note:: Flask-AutoIndex uses `Flask-Silk`_ to serve icons. By default, the icons used are from Mark James's `Silk`_ icon set. These icons are licensed under `Creative Commons Attribution 2.5 license `_ or `Creative Commons Attribution 3.0 License `_. Before using the icons, read the license. .. _Flask: https://palletsprojects.com/p/flask/ .. _mod_autoindex: http://httpd.apache.org/docs/current/mod/mod_autoindex.html .. _Flask-Silk: https://pythonhosted.org/Flask-Silk/ .. _Silk: http://www.famfamfam.com/lab/icons/silk/ .. _CC-BY-2.5: https://creativecommons.org/licenses/by/2.5/ .. _CC-BY-3.0: https://creativecommons.org/licenses/by/3.0/ Installation ============ Version 0.6.4 requires Python >= 3.6; Versions < 0.6 also work with Python 2. Install Flask-AutoIndex with ``pip``:: $ pip install Flask-AutoIndex or check out the development version:: $ git clone git://github.com/general03/flask-autoindex.git How to Use ========== Flask-AutoIndex is easy and extensible. It supports flask application. We will make the application in flask application. Basic usage:: import os.path from flask import Flask from flask_autoindex import AutoIndex app = Flask(__name__) AutoIndex(app, browse_root=os.path.curdir) if __name__ == '__main__': app.run() After running the application, ``http://localhost/`` serves a generated index page which contains the file and directory list in current directory. Or, use a shipped console script. Just type ``fai`` in the command line. (yes, ``fai`` is an acronym of Flask-AutoIndex):: $ fai * Running on http://127.0.0.1:5000/ Customizing =========== Routing a specified URL ``````````````````````` Just like a normal flask application or module. Follow the example below:: @app.route('/helloworld') def helloworld(): return 'Hello, world!', 200 ``http://localhost/helloworld`` will serve ``Hello, world!`` not ``/helloworld`` directory. Adding an icon rule ``````````````````` If you want ``*.feed`` files to use the ``rss.png`` icon and directories named ``pictures`` to use ``folder_picture.png`` icon, follow the example below:: idx.add_icon_rule('rss.png', ext='feed') idx.add_icon_rule('folder_picture.png', dirname='pictures') You can change the root directory's icon to your own icon:: idx.add_icon_rule('http://example.org/favicon.ico', cls=RootDirectory) Also you can add a more complex rule with a function:: import re def is_flaskext(ent): return isinstance(ent, Directory) and re.match('[Ff]lask-', ent.name) idx.add_icon_rule('http://example.org/flask-extension.png', is_flaskext) Here is a nice example for changing a directory's icon to the ``favicon.ico`` file inside it, if present:: def get_favicon(ent): favicon = 'favicon.ico' if type(ent) is Directory and favicon in ent: return '/' + os.path.join(ent.path, favicon) return False idx.add_icon_rule(get_favicon) .. seealso:: :meth:`AutoIndex.add_icon_rule` Changing Silk's path ```````````````````` :class:`AutoIndex` has ``**silk_options`` keyword arguments for :class:`Silk`. If you want to use another path for serving silk icons, use the ``silk_path`` keyword argument:: idx = AutoIndex(app, silk_path='/myicons') Now you can get a silk icon from ``http://localhost/myicons/folder.png`` not ``http://localhost/__icons__/folder.png``. .. seealso:: The documentation for `Flask-Silk`_ Redesigning the template ```````````````````````` :meth:`AutoIndex.render_autoindex` finds the template from the application's template directory first. When you made the ``autoindex.html`` to the application's template directory, :meth:`AutoIndex.render_autoindex` renders your template:: - myapplication - templates - autoindex.html - __init__.py - views.py Your templates could extend the default Flask-AutoIndex's template, named ``__autoindex__/autoindex.html``. Here is a basic example: .. sourcecode:: jinja {% extends '__autoindex__/autoindex.html' %} {% block meta %} {{ super() }} {% endblock %} {% block header %}

My Application

{% endblock %} {% block footer %}
{% endblock %} To get extra fields through to your template, pass them in the ``template_context`` keyword argument:: AutoIndex(app, template_context = dict(SITENAME = 'My cool site')) API === Configuration ````````````` .. autoclass:: AutoIndex :members: Models `````` .. autoclass:: Entry :members: .. autoclass:: File :members: .. autoclass:: Directory :members: .. autoclass:: RootDirectory :members: Template ```````` Blocks ------ `meta` The innerHTML of ````. `header` The top of ````. `table` The table for the entry list. `footer` The bottom of ````. Variables --------- `curdir` The current directory object. `entries` The child entry list of ``curdir``. `sort_by` The sorting key. `order` Ascending order(``1``) or Descending order(``-1``). `endpoint` The endpoint which renders a generated page. Licensing and Author ==================== This project is licensed under the MIT_ license since version 0.6.4. See LICENSE.md_. Previous versions were licensed under the BSD_ license. The main author is `Heungsub Lee`_ up to version 0.6.2, and `David Rigaudie`_ starting with version 0.6.4. Questions and patches are welcome, please use the issue tracker on the `Flask-Autoindex GitHub repository `_. .. _BSD: https://en.wikipedia.org/wiki/BSD_licenses .. _MIT: https://en.wikipedia.org/wiki/MIT_License .. _LICENSE.md: https://github.com/general03/flask-autoindex/blob/master/LICENSE.md .. _Heungsub Lee: https://subl.ee/ .. _David Rigaudie: http://rigaudie.fr/ .. _fai_gh_repo: https://github.com/general03/flask-autoindex Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` Flask-AutoIndex-0.6.6/flask_autoindex/0000777000000000000000000000000013640414347016001 5ustar 00000000000000Flask-AutoIndex-0.6.6/flask_autoindex/__init__.py0000666000000000000000000002557513636360215020127 0ustar 00000000000000from __future__ import absolute_import import os import re from flask import * from flask_silk import Silk from future.builtins import object, str from jinja2 import FileSystemLoader, TemplateNotFound from werkzeug.utils import cached_property from . import icons from .entry import * __version__ = '0.6.3' __autoindex__ = '__autoindex__' class AutoIndex(object): """This class makes the Flask application to serve automatically generated index page. The wrapped application will route ``/`` and ``/`` when ``add_url_rules`` is ``True``. Here's a simple example:: app = Flask(__name__) AutoIndex(app, '/home/someone/public_html', add_url_rules=True) :param base: a Flask application. :param browse_root: a path which is served by root address. By default, this is the working directory, but you can set it to fix your app to always use one location if you like. :param add_url_rules: if it is ``True``, the wrapped application routes ``/`` and ``/`` to autoindex. default is ``True``. :param template_context: would be passed to the Jinja2 template when rendering an AutoIndex page. :param silk_options: keyword options for :class:`flask_silk.Silk`. """ shared = None def _register_shared_autoindex(self, state=None, app=None): """Registers a magic module named __autoindex__.""" app = app or state.app if __autoindex__ not in app.blueprints: static_folder = os.path.join(__path__[0], 'static') template_folder = os.path.join(__path__[0], 'templates') shared = Blueprint(__autoindex__, __name__, template_folder=template_folder) @shared.route('/__autoindex__/') def static(filename): return send_from_directory(static_folder, filename) app.register_blueprint(shared) def __new__(cls, base, *args, **kwargs): if isinstance(base, Flask): return object.__new__(AutoIndexApplication) elif isinstance(base, Blueprint): return object.__new__(AutoIndexBlueprint) else: raise TypeError("'base' should be Flask or Blueprint.") def __init__(self, base, browse_root=None, add_url_rules=True, template_context=None, silk_options=None, show_hidden=False, sort_by='name', order=1): """Initializes an autoindex instance.""" self.base = base if browse_root: browse_root = str(browse_root) else: browse_root = os.path.curdir self.rootdir = RootDirectory(browse_root, autoindex=self) self.template_context = template_context if silk_options is None: silk_options = {} silk_options['silk_path'] = silk_options.get('silk_path', '/__icons__') self.silk = Silk(self.base, **silk_options) self.show_hidden = show_hidden self.icon_map = [] self.converter_map = [] if add_url_rules: @self.base.route('/') @self.base.route('/') def autoindex(path='.'): return self.render_autoindex(path, sort_by=sort_by, order=order) def render_autoindex(self, path, browse_root=None, template=None, template_context=None, endpoint='.autoindex', show_hidden=None, sort_by='name', order=1, mimetype=None): """Renders an autoindex with the given path. :param path: the relative path. :param browse_root: if it is specified, it used to a path which is served by root address. :param template: the template name. :param template_context: would be passed to the Jinja2 template when rendering an AutoIndex page. :param endpoint: an endpoint which is a function. :param show_hidden: whether to show hidden files (starting with '.') :param sort_by: the property to sort the entrys by. :param mimetype: set static mime type for files (no auto detection). """ if browse_root: rootdir = RootDirectory(browse_root, autoindex=self) else: rootdir = self.rootdir path = re.sub(r'\/*$', '', path) abspath = os.path.join(rootdir.abspath, path) # Disallow to access to an upper path. # This issue was reported by @r4dian. # https://github.com/sublee/flask-autoindex/issues/18 relpath = os.path.relpath(abspath, rootdir.abspath) if relpath.startswith(os.path.pardir): return abort(403) if os.path.isdir(abspath): sort_by = request.args.get('sort_by', sort_by) if sort_by[0] in ['-', '+']: order = {'+': 1, '-': -1}[sort_by[0]] sort_by = sort_by[1::] else: order = {'asc': 1, 'desc': -1}[request.args.get('order', 'asc')] curdir = Directory(path, rootdir) if show_hidden == None: show_hidden = self.show_hidden entries = curdir.explore(sort_by=sort_by, order=order, show_hidden=show_hidden) if callable(endpoint): endpoint = endpoint.__name__ context = {} if template_context is not None: context.update(template_context) if self.template_context is not None: context.update(self.template_context) context.update( curdir=curdir, entries=entries, sort_by=sort_by, order=order, endpoint=endpoint) if template: return render_template(template, **context) try: template = '{0}autoindex.html'.format(self.template_prefix) return render_template(template, **context) except TemplateNotFound as e: template = '{0}/autoindex.html'.format(__autoindex__) return render_template(template, **context) elif os.path.isfile(abspath): if mimetype: return send_file(abspath, mimetype=mimetype) else: return send_file(abspath) else: return abort(404) def add_icon_rule(self, icon, rule=None, ext=None, mimetype=None, name=None, filename=None, dirname=None, cls=None): """Adds a new icon rule. There are many shortcuts for rule. You can use one or more shortcuts in a rule. `rule` A function which returns ``True`` or ``False``. It has one argument which is an instance of :class:`Entry`. Example usage:: def has_long_name(ent): return len(ent.name) > 10 idx.add_icon_rule('brick.png', rule=has_log_name) Now the application represents files or directorys such as ``very-very-long-name.js`` with ``brick.png`` icon. `ext` A file extension or file extensions to match with a file:: idx.add_icon_rule('ruby.png', ext='ruby') idx.add_icon_rule('bug.png', ext=['bug', 'insect']) `mimetype` A mimetype or mimetypes to match with a file:: idx.add_icon_rule('application.png', mimetype='application/*') idx.add_icon_rule('world.png', mimetype=['image/icon', 'x/*']) `name` A name or names to match with a file or directory:: idx.add_icon_rule('error.png', name='error') idx.add_icon_rule('database.png', name=['mysql', 'sqlite']) `filename` Same as `name`, but it matches only a file. `dirname` Same as `name`, but it matches only a directory. If ``icon`` is callable, it is used to ``rule`` function and the result is used to the url for an icon. This way is useful for getting an icon url dynamically. Here's a nice example:: def get_favicon(ent): favicon = 'favicon.ico' if type(ent) is Directory and favicon in ent: return '/' + os.path.join(ent.path, favicon) return False idx.add_icon_rule(get_favicon) Now a directory which has a ``favicon.ico`` guesses the ``favicon.ico`` instead of silk's ``folder.png``. """ if name: filename = name directoryname = name call = lambda m, *args: m.__func__(self, *args) if ext: call(File.add_icon_rule_by_ext, icon, ext) if mimetype: call(File.add_icon_rule_by_mimetype, icon, mimetype) if filename: call(File.add_icon_rule_by_name, icon, filename) if dirname: call(Directory.add_icon_rule_by_name, icon, dirname) if cls: call(Entry.add_icon_rule_by_class, icon, cls) if callable(rule) or callable(icon): call(Entry.add_icon_rule, icon, rule) @property def template_prefix(self): raise NotImplementedError() class AutoIndexApplication(AutoIndex): """An AutoIndex which supports flask applications.""" template_prefix = '' def __init__(self, app, browse_root=None, **silk_options): super(AutoIndexApplication, self).__init__(app, browse_root, **silk_options) self.app = app self._register_shared_autoindex(app=self.app) class AutoIndexBlueprint(AutoIndex): """An AutoIndex which supports flask blueprints. .. versionadded:: 0.3.1 """ def __init__(self, blueprint, browse_root=None, **silk_options): super(AutoIndexBlueprint, self).__init__(blueprint, browse_root, **silk_options) self.blueprint = self.base self.blueprint.record_once(self._register_shared_autoindex) @cached_property def template_prefix(self): return self.blueprint.name + '/' class AutoIndexModule(AutoIndexBlueprint): """Deprecated module support. .. versionchanged:: 0.3.1 ``AutoIndexModule`` was deprecated. Use ``AutoIndexBlueprint`` instead. """ def __init__(self, *args, **kwargs): import warnings warnings.warn('AutoIndexModule is deprecated; ' 'use AutoIndexBlueprint instead.', DeprecationWarning) super(AutoIndexModule, self).__init__(*args, **kwargs) @property def mod(self): return self.blueprint Flask-AutoIndex-0.6.6/flask_autoindex/entry.py0000666000000000000000000002574713640402435017526 0ustar 00000000000000from past.builtins import cmp from future import standard_library standard_library.install_hooks() # -*- coding: utf-8 -*- from datetime import datetime from fnmatch import fnmatch from mimetypes import guess_type import functools import os import re from future.utils import with_metaclass from future.moves.urllib.parse import urljoin from flask import url_for, send_file from werkzeug.utils import cached_property Default = None is_same_path = lambda x, y: os.stat(x) == os.stat(y) def _make_mimetype_matcher(mimetype): return lambda ent: fnmatch(guess_type(ent.name)[0] or '', mimetype) def _make_args_for_entry(args, kwargs): if not args: raise TypeError('path is required, but not given') rootdir = autoindex = None args = list(args) try: path = kwargs.get('path', args.pop(0)) rootdir = kwargs.get('rootdir', args.pop(0)) autoindex = kwargs.get('autoindex', args.pop(0)) except IndexError: pass return (path, rootdir, autoindex) class _EntryMeta(type): """The meta class for :class:`Entry`.""" def __call__(cls, *args, **kwargs): """If an instance already initialized, just returns.""" ent = cls.__new__(cls, *args, **kwargs) try: ent.path except AttributeError: ent.__init__(*args, **kwargs) return ent class Entry(with_metaclass(_EntryMeta, object)): """This class wraps file or directory. It is an abstract class, but it returns a derived instance. You can make an instance such as:: directory = Entry('/home/someone/public_html') assert isinstance(foler, Directory) file = Entry('/home/someone/public_html/favicon.ico') assert isinstance(file, File) """ HIDDEN = re.compile('^\.') def __new__(cls, *args, **kwargs): """Returns a file or directory instance.""" path, rootdir, autoindex = _make_args_for_entry(args, kwargs) if rootdir: abspath = os.path.join(rootdir.abspath, path) else: abspath = os.path.abspath(path) if os.path.isdir(abspath): return Directory.__new__(Directory, path, rootdir, autoindex) elif os.path.isfile(abspath): return File.__new__(File, path, rootdir, autoindex) else: raise IOError('{0} does not exists.'.format(abspath)) def __init__(self, path, rootdir=None, autoindex=None): """Initializes an entry instance.""" self.rootdir = rootdir self.autoindex = autoindex try: rootpath = self.rootdir.abspath if not autoindex and self.rootdir: self.autoindex = self.rootdir.autoindex except AttributeError: rootpath = '' self.path = path self.abspath = os.path.join(rootpath, self.path) self.name = os.path.basename(self.abspath) self.hidden = bool(self.HIDDEN.match(self.name)) if self.rootdir: self.rootdir._register_descendant(self) def is_root(self): """Returns ``True`` if it is a root directory.""" return isinstance(self, RootDirectory) @property def parent(self): if self.is_root(): return None elif is_same_path(os.path.dirname(self.abspath), self.rootdir.abspath): return self.rootdir return Entry(os.path.dirname(self.path), self.rootdir) @property def modified(self): """Returns modified time of this.""" return datetime.fromtimestamp(os.path.getmtime(self.abspath)).replace(microsecond=0) @classmethod def add_icon_rule(cls, icon, rule=None): """Adds a new icon rule globally.""" cls.icon_map.append((icon, rule)) @classmethod def add_icon_rule_by_name(cls, icon, name): """Adds a new icon rule by the name globally.""" cls.add_icon_rule(icon, lambda ent: ent.name == name) @classmethod def add_icon_rule_by_class(cls, icon, _class): """Adds a new icon rule by the class globally.""" cls.add_icon_rule(icon, lambda ent: isinstance(ent, _class)) def guess_icon(self): """Guesses an icon from itself.""" def get_icon_url(): try: if self.autoindex: icon_map = self.autoindex.icon_map + self.icon_map else: icon_map = self.icon_map for icon, rule in icon_map: if not rule and callable(icon): matched = icon = icon(self) else: matched = rule(self) if matched: return icon except AttributeError: pass try: return self.default_icon except AttributeError: raise GuessError('There is no matched icon.') try: return urljoin(url_for('.silkicon', filename=''), get_icon_url()) except (AttributeError, RuntimeError): return 'ERROR' return get_icon_url() class File(Entry): """This class wraps a file.""" EXTENSION = re.compile('\.([^.]+)$') default_icon = 'page_white.png' icon_map = [] def __new__(cls, path, rootdir=None, autoindex=None): try: return rootdir._descendants[(path, autoindex)] except (AttributeError, KeyError): pass return object.__new__(cls) def __init__(self, path, rootdir=None, autoindex=None): super(File, self).__init__(path, rootdir, autoindex) try: self.ext = re.search(self.EXTENSION, self.name).group(1) except AttributeError: self.ext = None @cached_property def data(self): """Data of this file.""" with open(self.abspath) as f: return ''.join(f.readlines()) @cached_property def mimetype(self): """A mimetype of this file.""" return guess_type(self.abspath) @cached_property def size(self): """A size of this file.""" return os.path.getsize(self.abspath) @classmethod def add_icon_rule_by_ext(cls, icon, ext): """Adds a new icon rule by the file extension globally.""" cls.add_icon_rule(icon, lambda ent: ent.ext == ext) @classmethod def add_icon_rule_by_mimetype(cls, icon, mimetype): """Adds a new icon rule by the mimetype globally.""" cls.add_icon_rule(icon, _make_mimetype_matcher(mimetype)) class Directory(Entry): """This class wraps a directory.""" default_icon = 'folder.png' icon_map = [] def __new__(cls, *args, **kwargs): """If the path is same with root path, it returns a :class:`RootDirectory` object. """ path, rootdir, autoindex = _make_args_for_entry(args, kwargs) if not rootdir: return RootDirectory(path, autoindex) try: return rootdir._descendants[(path, autoindex)] except KeyError: pass rootpath = rootdir.abspath if is_same_path(os.path.join(rootpath, path), rootpath): if not rootdir: rootdir = RootDirectory(rootpath, autoindex) return rootdir return object.__new__(cls) def explore(self, sort_by='name', order=1, show_hidden=False): """It is a generator. Each item is a child entry.""" def compare(ent1, ent2): def asc(): if sort_by != 'modified' and type(ent1) is not type(ent2): return 1 if type(ent1) is File else -1 else: try: return cmp(getattr(ent1, sort_by), getattr(ent2, sort_by)) except AttributeError: return cmp(getattr(ent1, 'name'), getattr(ent2, 'name')) return asc() * order if not self.is_root(): yield _ParentDirectory(self) rootdir = self.rootdir else: rootdir = self dirlist = os.listdir(self.abspath) entries = [] for name in dirlist: try: entries.append(Entry(os.path.join(self.path, name).replace(os.path.sep, '/'), rootdir)) except IOError: continue # ignore stuff like broken links entries = sorted(entries, key=functools.cmp_to_key(compare)) for ent in entries: if show_hidden or not ent.hidden: yield ent def get_child(self, childname): """Returns a child file or directory.""" if childname in self: if self.path != '.': path = os.path.join(self.path, childname) else: path = childname return Entry(path, self.rootdir) else: raise IOError('{0} does not exist'.format(childname)) def __contains__(self, path_or_entry): """Checks this directory has a file or directory. public_html = Directory('public_html') 'favicon.ico' in public_html File('favicon.ico', public_html) in public_html """ if isinstance(path_or_entry, Entry): path = os.path.relpath(path_or_entry.path, self.path) if os.path.pardir in path: return False else: path = path_or_entry return os.path.exists(os.path.join(self.abspath, path)) class RootDirectory(Directory): """This class wraps a root directory.""" default_icon = 'server.png' icon_map = [] _rootdirs = {} def __new__(cls, path, autoindex=None): try: return RootDirectory._rootdirs[(path, autoindex)] except KeyError: return object.__new__(cls) def __init__(self, path, autoindex=None): super(RootDirectory, self).__init__('.', autoindex=autoindex) self.abspath = os.path.abspath(path) self.rootdir = self self._descendants = {} RootDirectory._register_rootdir(self) @classmethod def _register_rootdir(cls, rootdir): cls._rootdirs[(rootdir.abspath, rootdir.autoindex)] = rootdir def _register_descendant(self, entry): self._descendants[(entry.path, entry.autoindex)] = entry class _ParentDirectory(Directory): """This class wraps a parent directory.""" default_icon = 'arrow_turn_up.png' icon_map = [] def __new__(cls, *args, **kwargs): return object.__new__(cls) def __init__(self, child_directory): path = os.path.join(child_directory.path, '..').replace(os.path.sep, '/') super(_ParentDirectory, self).__init__(path, child_directory.rootdir) class GuessError(RuntimeError): pass class MarkupError(RuntimeError): pass Flask-AutoIndex-0.6.6/flask_autoindex/icons.py0000666000000000000000000000527013636360215017471 0ustar 00000000000000# -*- coding: utf-8 -*- from __future__ import absolute_import from .entry import File, Default by_extension = [ ('page_white_python.png', 'py'), ('python.png', 'pyc'), ('page_white_text_width.png', ['md', 'markdown', 'rst', 'rtf']), ('page_white_code.png', ['html', 'htm', 'cgi']), ('page_white_visualstudio.png', ['asp', 'vb']), ('page_white_ruby.png', 'rb'), ('page_code.png', 'xhtml'), ('page_white_code_red.png', ['xml', 'xsl', 'xslt', 'yml']), ('script.png', ['js', 'json', 'applescript', 'htc']), ('layout.png', ['css', 'less']), ('page_white_php.png', 'php'), ('page_white_c.png', 'c'), ('page_white_cplusplus.png', 'cpp'), ('page_white_h.png', 'h'), ('database.png', ['db', 'sqlite', 'sqlite3']), ('page_white_database.png', 'sql'), ('page_white_gear.png', ['conf', 'cfg', 'ini', 'reg', 'sys']), ('page_white_zip.png', ['zip', 'tar', 'gz', 'tgz', '7z', 'alz', 'rar', \ 'bin', 'cab']), ('cup.png', 'jar'), ('page_white_cup.png', ['java', 'jsp']), ('application_osx_terminal.png', 'sh'), ('page_white_acrobat.png', 'pdf'), ('package.png', ['pkg', 'dmg']), ('shape_group.png', ['ai', 'svg', 'eps']), ('application_osx.png', 'app'), ('cursor.png', 'cur'), ('feed.png', 'rss'), ('cd.png', ['iso', 'vcd', 'toast']), ('page_white_powerpoint.png', ['ppt', 'pptx']), ('page_white_excel.png', ['xls', 'xlsx', 'csv']), ('page_white_word.png', ['doc', 'docx']), ('page_white_flash.png', 'swf'), ('page_white_actionscript.png', ['fla', 'as']), ('comment.png', 'smi'), ('disk.png', ['bak', 'bup']), ('application_xp_terminal.png', ['bat', 'com']), ('application.png', 'exe'), ('key.png', 'cer'), ('cog.png', ['dll', 'so']), ('pictures.png', 'ics'), ('error.png', 'log'), ('music.png', 'mpa'), ('font.png', ['ttf', 'eot']), ('vcard.png', 'vcf'), ('page_white.png', Default) ] by_filename = [ ('page_white_gear.png', ['Makefile', 'Rakefile']) ] by_mimetype = [ ('page_white_text.png', 'text/*'), ('picture.png', 'image/*'), ('music.png', 'audio/*'), ('film.png', 'video/*') ] def to_list(val): if not isinstance(val, list): return [val] else: return val for icon, exts in by_extension: for ext in to_list(exts): File.add_icon_rule_by_ext(icon, ext) for icon, filenames in by_filename: for name in to_list(filenames): File.add_icon_rule_by_name(icon, name) for icon, mimetypes in by_mimetype: for mimetype in to_list(mimetypes): File.add_icon_rule_by_mimetype(icon, mimetype) Flask-AutoIndex-0.6.6/flask_autoindex/run.py0000666000000000000000000000025013636360215017153 0ustar 00000000000000import os.path from flask import Flask from flask_autoindex import AutoIndex app = Flask(__name__) AutoIndex(app) if __name__ == '__main__': app.run() Flask-AutoIndex-0.6.6/flask_autoindex/static/0000777000000000000000000000000013640414347017270 5ustar 00000000000000Flask-AutoIndex-0.6.6/flask_autoindex/static/asc.gif0000666000000000000000000000006513636360215020525 0ustar 00000000000000GIF89a !,   ≴Y[;Flask-AutoIndex-0.6.6/flask_autoindex/static/autoindex.css0000666000000000000000000000534213636360215022005 0ustar 00000000000000* { margin: 0; padding: 0; border: none; } body, table { font-family: Helvetica, Arial, sans-serif; font-size: 14px; } a:link, a:visited { text-decoration: none; } a:link { color: #36c; } a:visited { color: #333; } a:hover { text-decoration: underline; } #readme { padding: 10px 26px; border-bottom: 1px solid #eee; font-size: 12px; color: #333; background: #fafafa; } #readme pre { line-height: 1.2; } #readme p, #readme ul, #readme ol, #readme h1, #readme h2, #readme h3, #readme h4, #readme h5, #readme h6 { display: block; margin-bottom: 1em; } #readme h1, #readme h2, #readme h3, #readme h4, #readme h5, #readme h6 { padding: 0; color: #456; text-align: left; font-family: sans-serif; font-weight: bolder; } #readme pre code { display: block; padding: 9px; margin: 0 -10px 1em; border: 1px solid #cde; color: #567; background: #fff; } #readme li { margin-left: 2em; } #readme blockquote { padding: 9px; margin: 0 -10px 1em; border-left: 1px solid #cde; } #readme blockquote :last-child { margin-bottom: 0; } #readme h1 { font-size: 1.5em; } #readme h2 { font-size: 1.4em; } #readme h3 { font-size: 1.3em; } #readme h4 { font-size: 1.2em; } #readme h5 { font-size: 1.1em; } #readme h6 { font-size: 1em; } .breadcrumb { padding: 0; } .breadcrumb a { margin: 0; color: #666; font-size: 12px; } .breadcrumb .sep { color: #bbb; } .breadcrumb img { vertical-align: middle; } .breadcrumb h1 { font-size: 12px; font-weight: normal; padding: 5px; background: #f4f4f4; border-top: 1px solid #ccc; } table { border-collapse: collapse; width: 100%; background: #fff; } thead { border-bottom: 1px solid #ccc; } th { font-size: 11px; height: 30px; background: #ddd; background: -webkit-gradient( linear, left bottom, left top, color-stop(0, #ddd), color-stop(1, #eee) ); background: -moz-linear-gradient( center bottom, #ddd 0%, #eee 100% ); } th a:link, th a:visited { margin: 0 10px; color: #333; } th img { position: absolute; margin-left: -6px; } tbody { border: solid #ccc; border-width: 1px 0; } hr { margin: 0; border: none; } td { padding: 5px; font-size: 11px; color: #333; border-left: 1px dashed #eee; } td a { margin-right: 40px; font-size: 14px; } td.modified { text-align: center; } td.size { text-align: right; } .icon, .name { border: none; } .icon { width: 16px; padding-right: 0; } .modified { width: 120px; } .size { width: 60px; } address { padding: 5px; font-size: 11px; color: #333; text-align: right; } Flask-AutoIndex-0.6.6/flask_autoindex/static/desc.gif0000666000000000000000000000006513636360215020675 0ustar 00000000000000GIF89a !,  ~^ZT;Flask-AutoIndex-0.6.6/flask_autoindex/templates/0000777000000000000000000000000013640414347017777 5ustar 00000000000000Flask-AutoIndex-0.6.6/flask_autoindex/templates/__autoindex__/0000777000000000000000000000000013640414347022573 5ustar 00000000000000Flask-AutoIndex-0.6.6/flask_autoindex/templates/__autoindex__/autoindex.html0000666000000000000000000000206213636360215025460 0ustar 00000000000000{% from "__autoindex__/macros.html" import entry, thead, breadcrumb with context %} Index of {{ curdir.path }} {% block meta %} {% endblock %} {% block header %}{% endblock %} {% block table %} {{ thead() }} {% if not curdir.is_root() %} {% endif %} {% for ent in entries %} {{ entry(ent) }} {% endfor %}
{% endblock %} {% block footer %} {% set env = request.environ %}
{{ env.SERVER_SOFTWARE }} Server at {{ env.HTTP_HOST }} Port {{ env.SERVER_PORT }}
{% endblock %} Flask-AutoIndex-0.6.6/flask_autoindex/templates/__autoindex__/macros.html0000666000000000000000000000354013636476160024755 0ustar 00000000000000{% macro entry(ent) %} {% set icon = ent.guess_icon() %} {% if icon %} {% endif %} {%- if ent.name == ".." -%} Parent folder {%- else -%} {{ ent.name }} {%- endif -%} {% if ent.size %} {{ ent.size|filesizeformat }} {% else %} - {% endif %} {% endmacro %} {% macro th(key, label, colspan=1) %} {%- if sort_by == key and order > 0 -%} {{ label }} {%- else -%} {{ label }} {%- endif -%} {%- if sort_by == key -%} {%- if order > 0 -%} ASC {%- elif order < 0 -%} DESC {%- endif -%} {%- endif -%} {% endmacro %} {% macro thead() %} {{ th("name", "Name", 2) }} {{ th("modified", "Last modified") }} {{ th("size", "Size") }} {% endmacro %} {% macro breadcrumb(ent) %} {% set parent = ent.parent %} {% if parent %} {{ breadcrumb(parent) }} » {% endif %} {% set icon = ent.guess_icon() %} {% if icon %} {% endif %} {% if not ent.is_root() %} {{ ent.name }} {% endif %} {% endmacro %} Flask-AutoIndex-0.6.6/setup.cfg0000666000000000000000000000017013640414351014433 0ustar 00000000000000[build_sphinx] source-dir = docs/ build-dir = docs/_build all_files = 1 [egg_info] tag_build = tag_date = 0 Flask-AutoIndex-0.6.6/setup.py0000666000000000000000000000347013640411773014337 0ustar 00000000000000""" Flask-AutoIndex --------------- Flask-AutoIndex generates an index page for your `Flask`_ application automatically. The result is similar to the one produced by the Apache module `mod_autoindex`_, but the look is more awesome! .. _Flask: https://palletsprojects.com/p/flask/ .. _mod_autoindex: http://httpd.apache.org/docs/current/mod/mod_autoindex.html Links ````` * `Documentation `_ * `Code repository and issue tracker `_ """ import re from setuptools import setup def run_tests(): from tests import suite return suite() setup( name='Flask-AutoIndex', version='0.6.6', license='MIT', author='RIGAUDIE David', url='https://flask-autoindex.readthedocs.io', description='The mod_autoindex for Flask', long_description=__doc__, packages=['flask_autoindex'], include_package_data=True, package_data={'flask_autoindex': ['static/*', 'templates/__autoindex__/*']}, zip_safe=False, platforms='any', install_requires=['Flask>=1.1', 'Flask-Silk>=0.2', 'future>=0.13.0'], test_suite='__main__.run_tests', classifiers=[ 'Development Status :: 4 - Beta', 'Environment :: Web Environment', 'Intended Audience :: Developers', 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', 'Programming Language :: Python', 'Programming Language :: Python :: 3', 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', 'Topic :: Software Development :: Libraries :: Python Modules' ], entry_points={ 'console_scripts': [ 'fai = flask_autoindex.run:app.run', ], }, ) Flask-AutoIndex-0.6.6/tests/0000777000000000000000000000000013640414347013763 5ustar 00000000000000Flask-AutoIndex-0.6.6/tests/__init__.py0000666000000000000000000002622713636360215016104 0ustar 00000000000000from __future__ import absolute_import import mimetypes import os import sys import unittest from pathlib import Path from flask import * from flask_autoindex import * from future.builtins import bytes __file__ = __file__.replace('.pyc', '.py') browse_root = os.path.abspath(os.path.dirname(__file__)) if sys.version_info < (3,): b = lambda s: s else: b = lambda s: bytes(s, 'ascii') class RootDirectoryTestCase(unittest.TestCase): def setUp(self): self.rootdir = RootDirectory(browse_root) def test_root_dir(self): assert isinstance(self.rootdir, RootDirectory) assert self.rootdir.path == '.' assert os.path.samefile(self.rootdir.abspath, browse_root) assert os.path.isdir(self.rootdir.abspath) def test_init(self): assert isinstance(Directory(browse_root), RootDirectory) assert isinstance(Directory('.', self.rootdir), RootDirectory) assert isinstance(Entry(browse_root), RootDirectory) assert isinstance(Entry('.', self.rootdir), RootDirectory) def test_same_object(self): assert self.rootdir is RootDirectory(browse_root) assert self.rootdir is Directory(browse_root) assert self.rootdir is Directory('.', self.rootdir) assert self.rootdir is Entry(browse_root) assert self.rootdir is Entry('.', self.rootdir) assert RootDirectory(browse_root) is Directory(browse_root) assert RootDirectory(browse_root) is Entry('.', self.rootdir) assert Entry(browse_root) is Directory('.', self.rootdir) def test_get_child_file(self): file = self.rootdir.get_child('__init__.py') assert isinstance(file, File) assert file.ext == 'py' assert file.path == '__init__.py' assert file.rootdir is self.rootdir def test_get_child_dir(self): dir = self.rootdir.get_child('static') assert isinstance(dir, Directory) assert dir.path == 'static' assert dir.rootdir is self.rootdir def test_contain(self): assert 'static' in self.rootdir assert '__init__.py' in self.rootdir assert Entry('static', self.rootdir) in self.rootdir assert Entry('__init__.py', self.rootdir) in self.rootdir assert '^_^' not in self.rootdir class DirectoryTestCase(unittest.TestCase): def setUp(self): self.rootdir = RootDirectory(browse_root) self.static = Directory('static', self.rootdir) def test_dir(self): assert isinstance(self.static, Directory) assert self.static.path == 'static' assert os.path.samefile(self.static.abspath, os.path.join(browse_root, 'static')) assert os.path.isdir(self.static.abspath) def test_init(self): assert isinstance(Directory('static', self.rootdir), Directory) assert isinstance(Entry('static', self.rootdir), Directory) def test_same_object(self): assert self.static is Directory('static', self.rootdir) assert self.static is Entry('static', self.rootdir) assert Directory('static', self.rootdir) is \ Entry('static', self.rootdir) assert self.static.parent is self.rootdir def test_get_child_file(self): file = self.static.get_child('test.txt') assert isinstance(file, File) assert file.ext == 'txt' assert Path(file.path) == Path('static/test.txt') assert file.rootdir is self.rootdir def test_contain(self): assert 'test.py' in self.static assert Entry('static/test.py', self.rootdir) in self.static assert '^_^' not in self.static class FileTestCase(unittest.TestCase): def setUp(self): self.rootdir = RootDirectory(browse_root) self.itself = File('__init__.py', self.rootdir) def test_file(self): assert isinstance(self.itself, File) assert self.itself.path == '__init__.py' assert os.path.samefile(self.itself.abspath, os.path.join(browse_root, '__init__.py')) assert os.path.isfile(self.itself.abspath) def test_init(self): assert isinstance(File('__init__.py', self.rootdir), File) assert isinstance(Entry('__init__.py', self.rootdir), File) assert isinstance(File('static/test.txt', self.rootdir), File) assert isinstance(Entry('static/test.txt', self.rootdir), File) def test_same_object(self): assert self.itself is File('__init__.py', self.rootdir) assert self.itself is Entry('__init__.py', self.rootdir) assert File('__init__.py', self.rootdir) is \ Entry('__init__.py', self.rootdir) def test_properties(self): with open(__file__) as f: source = ''.join(f.readlines()) assert self.itself.data.strip() == source.strip() # assert self.itself.size == len(source) assert self.itself.ext == 'py' assert self.itself.mimetype == mimetypes.guess_type(__file__) class ApplicationTestCase(unittest.TestCase): def setUp(self): self.app = Flask(__name__) self.app2 = Flask(__name__) self.idx = AutoIndex(self.app, browse_root, add_url_rules=True) self.idx2 = AutoIndex(self.app2, browse_root, silk_options={'silk_path': '/myicons'}) @self.app2.route('/') @self.app2.route('/') def autoindex_test(path='.'): return self.idx2.render_autoindex(path, browse_root) def get(self, path): return self.app.test_client().get(path) def get2(self, path): self.app2.config['TESTING'] = True return self.app2.test_client().get(path) def test_css(self): for get in [self.get, self.get2]: rv = get('/__autoindex__/autoindex.css') assert 200 == rv.status_code def test_icon(self): rv = self.get('/__icons__/page_white.png') rv2 = self.get2('/myicons/page_white.png') assert 294 == len(rv.data) assert rv.data == rv2.data def test_autoindex(self): assert b('__init__.py') in self.get('/').data assert b('__init__.py') in self.get2('/').data def test_own_static_file(self): rv = self.get('/static/helloworld.txt') assert b('Hello, world!') == rv.data.strip() def test_own_page(self): for get in [self.get, self.get2]: rv = get('/test') assert not b('foo bar foo bar') == rv.data.strip() @self.app.route('/test') def sublee(): return 'foo bar foo bar', 200 @self.app2.route('/test') def sublee(): return 'foo bar foo bar', 200 for get in [self.get, self.get2]: rv = get('/test') assert b('foo bar foo bar') == rv.data.strip() def test_builtin_icon_rule(self): testset = {'7z': 'page_white_zip.png', 'avi': 'film.png', 'cer': 'key.png', 'html': 'page_white_code.png', 'iso': 'cd.png', 'rss': 'feed.png'} with self.app.test_request_context(): for ext, icon in list(testset.items()): file = self.idx.rootdir.get_child('static/test.' + ext) assert file.guess_icon().endswith(icon) def test_custom_icon_rule(self): with self.app.test_request_context(): file = self.idx.rootdir.get_child('__init__.py') original_icon_url = file.guess_icon() self.idx.add_icon_rule('table.png', ext='py') customized_icon_url = file.guess_icon() assert original_icon_url.endswith('page_white_python.png') assert customized_icon_url.endswith('table.png') def test_parent_of_root(self): with self.app.test_request_context(): assert self.get('.').status_code == 200 assert self.get('..').status_code == 403 assert self.get('../..').status_code == 403 class SubdomainTestCase(unittest.TestCase): def setUp(self): from .blueprinttest import bp app = Flask(__name__) app.config['SERVER_NAME'] = 'example.org' AutoIndex(bp, browse_root) app.register_blueprint(bp, subdomain='test') self.app = app def get(self, path): return self.app.test_client().get(path, 'http://test.example.org/') def test_css(self): rv = self.get('/static/autoindex.css') assert 200 == rv.status_code, 'could not found preloaded css file.' def test_icon(self): rv = self.get('/__icons__/page_white.png') assert 294 == len(rv.data), 'could not found preloaded icon file.' def test_browse(self): rv = self.get('/') assert 'Index of /' in rv.data assert '__init__.py' in rv.data def test_own_static_file(self): rv = self.get('/static/helloworld.txt') assert 'Hello, world!' == rv.data.strip() class WithoutSubdomainTestCase(unittest.TestCase): def setUp(self): from .blueprinttest import bp app = Flask(__name__) AutoIndex(bp, browse_root) app.register_blueprint(bp) self.app = app def get(self, path): return self.app.test_client().get(path) def test_css(self): rv = self.get('/static/autoindex.css') assert 200 == rv.status_code, 'could not found preloaded css file.' def test_icon(self): rv = self.get('/__icons__/page_white.png') assert 294 == len(rv.data), 'could not found preloaded icon file.' def test_browse(self): rv = self.get('/') assert 'Index of /' in rv.data assert '__init__.py' in rv.data class SortTestCase(unittest.TestCase): def setUp(self): from .blueprinttest import bp self.app = Flask(__name__) self.idx = AutoIndex(self.app, browse_root) @self.app.route('/desc') def autoindex_test_desc(path='.'): return self.idx.render_autoindex(path, sort_by='-modified') @self.app.route('/asc') def autoindex_test_asc(path='.'): return self.idx.render_autoindex(path, sort_by='modified') def get(self, path): return self.app.test_client().get(path) def test_sort(self): desc = self.get('/desc') asc = self.get('/asc') assert len(asc.data) != len(desc.data) def suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(RootDirectoryTestCase)) suite.addTest(unittest.makeSuite(DirectoryTestCase)) suite.addTest(unittest.makeSuite(FileTestCase)) suite.addTest(unittest.makeSuite(ApplicationTestCase)) suite.addTest(unittest.makeSuite(SortTestCase)) # These cases will be passed on Flask next generation. # suite.addTest(unittest.makeSuite(SubdomainTestCase)) # suite.addTest(unittest.makeSuite(WithoutSubdomainTestCase)) return suite if __name__ == '__main__': unittest.main(defaultTest='suite') Flask-AutoIndex-0.6.6/tests/blueprinttest/0000777000000000000000000000000013640414347016667 5ustar 00000000000000Flask-AutoIndex-0.6.6/tests/blueprinttest/__init__.py0000666000000000000000000000007713636360215021003 0ustar 00000000000000from flask import Blueprint bp = Blueprint('test', __name__) Flask-AutoIndex-0.6.6/tests/static/0000777000000000000000000000000013640414351015245 5ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/helloworld.txt0000666000000000000000000000001713636360215020163 0ustar 00000000000000Hello, world! Flask-AutoIndex-0.6.6/tests/static/test.7z0000666000000000000000000000000013636360215016500 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.ai0000666000000000000000000000000013636360215016531 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.alz0000666000000000000000000000000013636360215016726 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.app0000666000000000000000000000000013636360215016720 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.applescript0000666000000000000000000000000013636360215020466 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.asp0000666000000000000000000000000013636360215016723 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.avi0000666000000000000000000000000013636360215016717 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.bak0000666000000000000000000000000013636360215016675 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.bat0000777000000000000000000000000013636360215016711 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.bin0000666000000000000000000000000013636360215016710 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.bmp0000666000000000000000000000000013636360215016716 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.bup0000666000000000000000000000000013636360215016726 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.c0000666000000000000000000000000013636360215016362 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.cab0000666000000000000000000000000013636360215016665 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.cer0000666000000000000000000000000013636360215016711 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.cfg0000666000000000000000000000000013636360215016677 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.cgi0000666000000000000000000000000013636360215016702 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.com0000777000000000000000000000000013636360215016721 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.conf0000666000000000000000000000000013636360215017065 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.cpl0000666000000000000000000000000013636360215016716 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.cpp0000666000000000000000000000000013636360215016722 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.css0000666000000000000000000000000013636360215016730 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.csv0000666000000000000000000000000013636360215016733 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.cur0000666000000000000000000000000013636360215016731 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.db0000666000000000000000000000000013636360215016525 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.dll0000666000000000000000000000000013636360215016713 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.dmg0000666000000000000000000000000013636360215016707 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.doc0000666000000000000000000000000013636360215016705 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.docx0000666000000000000000000000000013636360215017075 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.eps0000666000000000000000000000000013636360215016727 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.exe0000777000000000000000000000000013636360215016724 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.fla0000666000000000000000000000000013636360215016702 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.flv0000666000000000000000000000000013636360215016727 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.gif0000666000000000000000000000000013636360215016705 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.h0000666000000000000000000000000013636360215016367 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.htm0000666000000000000000000000000013636360215016730 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.html0000666000000000000000000000000013636360215017104 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.hwp0000666000000000000000000000000013636360215016736 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.ico0000666000000000000000000000000013636360215016712 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.ics0000666000000000000000000000000013636360215016716 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.ini0000666000000000000000000000000013636360215016717 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.iso0000666000000000000000000000000013636360215016732 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.jar0000666000000000000000000000000013636360215016714 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.java0000666000000000000000000000000013636360215017061 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.jpeg0000666000000000000000000000000013636360215017065 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.jpg0000666000000000000000000000000013636360215016720 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.js0000666000000000000000000000000013636360215016554 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.json0000666000000000000000000000000013636360215017111 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.jsp0000666000000000000000000000000013636360215016734 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.less0000666000000000000000000000000013636360215017106 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.log0000666000000000000000000000000013636360215016721 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.markdown0000666000000000000000000000000013636360215017762 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.md0000666000000000000000000000000013636360215016540 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.mid0000666000000000000000000000000013636360215016711 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.mov0000666000000000000000000000000013636360215016741 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.mp30000666000000000000000000000000013636360215016637 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.mp40000666000000000000000000000000013636360215016640 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.mpa0000666000000000000000000000000013636360215016715 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.mpeg0000666000000000000000000000000013636360215017070 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.mpg0000666000000000000000000000000013636360215016723 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.pdf0000666000000000000000000000000013636360215016711 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.php0000666000000000000000000000000013636360215016727 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.pkg0000666000000000000000000000000013636360215016721 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.png0000666000000000000000000000000013636360215016724 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.ppt0000666000000000000000000000000013636360215016743 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.pptx0000666000000000000000000000000013636360215017133 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.psd0000666000000000000000000000000013636360215016726 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.py0000666000000000000000000000000013636360215016570 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.rar0000666000000000000000000000000013636360215016724 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.rb0000666000000000000000000000000013636360215016543 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.rss0000666000000000000000000000000013636360215016747 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.rtf0000666000000000000000000000000013636360215016733 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.sh0000666000000000000000000000000013636360215016552 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.smi0000666000000000000000000000000013636360215016730 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.sql0000666000000000000000000000000013636360215016737 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.svg0000666000000000000000000000000013636360215016737 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.swf0000666000000000000000000000000013636360215016737 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.sys0000666000000000000000000000000013636360215016756 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.tar0000666000000000000000000000000013636360215016726 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.tar.gz0000666000000000000000000000000013636360215017345 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.tgz0000666000000000000000000000000013636360215016744 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.tif0000666000000000000000000000000013636360215016722 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.tmp0000666000000000000000000000000013636360215016740 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.toast0000666000000000000000000000000013636360215017272 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.torrent0000666000000000000000000000000013636360215017635 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.ttf0000666000000000000000000000000013636360215016735 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.txt0000666000000000000000000000000013636360215016757 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.vb0000666000000000000000000000000013636360215016547 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.vcd0000666000000000000000000000000013636360215016714 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.vcf0000666000000000000000000000000013636360215016716 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.wav0000666000000000000000000000000013636360215016735 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.wmv0000666000000000000000000000000013636360215016751 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.xhtml0000666000000000000000000000000013636360215017274 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.xls0000666000000000000000000000000013636360215016746 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.xlsx0000666000000000000000000000000013636360215017136 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.xml0000666000000000000000000000000013636360215016740 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.xsl0000666000000000000000000000000013636360215016746 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.yml0000666000000000000000000000000013636360215016741 0ustar 00000000000000Flask-AutoIndex-0.6.6/tests/static/test.zip0000666000000000000000000000000013636360215016742 0ustar 00000000000000