diff --git a/CKAN_JRO-2.9.2.0.tar.gz b/CKAN_JRO-2.9.2.0.tar.gz index 7085589cda8b82c2c408541f80085537b07e4c3c..650f319b559cae6803e3b58a3a7aef388a009a5b 100644 GIT binary patch literal 13935 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 literal 11364 zc$@)bESu9GiwFp<={;it|3gbbPG3q=Pc1SoIW96TFfMdqascgp>vG$;(qMk;De%eV zqBxdm$(LNbqwM(Do{47?+n?>6`R4ezShNJ&oKT{Mm)M?cw)QplEw*YOV5`1;lYNry z#)Sk)kfLPSNzRCsibW7;G=N6m&;YD8Ywd?)=k5)41~ho~C{Kq!Wq&)Jjm`8orgyuW zTkFrr-Lofn;xKXosD9p!{6?Pjmt+{ZL)z;;f4n*T3eY~kPTi>;3Ow^QH+Z2oUH9Z2|E&f8U-170|6lNb$^T`-+I;8#bo_s7Ypc89|9=_&zy7?)|2G!=|4I1&dY1pc z+}gA{3(mjb|7*VozU_=%YkdEx{J*=|d9mKj&Hoo$ThE`7&Qs3+zbOB|3j87Ie{e=H z)WjWP8_5YB`VmD!Xt2)%C!)wB>^aeu9}MNYpL~hvaD3%@G%0iwN3JK| z{&X`R`~IjO2LT;L)>RzE0ZqUJ^pBW^QS$zK=#LspvUVrB@!U)KEsotmqv2j5f)+F& zgy!4s=*qW-&hLIedOfnS-5~I=E{y{Z3R`0*2$S)GH1^)0UPyV~{Fg@GbHb3ofI)|~ zOrELPY_h*U9vtqxJ=ojXPgz}^){`o30V_zsLm#ds5%#$f_ju+lMQ|0jVZ9+ zsEPJQ5hG4a?+{0eP zob=sx1|OYKUxgFi__yjSV<1XGKcK+wlmwWcnG8VSG?PIxIRz#5-~P}0?~dQ9WWChQ zQrE2;-N-p;+(glMdu?q1%-EuL&JY@50eu>6BDo`Dg*{_QK88u0kbLj-`!o#gku#*P zw+n+~Sr!R>VCMdq1`I+gG%+>BYCT&j1CaFc2-d}|F&!3#nk}SFtMBHC-j7@_9>+hp*JJD22YyLm z9Fba`(ZC0u5T;Bagb@$@Fa_E*$u0-P*dMU@2x!&`JU_{@ZbH=|^2k0kjq$*7;Dg8+ zI!T@lll4ijmQAI>74~JH5HOw6%X0Hq5Tga zRWTQkJ%5&xj0hd&m3ws$G{b=ar{79q{=yT$Rj9tLoZ1L1Kx%7R{%#vaV)PNn- zOPG&!%9C2AE@O(oj}FMbBugp?i;%JP#pddtTyvo>0Ra4;B*zXU7>Q2Jlx)&kF;+mj zv}74`#W0PuN?zuj|ECM&xVB|=Nb8-`cSn&Q-uxF3ToDX8BoGjk|3SJP8~>SPXAG0@ zS9RdU2 zD@qyJCgG$5bW)Wt!MaUAP<){Gy$taHL4`E1ookpnz1V5Xj_rxR=`bzL1mDb}m-z;8 zGVf_s&}?UPO$lgqK&h{J*^uJ=jZlXI6%Suk`jkqb1$q~#eJv9;E#p@g_`_{zI#tRz3Q zYyt!HTr#j8NbNKfj)8nI5G+HPk^u#cWW>Ix;>0R@w~>mU$+_NL%Rzj z@jchg4UuBNM-Y^zwmb6titO&3?r)Rh9hh1_0h0SWC%bP*DHj8}=e-U5m~m)ihFR=g zIZkXoj2#%tYie_~$tbED8EQ4IoIZ_gXk{NPx(L(-k>a^SS9!g1sW&h#3czssvK*jW zrjU!33OtjnyiNLi`0(%NEWZWDiU&VhhK&eWhIs*~t2r(vz_G^uxW#gsb>+w;=@JF^ zS?tBky9S*ll9Gf?DmiWVU$d1=pOhWl_31d*X?7cv?T?NZgW$DMV1u=ZNoZ;2WUHt< zDUeQJMN=2E7)`(sM$`rK9g}VJ9f+UN{aF4)o43bAG*d`yKgcAx*CRimHjE67T&ALk z4;tpMM0TzNdJXeEbU_P(;Rn_g#N)^vaN{$geKZP_0*1mD>u?h^2$(h*kKDcwy#d+^ zXm71?Ou?cB()MDPea9K$egt(h^!qN<2-WeVL>2Bko_bhS@H=-w&W8IYw?pZ=EaZoIiWg~OIgk%8I?Q0 zSGLDdLbW`X4*FUBGh z7+<0UoMUEWT)c)t##)SNDX*^^esn{F&?w`nY4tMaMON=9szLx+QT+v*O-iHg8b)SS zL)Dtlk7fY;S`$>VxV-P_~k0 z0=h|nE}9CcCMSIwVGC+vrllOvZZU`DhHPplMKm2NQT-9}kmhpOWB@>;3nPOp6QyjU zZ0N;YzySg4exzb(1ebkUV`o=Fd$4+D@`dW+YJ*&Kt(U`SS?BkU7vAulKF;Z zE6K1Nd!-_?VkTsXg#4Xbt~JSHTk^&xw7vNnv-T4rQ)p*Nwhm1jCn{^-Qo(eve)ru` zOZcX(WB99#iWSCJSMD8Ew2URul^*2^y~U=@YtqS8lIul*)&+AJ@KPX^#x!V|=iTj# zMvYmV=(=x?ew|*il41|tf`CN1f|aVikkc?*?x2^7O!M3bXz0fQ2v7PsrMx z2slPEQhP2>*=ljif$=iDs?<|#g73ady5=$MmW0$4+eN=#ps{9<@$pP$md(()V-B2N zx6|Qo%Rp%orxw( zq4P4P%R;t2x@?;>?|flCLb%s3n-JR1T0^B?` zQ5b8*g3an4M`~)NeAq;vbCC>$4WZ`yx1MT7B>W@EVTFDW<+w{`BBohOeaAVIIX26^ z$4c(h<}>T6sTycC)z(^SEMi|nh1E2`tgNt9sntPZYAwU$)(J(^2IP|Voj9zo=H{Q` zWXnG(4NI2#iSw>)4VJ*yP+K#$*py*xkQKK=)S2K|IBBin{_a5g-MrAfPovR1xjX~9}FnE3eKgFu|U!0_+q{G@?I)kf=l~3>T28eNL%5gda!3-T0(2)@lZfPX_zKy0kXd)>SE|U~MkYY5AoYjJn#W4>D-mU{3f7F9Nr;fVx{Qd{DRL{>Z zl#magYc^mkTtlWZCqprrISuSlJj|pb7i20mqs?UM6{G>nbI#}91$oUPQpk7m&lOCp zs3rX!=42X%xxuhUW1CrW2~UIBu^hhp8*#>ge+P!NN1Wfe`15Tka18n;Q9 z@4ppbym%{v^IA(m8OUkf%qcj6L3hdbJ?yJi;;%6=<<+ZK^;*S>$Yw!rUxHACH$MO6 zth%JpEu|x<4A+qWwzi=Rlx(Tq<&vj@^!G}3$TB4|6r#MWkZ!(9Qh?w0st27lMFCdm z#$x}WJE`fV^d^ zf)a7DqM=zDEC3YL$Kh&7udra4bZEL-$bahB3iacR3)R?3ww>zn_NuUA6FN3m`KY4} zYun1wcCMlA1Sy$E-{55GD>+Nl$qdzI=Ks28IMw+nrU)u^pFVTJisAKFC>F`<*J7>1 z9bIcCP&?%Wre-n~R5k_Q*o)-4Ef4T?JkJ*Kjiow&;&lw@M>nKKyENw~V~ATXK=(I3 ziD4@0XE;uux%;v(xV$H!yy8d8b+h@oynaSHy_A4TGwMfPKS1x@SC zdH41BTY-VIQ0279L{9`Cx}vG0@#t%v^|QI;XIdnf=+7^;a}vAk(9cbX$QKi$SyZx0 zR|Y4n2r}9ezmZqV--~6xM_cxrez}i*L*uq${VyHJDGR2fK4rlf!yOlEhKn`BM_n^) zq)rha$5dBN{A%YHa%m8Ley$8T%P+1i<={&F^^+`w5Y5FJ)M5?ln_GiYs5;g78WuTDGEpvdGl{Q9v;@$m^h3^t-3!r$Dn3%)A09Rf7yy;WXdmpyFrt3G5dc zJGiZrm8{D+HYMGq>$VBI4$G%&uHPOW?KyR9XMW`772p|xtfE>CNuf5SvU9~beQPq( zxJ_|RvtHzw)r^6r70s>{ZCbDL;)c8lb>~6MqWJQ%D)(e#!Mg&vD0<@_Mq40b?W{W_ z=fg>t3RUk0OD)Xm955;OP>zdLAN>v~%z#a50dsEUfS4u<|8BLc+3`HqCux8Jddfo7 zgaO=jbhAyCLnh0(7o?yg%|9?*=%96%uS)SUv!lUObd0blFOlsk?Q&PhSCLCriGg=9 zkb;?W!pISTmaD7a&n1+E3vx6+UX<1;rje{xa{Ph}s9Cwloz^cB8s$fPNQ#|m!x--M z8VxjhxgY^%5icpLnP_&za@9<`TJ~|J+t#V_(0jRh%9gmMUXv>HK~lU{!&vB9O4sSK z?UZd&4&-6j%yU{M>tX1M7Rz5uneoSbaB&Sxvy3&(sub{Rf8==XpU%MHYgF;bA(wIZ zM@%7wj@Y?oefP@k`(Mv;6zdSBD~iic`X#AZ)_F48EU!-QuhDWYQ98jBbQ@`#SDH~% zE&F8XK%)a{kdSO)W-JoE@*p(Ef&V*Lb2DS%2iML>96t6iO!~g(IhQ^=AMC+HqXJ`| zKpU8fjpww@jNg!AWaE4~YCaf&rR7}4o)g^9j8zKaVS^Vr*GB204zop+n!vQK<0ukB zv6Z}xARg#qx=ra;Wt)WO6M|8jxZI!)0j>a;51dX;0Ip>s-9tOsbgwrVsf8c@L z;*`<3D-2Ru2-#t%A+VV6$^mXe9Pb*BfDJ(X4cxCud*J<4sXwqDQ<6~w{AP3rv?j!% zdi)T;KiElse=x?6KiQdS18M`0`^Y?crC`RsJDST$g0pztDm-vX6DO|usAX7tCa?Eo zw?XSqC@gWgO}EHWx#zk}qH*FZJup(|SY$;Q&FRloD%lDxY34#7!<|`EIDG%kKG{D# zdVjLJe`>!wI3#N%m$vgC)gT_`!YFCKkwo-FP7rYyHj)GDlF6f!>A`ayunYZMF5Pce zr&c8zjNSZz=Q54)M-?7Go6EngE)Q3i2ZmX@3gOVIY~R1(UX=P+t1_%vgxG9L8MY0) z`8Rl0-@RMi+k0))u0cnm$+}gs#_guDQqjN_qd7%~6MP#^4Nn;2N9F)9So50y38*hR`%^6DIrr7J&12?Ecop-0 z8jK&v&~?I8KSRiCQra`q)l=Oq$qcz>KH7jpH=sW2=F$`$Rf|JP6g2!XZR)(ZV*>Gs zcw^eXH8`U}^N-0Fi(~#}xS~+S+v#3p)*qAgaAoF*qNy6Hu7%e)Fnk({#b_viYOWYa zs`$oz{nfNNd7zR3V$D}Z1@S23OH=r0`6=yYD`#=BOFnYP?#;z<`#=*biBw=_Txira z6effrWGw!tHD(@3qe!A*&?0_-I+2C*MRbWA3iD7T3axsG7Lft=K+|DnnUY1KN}%N1 z{ut6Ehs~E)uoZ-yyZKB9fb*rN1EMhJ>A+hxr|IC_%}b-6nVspC>D(Mh_2^trJV1%g zc0-8K>)&h`d8?J(8d3Wp;!F4HY^n#0eXbfj|0x|Koq+D0)8Rk9@Ew?uoL{Jj+fWfyB|syH~18t6-r&N*yu) zNJd0vn~lLgUr3cjMlFbPb_pv0TqH5Z7?)X^p|mvWX#&l9hMeBUjjLPFh!_A7(e51`~#iCrNtH=3gt@q(kT{HK)OK-#S;JVZwiMcs@ zEf=fW)9))3gNG=}nxK&>{Lxcs%~M9q@}aOnQaP~~CFf`~kr{$nk z$d!@LWUZ+|2^^EbXHl5P*AUy|fV^=kukgGaCH!({Iz8ZChxBsuC z?XVVqVP$7V9Ok$GU`7NM%GQFDmT}SnNS(*EAOG+F)*6r$gK0-jKtT-OpRmRT1$(YjuQyLlT@};p+thq zAVMC9i41z-fa@Vr*DE&<9dc^f_%BX58KL&&$tSC4d^MWVH z-iJF&YSp~ZoAP?o6^5!tF&=!7s!w>uNn4zF&5s3E^d){$&s`*MF2~O+h62TckGSXN zR$2P1UC1$%B@9{0y2TA?Eo1NK*Tc6*JA318pp8DI24tp{sLgyoi9A3|e!rYtnI< z(pt?Ar_sbdp0Tfs)1nAKNbn*6Wm2#cLiudKpSDnoaQec35gm>Pu6kO}?F}AO!FkgS z?SIf*i779MZxpo?DCFaoJ?(M1%Bhd+ytJ?-swXQM+~5_ED?PC!!9XpuVzhW!9UZ6CwCjLm+zEYlxm>En^5P%8cs#E`lZ;$q=n|gTT{DZd8LK+DWgx6 zLC_vn0`T&5`lpL67Lt^L$NmU!I1nV9AG(4Oy+qPDE^@Me{B~z|pS(YLn=g^@&K%1WhEdC< zBztws>kDB9;&qF}*j`)18|5aU)}A^{Q9hb(Dz81?m04O?nl=dU){SnUcm9Ye@G}ck z-hA`eDRI;pip>Z&)EUqq?0qtJ;^@W?gym&ybB2*g{LHQgbg%Av>>K}W5+`KCq2;mo z!4gVZ-ycvM@AXbe6fDD?DR(LnucQr-cK{i;mjN0~`4x zg&D>^v0K$rCM{DYFEO&bla~|`L%|4G2{V5uVlr0z9lANRPI%hBOvzL;cET{r#1o#N zUYRoYI2X@>%ECUt#2@J`CQNife}XW8Ae|HQj?b(}3qYU5{6rWPc>n^$serwrLeN~8>?XIbr=Bpi z2wucqUSpYR6G;0?ctur+FzQB|)ZuGMTQrkpg%rFfx%QM5s&0`w+H&cDxzkT8Mtic; zYfl&?nKOv->}|#Ul_A8Ohl%+KnU{-QAHgq!BkFB%i8&3%Za)qJu+OZk80emc*4YhS z9&-%3>HZz<$I#{$Gp4C{+b+LNE$ePmoKA_yEk#++%v03!H@_rT>Xk_dj-3_8mqRxa zcP{6=VQmt(lTp|7nRLnK&J<6-NgT?rQ%ayux=cxC)Lf;c9=k4^P;xhIo+OH>=80oz zmc5&T^J$=$T*0T*a>{HBatJm?#m>+i56l=Qm6zY@=25v5IkzC#r;B`9|y-|_hf(PY=5M zACKN2?iq~|r>^Y`KC(++xN|qXh`kMj;iI&mVXw;<@Oo+E$IfVgu`R9Ue{Y)e^$9zG z&-Bh=5Rs;I5QC`uT7ASxcc&elbs6JcV|J_bT(6R5mISHcd{b@#;>(c5n}4(yNt&e# z;hbPbgAlbwRAexwq3jZ=2!#Xt!$Ke+tHziKBjHXE8Rz6(Ds^HM92f$F3NJ=24~F8s z5D+!IsKR|QXV(QA#@T%nWiHX0SLKyEH>&CS7=P8t;>&&q*WdR z%3`$jnf%d}dtH?S`$L4%hmemk*Rp&eSfg}R9>>C$C$yQbX|yVqc`Ne)8Gwx&pe>IR zL0M$iX7_w-im`U%59wOygXR{|wY~T6j@P6x;~|l{vdLV*9*%-^rkUF8f5a}W#vNH? zMCEwJfv3%N>jxj$5S0L0!jbp9>I~PYc~<7|<7ga5rQ?iQhRz+}-1h@EcIEjvs8zhA zuTGsT;{^Qq{;XBVcVC_HhI$hk>W(J0ljW#^K09t!^axT_*U;yS$Afyv^INu%Nc~zF zQ@?LzZn26~L5l}__R)!rY#cHv47He3Fh8u31;c1^#KUpv*Ck_T_w3;4P}Ws82*2$A zw*B+z(IIoum1O9Fl6r9XQ&pB9&{inTz1emt)1e|8;o#dme{MkSzt zdgv^v$|BCosmOusKB=Yf{c}D75=hbQ+X-*Pv9+TccXS=v{Tp^$VX`FAR*0jW3M<8e zdN$o-tyyb796NV!Sh&@*M|nE@Df`>$tUphGV|ur{xwY|(+&z1OCq@PX)z7<;-^jDR zPKIdh^t#WVZ*@A|m(O2WoyN1p^A~w`f7v;-e?B={UAJCY>sDt?CamSS()j*CQ{(yb zP5j$^vDH!k;^gl<@4m>+|MhOSyY-B8o^t*RJ+(C7r0?J8{9n2X{2@Wn0)~yHSQ*4c zmup1E{y0XFXtPLR$Hx42Vr4Wk#rvKsi*bb-1QSZLLM{uvnPE}|$ie8|MqRK?`u=bX z`T)B@F>+9}VG3vw;ycs$Z7`edu{##^OAn3&DBm06J-iR)PXr==`$?*dbxjJmcZ~*a zV7U)1q1dqndu!Ajnshj`O*n4a5zIlK6i+y_V zk9~rN@OH>|@c;T|qrp6_MMZ$?04yyd{&{!XW8e40aR6a70L?#rp+TTOC;*zNlrC;1 zRzLRSxLQi8gu-hq0ubp+fCcobZS!Q?29@SAzPbYIt4*?BOa(HauZ4{1S;#yw50$5i z{R#jw>AUmP`coDSgl2{#kkQ9@&XQr^_)1qQ@K3-D5!Tj;MzT^N&&~XU#cX2ppbDLt zb2hi_aD|O^nYN;g=Rm132Z2@Xht`089L1g|V%d3rp_zgX5e2Sd%v>a$%Jbp&3dMEA z63;sqe34Ia97(9>VBE0{0eoe*oxHjO!!-Hc9@@v%ZdT$V(+_o9Tga4glHjsB+ENm9 z;`Cpd>@~V_y@&>MV8g@?(oZJ-rG|JAyvm8xq}|}#T9o1&p!%DaZ0BRJ!k$x zWy4FI?qYfRLkx3gGfPY-8#w$BsK&-Ei!J@EO8h`j7S|gy3PV7Yr;nBM>?PJh^4UjJ>vPZtRkA>Z2#ixj`!BEjK zyPFPgKXnHo?xq{L;SDYb@S50#@`V_5;Uec*N`3y>^XgDSL$3|TZH@uffLVxvJiHh%8-F0ntaa`8y?hXFgQ+I+O+7XVx)}XCSj0p z#m`;63&57xVpiM4;UFFA^4Qrd+_+i8|$)OVhH90GWGq%uk1ics`e1=tQ7sqzYboyDis!c`_&av}vh6*oN$iLc@2rvTx@G9|x$JPnwd!$x=P; zLv=^F_;VDTNknf7KiT<;dwA6kY)|iJtX8F}8Wo9PT@{R}IX@yPs}0n_-~_Q8t)-AW z`n5(>ISWad(kZZHjO##aCpaqSq`(wqY9*hk=@Gqhn)3Hr^D#em2zo*f8nbNdNSDqB z9QjYYAGWi-P-wJnQHzHCz#WVAB1D)|x|+`Caus|x)(356Ifx8hmkIKm2BCuTT?YxQS(F4|@ z5hUWPs18M=)Msi;36Wy4HDR-n-FTnCQa0IxJWeUvPb9PAPE>1>H>F6|P96s(p`D_h z5uFd3kQ~+8r(39}T1aS9oobO`ptVl5$Q9yBl$xSF%_3V*B27vj_k7F||g+)GpQkfLMB3LH0N0$=PWXw^FB z;mz6EF*9D7dq5khHQR>m6xVcW=LM*Gj7IS!uJqiDvO_a^8Na$dvb5rmjH~Ra7!6%l z?fRn;WzMc%iEYO!4#xItQ|XgtLvuSrLG1gf#BUG>~57L+RcPAsa_5n#6BsveBh zy=-cRM154~2%XmXTx_e0nnx%|*<6D7)qI|V%!>s!@$9)fBC`O7G;%P-9{L0K%B5_B zO;cVMdA9s!d->h=@~MSE%xaYLV0HO&b@?~4d|)lVBg^9^C^8viE>z?`R+YCu5}#|5 zl#cFTe6HkV+t*+g0N*Q&KtZ@x-a*AIBh{!8>jF}`kA>i_SyytzX*%x7VS7FJ>OA9kGTXHbfV;Zb$bfv0bTX7yr-KuiF>$U201YC(+s9oH%}haPCb@t+M{q_adhw^&sL zrkvSmY)`&!!!%BQfN9T=!_xO-c37Tp*E8oA>Io?pG6(;=qBzv`#|Gy2ee&Idre;S* zt@DCK8<}BUKhnPhiAFZqycYKI=t0(ge(c~p8dL)IAx$j9v?2r^&(C`D_>Zq5{%>Qm z82`7vi2r+%_`jFg_`g@3uJv+#<7M~d`XUPOuN?np(d+9~3=deF%lv=wVyh(nFUJem z{C}~&x$%r_E#m+F8vK6||NYg(eVqS{P$Bl?}XE6_3u2)d7I$;=P^o13ada0jpUmklE!H~96DgQv!Esx^c1?0AKa5w zg8AS0L%KS4t^vkP6pgpn*4$API3pS<3lG~bJ1^JQ_IA#8{`nej)!C@n3&I`M-$&TF8G@{y%uNe|q^} zSpV;CZFU#y|4;HvTK~5f>;DV+zmWe6`M-Gn8uFhn2=}k9pHBXFHuL_!=iSZ4`u~$W z=k)rTodS5#h@5NtGIl*YJ&C>GhEuj3ZNUi^^8YdA|HA+O<>bHO|KEJo-RiDyE&Trr z`Tu~^-t|+XYX8?(cPlUdJDZF3|0j8t2s=81-BHU9&)_GjGb)IDKRu+Kr8FAsPb)bU z8q|ZPB%vlhyF#3oj$Z^#i4V##UieY#IuKd;eRG&gXZ2??+06FGtQzZIO=!22~ diff --git a/script/CKAN_JRO/jro_api.py b/script/CKAN_JRO/jro_api.py index ee744fb..6ca2d07 100755 --- a/script/CKAN_JRO/jro_api.py +++ b/script/CKAN_JRO/jro_api.py @@ -2,6 +2,7 @@ from ckanapi import RemoteCKAN from datetime import datetime from tqdm import tqdm from CKAN_JRO import logic_download +from CKAN_JRO import resource #from ckanapi.errors import NotAuthorized, NotFound, ValidationError, SearchQueryError, SearchError, CKANAPIError, ServerIncompatibleError import sys import platform @@ -318,19 +319,21 @@ class JROAPI(): resource_extend.append(value2) print('BLOCK N°{} :: "{}" file(s) found >> uploading'.format(count1 + 1, len(block))) - try: - result = self.ckan.call_action( - 'package_revise', - {'match': '{'+ str(package_id_or_name) +'}', 'update__resources__extend': json.dumps(resource_extend)}, - files=files_dict - ) - print('BLOCK N°{} :: Uploaded file(s) successfully'.format(count1 + 1)) - if len(blocks) == count1 + 1: - return result - except: - print('ERROR :: Use the "print" for more information') - _, exc_value, _ = sys.exc_info() - return exc_value + print(resource_extend) + print(files_dict) + #try: + # result = self.ckan.call_action( + # 'package_revise', + # {'match': '{'+ str(package_id_or_name) +'}', 'update__resources__extend': json.dumps(resource_extend)}, + # files=files_dict + # ) + # print('BLOCK N°{} :: Uploaded file(s) successfully'.format(count1 + 1)) + # if len(blocks) == count1 + 1: + # return result + #except: + # print('ERROR :: Use the "print" for more information') + # _, exc_value, _ = sys.exc_info() + # return exc_value else: return "ERROR:: No file(s) found to upload" @@ -658,6 +661,8 @@ class JROAPI(): try: if type_option == 'dataset': return getattr(self.ckan.action, 'package_create')(**kwargs) + if type_option == 'resource': + return resource.resource_create(self, **kwargs) elif type_option == 'project': return getattr(self.ckan.action, 'organization_create')(**kwargs) elif type_option == 'member': @@ -703,11 +708,12 @@ class JROAPI(): if type(type_option) is str: try: if type_option == 'dataset': + #Agregar que solo se debe modificar parámetros del Dataset y que no incluya Resources return getattr(self.ckan.action, 'package_patch')(**kwargs) elif type_option == 'project': return getattr(self.ckan.action, 'organization_patch')(**kwargs) elif type_option == 'resource': - return getattr(self.ckan.action, 'resource_patch')(**kwargs) + return resource.resource_patch(self, **kwargs) elif type_option == 'member': return getattr(self.ckan.action, 'organization_member_create')(**kwargs) elif type_option == 'collaborator': @@ -754,7 +760,10 @@ class JROAPI(): else: return 'ERROR:: "select = %s" is not accepted' % (select) elif type_option == 'resource': - return getattr(self.ckan.action, 'resource_delete')(**kwargs) + if select is None: + return 'ERROR:: "select" must not be "None"' + else: + return resource.resource_delete(self, select, **kwargs) elif type_option == 'vocabulary': return getattr(self.ckan.action, 'vocabulary_delete')(**kwargs) elif type_option == 'tag': diff --git a/script/CKAN_JRO/resource.py b/script/CKAN_JRO/resource.py new file mode 100644 index 0000000..8631ad6 --- /dev/null +++ b/script/CKAN_JRO/resource.py @@ -0,0 +1,343 @@ +import json +import uuid +import os +import sys + +def resource_create(self, package_id, file_type, others='', max_size=100, max_count=500, ignore_repetition=False, **kwargs): + #---------------------------------------------------------------------# + kwargs['voc_file_type'] = file_type + kwargs['others'] = others + + if 'clear_upload' in kwargs: + del kwargs['clear_upload'] + #---------------------------------------------------------------------# + + url_upload = {} + if 'upload' in kwargs and 'url' in kwargs: + return 'ERROR:: Choose one: "upload" or "url" parameters' + elif 'upload' in kwargs: + url_upload['upload'] = kwargs['upload'] + elif 'url' in kwargs: + url_upload['url'] = kwargs['url'] + else: + return 'ERROR:: Missing value: "upload" or "url" parameters' + + value_u = list(url_upload.values())[0] + key_u = list(url_upload.keys())[0] + + if not isinstance(value_u, list) and not isinstance(value_u, str): + return 'ERROR:: "%s" must be or ' % (key_u) + #---------------------------------------------------------------------# + + if isinstance(value_u, str): + if len(value_u) != 0: + if key_u == 'upload': + if os.path.isdir(value_u): + path_order = [f for f in os.listdir(value_u) if os.path.isfile(os.path.join(value_u, f))] + path_order.sort() + if path_order: + kwargs['upload'] = [] + for name in path_order: + kwargs['upload'].append(os.path.join(value_u, name)) + else: + return "ERROR:: There aren't files in this directory" + else: + return 'ERROR:: Directory or File does not exist' + else: + return 'ERROR:: "path_list is empty"' + #---------------------------------------------------------------------# + + if not isinstance(kwargs[key_u], list): + kwargs[key_u] = [kwargs[key_u]] + + if kwargs.get('upload', None): + if len(kwargs['upload']) != len(set(kwargs['upload'])): + return 'Duplicate files found in "upload" parameter' + #---------------------------------------------------------------------# + + change_kwargs = {} + for key1, value1 in kwargs.items(): + if key1 == 'others': + if isinstance(value1, tuple): + if len(value1) != len(kwargs[key_u]): + return 'ERROR:: "%s" value(s) must be same length as "%s" value(s)' % (key1, key_u) + else: + change_kwargs[key1] = value1 + else: + change_kwargs[key1] = (value1,) * len(kwargs[key_u]) + else: + if isinstance(value1, list): + if len(value1) != len(kwargs[key_u]): + return 'ERROR:: "%s" value(s) must be same length as "%s" value(s)' % (key1, key_u) + else: + change_kwargs[key1] = value1 + else: + change_kwargs[key1] = [value1] * len(kwargs[key_u]) + #---------------------------------------------------------------------# + + try: + dataset_show = getattr(self.ckan.action, 'package_show')(id=package_id)['resources'] + resources_name = [] + for u in dataset_show: + resources_name.append(u['name'].lower()) + except: + _, exc_value, _ = sys.exc_info() + print('ERROR obtaining metadata dataset:: Use the "print" for more information') + return exc_value + #---------------------------------------------------------------------# + + for c1 in range(len(kwargs[key_u])): + new_kwargs = {} + for k2, v2 in change_kwargs.items(): + #-------------------------------------------------------------# + if k2 == 'upload': + if not os.path.isfile(v2[c1]): + return 'File "%s" does not exist' % (v2[c1]) + + if not kwargs.get('size', None): + new_kwargs['size'] = os.stat(v2[c1]).st_size + #-------------------------------------------------------------# + new_kwargs[k2] = v2[c1] + #-----------------------------------------------------------------# + + if not kwargs.get('name', None): + new_kwargs['name'] = os.path.basename(new_kwargs[key_u]) + + if new_kwargs['name'].lower() in resources_name: + if not ignore_repetition: + return 'ERROR:: "%s" resource already exist in this dataset' % (new_kwargs['name']) + print('WARRING:: "'+ new_kwargs['name'] +'" resource was ignored because already exist in this dataset') + else: + self.list.append(new_kwargs) + #---------------------------------------------------------------------# + + try: + uuid.UUID(package_id, version=4) + self.dict['match'] = json.dumps({'id': package_id}) + except ValueError: + self.dict['match'] = json.dumps({'name': package_id}) + #---------------------------------------------------------------------# + + if kwargs.get('upload', None): + blocks = [[]] + size_file = 0 + count_file = 0 + inter_num = 0 + for value in self.list: + if value['size'] > 1024 * 1024 * float(max_size): + return 'ERROR:: The size of the "%s" file is %sMB aprox, please change "max_size" value' % (value['name'], str(round(value['size']/(1024 * 1024), 2))) + if not 1 <= int(max_count) <= 999: + return 'ERROR:: The count of the number of files must be between 1 and 999, please change "max_count" value' + + size_file = size_file + value['size'] + count_file = count_file + 1 + if size_file > 1024 * 1024 * float(max_size) or count_file > int(max_count): + inter_num = inter_num + 1 + size_file = value['size'] + count_file = 1 + blocks.append([]) + + del value['size'] + blocks[inter_num].append(value) + #------------------------------------------------------------# + + if len(blocks[0]) > 0: + print('BLOCK(S) IN TOTAL:: {}'.format(len(blocks))) + + for count1, block in enumerate(blocks): + upload_files = {} + for count2, value2 in enumerate(block): + upload_files['update__resources__-'+ str(len(block)-count2) +'__upload'] = (value2['name'], open(value2['upload'], 'rb')) + del value2['upload'] + + print('---- BLOCK N°{} ----'.format(count1 + 1)) + print('BLOCK N°{} :: "{}" file(s) found >> uploading'.format(count1 + 1, len(block))) + + try: + result = self.ckan.call_action('package_revise', {'match': self.dict['match'], 'update__resources__extend': json.dumps(block)}, files=upload_files) + print('BLOCK N°{} :: Uploaded file(s) successfully'.format(count1 + 1)) + if len(blocks) == count1 + 1: + return result + except: + print('ERROR :: Use the "print" for more information') + _, exc_value, _ = sys.exc_info() + return exc_value + else: + return "ERROR:: No file(s) found to upload" + else: + if len(self.list) > 0: + return self.ckan.call_action('package_revise', {'match': self.dict['match'], 'update__resources__extend': json.dumps(self.list)}) + else: + return "ERROR:: No resource(s) found to create" + + +def resource_patch(self, id, package_id, max_size=100, max_count=500, **kwargs): + #Cambiar el nombre al actualizar con un nuevo archivo + + if 'file_type' in kwargs: + kwargs['voc_file_type'] = kwargs['file_type'] + del kwargs['file_type'] + + if 'upload' in kwargs and 'url' in kwargs: + return 'ERROR:: Choose one: "upload" or "url" parameters' + #---------------------------------------------------------------------# + + if not isinstance(id, list) and not isinstance(id, str): + return 'ERROR:: "id" must be or ' + + if isinstance(id, str): + id = [id] + + change_kwargs = {} + for key1, value1 in kwargs.items(): + if key1 == 'others': + if isinstance(value1, tuple): + if len(value1) != len(id): + return 'ERROR:: "%s" value(s) must be same length as "id" value(s)' % (key1) + else: + change_kwargs[key1] = value1 + else: + change_kwargs[key1] = (value1,) * len(id) + else: + if isinstance(value1, list): + if len(value1) != len(id): + return 'ERROR:: "%s" value(s) must be same length as "id" value(s)' % (key1) + else: + change_kwargs[key1] = value1 + else: + change_kwargs[key1] = [value1] * len(id) + #---------------------------------------------------------------------# + + for c1, v1 in enumerate(id): + new_kwargs = {} + for k2, v2 in change_kwargs.items(): + #-------------------------------------------------------------# + if k2 == 'upload': + if not os.path.isfile(v2[c1]): + return 'File "%s" does not exist' % (v2[c1]) + + new_kwargs['size'] = os.stat(v2[c1]).st_size + + if k2 == 'url': + new_kwargs['clear_upload'] = True + new_kwargs['size'] = 0 + new_kwargs['mimetype'] = None + #-------------------------------------------------------------# + new_kwargs[k2] = v2[c1] + + if new_kwargs.get('upload', None): + #-------------------------------------------------------------# + if new_kwargs.get('clear_upload', None): + del new_kwargs['clear_upload'] + #-------------------------------------------------------------# + self.dict['update__resources__'+v1[:6]] = new_kwargs + else: + self.dict['update__resources__'+v1[:6]] = json.dumps(new_kwargs) + #---------------------------------------------------------------------# + + try: + uuid.UUID(package_id, version=4) + package_id = json.dumps({'id': package_id}) + except ValueError: + package_id = json.dumps({'name': package_id}) + #---------------------------------------------------------------------# + + if kwargs.get('upload', None): + blocks = [{}] + upload_files = [{}] + size_file = 0 + count_file = 0 + inter_num = 0 + + for dict_key, dict_value in self.dict.items(): + if dict_value['size'] > 1024 * 1024 * float(max_size): + return 'ERROR:: "%s" size out of limit' % (dict_value['upload']) + + if not 1 <= int(max_count) <= 999: + return 'ERROR:: The count of the number of files must be between 1 and 999, please change "max_count" value' + + size_file = size_file + dict_value['size'] + count_file = count_file + 1 + if size_file <= 1024 * 1024 * float(max_size) and count_file <= int(max_count): + upload_files[inter_num][dict_key+'__upload'] = (os.path.basename(dict_value['upload']), open(dict_value['upload'], 'rb')) + + else: + inter_num = inter_num + 1 + size_file = dict_value['size'] + count_file = 1 + upload_files.append({dict_key+'__upload': (os.path.basename(dict_value['upload']), open(dict_value['upload'], 'rb'))}) + blocks.append({}) + + del dict_value['upload'] + del dict_value['size'] + blocks[inter_num]['match'] = package_id + blocks[inter_num][dict_key] = json.dumps(dict_value) + + #------------------------------------------------------------# + if len(blocks[0]) > 0: + print('BLOCK(S) IN TOTAL:: {}'.format(len(blocks))) + for count1, block in enumerate(blocks): + print('---- BLOCK N°{} ----'.format(count1 + 1)) + print('BLOCK N°{} :: "{}" file(s) found >> uploading'.format(count1 + 1, len(block)-1)) + try: + result = self.ckan.call_action('package_revise', block, files=upload_files[count1]) + + print('BLOCK N°{} :: Uploaded file(s) successfully'.format(count1 + 1)) + if len(blocks) == count1 + 1: + return result + except: + print('ERROR :: Use the "print" for more information') + _, exc_value, _ = sys.exc_info() + return exc_value + else: + return "ERROR:: No file(s) found to upload" + else: + self.dict['match'] = package_id + return self.ckan.call_action('package_revise', self.dict) + + +def resource_delete(self, select, id, **kwargs): + + if not isinstance(id, list) and not isinstance(id, str): + return 'ERROR:: "id" must be or ' + + if isinstance(id, list): + if not 'package_id' in kwargs: + return "ERROR:: 'package_id' parameter is empty" + #---------------------------------------------------------------------# + + if 'delete' == select: + if kwargs.get('package_id', None): + pkg_dict = getattr(self.ckan.action, 'package_show')(id=kwargs['package_id']) + + if pkg_dict.get('resources'): + pkg_dict['resources'] = [res for res in pkg_dict['resources'] if not + res['id'] in id] + if pkg_dict['num_resources'] - len(pkg_dict['resources']) == len(id): + return getattr(self.ckan.action, 'package_update')(**pkg_dict) + else: + return "ERROR:: No changes have been applied" + else: + return getattr(self.ckan.action, 'resource_delete')(id=id) + + elif 'purge' == select: + if kwargs.get('package_id', None): + pkg_dict = getattr(self.ckan.action, 'package_show')(id=kwargs['package_id']) + if pkg_dict.get('resources'): + pkg_dict['resources'] = [res for res in pkg_dict['resources'] if not + res['id'] in id] + if pkg_dict['num_resources'] - len(pkg_dict['resources']) == len(id): + print('[DELETING FILES]') + resource_patch(self=self, id=id, package_id=kwargs['package_id'], clear_upload=True) + print('[DELETING RESOURCES]') + return getattr(self.ckan.action, 'package_update')(**pkg_dict) + else: + return "ERROR:: No changes have been applied, please check 'id' parameter" + + else: + print('[DELETING FILE]') + getattr(self.ckan.action, 'resource_patch')(id=id, clear_upload=True) + print('[DELETING RESOURCE]') + return getattr(self.ckan.action, 'resource_delete')(id=id) + else: + return 'ERROR:: "select = %s" is not accepted' % (select) \ No newline at end of file