From 9198625280d15688e3d392bd30a611cc92c83313 Mon Sep 17 00:00:00 2001 From: Tue Herlau <tuhe@dtu.dk> Date: Mon, 13 Sep 2021 15:32:36 +0200 Subject: [PATCH] Snipper compatibility work with 02465 --- .gitignore | 138 ++++++++++ setup.py | 2 +- src/snipper/__init__.py | 2 + .../__pycache__/__init__.cpython-38.pyc | Bin 167 -> 221 bytes .../__pycache__/block_parsing.cpython-38.pyc | Bin 3161 -> 3482 bytes src/snipper/__pycache__/fix_bf.cpython-38.pyc | Bin 2198 -> 2505 bytes .../__pycache__/fix_cite.cpython-38.pyc | Bin 2536 -> 2505 bytes src/snipper/__pycache__/fix_i.cpython-38.pyc | Bin 2820 -> 2820 bytes src/snipper/__pycache__/fix_s.cpython-38.pyc | Bin 1384 -> 1571 bytes .../__pycache__/load_citations.cpython-38.pyc | Bin 4979 -> 2652 bytes .../__pycache__/snip_dir.cpython-38.pyc | Bin 2103 -> 2057 bytes .../__pycache__/snipper_main.cpython-38.pyc | Bin 2644 -> 3025 bytes src/snipper/block_parsing.py | 30 ++- src/snipper/fix_bf.py | 63 +++-- src/snipper/fix_cite.py | 2 +- src/snipper/fix_i.py | 18 +- src/snipper/fix_s.py | 25 +- src/snipper/load_citations.py | 237 +++++++++--------- src/snipper/snip_dir.py | 42 +++- src/snipper/snipper_main.py | 17 +- 20 files changed, 384 insertions(+), 192 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5391d87 --- /dev/null +++ b/.gitignore @@ -0,0 +1,138 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ \ No newline at end of file diff --git a/setup.py b/setup.py index ad71618..a7fc926 100644 --- a/setup.py +++ b/setup.py @@ -14,7 +14,7 @@ with open("README.md", "r", encoding="utf-8") as fh: setuptools.setup( name="codesnipper", - version="0.1.0", + version="0.1.1", author="Tue Herlau", author_email="tuhe@dtu.dk", description="A lightweight framework for censoring student solutions files and extracting code + output", diff --git a/src/snipper/__init__.py b/src/snipper/__init__.py index f102a9c..4e820bd 100644 --- a/src/snipper/__init__.py +++ b/src/snipper/__init__.py @@ -1 +1,3 @@ __version__ = "0.0.1" +from snipper.snip_dir import snip_dir + diff --git a/src/snipper/__pycache__/__init__.cpython-38.pyc b/src/snipper/__pycache__/__init__.cpython-38.pyc index f52a70bcdae56e64584b49d2330bcdd216e21e6d..eae9fb89b94899b9aab163c73358f43efa116212 100644 GIT binary patch delta 157 zcmZ3^c$cw0l$V!_0SF{sSSC6E>Bk@rGGGF79Dul31W2SXL@}f=rZD9&<}yVwF*2ku z2Qz50RIwW98R!|l1S(+AWW2>uoR?V;pORVRr^y_}9UotoT2!2wpBEn=B><8sNG;NX bsVL$F8NZUDh#5!~F;9%}VlM`XurLAu*oPp2 delta 102 zcmcc1xSTN}l$V!_0SK;sHcS);(vLwLWWWgIH~?`m2arf%h+;@#3}(<|s$w<JGte{i k(`3BG9UotoT2!2wpBEp$lA(wRsIG`<VviT=XCR9K0CtEIL;wH) diff --git a/src/snipper/__pycache__/block_parsing.cpython-38.pyc b/src/snipper/__pycache__/block_parsing.cpython-38.pyc index 5f0fa38e06964f4ccf08c26117b7b787eb3b0791..f863b8116bd2e1ce5093ddf2a92c11e93ae21392 100644 GIT binary patch delta 1887 zcmah~UvC>l5Z~F`^ZoJplGsUIH>F8QDLNtwO{2clv{hPoBM1c~6cJgDH*t)OZT3zA zp*@U9Py=eEMkijVkmAQm2&tcdcO)bpc!2u``3iY~nRA*yNEK(@+|2Ck>~Cgg#($sx zaoYc|P;ePOzi!>Czw7V$7v1|PNw&)5#NOiN8CT|a*s3XuvLO8(Sk1{XIgT1jdMhj_ zJ?oVC0La17!|^Ndy@zkOgG4h46&6FpG;D+9ZLStINTWh4qQc5dnq}g1#5W;^ZuQt! zsQy{oCZNov^(`lB<gE%DoNO-RK`7bi95Sa4nITYjIW^Ziy+-?hz$zlC+3$tX^+T8) zaSI3k;FFr0Efq$o=+wjLDJTOi1FpttgR$Oet32(`h(|hiy)!_!wNHAjZW$FJX&Kny z!7RRSg1U%ugVOT+8AB$AFS!mqT-gPQNurRxV=WeQ3?Fsd{9_&)v3LNR6tb~n$EG$U zYuoCk#F(_HnWi)jgk-dN8{(YKQBI|38)|D8o?vcAnkVchqsw<8wzL)7bbz+Cp@qz0 z{;fv>k8)yHJLsOPpV99BZ2pWu+WVX!3`WNf@p^$phI9z~H-PS)Hh&Ci32y|=2;vAa zO74lI-O>IgryD~E1Sty$Z!;eWoyYvRk9h29Pv$FZ-yAYLC#St_K#f-&Fpaf%>JTmq z)&IECT>4e^fMGIuR>5{$(1j5kEhyD!F@d|dEFz^9EFJA0t(3BrNu*iIF#tgUU^Qm( zBVz54ViW;hz)^%vtissWKDy0U2{T8`95FMEyquyhT^RD`kmoD76RWknd_V=$INexO zE!0>gs+zBmXts}4GlV$#%bXwV8&V+8r73ee=;=O{12)QODH75?k+XG2^R}hFl=zj- z2m$trnnM3slPEgw5N@4;^1R1a2+AaqCcCWJnuomy`)tVe_-A5e)Fc6<W*Dhf|7r4l zZVu*?Uvl>bFLp+~(!|KtCXWXOYYQbbjC=+#LUjS{)GU#+?WpEZcMac=8Z5^+^Uh|G zpbtzW8FsSFj=LIT3u<WR)CCGbvLSSR<Y375`4H2*$&Uc=LwM_hz`&^bomP~Zo!;jg zO3k377vgyX7el%_!jrOK+EgTEqh+-76%<n;Ta73wS~n}N(gvD1jJvP^zTrcW+hFr# z&AO7ORdt0(DS2pJ8-I=1A`zd+`Q$gNf2l-lHtNV62iWn6fvJMzBfARkCqLLX2CtJL z-C-)~s=1)f5$lIhT}8F1-mIZAOhvc;=|*6w0xg<-)#~Daq=}b0Z-3F)=tr$ySJ7BY zjef76O}t=CQJNLqLpD8?MVw7!p2!U(t4{KcGq-r1<Y^+=ZBo7zjnT~IEHdE|5(b_j zz~|nW4MHSCXIPN5Mpw!}-AUeazlN8SKio@GTcpqa*0MoN!&ogPM*bnpB#-m6a65UH zFPnGKs-OIxf9W=Hn4{yrh5(iWJGE*x*=y8lS=ed<ZL-KRRO$|i1WVmb=De##%DpgM M+jj7G-xjX@FPvy%vH$=8 delta 1542 zcmah}OK%)S5bo-E?Ck8!dW|3J#j#}*5i}wg2oC|?_&^|$0Qs_lg9WVC?s&D>c$c0z zL{X0xVMlQ!B4LfV5FzZJz(3&1<HU{O58xAbqiFeRHdcTOBXv!6J-@21?r-LQo2$Mb zhQ7cz_sc7thrv<xg5ShWi4CD9j$U4_*HlFX2ejd+P*o4ahO7LRh$g>JrsPnv<D;*J zzl&vI#Y@l}k`jvU$cDHllvLJ%NM%o?Rw4{^`|?AX+NpDwwn^E_Iq*`~*h=hpdQFLz zNXQ6dH^e@XFz%Q)juISipVE>kDR<Zq%H6TFIiv?d6{3cCAilNs<RPV=@zOFUGi77L z)vF6tzHcL~pH_^IR8s!{yZ^KKBO&D<ONKB`e?kl@vDC1_b$mex@9)U3NPl3^IAb%$ zF=Fg0k9Vdr4$zf#*82sdqN2J;gTyugdKTQ5X=p+fHpH=WB2c|F;XXl9Z3+{%;CY^7 zXe>1W;lDybR%?p80*#ewQaypjR!tQ)Xr^(v?XZ}Fm!+mbS>r=fd8C;sG_#<E2U0m) zK({y!25fxZ7X@60<9UT$LJbpU0%1cqBMC5D1?Cd|b;xjHNMxxw@Ky_+n4`w}smvxT z(?c6$)8f&24+JF=w@@LIvI-99>p;PI3#p^ra~#E<Lt_U1VdXK86y^2Y+3x8$$(_yJ z{??8rWXPRCKTcjeW&U(D8VyHd$(7vR?Zk<$Kpv6ip)U9_3E0#Aq~F_{2NxIjhAz|e zNRm6c-6+Dh<H2q(S!p6wXE$D3Ve2hUbN=xKaj>Sa;%yKkjz#vD^TM@MV(R5SDT&d1 z2e-oR5pIH|Q0xJEdTguG3B85+#|@B1qBw8;jFyUu^ejT<*>|P+h`BDpepF4#&@noF zLPzp58}@WYS0l=u0%Vl^>|UfO`_sL)d`7F0qxlpx1B6AQdxP9oy{$wqLXy4fy;@%e z6LS}Y^y#t;$dhw)dpUdPE(iJo#Cn0rZ1$tKQoF?LG?OZmsjO5UEHbt+UN(>9<CIAM zboO<*NjI`z%P$QhHk<*;?T+qV(R0jJ<D{dLcGBs#A&hf-uk-26$kib$oq_J{CHhI` z%WvP>x;aRC{XIRwduz}iL^aKQ*ZfKqR^#I>@z!JV43p<UHp;E+j{nqa&w<aa&E1{x z@juIYuD*!Lfa2>Qf&%GTHdSR%@yM2e%zpPz!VT6JFC^*J>|W(_TFU%japq%|k4MKN zbP!9gWmkhQ>0<U%u(a?7^tn{G{xf%)pXKeW6fV5Z96HBCRgj3*qf%aKw^e_u-7cD; eCt1m*>s2OeOq$tdc&Ww(*pBaczW1hQ``+IYdN~RJ diff --git a/src/snipper/__pycache__/fix_bf.cpython-38.pyc b/src/snipper/__pycache__/fix_bf.cpython-38.pyc index 50edfabfa447d901387da5638cca83d0bdb560f9..08110df11cf8ba047f40b6a36f84bec56cdd98a5 100644 GIT binary patch delta 1296 zcmZWo&5ImG6tDNHy1J)lcHFqht`nCWg3&a{5cd+)adR-N5g}O!UWV0Swri$or>AGO zx>r<c7%(e%@B?j7@B=nSFM<azf;TUMe?k2R-g5P%uX?hHXf^ffy{cEQfAxFseRb~l zjrN;sYayfYOY-vYkMN83_Hv&r#S~<$?^euUihTs9^NdeLU(~uF-RpZ(*_UK{N}jO3 zuUaZljT7hxYE6ZzNm@g}T^6<fbU(Qrf%TGjHZ4ezX|6_j8KG?+X0v!QDCSvO+Ge=2 z-kGKOPhY-{7aDYtoUnV%Li__*OqFg_4{#4IRoD63SL<_%Ta-GTN2uL%EM&Sxt9FOF z?Zgw+ul!bf-5tu|d_KyR=GBI{1Lvw(^fqh9`ik?m-Z*`4F!rmT#fvv!6V_>NLWm)R zpr0X!z1SmpHr!=N^HrL~0}>@O#9)WrgN0Xp<K0<GgQs|(E&LLUe-D(Hc=}`GJ0Imu zu+~xWkFY~N25Mh0T%RhLfRX3fBFJwUp?^$BQ?QWvOB4wx5=?~t&3Fd3SOPgF%y`N- z@>`~Y@A;Oq8pgjuX6VcWw<v%Kj2t7SrFmNe!PUMK8`bA>|3btych-3)99>aEZ&!cG z?Hgh;8qKXN(u~rk*XYP%99tZXEM_|^svq%f!@(+#<Kz5!axE@b2YzQMK!C(&q5ZcM zx=Z^pk~kX<#v>j-A%k9v^jco?N&I|@3t@y}#Mq^y50y~f2_su}*eTp+H*3BP(vII@ z*XeHgP#**B1s%4er9qU3-yspxG?2pA{4+SH-Fj>xOKt=ujTvqv1>i@4aXOAUvDJFW z){}&c3YeF}BzE+j4ab|Hd6#B!nM6uu@YclxTmV5~l&&QZcA<p<gB2bL3JP@wXmNxS z`K$7sSa|n;jP_I-m()G;-8bAH0uqwG7DM*IMOUzgJKY|&(l9G_yN{i1yC{dc91z^) zV5pPAdUa~7AmfEv?oi)6N8$8UCn6FNp`^unX*rq}b*i*0`N-GXXFgWO$K~v}w2)gk ztOFGmRsLV#a)s?CW3RDdlWsGr0)Z_E0I987aE-K(>sMTS+}n#_FA8mgDkm;yv#g*8 z<SDhR?q;K87{9Nv+6|uGuglbdtbx^Sxx(q<{0qb5nhbi=nL5r!yDn>m>-K>D-hy== ITnV502Ph#FssI20 delta 1053 zcmY*Y&1+Oi5bx^l_cfV}quEW2Q4kdL3C1Lgh#~7CNbr;_EFK)h@O=Gd80XCg^<LQQ z(!(5#=*7eGU@wcHM~`0o3%rPbfY1ng-s}DaTlL}xc2nI|)m7D1UB7<6@Yl)K-TC>3 zpz-P5^<+Exvvqd1Ns<u;a?#;k<}j2UIaD15EUR1(y^cq`Hr|ow_$D%e36G!?82DAh zjej}ZZY-VGOUJ{)%|Fb?>0p0?<1{OZ7@Xf9nQT<1k_|tP7VRF95^p|i$R9&uDS}*G zbCA9UC;JA&>Xh1nbJacd;BtKq&MQjnPhyD?**nN_j&|fjoad!g{iE)*PVk|hOeWdL zpsud#J!n@?^wwf+Si7*b^Sb@R{jOhq)Hi2x5!z}I7NMaV&;YzZ20Pzn9FT@d5f!&- zF<@jLrqYB@MHh@R`Y4*JQdnWU5*|sbtTg^}X@ckKzMkr-N7J{Ow6H9!-&OQ_(XN9L z!c~fw@_T$4+#{c8g{b(CmO3u^J%*`Y?Rk5%z{;2Mm6(Pl*zhqJJ@D|E4LP>)2D0X* zQBUMD*;uG;;hDgf#_xd*eh|}Wv`M}|zA(`E*7_EfL=Q%?N7<Rc27e0^zEDdnMK&a< z!BS5yk?$p|&73Ewkl+Tr$(FE@4Z4y_YVIOX!pQ04scPH*Wri1tj}>ZGE%3rUiW|t~ zxw)cDu-wlMOH5ouP5aC$(sIj_vT*+3w*-3yHrYX@sgqgeWWGUI(St0Td;@`tj`7z$ z7;TVoaYl%l5YU8+G((!Fi4Q?TQ*O#O{ISd^c(}2;MW{{k;@0X{cRa~S0$$-wI#nh; zT(4ETR14$4MRZGAj>mc7f(fPDPx3gZtHL!puU&CHVfGx`!@l#=gK~UO9w&T_Piipw z$7!%v!8jF^W2=20@CNZQ?8G7dM4W3Cqdp-USM#iwq`xD7Dpb{jXyxbnbs4y|&+!E{ b<iCCp7j6y5<{-~*afj-ALTE!%g;)LuTO{4T diff --git a/src/snipper/__pycache__/fix_cite.cpython-38.pyc b/src/snipper/__pycache__/fix_cite.cpython-38.pyc index 8182783048657d4e03b7fdc09bc39298fccc3065..41ff88198ed4802e312744218929d4693baa9cdc 100644 GIT binary patch delta 229 zcmaDMd{US<l$V!_0SIDWTPD8T$h(_aPXx#-VW?rKVN796VM<}{WvOMZVGd@{WbvzF zi784=3n`KTD$!&tk_S?gMOgGXSbz)$MggYHzARac%(oc1ChuW&VvL&npLG-4EtahO z%)H6l*vfcRfvRq?6qQtz6lrg^U^ixDRGOT_p>3cE6nE2Pyv327np%*Wmr|_BR-_9Q zD`El>dLUh_1x1;8B}E1x0prO>Ipmd1Kul8*VFn`1L4*a6h+;}DD$)k=tR}N_J_G=D CKQ$Ww delta 260 zcmX>p{6d&Fl$V!_0SHzfGEIEGk#{$<j}nkq!cfCd!<fRD!j!_?%Tmi+!kEIcfT@Og zA!9QmBSQ^yFoPzmUlmJCQEFO9kql77Ek-U)<|26zi?yIAGq2<pOIChn-sEr0`dn;4 zQ3gf<Mn1;Px-40YtVN1I{^VJ#PK>uE-(}szTBHo(Ph~6PQ3o<^u@se5loaW07H2nR zWK@~#&7rNQ0~B}DWW2?Zotj#ZnwL_n$p+R`!~~QmG5`@ER~H$92-C^SIOLVhKumKG aVF4m6L4*~Mh+;}DD$)b-Y$m_pcnARNjyuZ$ diff --git a/src/snipper/__pycache__/fix_i.cpython-38.pyc b/src/snipper/__pycache__/fix_i.cpython-38.pyc index b538f528512b367e6f1e99eaf64f3f4e0c4363b5..1f1675e90766d6fb6d166d74c20670272061e74b 100644 GIT binary patch delta 931 zcmYjPyH6BB7@u$UakGy*z!(rcjU<8`AmIXyc%X^ISQuZ#Xf7e=!Yn6n?47gAqu2|D zm|$T+rnSI=0t*wPrGLqEloS@WQs_5(M4e=Q^S!@selxqhyS;^H`MgVTojjNhzUTJ~ zMR>74I#wne8g|tV?bRGN*Ql7|+QO<%#4^dPI^5#+E~$DP=1D2H&j(FKqvXpw4uvi( zXycy89aDJ<%R74sTXi_&4tKft-e|k2d*E`v4j%zX>ZUo)Dnw&HX?r}+3%jK4rzTpu z`Uxj*DWX+}J~BrZitT*r9e8Oz%k>U??sL0Nwf6dR>Ze{x-q3bI=USwnBqTMZY4j8e zZIY6drKC=mDGuHJPykM-peC3s8y8FqwXaW%pKwKUa_{6ft}NsiID(-`=$i>ozO)Vp zmA4Yrcr&T3H+iVct)}3jh;EfbqqZFpQIaF}0)X7JFIzASHkF_3vYo@IQeGb0vpZX% zvf@^-6)8L1ZiP#UxTrf^(h*%^K$r94BoIk0+)hNGoG{{NqJdUrz6t}b%p_Q82+g>% zI&o%mBUx4uD;h-NDmuidhHDxIHIy=#(l~;koW(|SX|1-r5fxC4bs)is8MxrXIqE|< zo{TbJL-I5?-lv<1n+PSUj3lUw8EvrS9X2zpYadZX$0rnQo^{gRPNPa3CQHrr*6d?> z$gYEnDd*)eyEUmf7d;3i5Mx@tjc^2FTFcqISpm1wScy9op2|l~&CVW%$#2f2ou%E7 zKb(mte+SGaQxGUvRInr*tfq{$%~%=8kpg5X>{P$2`(!OFu@Ti)eAMG11Of$cD>8Bi z^3PE#`QknvVqAW3rxp}##>$L>^-$%u&fc($Zk21DX*%aW7XICYRq&f^G{RZ^3*&AC Oq!(#MqLFr&GUE?@-P;@h delta 916 zcmZWnO-~a+7@l`_yI<XHiw6j#8i@iekQD=%7%N`T#ES-riP?nIrL!%Cvc=gg5V9Lg z#Dv6n!1)7^=mFz}_!qo+lH=Swdi2UgXBLAdPBPCt@3ZgMygPgSd;Nu{j$<LQzI~nb zkBSF{GRz!IOgbvb?IBMiu!ySK!T!j}34ubN@YBRz6gwJa*Kl+969IxcMrtM2s!7Z> zOkZY-mF7buWBD|n<X3HC5R2rA{Z>is#6EP0(}E)al-P+*j2e<Sh*F0XNO2FPg+vuf zX%G?g8Vk&|U;xddrE*$KoWnv=%wnDLVUajQYhh`=I86$Plb}~PEy>__%3!UOq68&I zf?BwV#a;RyQ4rm8s8d~>JDMA<1f32C>r8Q7cL%#JRiy(C<IfAqPq<<V>%os-Vr7wM zU}llDD0FJE=eZ9fUcMdHNjI*qcS*q2tu7_BEIxa>5T$mE=olN<mOx?q+T|RsfTpvL z+D%PPvsz-`wYi~g#MRJW4?KM<*xm>lv8QjG6E>_5?e@`OnK2*5K8@?ac1(TG3_|jU zDnjMzO5hW&#(uj)bHbbFGC!_%dvTLPL~qCxcq`!859w85(5i&%5=JD9T|h-JZZ3Da zjkS8S7gpsMqDcV=Dqw&GHeAAX#w=_=N!W%s4VRtj?trXLX9ZL-S7N_KZ%aXC1IFEo ztZ|GvcBeRO{#UUU1#zRhzA^WVCB_(-?7i`LS{A4B^;Ln6OMXY@0D4REtmmv<tJY~p z=g}S;HS3!E#Z+f+%xNtPn_yqesfCN?vaUGz9F{pWs3E*PWo<L!iWnFNF|y!1`#qT_ zE0LqUu-=w=qfr3}3Sd2C_pM>)iLk0Vofik4WRW#9L#6c31^+f`)Woakb%Hth79&|# KOioPDR(=CaAkwb@ diff --git a/src/snipper/__pycache__/fix_s.cpython-38.pyc b/src/snipper/__pycache__/fix_s.cpython-38.pyc index 82d5e8e8b679eff28ef31891521b5b451b77d499..9ee4629819d4fb80d652bde8b91cbd64e3ec86af 100644 GIT binary patch literal 1571 zcmZ8h&yO256t+D-Gn=I8vSqufs8T9X(!)Ya3)?DPRqBdUREbs<)hJ~&J9g4(CNs0P z(}l=61vvDAxFI2=<jB9lpW!Q~{tJuH@;u3I0ZX=@JumOQ?|q;1tkDP%4EwKp@kbs) zf11O;hXaR)FvS~KD55w+V;o{^Y?6_Xz;0#M*beRL&d!{%8@gaS)cqcX9`&dXyH9Ij zjRiCq5&k3dSZ%SfL~|V0S$)x1q675e<30(S;RV*B8>~4e7=cw^Tx1uPcn<mC)G+%| zpOUAj(|il{pbpj>lnvrZCTW_;$8c^OW<@fJQptEM8C(Q|NtQ)I^0Z8_`O$g+T4c~Y zf+-X%5=qE3!;&b#IVVul-i#<h$qrgr)S~v1h&^e;jk5!_o4t#2q>Sb6An<Y&S(+L* zQ#7*_Ubq#qt9>%FXU?h<$~l1F&RpdxOW9p?^jukhr#8LPe!}F0=WUUvrDzX$F>c?; z(wvDK?WuMBn$S%lV=f~Z52Kh5Md*(hE8!%*)J}z3+j%@@|3PU1FdODmgYqgYL!{7) z_h(pP3KauJ-(dXNI%*x+PzUBNIQ@<~mL|KOYMf}CaUZU#<>bzz`~7EvanYBPm#lwK zB$F}ArRbZYOUC<xC+GGc{WcQ2<##&hW~q=#F)sHnnL1277ZDV|obC*n1h+2G7H47~ zj5FVk#|e09+uU%2L|fp@4Ib^rkT0j&0j9^I<7ubrRp?fo5ZuUGyTwG76UhzNnj}T& zipuL9B3?J2oT>(cTx`LDh>x43g*TloV&fKWIsxXU^28KzHVg`rr4rB|U`S{!P-{u7 ztU0E5Wb>Pnys{Ry!b>c`27!Quk+Rm(c(alQ2nda8{2N6U9wpRTk{O{Ov|rJ0WQdis zjX*xm!dK1`q$6uUp0$mt*nyE8JVN&ekSW|@Wv_GpLOo?~qnwzP`Y>yA@>6T(DQ~f% zTvNx_=q~ySJweaW(QOJE=>(6tc_Syde}X@mlIv}agSUU5o}OwPO)bMEKJL`3UT7<0 zxh93sb{Wf;K!l(v*UoqZ8@~uqw8vSQ#R=2)t0K*{T>xX+Ka2%4I@QiG2l6^T-!#s_ zimS*3sSVPMMJ8<MB}FblVikuW$uez$qsD{(bLfirHH*YGh_xaS`{XhXfJPtJfy973 z#QY|FopyuXt)O?i4R7i}9P~b`jKiRJC+OX62ffc>esT734-WU%4#!YNp#3Ns$7vo# zQ^%mV&o7&p!GrVB+0+|Jk!38AX_1Rc!~6pS@zVO0?5_T!%9x8ZAFh<Wb@pw&S4k?V zSKY2E*F@Yh`Ayy^(t#+mRIUX59>iZY9gj4At(}sm(6kTD_4)H%S(W1b?zo_njO`n` Xg@I77`cx<W6~ATIeXHsjZsLCcStWu? literal 1384 zcmZ8h&5j#I5bo;v@px=+oUmlIAR?nkY<yV=WCKLbDpFRQtOyb%ppnsNcDlWpcz*2e zb{4F0gye8WoDq_J1m1!N-~sx|DX$O-E!AW1^3zgRSGUVmU)A^7k6SID;QH<NgXj;N zkU!1k-^;<vJ>2pI8b%nTB!d9J_%x*f#nVcy%nodPvzhaf1P*gq4NsSOL5+K?KB8jA z9bQ}3S7ZT!&;4a%MUKeVHwH9l1}(nDeBNA8Am}xgmw0Oh3#@^+ra32{Gx~^hTdxoU z>4I)BK8&WRVo9tX;JtO67V#)d6c>@=F_^H;a`D8z$bH=M2^vKd=AMJ1C3dr*h~ny; zmQYegcgZeUS|weXnpYAsw@O&r71Fl`bZ*ZbW-<FEDV-ziqqIu9M<%yR3$Zz~w>uBH znu@$5^JFYLLs4X%y)?<W-0RG&>+ec!=TY`wbk+vlBZKZ5niEnQJWv8dEQrlRZ1hKK z(w^8@1+-JO`U~k=n(lv~A=Z!z(`02{-@1Qi@K|yo2WtA14~~j>n(<u8fdMt<Vjx9) z;SZB<Lb*TwR{Om)kt!~-@nOp#@zA)05+C<$_k=49>*0u_R34&p9@}*U#Yk<N7h!tQ zZiH2GrXA!WlU-Lk)daL#!Ir{g)^0IX<Eavc7fs{hAN<0IQ9D&dqdd8VhENZ-V4K>| zhHVgU;7e?ZoiCHqe6OPTS9BB(5h=D5Jflb_tUz8<NTl(Al-AOzD1EV}6p1IJy7-Kt z1b!kv(-SD29fDNTrCT~Hn7gWmbXYqm9L(n#d7$X+?@=!JRxj-ZFlS_o@0eTKJ0z#Z zvKnr0L4Rn^Yh`Wem#(S(B{?8pkcZ?eGI@^?B((luMz41?_^;vpSAU(Ioe3je4dKi( z#K38{Q8lb-f%+Lo>M4#^vP5Vn8{r|$fVBOrNOEl#IC||JN0J+%X)DF6b1IOEt|u;; zKz}{?5WgAJhe^uADrGG$a)mP4Fp{R)!axnf|1;yt=s6E%8*|AkXb5=F1Rsg<aQko% z#2&uRdVc?=-~X_Ks=pig{f{c=*ze!+`v)Dre;fD5=O2E8mrpkVrwGE=UKnOkl852U zF^$|2+a{-f_hNP1x)B#?%43xjxvW$ub}=Y;bEEV9^*_Qm5;Dn8Ds5JCtl()XZ<-<| zc^GP6j?+X{Iu(~O$$F+R((qh6W0Bxo-Z9S?zp}MgN!9CR1)HY)(9kBYqG_6uP_N-N M?WSintFdgs-!xoIpa1{> diff --git a/src/snipper/__pycache__/load_citations.cpython-38.pyc b/src/snipper/__pycache__/load_citations.cpython-38.pyc index e79c0857a12b2136f7aa6dcb235a3dc9c4293688..d56371f0185a8d8fca7bfd94be7ecc44f1d2f380 100644 GIT binary patch delta 1403 zcmZ8h&2Jk;6rb5|+v|;+22!X|Ow~4BQ4v%LC}3I8f<!^8N-9*eO=Yb;<769q?aa=S zWHT!tTF$820|!8gkBAdO`~jTcZy3QDg)0Z7ND$tv!-v?_{^relzj^P?o451Z<)4<k z59{?Rg2#OKjWB!eiPyyIPhPk>MZ_3dBRjA$A||mOqrf3HabT<vmsCmZF%GH(-$j1? zNG-qZV`)u>>1GrwsTcJ)-2=(k4O!gBigNmRFjnBZ3189x3r7#}p(fA_Crz#sEYLEV zKEfD9=q}=hKty|_ed^^{;6rnUa_t^^8GV4((MQ0@b)mhD9{iXa!Z@_Rsz#gWGt6!f zkhd*%12hgXXE--Y$pXm|hA@e}jD+=x_6*AH(&7knrjg1r%BN1Ls0wGM<rN@1qEZs8 zqDqjcg2UPjmztUY-C;$|l|zC`tt)E8-PYKzq%Pdg5%Ip%^LpG6wZrNRkp&3sLYTU! zi<)pr;|pEr!fvCT8$ySgo|)dxnm5PkkhJ14Zw;cDwB{uRc}QPxNzAg!Mof2yVUG?o z^UXe^1BnkZtCaF1Rq;$eIJkeLgCuc&j2}pc?xZ1)#&KrSoflhIj<J7?TfQzUanz@! ztH5C)IDH<xN-IuBJ<9x=)W(T4CL!OF7Tt>yo-m{MOna;91$LP3sg#OewCjxp2o+dy z>F6uOE){F~`<|oD`6>X?UEM9dSzIZ;)+>1R+wb(6hO^>(^E}|s<_h2+=7l>ZFr|_5 z!F6aKhsOOeiQ>(pKTl3hB+879lnt2;oXp;U7UR7^X1CXpNf>vIaVIlc?OrD{+iSf} z>!_p^W9#Xuubi5bVHm~iqLLkzbR3STf1Wi!!OkdHRG<L_HC6NOyrEfHLhDY*63W<F zWp*cO(oHy{;VAG1V>SwTm&Tk$G+|AkNbBQpn9@XQ(O4FSeQqhJ?Xrl|lC{rTz+o4Q zm+V)k%ZhF@3hDK!|5RYZQLFSI%D(!IAk03@&YsS;_-NSeh5c<BlVIsoS#IqgZT)ZU zJmqIq0E2`)3_OM1dA^(yX)sC#i8NK}`|LF!2JSfJla#~eRkc***fr%qhssMFNjzaI zYOY1s0-bDe5K?wY(Mq_iY}HN5yYr4+gL$%E#0%$&p3~MXcB_~<KTOpXP@dy4zR%PR z#4G?GGgS@Wkr<Lnc*uBJDXH^4&fWoEy>hdRm%v^-_dAoTyy>*e98$|>RqRwYXS z2pibN4)y>qG&B!4wI*ikVDL4jei-(il56vZc%}G#@yfmO=pA*5K@&pTE7q!lTME?L e{{;Vc|4w@}Ch3rNl-opIc@6}2)vG(JPUkOl`F>;o literal 4979 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 QBEoh2C;iuhivQYw0gQ*8e*gdg diff --git a/src/snipper/__pycache__/snip_dir.cpython-38.pyc b/src/snipper/__pycache__/snip_dir.cpython-38.pyc index a8205b9d82839835b55f286b4d28b2c5c8467e71..4ce3da3636250429478c87ecb3bafc063b86f0dc 100644 GIT binary patch literal 2057 zcmYjS&2Jk;6rUNdch{S><0Q^UX+SFwNRC8`5K^VKN-HRWQ-nx*F)7x1XJRke4|irv z5^F3~q!MtT3MT{w$vO7M6%PC%bLGUJKm`(S#tzL|^X9#IAM=~{-i#mA>j8rAX76_V zQ4^s*jd1nzLAVD)>;j>P;tX|WGwxuJNk;NYr-IE|C3Es>r)qhexgFQqdmYcte#fUC zty1?1?$jvWLv8;rh>3RFST7{35GC&(rWpg#`6QNu{iJ5p^KT921sD|=A|nVX*!_s` zO^K%X0!^?a6jP$`8DLQrt9w_%Oi>?@eOH-Olw((S`e@<+@AUCa;H2|Kb?Pd7fyL+2 znR<r9$gcVdUEs+j59<@Gh>h{o>T5<%tLtb&=Jo_^W_+Lk;RWHp$_474;jgf&@;_ua ztzX8!+)3d{jd}{DcoM)Fd=*gd8hVCkP1T;EU!1c`G#2AI=FXKU;j}T^2M{k#n>4W4 zm*g_!0Z&)x!UfEe1vqi27Ve{m?@#I$Y0J`8WzYcTZ_(H25Yv#>pZLnTkHDv)!s(i- z%XQT_!y!5ZD~!(ZqxWcIvZz9c_4I&Dnv*3PX+t$H@HrNb<u%oWonN7gM&>VNtLMK% zgvV;hXaLi4iY6=ax@sO`<tm~)1-Mm3`E==LPp$kwp5jSMwP@qWIVW&#qFRubWz~ed zR7_sfqG~}67j0C7=~KY8I>+RzRj9@)>_)`wyqjhPB7F>Xe%0_86`OPXt8`@@stMYb z&9Bv-lSeJJ2%Xy69oIe+MLHZZ{&0M^C?m>*Op92iWf9SoN5`><#E>QFVajME%4j6g zq8}AyA)vL{Rr_1*imt??6YciWo@6K5Ps%)x3o6F-t!{UCn#9R~b-P<*??yS2!;u`n zzE_TT!Xhxb8YxOeBnK=Kan7{Uiv=6M`9I8P@3cq;ye!hOK>{FIB1@h!aVr`-(c3#w z|EC|#_uJjEyR~&=YkMof^V?=7xMRqLu>wPE0O=!z9yZ~op(*;tcK7$>k+X-MBe=5O zVUfo&8MKKe+wW+?PM%|36~io*+`J(#Zhmm<;DKOV9LUjt9o#RIQO*h}4(4e+5IlLw zL#n%gczbxNgF9I&B&2A#bK5|1fVhBeylFhG)t#(N;!Nypzcl6MDB}tQ7}vUe9#aNv z+tW2ZD(o{OI-y}9!6t;zwFEfx{s>(cWi~RE?V6o+%_O!vgeOS{oE<XGiUh2}EH$qd z>ke2<$7CmZfe+fRX<xE@XyRxuKcYs^)gey{sU4aoQj=0>#|CrR34|Bg&*LLzF?exL zSd|B2VT$UT(%NXX4^I*{G^n&I1^_S9F3%-rV3d@@Q_DFr1*fXW7#nKGpy%en)J{Ju zd)hBbp3mZQmd!B4(9#8kek@LPH5IV0u7H>JVO1Qba==X=Xg3uWh09r9e#zQvIuN!c zP4cvFZiD55S;HEhw~V95PLgayS!XrLSX^|k+#72I|2c>+8M123E8wrm;8>GPbb>fB zM~-`tOq^+)Yg}l2sNLB*Up5}@(Q(ZCqT>_*t>f|B7SZ+`4^7;LvGOl_#q^?(Kv3Xg zABV)p4HymyaEJpE0`+kd<_7kOg9BJ|fZG7sXalm0LB?x%8E@1aC&b&}>n=FhsWvb% zzkeNv{Nq*wurSd=?1FCyehtF!!M<&O7ry=d{oQuJufqa=1Bh<T@4@zb?&fh?%#!b! zQe|n+){?(vT+Cl1UpM5QA?8$9$n3~>@{*1+wqtIB*aXtFaLlp&3c~h>=JVhG0n(B@ A4gdfE literal 2103 zcmYjSOK%)S5bo}ootd3|_-(Htibj?|T1zn;KtWMt5F{KegdGlpt<89*cX#kSHr>70 zUiDmXBmxr1TtJW@+1&CUI3w{FTHHAC7os4j?p@27RX?h_9$!^g^*(5|d<5UtAMZp_ z8==27@#<#-@c|6}F-!?caE8L^ibD)E$w+R67S=o~v-4V5Gkcslp=0FT&`sQ=mN<`b z=p}d;b-jPU7TW1z)re`qOV;bB83oe*Bof2D*wM$cZynYK3=0OI5QL<apd-Roh4zRB zfap7`vZQUe8v|6?0)Ig+EQv2Me^1~GTkkNMaS3pD3>S7YZcW0zB1WPn5$vbZHLY1; z!*?VCim)fbO~@Jk3d<V%QFs^iE9+N&B(AiqomkIE<qAKsB}BiDo}$E&&QtWOeRk#7 zU}S$?TbW8$9&j4c)BXTq^P-iw25Vc)NqmMc<`eG{)~XKC`m%lx9eh|d49W#FFUp42 zy~N+3uTdW-^~8VdN&6lGou>3JmSjUL%jOwwqQ1$(IexU9G^&>L!Pf8lq-s}l#?p#x zU*dDjABt7k2G46r)6n07#=}=U&g9r{vR(Lw-_e?oy?Hrzj@d)Fr&iL2j4Y(6S_Irn zur4Qa)e4MNu`b(kp-<$hByvSA>Db|(=byQ9`6u!{uGZvQ(m1lu30oAtT!UOL$TsBC z(z%o^xpo^>Ese=U@F_&lnMF{O9YE0m6ohXWWUpxsSo#dA;B~#nsJJnUwv#Nb!TrPO zhPf4UdQKi~$QIP?(oWY>Ry00Q&S82e=!x>;GS8zT;ggNsa?D~H01+gVi?oPDS{6ad z12Lolk8;{2%07%Z4eRtI&c+;$CvSYti*z)i>>$`ZE#e_7i*%9}gCI#6jYY{)%I^fs zh3cQ!!L99J@XOEo`}6&Yv$^@!=GJD6;q2;z{y@5WmSFG>Oamm*!93J3x<F4%1^+-E z*}LdDf_8KJMIMQG2*AkJ+ltVW=UCPFC`$$NK>5Y(kM8V0;FR%wF&@(Wdu2S%X(9Oj z4D>!{@%0`8=>hDm(W&z9W+@ktoYD5X8j5~J97NFMhSoGvce65%GQPcaEy{E#6AKJX z=>3x@A7zj@F;2i`5SIzv3igJOPyJZvyhdYD0{#@tWT(M^7L-MTCPAN-xk<Vf<Uv{( zA}zRJW1Z4lSGhgylCWLS;~t}Z%4iW&9=5fkUR;h&SvnYsy{@b3Y+RTZiib_TEyqGf zz*RklopGXCyv)Y>!h1UKa3L+=hQZJX9<-jmbXC{0p_PB_Z$h?%7kIyWL)l3h3q?w< zY^|gmdIFZX^78128h37V$jy<bt4aG+_4_9=9cjPH;X?qBg$~OFqg2&KEG<L`6*@XK z3|pi*uz5!5NZA@D(~oLs53=%5c}2-`W8Gymn<9vyFpC5#zBpC2lmiH5ftK=s%a2n4 z=>o3+FiaPoa#C(kIgIAzm$bVc`rLGdP8YoW&=z{9e8}Kvnnbp&A-JX?5*n_=8I6kG zD-C2+El>!_@YwW0NHQM!QLF=x4j~CRQ#e<+P`DpDQ+`<M8&7sx^h-zuB$Ts7gYoD% zVgt?=fME05xm^I<&}F%~N>li(sZZhW5Gn7fV0A-q2@`TW+$J8jNfY}R2CVwm#vZYO z<6AZ+nEdBh9dqhwIkJdt?BP|sh&wggZsMCjzloi?59`%$Uh84<uWgf;PR$2dunXD_ z*lvP_HetG(y7tb_&R)09)_`C)VG5UL4Y@U2dwG-=(@Sx6@L76jE}I2frLHG!X&S7K fY`U99d^azXaYnawH*%e{c@v+9y&A&sL+IuIYNJT* diff --git a/src/snipper/__pycache__/snipper_main.cpython-38.pyc b/src/snipper/__pycache__/snipper_main.cpython-38.pyc index fd90def87e043144655478d490c81d7f34538bfe..44240208f1eec24853d05c9805203b70e188365e 100644 GIT binary patch delta 1307 zcmZ8g&2Jk;6n`^bf9%?8ukH0`0Hp<0xCKfNNT@^=N+a<l0&P>ZL@g%WXQxYyKV~Na zqFF5ATtJGNYPlh#HA37G7sQD(H>8S#uW*6C0Er84Hc3@Ft9kR@?0dg?^M3OlxW6^d zUAJuuXpFsAw%#lO{Gp9Uhe^h(G=szY=j5ph7SP^jn-#2L5lf_1(ZTXQY`Vy<LC5{! zryuz=K|BUoqBT$Rvc~w51E?Ir4i^O<!W^>DlAr)NrqDP@9rAn6hIy5b*&M=xD#ZMF zO<{V@LR%Wjp0PE!eeo6#i(yHX;xuOF46{3i7|M)-uK{yYRiwrI#+We%<dQ`T^K-6j zRa}9|+FnKGNYAM(77kLOeFKIs8z9XcOZ>_pbQtWl3ChvYGK02)87Ca)b9Mt>0wj;m zoSX0-4Eaq^Ecjie4w(>&)3r>kZBHRAE8f?6o((Ii99uH~VIj6vC0UCK<}6NOQRm%) zIiJ%(lfPA2Ta;`G9ZHt06@n+g4Oyae;pjh>4^ott^Z3qD60)ppnV-^O6$;1@497|m zP*pZj=3;F-HRGYJ(gggibP2}Nwyf#G-lA%R)zBRpm<_A4uJ;mOE*#lV?kp+vAz8{u zZmTtjn?zDg)rg8ZkyO|BZ(swP`=H!4Ac!XM)=YS-6L0mfr5drNT79N(e#j>O5I7yB zStRg_+QL?gB2RXd9b4Ge-k7F3+H_1?lW_&E0+C=ICv!)(R9l&6=|=73SuNoc`dQs` zl1J563B)6T)#%UkcWg8IBJ&l=r?RVTDcZ`u&(24`WM6;R?)#r~z0vqn;cwrSi}c6B zm%YxCc#fX(!W6s1Zr>mDf<-~Aqg~lWUjz%&Bkkyi9gGIM(jN`G13!?9=#AWy?S&<J z{hsIzJsmmlz1}eBb?^4JFcP`f*dqEl*U5Z9CqOp(D|ec?QNetEy38!*a*J6hhq+8# zr{5m+(!-(kG|i;TmPtVtCtXDxFx^d>2YPR;LEY8>>QrN0oFPAtkvJJADA#BsXp-0_ z@7qqurl?_HPNDbt#Gr7t$DdyAuthqM!XJ0Ic#+)2J6g0K3f=qSf)+FbgG2^6?49~w zU0+xkjJ&NuaETPEk~jKje2MVRllQ_3#sgmt{PkfkpuM*>)LU9ScE&30O=t#5O_<Pj whi!DsjrF5%y;Bn_I<QP)GrD75CceKny^OA;SdA>}40|TJV4Y4g_}9AfAHFv;;s5{u delta 895 zcmZ8fO=uHA6n?YWZ1y+1NjAT=PznmM3SJ6QDyS{~K?~MO+t44RFR8I5rJD&tnKfW~ z5V2TUML~qk)th)01aIO+kREapy!YhMgKv|9#aU+O{eJW2d+&SxhdXxHvUH$T_%?oT zBnj{<Qcf<Fl*_c6PhO1iqJt({d#sYi6eiIoDTC||l+zzRf0WwViNq4g2JNXRcU1xq zD#E7ZnRW10WWL5h07@7`c|Ud_J$HOv=ppNZZwMolj?WmzyUaJaEX)p@hLwqB$+!HZ zNQQA#x(pMWve)2>fVY5ZTUc~x@8k|+Kp_d#(dbIT6xJl{Oz)<-O0p^vXzs^+a{(F` zW#HPT?tNw8+YEL~1Z79rTtQ1fM<N{iF<XFfK#F)|FTxTuq(u;{c_?BB%)7q<z9Xbs zRGfX*PYEZ~x$(dZEs+YI%0oAQ3I`KKpki!vs2I{FDV<VpahuA4fge-*F}l|I-!iy_ zr-T_C$@#X48FVqb5$j04DdL3khP#xbMLN$$EG^U1{Is8G$e8fcJQvyev683oyvTI= ztR0XhWa^04mmn+<<F0Ut*BmjPrDx?ZkA*!DnQ0(|JoO;o?l&PvP00EMkqdQEsIe~b zb-;Fx2;9VCk%FVP5bUThLmf+zALB%bNx;R3%iAyqi_jl{Av_fgz;XMFq8LU0ixFuW zuHo5hJ?8b~77tD<uURknq`YKH!Cc}hD+R9-tL#GXJ8|Pm{GnIp)pE%@M<Z9!yjEka zR^O^ND`q5axA+>?y=FyQCu!iYn%i3~Uf*u4ZPlB+5<F9f&5G_-YgMn>Sg$sNFY0wx z2@I{QEE6Uu!Gt!-^k79hUrsZfxst<N=FO0+%;wAL{OsT>yWS<Tc`5q!f<t|ZYAzY; RY$oU!XV^&a-WX+n{sLr9+`9k( diff --git a/src/snipper/block_parsing.py b/src/snipper/block_parsing.py index cfad9c4..23d4271 100644 --- a/src/snipper/block_parsing.py +++ b/src/snipper/block_parsing.py @@ -20,31 +20,41 @@ def block_iterate(lines, tag): yield contents +def block_join(contents): + blk = contents['block'] + if len(blk) == 1: + blk = [blk[0] + contents['post1'] + " " + contents['post2']] + elif len(blk) > 1: + blk = [blk[0] + contents['post1']] + blk[1:-1] + [blk[-1] + contents['post2']] + return contents['first'] + blk + contents['last'] + def block_split(lines, tag): stag = tag[:2] # Start of any next tag. - def join(contents): - return contents['first'] + [contents['block'][0] + contents['post1']] + contents['block'][1:-1] \ - + [contents['block'][-1] + contents['post2']] + contents['last'] + contents = {} i, j = f2(lines, tag) def get_tag_args(line): # line = line.strip() k = line.find(" ") - tag_args = ((line[:k + 1] if k >= 0 else line)[len(tag):] ).strip() + tag_args = ((line[:k + 1] if k >= 0 else line)[len(tag):] ).strip().split(";") + tag_args = [t.strip() for t in tag_args] + # if len(tag_args) == 0: + # return {'': ''} # No name. + tag_args = [t for t in tag_args if len(t) > 0] + tag_args = dict([t.split("=") if "=" in t else (t.lower().strip(), True) for t in tag_args]) - if len(tag_args) == 0: - return {'': ''} # No name. + if '' not in tag_args: + tag_args[''] = '' - tag_args = dict([t.split("=") for t in tag_args.split(";")]) return tag_args if i is None: return None else: - print( lines[i] ) + # print( lines[i] ) start_tag_args = get_tag_args(lines[i][j:]) START_TAG = f"{tag}={start_tag_args['']}" if start_tag_args[''] != '' else tag @@ -62,7 +72,7 @@ def block_split(lines, tag): l2 = lines[:i] + [lines[i][:j2], lines[i][j2:]] + lines[i2+1:] c2 = block_split(l2, tag=tag) c2['block'].pop() - c2['joined'] = join(c2) + c2['joined'] = block_join(c2) return c2 else: contents['first'] = lines[:i] @@ -81,7 +91,7 @@ def block_split(lines, tag): contents['arg2'], contents['post2'] = argpost(lines[i2], j2) blk = [lines[i][:j]] + lines[i+1:i2] + [lines[i2][:j2]] contents['block'] = blk - contents['joined'] = join(contents) + contents['joined'] = block_join(contents) contents['start_tag_args'] = start_tag_args contents['name'] = start_tag_args[''] return contents diff --git a/src/snipper/fix_bf.py b/src/snipper/fix_bf.py index 3a128bc..c4d5254 100644 --- a/src/snipper/fix_bf.py +++ b/src/snipper/fix_bf.py @@ -1,6 +1,7 @@ import functools -from snipper.legacy import gcoms, block_process +from snipper.legacy import gcoms from snipper.block_parsing import indent +from snipper.block_parsing import block_split, block_join def fix_f(lines, debug): @@ -29,39 +30,53 @@ def fix_f(lines, debug): comments = [id + c for c in comments] if len(comments) > 0: lines2 += comments[0].split("\n") - # lines2 += [id+"#!b"] f = [id + l.strip() for l in funrem.splitlines()] f[0] = f[0] + "#!b" - - # lines2 += (id+funrem.strip()).split("\n") errm = l_head if len(l_head) > 0 else "Implement function body" f[-1] = f[-1] + f' #!b {errm}' lines2 += f - # lines2 += [f'{id}#!b {errm}'] - else: lines2.append(l) i += 1 return lines2 +# stats = {'n': 0} +def _block_fun(lines, start_extra, end_extra, keep=False, silent=False): + id = indent(lines[0]) + lines = lines[1:] if len(lines[0].strip()) == 0 else lines + lines = lines[:-1] if len(lines[-1].strip()) == 0 else lines + cc = len(lines) + ee = end_extra.strip() + if len(ee) >= 2 and ee[0] == '"': + ee = ee[1:-1] + start_extra = start_extra.strip() + if keep: + l2 = ['GARBAGE'] * cc + else: + if silent: + l2 = [] + cc = 0 + else: + l2 = ([id + start_extra] if len(start_extra) > 0 else []) + [id + f"# TODO: {cc} lines missing.", + id + f'raise NotImplementedError("{ee}")'] + + # stats['n'] += cc + return l2, cc + + def fix_b2(lines, keep=False): - stats = {'n': 0} - def block_fun(lines, start_extra, end_extra, art, stats=None, **kwargs): - id = indent(lines[0]) - lines = lines[1:] if len(lines[0].strip()) == 0 else lines - lines = lines[:-1] if len(lines[-1].strip()) == 0 else lines - cc = len(lines) - ee = end_extra.strip() - if len(ee) >= 2 and ee[0] == '"': - ee = ee[1:-1] - start_extra = start_extra.strip() - if keep: - l2 = ['GARBAGE'] * cc - else: - l2 = ([id+start_extra] if len(start_extra) > 0 else []) + [id + f"# TODO: {cc} lines missing.", id+f'raise NotImplementedError("{ee}")'] + cutout = [] + n = 0 + while True: + b = block_split(lines, tag="#!b") + if b == None: + break + args = {k:v for k, v in b['start_tag_args'].items() if len(k) > 0} + cutout += b['block'] + b['block'], dn = _block_fun(b['block'], start_extra=b['arg1'], end_extra=b['arg2'], **args, keep=keep) + lines = block_join(b) + n += dn - stats['n'] += cc - return l2, cc - lines2, _, _, cutout = block_process(lines, tag="#!b", block_fun=functools.partial(block_fun, stats=stats)) - return lines2, stats['n'], cutout \ No newline at end of file + # lines2, _, _, cutout = block_process(lines, tag="#!b", block_fun=functools.partial(block_fun, stats=stats)) + return lines, n, cutout \ No newline at end of file diff --git a/src/snipper/fix_cite.py b/src/snipper/fix_cite.py index c4cfb1c..4b49641 100644 --- a/src/snipper/fix_cite.py +++ b/src/snipper/fix_cite.py @@ -19,7 +19,7 @@ def fix_aux_special(lines, aux, command='\\nref', output='\cite[%s]{my_bibtex_en def fix_aux(lines, aux, strict=True): l2 = fix_single_reference(lines, aux=aux, cmd="\\ref", strict=True) - print("\n".join(l2)) + # print("\n".join(l2)) return l2 def fix_bibtex(lines, bibtex): diff --git a/src/snipper/fix_i.py b/src/snipper/fix_i.py index 0d17a39..28b5bfb 100644 --- a/src/snipper/fix_i.py +++ b/src/snipper/fix_i.py @@ -2,6 +2,11 @@ import functools import textwrap from snipper.legacy import block_process from snipper.block_parsing import full_strip +import os +if os.name == 'nt': + import wexpect as we +else: + import pexpect as we def run_i(lines, file, output): @@ -14,11 +19,6 @@ def run_i(lines, file, output): lines = textwrap.dedent(s).strip().splitlines() if extra['python'] is None: - import os - if os.name == 'nt': - import wexpect as we - else: - import pexpect as we an = we.spawn("python", encoding="utf-8", timeout=20) an.expect([">>>"]) extra['python'] = an @@ -34,8 +34,6 @@ def run_i(lines, file, output): lines = l2 alines = [] - - # indented = False in_dot_mode = False if len(lines[-1]) > 0 and (lines[-1].startswith(" ") or lines[-1].startswith("\t")): lines += [""] @@ -57,14 +55,8 @@ def run_i(lines, file, output): if 'help(s.find)' in word: pass if dotmode: - # alines.append("..." + word) alines.append(">>>" + analyzer.before.rstrip() if not in_dot_mode else "..." + analyzer.before.rstrip()) in_dot_mode = True - # if i < len(lines) - 1 and not lines[i + 1].startswith(" "): - # analyzer.sendline("\n") # going out of indentation mode . - # analyzer.expect_exact([">>>", "..."]) - # alines.append("..." + analyzer.after.rstrip()) - # pass else: alines.append( ("..." if in_dot_mode else ">>>") + analyzer.before.rstrip()) in_dot_mode = False diff --git a/src/snipper/fix_s.py b/src/snipper/fix_s.py index c740280..5a97096 100644 --- a/src/snipper/fix_s.py +++ b/src/snipper/fix_s.py @@ -1,26 +1,47 @@ from collections import defaultdict import os from snipper.block_parsing import block_iterate +from snipper.snipper_main import full_strip def get_s(lines): """ Return snips from 'lines' """ blocks = defaultdict(list) for c in block_iterate(lines, "#!s"): + # c['start_tag_args'] + if not c['start_tag_args'].get('keeptags', False): + c['block'] = full_strip(c['block']) + else: + # In this case the #! tags are kept in. + pass + # print("keepting tags.") blocks[c['name']].append(c) output = {} for name, co in blocks.items(): - output[name] = [l for c in co for l in c['block']] + slines = [l for c in co for l in c['block']] + # full_strip("") + # c['block']['args'] + # slines = slines[ 23] + # co. + output[name] = slines return output +# def _s_block_process(): +# +# pass + def save_s(lines, output_dir, file_path): # save file snips to disk content = get_s(lines) - if not os.path.isdir(output_dir): + # Only make output dir if needed. + if len(content) > 0 and not os.path.isdir(output_dir): os.mkdir(output_dir) + for name, ll in content.items(): if file_path is not None: + file_path = file_path.replace("\\", "/") ll = [f"# {file_path}"] + ll out = "\n".join(ll) + with open(output_dir + "/" + os.path.basename(file_path)[:-3] + ("_" + name if len(name) > 0 else name) + ".py", 'w') as f: f.write(out) diff --git a/src/snipper/load_citations.py b/src/snipper/load_citations.py index 786c02b..0512cd1 100644 --- a/src/snipper/load_citations.py +++ b/src/snipper/load_citations.py @@ -1,18 +1,17 @@ import os import io -# from coursebox.core.info_paths import get_paths from pybtex import plugin from pybtex.database.input import bibtex +from warnings import warn ### Newstyle loading. - def get_aux(auxfile): # paths = get_paths() # auxfile = os.path.join(paths['02450public'], auxfile) if not os.path.exists(auxfile): - print(auxfile) - from warnings import warn - warn("Could not find file") + # print(auxfile) + + warn("Could not find bibtex file: "+ auxfile) return {} with open(auxfile, 'r') as f: @@ -104,17 +103,7 @@ def get_bibtex(bibfile): 'filename': url, } - # newref = {} - # ls = lambda x: x if isinstance(x, list) else [x] - # if 'tex_command' in gi: - # for cmd, aux, display in zip( ls(gi['tex_command']), ls(gi['tex_aux'] ), ls( gi['tex_display'] ) ): - # ax = parse_aux(aux, bibtex=gi['bibtex']) - # for k in ax: - # ax[k]['pyref'] = display%(ax[k]['nicelabel'],) - # newref[cmd] = ax - - return refs#, newref - + return refs def find_tex_cite(s, start=0, key="\\cite"): @@ -132,112 +121,112 @@ def find_tex_cite(s, start=0, key="\\cite"): return (i, j), reference, txt ### Oldstyle loading -def get_references(bibfile, gi): - """ - all references. - """ - if not os.path.exists(bibfile): - return None - - pybtex_style = plugin.find_plugin('pybtex.style.formatting', 'alpha')() - pybtex_html_backend = plugin.find_plugin('pybtex.backends', 'html')() - pybtex_plain_backend = plugin.find_plugin('pybtex.backends', 'plaintext')() - pybtex_parser = bibtex.Parser() - - with open(bibfile, 'r', encoding='utf8') as f: - data = pybtex_parser.parse_stream(f) - - data_formatted = pybtex_style.format_entries(data.entries.values()) - refs = {} - - if 'auxfile' in gi: - all_references = parse_aux(gi['auxfile'], bibtex=gi['bibtex']) - else: - all_references = {} - - for entry in data_formatted: - output = io.StringIO() - output_plain = io.StringIO() - pybtex_plain_backend.output = output_plain.write - pybtex_html_backend.output = output.write - pybtex_html_backend.write_entry(entry.key, entry.label, entry.text.render(pybtex_html_backend)) - - pybtex_plain_backend.write_entry(entry.key, entry.label, entry.text.render(pybtex_plain_backend)) - - html = output.getvalue() - plain = output_plain.getvalue() - - entry.text.parts[-2].__str__() - url = "" - for i,p in enumerate(entry.text.parts): - if "\\url" in p.__str__(): - url = entry.text.parts[i+1] - break - url = url.__str__() - i1 = html.find("\\textbf") - i2 = html.find("</span>", i1) - dht = html[i1:i2] - dht = dht[dht.find(">")+1:] - html = html[:i1] + " <b>"+dht+"</b> " + html[i2+7:] - - plain = plain.replace("\\textbf ", "") - iu = plain.find("URL") - if iu > 0: - plain = plain[:iu] - - refs[entry.key] = {'html': html, - 'plain': plain, - 'label': entry.label, - 'filename': url, - 'references': all_references} - - newref = {} - ls = lambda x: x if isinstance(x, list) else [x] - if 'tex_command' in gi: - for cmd, aux, display in zip( ls(gi['tex_command']), ls(gi['tex_aux'] ), ls( gi['tex_display'] ) ): - ax = parse_aux(aux, bibtex=gi['bibtex']) - for k in ax: - ax[k]['pyref'] = display%(ax[k]['nicelabel'],) - newref[cmd] = ax - - return refs, newref - - -def parse_aux(auxfile, bibtex=None): - # paths = get_paths() - paths = {} - auxfile = os.path.join(paths['02450public'], auxfile) - if not os.path.exists(auxfile): - print(auxfile) - from warnings import warn - warn("Could not find file") - return {} - - with open(auxfile, 'r') as f: - items = f.readlines() - entries = {} - for e in items: - e = e.strip() - if e.startswith("\\newlabel") and "@cref" in e: - # print(e) - i0 = e.find("{") - i1 = e.find("@cref}") - key = e[i0+1:i1] - - j0 = e.find("{{[", i0)+3 - j1 = e.find("}", j0) - - val = e[j0:j1] - - label = val[:val.find("]")] - number = val[val.rfind("]")+1:] - - if label == "equation": - nlabel = f"eq. ({number})" - else: - nlabel = label.capitalize() + " " + number - - coderef = "\\cite[%s]{%s}"%(nlabel, bibtex) if bibtex is not None else None - entries[key] = {'pyref': coderef, 'nicelabel': nlabel, 'rawlabel': label, 'number': number} - return entries +# def get_references(bibfile, gi): +# """ +# all references. +# """ +# if not os.path.exists(bibfile): +# return None +# +# pybtex_style = plugin.find_plugin('pybtex.style.formatting', 'alpha')() +# pybtex_html_backend = plugin.find_plugin('pybtex.backends', 'html')() +# pybtex_plain_backend = plugin.find_plugin('pybtex.backends', 'plaintext')() +# pybtex_parser = bibtex.Parser() +# +# with open(bibfile, 'r', encoding='utf8') as f: +# data = pybtex_parser.parse_stream(f) +# +# data_formatted = pybtex_style.format_entries(data.entries.values()) +# refs = {} +# +# if 'auxfile' in gi: +# all_references = parse_aux(gi['auxfile'], bibtex=gi['bibtex']) +# else: +# all_references = {} +# +# for entry in data_formatted: +# output = io.StringIO() +# output_plain = io.StringIO() +# pybtex_plain_backend.output = output_plain.write +# pybtex_html_backend.output = output.write +# pybtex_html_backend.write_entry(entry.key, entry.label, entry.text.render(pybtex_html_backend)) +# +# pybtex_plain_backend.write_entry(entry.key, entry.label, entry.text.render(pybtex_plain_backend)) +# +# html = output.getvalue() +# plain = output_plain.getvalue() +# +# entry.text.parts[-2].__str__() +# url = "" +# for i,p in enumerate(entry.text.parts): +# if "\\url" in p.__str__(): +# url = entry.text.parts[i+1] +# break +# url = url.__str__() +# i1 = html.find("\\textbf") +# i2 = html.find("</span>", i1) +# dht = html[i1:i2] +# dht = dht[dht.find(">")+1:] +# html = html[:i1] + " <b>"+dht+"</b> " + html[i2+7:] +# +# plain = plain.replace("\\textbf ", "") +# iu = plain.find("URL") +# if iu > 0: +# plain = plain[:iu] +# +# refs[entry.key] = {'html': html, +# 'plain': plain, +# 'label': entry.label, +# 'filename': url, +# 'references': all_references} +# +# newref = {} +# ls = lambda x: x if isinstance(x, list) else [x] +# if 'tex_command' in gi: +# for cmd, aux, display in zip( ls(gi['tex_command']), ls(gi['tex_aux'] ), ls( gi['tex_display'] ) ): +# ax = parse_aux(aux, bibtex=gi['bibtex']) +# for k in ax: +# ax[k]['pyref'] = display%(ax[k]['nicelabel'],) +# newref[cmd] = ax +# +# return refs, newref +# +# +# def parse_aux(auxfile, bibtex=None): +# # paths = get_paths() +# paths = {} +# auxfile = os.path.join(paths['02450public'], auxfile) +# if not os.path.exists(auxfile): +# print(auxfile) +# from warnings import warn +# warn("Could not find file") +# return {} +# +# with open(auxfile, 'r') as f: +# items = f.readlines() +# entries = {} +# for e in items: +# e = e.strip() +# if e.startswith("\\newlabel") and "@cref" in e: +# # print(e) +# i0 = e.find("{") +# i1 = e.find("@cref}") +# key = e[i0+1:i1] +# +# j0 = e.find("{{[", i0)+3 +# j1 = e.find("}", j0) +# +# val = e[j0:j1] +# +# label = val[:val.find("]")] +# number = val[val.rfind("]")+1:] +# +# if label == "equation": +# nlabel = f"eq. ({number})" +# else: +# nlabel = label.capitalize() + " " + number +# +# coderef = "\\cite[%s]{%s}"%(nlabel, bibtex) if bibtex is not None else None +# entries[key] = {'pyref': coderef, 'nicelabel': nlabel, 'rawlabel': label, 'number': number} +# return entries diff --git a/src/snipper/snip_dir.py b/src/snipper/snip_dir.py index 328e93b..f264c59 100644 --- a/src/snipper/snip_dir.py +++ b/src/snipper/snip_dir.py @@ -3,13 +3,21 @@ from snipper.snipper_main import censor_file from pathlib import Path import time import fnmatch - +import tempfile def snip_dir(source_dir, # Sources - dest_dir, # Will write to this directory + dest_dir=None, # Will write to this directory output_dir=None, # Where snippets are going to be stored references=None, # Reference database - exclude=None, clean_destination_dir=True): + exclude=None, clean_destination_dir=True, + run_files=True, # Run #!o tags and #!i tags + cut_files=True, # censor files. + license_head=None, + ): + + if dest_dir == None: + dest_dir = tempfile.mkdtemp() + print("[snipper]", "no destination dir was specified so using nonsense destination:", dest_dir) if references == None: references = dict(aux=None, bibtex=None, commands=[]) @@ -17,14 +25,16 @@ def snip_dir(source_dir, # Sources if exclude == None: exclude = [] + exclude += ["*__pycache__*"] # Just...no. if not os.path.exists(dest_dir): os.makedirs(dest_dir) - if not os.path.exists(output_dir): - os.makedirs(output_dir) - output_dir = os.path.abspath(output_dir) source_dir = os.path.abspath(source_dir) dest_dir = os.path.abspath(dest_dir) + if output_dir == None: + output_dir = os.path.dirname(source_dir) + "/output" + + output_dir = os.path.abspath(output_dir) if os.path.samefile( source_dir, dest_dir): raise Exception("Source and destination is the same") @@ -33,15 +43,14 @@ def snip_dir(source_dir, # Sources os.makedirs(dest_dir) out = dest_dir - hw = {'base': source_dir, - 'exclusion': exclude} + hw = {'base': source_dir} print(f"[snipper] Synchronizing directories: {hw['base']} -> {out}") if os.path.exists(dest_dir): shutil.rmtree(dest_dir) shutil.copytree(source_dir, dest_dir) - time.sleep(0.2) + time.sleep(0.1) ls = list(Path(dest_dir).glob('**/*.*')) acceptable = [] @@ -50,6 +59,10 @@ def snip_dir(source_dir, # Sources m = [fnmatch.fnmatch(split, ex) for ex in exclude] acceptable.append( (l, not any(m) )) + # for f,ac in acceptable: + # if not ac: + # print(f) + # print(acceptable) # now we have acceptable files in list. # run_out_dirs = ["./output"] @@ -58,7 +71,7 @@ def snip_dir(source_dir, # Sources # edirs = {os.path.normpath(os.path.dirname(f_) if not os.path.isdir(f_) else f_) for f_ in edirs} # edirs.remove(os.path.normpath(out)) for f, accept in acceptable: - if os.path.isdir(f) or not str(f).endswith(".py"): # We only touch .py files. + if os.path.isdir(f) or not str(f).endswith(".py") or str(f).endswith("_grade.py"): # We only touch .py files. continue # f_dir = os.path.normpath(f if os.path.isdir(f) else os.path.dirname(f)) if accept: @@ -70,15 +83,18 @@ def snip_dir(source_dir, # Sources # if "assignments" in str(f) and "_grade.py" in str(f): # continue - info = {'new_references': [], 'code_copyright': 'Example student code. This file is automatically generated from the files in the instructor-directory'} + # info = {'new_references': [], 'code_copyright': 'Example student code. This file is automatically generated from the files in the instructor-directory'} # paths = {} solution_list = [] kwargs = {} - cut_files = True - run_files = True + # cut_files = True + # copyright() + + # run_files = True nrem = censor_file(f, run_files=run_files, run_out_dirs=output_dir, cut_files=cut_files, solution_list=solution_list, base_path=dest_dir, references=references, + license_head=license_head, **kwargs) if nrem > 0: print(f"{nrem}> {f}") diff --git a/src/snipper/snipper_main.py b/src/snipper/snipper_main.py index 4b9e7da..b2f5803 100644 --- a/src/snipper/snipper_main.py +++ b/src/snipper/snipper_main.py @@ -33,7 +33,8 @@ def censor_file(file, run_files=True, run_out_dirs=None, cut_files=True, solutio censor_files=True, base_path=None, strict=True, - references=None): + references=None, + license_head=None): if references == None: references = {} @@ -55,7 +56,7 @@ def censor_file(file, run_files=True, run_out_dirs=None, cut_files=True, solutio print("Error in file, cite/reference tag not found!>", file) raise e - if run_files or cut_files: + if (run_files or cut_files) and run_out_dirs is not None: ofiles = [] for rod in [run_out_dirs]: ofiles.append(os.path.join(rod, os.path.basename(file).split(".")[0]) ) @@ -96,12 +97,20 @@ def censor_file(file, run_files=True, run_out_dirs=None, cut_files=True, solutio # with open(sout, "w") as f: # f.write(sol) - if len(lines[-1])>0: + if len(lines) > 0 and len(lines[-1])>0: lines.append("") s2 = "\n".join(lines) + if license_head is not None: + s2 = fix_copyright(s2, license_head) + + with open(file, 'w', encoding='utf-8') as f: f.write(s2) return nB -# lines: 294, 399, 420, 270 + +def fix_copyright(s, license_head): + return "\n".join( ["# " + l.strip() for l in license_head.splitlines()] ) +"\n" + s + +# lines: 294, 399, 420, 116 \ No newline at end of file -- GitLab