From 396bdfde8a05d37be283f4ba411debc500ee4328 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 18 Jan 2022 17:16:32 +0100 Subject: [PATCH 01/74] added few new attribute definitions and their widgets --- openpype/pipeline/lib/__init__.py | 16 +- .../pipeline/lib/attribute_definitions.py | 125 +++- openpype/tools/resources/__init__.py | 45 ++ openpype/tools/resources/images/delete.png | Bin 0 -> 12343 bytes openpype/tools/resources/images/file.png | Bin 0 -> 2801 bytes openpype/tools/resources/images/files.png | Bin 0 -> 3094 bytes openpype/tools/resources/images/folder.png | Bin 0 -> 2627 bytes .../widgets/attribute_defs/files_widget.py | 645 ++++++++++++++++++ openpype/widgets/attribute_defs/widgets.py | 95 ++- 9 files changed, 919 insertions(+), 7 deletions(-) create mode 100644 openpype/tools/resources/__init__.py create mode 100644 openpype/tools/resources/images/delete.png create mode 100644 openpype/tools/resources/images/file.png create mode 100644 openpype/tools/resources/images/files.png create mode 100644 openpype/tools/resources/images/folder.png create mode 100644 openpype/widgets/attribute_defs/files_widget.py diff --git a/openpype/pipeline/lib/__init__.py b/openpype/pipeline/lib/__init__.py index 1bb65be79b..f762c4205d 100644 --- a/openpype/pipeline/lib/__init__.py +++ b/openpype/pipeline/lib/__init__.py @@ -1,18 +1,30 @@ from .attribute_definitions import ( AbtractAttrDef, + + UIDef, + UISeparatorDef, + UILabelDef, + UnknownDef, NumberDef, TextDef, EnumDef, - BoolDef + BoolDef, + FileDef, ) __all__ = ( "AbtractAttrDef", + + "UIDef", + "UISeparatorDef", + "UILabelDef", + "UnknownDef", "NumberDef", "TextDef", "EnumDef", - "BoolDef" + "BoolDef", + "FileDef", ) diff --git a/openpype/pipeline/lib/attribute_definitions.py b/openpype/pipeline/lib/attribute_definitions.py index 2b34e15bc4..111eb44429 100644 --- a/openpype/pipeline/lib/attribute_definitions.py +++ b/openpype/pipeline/lib/attribute_definitions.py @@ -38,13 +38,19 @@ class AbtractAttrDef: key(str): Under which key will be attribute value stored. label(str): Attribute label. tooltip(str): Attribute tooltip. + is_label_horizontal(bool): UI specific argument. Specify if label is + next to value input or ahead. """ + is_value_def = True - def __init__(self, key, default, label=None, tooltip=None): + def __init__( + self, key, default, label=None, tooltip=None, is_label_horizontal=None + ): self.key = key self.label = label self.tooltip = tooltip self.default = default + self.is_label_horizontal = is_label_horizontal self._id = uuid.uuid4() self.__init__class__ = AbtractAttrDef @@ -68,8 +74,39 @@ class AbtractAttrDef: pass +# ----------------------------------------- +# UI attribute definitoins won't hold value +# ----------------------------------------- + +class UIDef(AbtractAttrDef): + is_value_def = False + + def __init__(self, key=None, default=None, *args, **kwargs): + super(UIDef, self).__init__(key, default, *args, **kwargs) + + def convert_value(self, value): + return value + + +class UISeparatorDef(UIDef): + pass + + +class UILabelDef(UIDef): + def __init__(self, label): + super(UILabelDef, self).__init__(label=label) + + +# --------------------------------------- +# Attribute defintioins should hold value +# --------------------------------------- + class UnknownDef(AbtractAttrDef): - """Definition is not known because definition is not available.""" + """Definition is not known because definition is not available. + + This attribute can be used to keep existing data unchanged but does not + have known definition of type. + """ def __init__(self, key, default=None, **kwargs): kwargs["default"] = default super(UnknownDef, self).__init__(key, **kwargs) @@ -261,3 +298,87 @@ class BoolDef(AbtractAttrDef): if isinstance(value, bool): return value return self.default + + +class FileDef(AbtractAttrDef): + """File definition. + It is possible to define filters of allowed file extensions and if supports + folders. + Args: + multipath(bool): Allow multiple path. + folders(bool): Allow folder paths. + extensions(list): Allow files with extensions. Empty list will + allow all extensions and None will disable files completely. + default(str, list): Defautl value. + """ + + def __init__( + self, key, multipath=False, folders=None, extensions=None, + default=None, **kwargs + ): + if folders is None and extensions is None: + folders = True + extensions = [] + + if default is None: + if multipath: + default = [] + else: + default = "" + else: + if multipath: + if not isinstance(default, (tuple, list, set)): + raise TypeError(( + "'default' argument must be 'list', 'tuple' or 'set'" + ", not '{}'" + ).format(type(default))) + + else: + if not isinstance(default, six.string_types): + raise TypeError(( + "'default' argument must be 'str' not '{}'" + ).format(type(default))) + default = default.strip() + + # Change horizontal label + is_label_horizontal = kwargs.get("is_label_horizontal") + if is_label_horizontal is None and multipath: + kwargs["is_label_horizontal"] = False + + self.multipath = multipath + self.folders = folders + self.extensions = extensions + super(FileDef, self).__init__(key, default=default, **kwargs) + + def __eq__(self, other): + if not super(FileDef, self).__eq__(other): + return False + + return ( + self.multipath == other.multipath + and self.folders == other.folders + and self.extensions == other.extensions + ) + + def convert_value(self, value): + if isinstance(value, six.string_types): + if self.multipath: + value = [value.strip()] + else: + value = value.strip() + return value + + if isinstance(value, (tuple, list, set)): + _value = [] + for item in value: + if isinstance(item, six.string_types): + _value.append(item.strip()) + + if self.multipath: + return _value + + if not _value: + return self.default + return _value[0].strip() + + return str(value).strip() diff --git a/openpype/tools/resources/__init__.py b/openpype/tools/resources/__init__.py new file mode 100644 index 0000000000..fd5c45f901 --- /dev/null +++ b/openpype/tools/resources/__init__.py @@ -0,0 +1,45 @@ +import os + +from Qt import QtGui + + +def get_icon_path(icon_name=None, filename=None): + """Path to image in './images' folder.""" + if icon_name is None and filename is None: + return None + + if filename is None: + filename = "{}.png".format(icon_name) + + path = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "images", + filename + ) + if os.path.exists(path): + return path + return None + + +def get_image(icon_name=None, filename=None): + """Load image from './images' as QImage.""" + path = get_icon_path(icon_name, filename) + if path: + return QtGui.QImage(path) + return None + + +def get_pixmap(icon_name=None, filename=None): + """Load image from './images' as QPixmap.""" + path = get_icon_path(icon_name, filename) + if path: + return QtGui.QPixmap(path) + return None + + +def get_icon(icon_name=None, filename=None): + """Load image from './images' as QICon.""" + pix = get_pixmap(icon_name, filename) + if pix: + return QtGui.QIcon(pix) + return None diff --git a/openpype/tools/resources/images/delete.png b/openpype/tools/resources/images/delete.png new file mode 100644 index 0000000000000000000000000000000000000000..ab02768ba31460baedaaa4d965c6879e9781517e GIT binary patch literal 12343 zcmd6Ni9gh9^zieY8AI8cTlTHcrYsp{XS$Kx78H_fr4U!hzLc*vN+{jP5-PVC*`mn$ zy=^KZZr7G9lWwZ9Crer8Jzw4T_r9O^FL?WW`iwbqp7We@p0hvC1?xQ)qDy6$B7{UO zcbM%(hys67kPsa{zJ;~^fDc;Wua>q#@GnZ}NF01$;=kiSAVR{+$^RHi&y)tBOpv)l z&^|wppwL4nj-t@eP>o~9eFEJN`5)ErJK>ozVkC>uN@Qua)ix}1xF@pw=zhCTS%+Fem>Z@nV6JYng@ zr7yNo%JYmK-H>fO3gb=T*+M2qyasvrZyfJB}If>%e#PM0$ zv1a!kX_R|Vl2Jjg6Ah#IWB!iA7lZ!Dh^e6Zq2B9h+3Q`BT8*f9kUV4j8X+7Lk2^nW z{ChyvfBo1Tr=~n&)7}CR^oFk7pGXMfcPWM!Q*RGf)54B>EZ9x{n%fSvRm`3$a>I$T zn0@i7x7+lDYA9h@x3Mo;RJ?ozBNRKOROveDs1vsVZ}1$*w%0WC{>!pW__E_NhB(~> zS6T=RiR9j3j2pKJUvYFp*3-)U>j^_#bA!vp^A&PoN6qHU%);jPb;x6RK8$gtnCt?V z*x%;1dzkzg!PqN7#j7M3N%Y>cH%hXM*E0G0CzW%T(oyhw<+`Oa%ej|$5As^KayO-Y zZ|9xc;m$;PhKztMW2d+yZ9X>3i?G+toJO{ka>C2@yAj`(&W&{(s-X8SWAuKpao&XT zHZaC_NKSuCO$^fH3KmGMN_fe@s~8L{N@yk>2wP@TN3Nu~-gAl5p&KIJ%g_(8^@+m| zi6nc?UuEMJQ1B|{J(vddb%9HK`a`KoPY)ND+GWSQLQrdb{P+{siXmIBOk4cr=ODDE z2HOQ+^Q7Zq6<3H=R`EMOT2ZesLOuObuI`nnukY}nFSqM!i<1W z?oHwh9vJfuRX8sg*7_ey)-jKaX{Kf$T$tTBhH>|Di{FSBFZV#5cRuQ#iI1@;o8i{G z4_{Qxm)nnxVhhW{j(WH_*JN30qu*`JqV>xU+a!e5#6N?K|PQEn_>=zJF?qPy2;R ztTBID8nyd2Da;9c~4#^qSLbubF$4 zj(>=Yi^pBj$lh8>%Qq=b)Hx~cpK0MG5u4Ouzm>`%$W+*gnqP>i-PO<|`LX_UB(5h|d8)m4S8PR^C6rc|zD_PN$xwwFdJ z%KdwY?2^h0Nvg+A6$#d@XY%hwtWwuPV}Cy6SI5lS6`LpPoIh<&=%Z>*l&1IUp zbG5RjbF1?OE2zD)3{N}FT*qk)g)Q;lI;pH`dHa#n*!j56KYBHs1@X8_{F(2`)s`p2 zrQ_vlf(zamBSwJQ*nXmi-Jxu$Rw^~abD5@o>&C*cQ!_jFHt!KQRT{yts~SRPPfx~( z_t(y^wj3*FP6W5bOCKy&z@@mcAlv(TJI$P5LluBLb1cBkV$xC7vS}uT6BRkB{Jhm& zkQ+Pp#5K9RJvz^Y=&a%at>fH%gfF?J_bZG$lJ@-q@7$$7E5wLrGw(Gm9sLBy%6aCO z@+;6-E>B=ba(Y{vrJc@3B{vZA|) znfyB^pM-hHp%VBWI2Ivkkzc@>dW!%X zEuz5P8U7ee9?_Rm436%ZZt)uZFLa^3;2sLliVQ939Hv`G%)YcPQ1TEOkaPj z1YYP@)3T|(2P)4VxIw?Z8+ql-^CQ#J&P{?*Uy~~w6)`F)S@^AK4YKZA2!-{c#StP} z8ULWbrRZApAB_Pds3>L=@%tVsM;Xj3jZhIz9dmrgPu59)CE5{sc#S)LfQEQ}3m-0Wr(iSe1|+U_ul|>-;;6M^QIHP> ziqu^TI)oF2buq)2?=UM&*f9c%A8+2VcXWYL8ErFMOx0M= zKKWP#y$jtk_V?o-$+?c#vbV1N{f!D*v(T8Ty1Oga^voSa^n3lzWOnx&<<~_nPeXPa zqi&~KWVyFv&8)u8B=X-jNl~?Qes{1IAJ#@YlFN;CJv}~ddb<2Dq={pZYi5U)L{PG- zZ$}+ZATuss5O22CWF@y2T1L}>)SL~uy64A-|9-5n``;_QY?Q6hnm4B8eNJR^OleB;Jtwj<1!(Aog&JV~X=!;#Kp7JE+r~T~?UwE6zL- zUE~rA0o>GZQat+lRzdFNxG>!@(YC?Ms!d&c>01A7PX)<@n14ApBd`j5H<w`otP5Z{T3Qn{6u26e6iBgWI>(Vugu{;JgwsN82fB{Sx$!U?DS zz>soCiJscb3T^SSZ(stI^0e60bBaaThk_6}1LQETlbCQCpq=*g5~v)XAlt z)qn9#Vw$mRx6=I4<&Dw&KhjbYDr!Pxko`tw4FN?*>mU7`sNGwgEtQo`=uzQYzr-FH zm|e=-(>r8^t(bAL>3JvFc1<;}nr`PDxV9OUL}Y8SBQtJQB^yXF?xMR=*L2bES24HA zA+&?HyG`oy{LEN|FB9F%!dQF#*hQwtaA~v$$K0N2Ptdtlx4tG~ zs&?xP1*~mDB}LE^e# zGjDwjStKS6WmK(RMtXDdQ!!%6CM5Et8vBiB-WL3c$LV&pjg$Qp^99h&yt>fFwZb8$l4EaFjPbR@n3x1#bdr|p;0@RNjiK-9)C9gLKx*KoDD z_c=9nCw!^nLR>T8;SlOP9jB*IDLv!DT_t~;DZ$7_y;zMAv(LD9>0M1_MKL2rn7n_3 z`&{;LQd}t2kLGeM?e%`$^~xinbIZp3xf_zkqf;2;hqw|OPu26a+kempmf#mo(6mG> zP{uNbp-R6#@sTK|h<}_ZemQ~PMXB4L&MNoYJSjfW1$ihgOlquw5I->_9_5zzY$X2fd6J&OOaRwUrGL=AsxmDuE?PVa zRmMGwowXmLWj*Vko~^Vi_B|4U*1SSmm)KGR#~7v6c~f`HpH`q$%JhN1k|NiP^~UM> z2$=dvrZk@oV~!0;%vA;+2y&_mT!h^y=)+tnnI}%0j))P1D*a#9*4@`0!LF~P5=eVO zmOF6k>+VoYxqlOJ&>`xH(=|bqYWB3yeulaB*jv%?(?Nn%54Mo+}l zRpM&wkGG9Y>H9t?;uo}$NW)2FK^DcMlx-&WXKuxXy}?cEk2Ui9>ivjc?qbD>aSGIS zFMBg1G;;;pnMs?oH;a0UZ$8fza=QiQyb0Z#JmPk#>4@gVIHpD3KYtt@3yHMS>Wi05B@YQ8#?~J6Vn@_NQO?yHBKiw6i8Ufl(s)2RJPyiIDKKG09Q&#T9bbL~Nhf05l2X6Uz~Z=>A6I-*F2osb>aF-^Ta`Yeq-NhobCuK^ zuXY!)i*#qT1O04<-)ey#7{sAIC+mqAfz1U@4%QQY!)JHWc>TvL(<|pOtwwC_6e>N&&nOaoBpY4)UD1h7bj{9wJoHZ8tGIgU(;b5CjKCiY+ z0&ER-%w$V_KG4W)EX?a#WfXh&o^N~6YhGd@?@ZWUhkb2SOJB29jEso@8Q6oYRI-W^xv6WGtRP-+(YyH~ET-cERQwK`Js*A2!(Lvc_u~EKX!%UfuG9ZR zIG-IMy18e;^{Wu~DRB336LF5+w2O{ztkXq`85U^mYoxW&0tts89XmSiK0zZE(bg{# ze#Ib4WzZTxxyP2`t!MoGrqI7uq2$ghF{0G&tQf^P1Kih_ zSho^(wX#EAC#fr?k;h+1OKeeF#&*Rw)(0UYx*nB|2k23NUW7abUF#l!J?d(sU?SS+ z(h~-bvHtlW6I6{jXQE8H5=3-mNYRCddc;aEuX2 zaH~hJh|@mXx@((QZ58RpqQP5r)DzK`0U@_FHCl;xr*GpOlmphfd9!Qo9s|{HvRGVY z)ggzaTAAOgx)6)8-n|DgLXgK}q@|cdsS;=X(+>dfyd_j3EJ6t*CG8jDu49xg*DK4b zQNSgb=+fOm1_1+_eS0UXj)l|w#o|wHb~i*$cGjWopxpq{s?5xut|y9aeQgRsdDU4_ ztC-@FZCUC-a|lTz9R<5#zFca<`GX(ngv=&%slgb5$g#ux1R%E^Xp~Y(%dEuwN#33U zZ_|s*;Kct!$p5XRTIH~n&G2m)2}%4E8WyU&2w_jwcN%;usMBD3r6ktwMiysscXAE>dyja55lZqyxZY8Ji;lYjmYU0k~R_pI{74&bH16{;-OCgVSWU-dpw+r zOw*wfGxAt#2{otb1c*J%mjQQb79+K~1p-&Zag@0VP$K%^_^k)!v3s8AItds;t#F)W z{|CT!Y58PkwxZ1h%&-tlJ1Y`-Kp?1NOMTnJ<$$ATqrBim)Lur_+D6B(sQXPGnB4An zNW@wKh3I}WGkeekyTPGqqt?$;>)bp>s8dqcDui=D_L3}>MfjNNB3n-Y5p3`UvVL+E zZ5BaYm)IQ_RB))pspR4iTFDV)-8h8gSHYaaQv!4>LgN0E=?N-nf7=>mFHftpwyuz) zt-6S2cc)W8`34Eevol6loOX)EF|I4~H|1^!VB9sVvcHQt;0yw#E|+ zU^43LlRMc(Kqf{8dFxR~O6uc^Xwc4Cw?>d4M9^kXE{PA0V+_uI6y@1WJ~r8`eB91< zb_X3jc!fym(zMZv7aUEBuEaIJo5G;!0we4{cK!J1{U?0*f{^Qk z0R%-KJ7>+JCXQUZcj%M&LpQQ4PzSactIpp&RzfX-`Hu_}wSEbKL}J+^02_SBk2qQ0 zg^kgOOEQS}&4_|mA+8BhNNT1yG%iO>50v-Mgb?Z$%G&}q2Wgx{v#lkX9Ze=`(lM4g zSX>I22?tq!`i-~c@dGWo7RoaRBe_r20tZ)43rCggyc&$vbzKF2(7gzB?8%}*+<0zg zhVFv90tL*CM#mk&JwU>ZcT1(OB&f#>3iFPi|4F*w(`_6SeFsW}p0B;quqjE~(U^=a zd7HD4-mhkvyLx7yAuS4(rEY;fFwtiRP``a!aQ_|7@7gPx60n?JbhYja_X^sQJ^vcyFb{$l3?|35X1cpmW-RO2MHBMmDwrxB?@<+s2pl5ZDt2^VY?U zxAC+`N}c;{do}Pa5cI)GQWWqj(ufzn!XJ3>g~snc+~%vKNM0)R|IJhf?C=uhqyXO+ zDl!9kH5624Ze?^=v|| zkaxfe67(o~obSt(P zv$)ycY?tL7o&yje8{E-n9LsUBYaA?(>vXoAz05||58mz^K0)PzBnECMFLZNBeO}0< z2{J_9=P);QL!_XERy1;Q`yw%0=Q$B%kiHhRYoj0nwVZburF#jo3Q5Doa;S8C%eOAb z?RgTQhHh#LMrFxG7%u@&+W;y*D!7ONG4d#C`FjX$G=F-G)wTrUT$~8<{XBUbx5L~* z&4$$2gS6{2ndx7gX}E zG)vu|<`3Qm1;v(c24wQ+;tFv~*n?1{9syYAqJ}I^(EJ_Rg8x#%RhY06iY^64TQNq( z9RXR(0^P`~oAJ4+_C1T1xzBcX*?({jQA`$E z-Z3ip6A*d{m1PJ?LmPeGk%+_sX^VgeJ#whEQpjS*axFKTzF1)8u#v@{I+-OR&9d}xE3t3JI_?8WJ-tv$M? z51xsUzZx7yUOPkGan3HD#@R#+0)>h`<#QaCqkfzwpQ?aBGb(SfMF3>>x7af19+N?L zi_28-)l^(f2H`LeS)8pb1;s#61;xO+ZLet|lC8VBuTEF>fKLAGK-@JfI|$R(!3ve^ z2X~dH9;22NHiH$6AiMqsjmjtfjZJ{arg9b0Bve7CEs&u*@K;QhscLUAhcO{HPcS&L zu0bu2;yMK~_uBTN60T4V$+4Z^S*CLTzqh);YHzSRh~0~|fqMY0MTW{cScl}-v7H}@ zLu^!g$QOsx1?aYv>1V|T;s^D~ztd#11 zT>*a$g1RH=B#dQ;<$z6KIZ#_neGAiNQE|3yEj^vQ1<5BMF)Cm`7guBU5T_c2vwuKz zxyhTa*JVyiwvA+AImSH+C`Fv|mW)-bK6z|o=fdb^5-fnPZa{1p4g7^#R#91z5k_>l zfp3FQ#)aZq1~?#9jn_f$D4{N5uzQy+));gu4$0O*3kAJEEm`c8PBHG#qFO}B<^_kf zvRBh|ZKe-(ez0Lt7dNdG%-II6Hd#q3XlWvn99mqwW|Xd{_!C1K85}`gS3{}tNmz~_ zV8~-6`8ALcHlZLjUJLL2Q^Ykb+ zN|jYPMJaHWJWw@smbZ=z!z%*uJn}8TmQQ@)qr-d-6h&YmYKA2JZ;(NR?M5R%@t?sW zD8U*~i>4tG&O)CdeeYIWWXjbpdbWKJl!gXJk=MSY22@ZdA%lJ#6?FSc1-}7-C|?bA zt0_;dXe;_*Uv8)zBGG0K1^#ITd=F^kkF*YouH-e%N75UU%zK<{6EBw)A29h{97 z1%gC!Hh~f5MKsHyi=h6GmiV|d`f&s~j7huQ1+)38N`#4^lduRZav%8VWY{mDO>&Vx ztpzHPYA8H_@w+4Boq=qgfxri$9Ef|)keh+fzd|`9^QVG6Ml{)ls{tAEIjBCnY7}wj z>V1G5R4+z!+(ZUt@p1GbSWBiLtP*thluja&!D|EDMp!UA^>CqqbKOKsGY>aM!5>XY2V^=V=g<%trVGBY)&kKf3qOo&p$d2(L z2<%UD6U>RE zl<#L&zj^hD5&xH#ihr`hDHea03A5z(%Xq6T7R-H=zd3LXG9V>4M%XF_(WCXm{X zpzG-8R!>ABRvkjuDd0S?^Ap5nu*k2|FbY5|Nkvv@V>r#4jxWjkjS~s834!1Ojbs?$ zw%+QJg{W_V!0~E0HL{hD^5#BEUEp+!56M-JBs=3K(vUBq^OiW8B%r|_lxA%^L9?Fj z4H0K;6G8uQw-Y2&Zi0juu7!4;v%ne-q0eV90<9E5``%kFvdk4C7>mFDl%OS85M~vE zd)BM@3FfS#0IW?T!>Aj8VcSw2SzP>F<}iR$S=-qpOuER+ZfcV0r;n0D>*ofBB*c z1;w`fA5-<3OmS%L(*J`WQ-Qv7+n3sT@kCS(=aQI}NRGDtVAlt17>@R*<*cR>K~UH9 zj>L7^*&h7x`3H>!Wwx`BHqv>Hv=n-VuooOToE>@ooxt@9klAj6|8s6*K!=szbfA~; z+eOF22T#(tbFQw3$t@OrLG<<@=?lR$Knr409JG;_P$Jo?$pRZz%)wf;@geKQO@&8^14HUjZ%NQ6` zYQ3msCE)2%q+zDe8v(;y(V=yDk;^LCIYq}~fTTPo(u}nHdSEQ$!*@+f6O8vB1jit! zK4CCIa5Pyu{Vz^@S1e>c!?_>WP2T(bgWpbLZP8mXI~dZ7`~j zYFwDp*=Q=JrL~?6gzI&y+E7v*&}T2dKW9DkrIdhyh}xtg_`Vmg^9}ALfz5Dm6R<+K zp!gQ{i(42>tM2w1LO3cvkGVw{EzvSEL=&x%2y_I5$Uz;sh8IFx#)!lZk}bLp+?5z7 zqVv$w-pzvgdYG@d<%E=(FBq^fOvpi_FOinXC%z~QjgunL`HF(Pkr2CXt^E7&G4I@H z0sVOgousXZzke{6;Jbl+%1S+|#Miv7@4>mgs}|@%BCrx6i$&eaS+h$MIrSds8D{^e zwy#Z0f>%lgbo@(x#I_sGW0x}6-$+l%xz+As9#IP+rgIhS*^uf z^iS08PjDJNtKNK|{^-B=3qdAF4@Kl+c;aoTYd!RqtU)-p{JU3?AI*fhw{Sy@t4w}7 zdtT&&LgVZ_XYSn<@4_yt((8>$?`zY(r>eA7tqwuupp5h?{Us&xR3p#a6Pm9$gBI)u zd(*zJ;so_6K zY<5Xbi#GO8xM_U#z15z%QO+Ef*t})6atP*0&bV}7n!4L~7}NXL5Kj{SR#q&KRo?BU ze<1C90QZ7O=!yOtM3Tt2G7ItD<$XEJpt1jQK#_Xd+ z8Lxd9+HW8!x1gAjrrzCr>ZA6AI6iygaKpN3%#`lb$&EDyXKZi-PDZvPi&q>t79DQy z#*iSthw8OTm9&}XoG9)A-lZ`kwbs zf793!o%xl{{gdcnPBh3Z7{A3@&cp34>)o4=LR_!Lvd?`Ch9@Rf(y8Jf$`#w#UL`dn zJr+u2Q|mL*_ODQ{*yT~j2y-{q$h)*BNN#N7j&;y#g@+ESURb%`^^J)$#v zxTlC(hnhRd&qlv6iN5up4GBThqc7;-}otRm07DxpC+Q_MjsE98_7rYYHBPoA-yGPMHTQU^;Ns z;_Tj|#P^zB&)#q>Ub+7vp%DLSzw_;KOK?$kmBOG(Jny%zDnIpm^M60?>LT+%Azd0P*$d8ef}An*pwn;#m!E7_h>zNGQPr9LOyQz^Qg>2mOcT`)qY z+`8 z4Lv3F`8~1EP+>qFaPTNXVaLpDN3>Id&c;i| z)VM+Jh&j9-3&mqsXnuqn^!zYUQh@SW;k;9nw_k{A<^C_v1}|4V=>B8Yg&WZ3gZ08& zN?&l+$J!J72qpVss@}P0dfYZfKq~Lqj@r051@al?8Dc&@HSh&L-v!^&fV57k*S^gX znmcJ$qpCdOR4aX~2-?QDuwUX0PcO*&+m9!UeJ|tOtFgH7kZ8cHoXj#soWwHs)uxC> zNrwrKDM~hH)XP_DpZwc0<6(Das31IQt(Wp&6@TzVw#%a;_nE&qbJuw0UV$*;TE@_% zXW7+?!Al+C?p4fshuUSni7I$_SU5bu2_D^iYQ`!a?wQC3B-wVw+xB*xdJuti$x?}^ z@^TsLy{;OKoM~IlUk^fXOzJyQ`uCpX=TrOORcX5n@=#_LKS{uopHCm>b`(h6ESy+D zaLk?_bdX=3oO`oJB+A!gA$aoF^576O@JWWKh-s+ShPpVg6K%yO~%H&;E`{)(J(qdz`9_SY;3ZyT!-t!%b0L zDZHRuGrWd-niFLKj6ntBp~3W{X;7lJSL6;G2t~m=zlp=>Gt0w;>V)Rp;Wf|hH%#Wl zX5hnH1{qvQ+mDhc3xASiKAubaz7ycQM}j#_MnE*zm(XwXxzbvb>M_6sc@A}ApLcnj z5~?&ETL5{y+Y^X?=EkyhsjOJ-iL1o6m{j{>^Syy4Vn%vQSNqy!qKypJC*}TXJQa%s z3G%x$@aU^)`}b>_Jt?EMJmN%2_?!420FJKdBO|HG7vlU=o!ByXU1<=%hX@5)Z}Kz* z>kP@arppo<#c+tiKFkSALKpQ8ZA-7;5Thh8@;){?dkA@LV~qQA>#5>JF7dh7s^~KZ zxX;KJrH5@BU}AhRPWS*VCfW`jqOScnf-8k*zvL9KrEW(+82Qc22n!R77d?}hnEPc$ zimMxw{c6`JjSW?m*G}dBMqD_i0rf4-w5e9Ml$#0UHW8}{LG1~*@rc%ya0jHW98y|& zv&B7yKXRa2Isaf}jOpR=oBRRJT+n!g4hDD5yUe;J^u#NleC-=fni-8<@XX%2(zi(z rp1^NN{L!q!pS6II-hB!0q#(k*5NUNf0pKZ%!+<>JN>@^>Ma{6 literal 0 HcmV?d00001 diff --git a/openpype/tools/resources/images/file.png b/openpype/tools/resources/images/file.png new file mode 100644 index 0000000000000000000000000000000000000000..4b05a0665f3f86f3adf98c65d87f14bb446b64c5 GIT binary patch literal 2801 zcmbtVX;@QN8a_9hm&kHuGg2rwaYsWI79m3*3sGQ*AfSM)NFWz-2S`E^ATXjK2De%o z85~Ee5YbwfRw+87)Psy6gjOh{qO>wp#`Y#y)KO=C%#Zt=@0|Dj_H(|w zK5^j!7rGA}0N@fE6P*MAi4aKuA`{EskIp|10Hp~}Ni(F$;|1B8frmK2cMs2p}11WN)3^7~JM3Dv};y z6c7dqFoOa$7UZk-0;7=Suqz;B`!R=wIw*!bAuCOuh)Oj&3=Ihk3FNXO>1c#bnIlMw zp8rgl*a=xGgF!3ca7s!_0!xAdHM(35FFZV)!{u}Md^W*g>r2%Jg^{h+PqmvEvk{Hy zvvs)EfNRvK-KHW-Q)CdbSOktfGmaVY=hoHwXXz7#;MfrkFObW5k#4|q-axk_uh6wB zjX|SVX|&@ByyRjWenpWe-|JP33hnF2a`}I!7ZkjdhTb46CJOPas4vCzn*)7HsTSiT zVR}uGE*p~-V`{@xM2#^0CX!@H_sU}~eOD3)rCS>s( zO7_|bVha?xSSqeGsGeJU4#Z>X+*c5LbooX0_AXZAL_T97IF!92*x zdm(VdC)X&6@PZuSJ%?hY(nOsm2hS%kebNF68Y`2A^1?$y+5EsU4@Bbxgf5;_8m%x8 zEIyadWApgzAZ`keF9_xfcp-DRJOP*Mu}T9Q8uP@I48`Fp?Xb@p+up>#JNP1g)DJS z4o;M_6eXSyo~y=mC@+x54Gex+sYHbl2H%_>=UH$Z`@{P!x(LoI@kclaFT7MjZ|sbi z0K_QajL#BcGd_(lH8Fy8#H<&UN|q$Fxj# zLEO%*?(+hVGAiFIxS&0J^2tX>OaFK~R(IeZ2WJ)bbWm48O&9)}6diZJChrdIWNpbi z1?Ouo>uWEK)DA`L81ijc6BM`P(2yu}ONSY%(?>RTq%S-M>rzVDrDO z_NJ^qEx*<(j!Ju{a>u@as>PpGUu$fAqaa(g_l zs!lXJY=>_J-73(tgst%G>*DXT_Hh6bd zzQ^t}rtDgJWY+bwpPrv~VuwUexuLe!@_VcPC2Ej_3JK`Z{<`~f9029^tSGvqJ*gKniGBLXZN{}k}fXy zI%LF_E~yy6vJPB~x-~fRT{=`oif{s-o02G*Hc{$?zLAeUC5^hqB~$0So>)>*OAfXq zt)fI&<_u;)Dmc~l$hj2ma69MIzSy*rcErne2y&Sa`G>ogk+^aXBP{!t;?wHil|)S= zM469dQt_rWiI!!%nKeJ8_BZ>`t_0bbD&Vve_WK&y&_2n95WKw2uz|wxvQ2NXfv?iR z+QgdbbXYcfYb8nwv((qT8v_Tli$x;=p6+IPa4y7HndCf| zvaO%AaV~{=tO4=tdcV>Jntq9VKvSQV7=}qrx6Q4)rkN^HXfDMmlNkdhib-j(dyB*h zyv>vbB-muJLDMKMsJ#+mat!PvlC%SNGtG)bgSAA`lu0ejb--0j(ZVc~6oGura2JvS z)(|OEyiCl!z*$Vqgad#y5n`C>Er=3SqU2eWDI#VYpo?jVFyADxLY`)48)5(!8yThe z0cIb7#S=uZ07%*)#7t!7F7lO-)=6VPA?$>@GNH4~X{Im>1zBqacM!gaA)&$2HlTo~ zpw3LPg{d@gEzZaqE7Xc4i999rb&?op5j-2EGpW(c-KJR60d6lSjpwfG_yt$%|c1DLTE6GWytGq{;8E!h>BQ;2o^;QtU-%xizEYjwm**5JcB zAh^Q=%}*+Z8C_>2;oM$R6Qk?${Eh*4@`@XK!63eCAmqN=-JZ==1A`A9LJ8-tl5LYN zEzfw{NV!t|y>sY;gx%RkT?fqIr`fJZ`+Y^}>YnfYs=v%*CJzKRl)CH*8@#s``Y^R( zL-z2g$*OBDKf<<~p#1H=(3U}vc?0yMi+s);Pfy6LxObr9!v%%kwi!~{t{@wM!f9qA6s19ld43E41dottCe{5v*@}~PsJV>iu^RJN?+AaV9 literal 0 HcmV?d00001 diff --git a/openpype/tools/resources/images/files.png b/openpype/tools/resources/images/files.png new file mode 100644 index 0000000000000000000000000000000000000000..667d6148ab75e01919bcee7dc9e59b2ed76d1fe1 GIT binary patch literal 3094 zcmb_dX+Tp~7QXLgArO|R6)~cHiB+*e76c?QkwBn=O&EkY1au^kJV+3dGzl8E8c=Xr zN5PFMDosaR+KSW#1sx=65m86uf?B0a9G!wv6d16W0i2g$T}C_eXMW_}d+zsr=bn4c zy(gc=#m@I|qq+eAJYu3F;{kxNDGVSSHe5dTQ9S_o<0^^NAQg+ashTW?T%lQpGK^VT z3CLM8749od+sW=W1YIG>Mfjv7_3ysPyuj*lgR=|Grl28;PR-JnYQ4Y~t) zi>_5_3>v*sqkVaRH@0{Qza_-d_il+%u6-9-EdKBGtgJVVp*KXWz!LEysc*#e>jrvB zjuvIcqk2uYE)|VhfvOEtotbdtg&U_bqM6c2RTiq&W7*}?gV}-qfhPSHD%50ZbP3qC zLiu#IQ{>1UHzrG-jwY%U2IVVnuK*FMPJat=M3fjP8IHj*Dqk zX*rQ{1I7wu1+oL!fdR8w5_TXrh{X*KoW){uSuCe#CmVYY3b{f4zxa+@jqosqSj>%9 z=?xlPj&o`BswbeIj9Q~+rpkH85yV+(t~}L|BtBiM(R^PGg& zUMi*=UBfy6)=HQ!dkJQ|>_(^>Ye71!*KkgVmjeJ5sj$ktRS^LEHfC>Z{5WFad(B}P z3#%5!359Fcge3Ljs>+Fb{Pz=s&u3iis1bDcR*tzwJ?chS_;F*2ot)uOvD)lcq$F3Y zOa5?a$Jge_%8T_K`o>=>&o*=v1@ByVIQJ}~(B}mB^l&E7*InK_!M9)5ES@j9+WLc4 zvF*guoYJO09Uo4sws(vK=kdOpB~y7%Nt6UIdDD1DDig)+V;)PcU9Icc{@wh|WVgR< z&pmLdX8OJhLs^HtJ?*FOFn$)bY7dlbJz74#{EPb+(r#|KP;lvs(6RN;%D!LPt2Pwj zd+sSJT!)Mkmxw=RiF+X_=>RYh-Zp8BXl^1Eo!=app}zmh$D zu1Ohqa9&$~;;hU1D;OZH|B&ZM5ZwNXCgySm$zp>G{(75WTQ8l_;fShwY@nTJ z_4;F!|Mqpg6dvP9NY&t7@pfiPtY8Q8&!RB!XfkEu62Y~?b{ucu*|i+gNoZ&QY=)Nb zElQ9<;>a%D5}pUuXV6g4#knCoZ)(BYL&`+v<+$ChN}9sNN%4@o94L$OlDqu8NFuxq z<&AHpJiWVq&gx%$k}WrY-Mfq`xCNghn%CG|woq1>*(qc>jym~kTBcz4)TMJ`t|{(}BK`|ebrkq^d79_e!Cqe0S}>G*7djeEFs1a)HI3|ot$cql zw6_-5$w@9e=_0r|R4-mtPL^3sJH~YeTcjO?!QCU4Np*7y*HO<*+IGjXzZmH%4Kh^~ z_rS-h!)tJxz0Z*A=9+eRpXu7$0=3mrmI`#ht9!;$Q)`PGuXbNjU-wq%QZi}NlMVg? za(Lfg*AtYq=u`EFKmfia>~;XQmaMru%Up~+oBjiQl+tGME_!e>lWdJB%io*{FTjMK zhy||Uef)#2ewgrV5Ht-RW?q9l^SqAVLaFMlKZILA`qaUw$qO+F5#U?I`w@5+0xhXe zi*x4g{Er?s3JI)5=7a&^Ah@_T9cQBDo7!;}ilRRIDPXN34C)~4TXzEZ6jh-r9&ndK z+zCJ^HMP5#Dc-Uk$Pe!(pq;PtuOY z0+KI?kiNgg>!tlc+*$#gO?v0xA6IOF7m?mM1Zmw1i5qBE3mZ=jEfL_FDN36U?BOdM zOp%dKyGrg;1pvZRoFB^*xVhIIF#(wLfB0w!C%|RgqtmmS{AwOHz~{D}YMflxWofPW zrNAO~VWdODls);Prq63Ed7lgjxAbjvm-T?%Q2!KxyZQRQtosW`z8Nnau_ZO1BpAzS zGcBF@W6PV9Q>MB-_gYo3llYTcbfc%}#*jTerK9j^j{mc|A)wu7>Pj-7da&cZbQiIw z%JkUZddree^_eIOC0_#3-{)(e2_H9U!@>2w@sQ|qiYy+Vc<8}`M-3M|w(tF9c9S>n5uBWZ|{-P&j%aoe;t4qsF$44j#msMA2_gVjdSV^?zfuTKV4a(sd z%Rq7OA`B`6&+^VV!sK+A7OLHYs*=krY^Rv p;09cG6KXH)X5F|^aj-k;IplIgmMuFrs}bwFASNm{@?eCl=-+XbdguTE literal 0 HcmV?d00001 diff --git a/openpype/tools/resources/images/folder.png b/openpype/tools/resources/images/folder.png new file mode 100644 index 0000000000000000000000000000000000000000..9c55e699278dee8f6f94cfc33dfd1db570f6e1f1 GIT binary patch literal 2627 zcmbtVd0Z3M7M@82C2U1SLHl$XvC5LnBp8*Hu$WK;35KvG7Ft3wkQ7KlCX|5Nh+3%n z>Q)7Xf@>}Cv*kUXOBG54tRgPBU_q#gf~b`WiYSWo-2@8y(D(j$`TZty&;7o0?z!K& z_smzK&_G+-6dD9Uwm}O8VhEyuAq9e|;C121$3H>Pn4_u)iC!WM;mS2BOqoIxk24J^ zT7W~4x357flPBSNBpy#xsd@BACo1WPO2MN?bA*^s%g2?fg_$}$JTo*xo|z=~QqX;U zXx;`c2#|v7Wr!gqSxs;aJi0k97mQ8QC>=3V^hrFrL?}Y|8Xb;sm>ecX_n{%)Iz<9k zEckfH8CX2JQm@x?Q8Yb0otf^*)aVjXmY0_oim_2Pn*kUMB15g085n9}hAG5g3;|Ba zbtyXh{(|5s2C?S zX*xL`@CB~c&oC=t(uFHh8SrF@K$U{437{^I&SA0t1C_oD_=WjlQ;!^sUfvEx6|V zgc=1%&(oaV2o%KUi*%X!Md&rU4D;0BQ4hyc z2dzOfS!F)s2x6`@S0*=!#G`9<8bz8MSC|(E;RaDclb}zR>2Uu19RRcvbhwuQ zW4IgPYS4mopx1O)ZQTVyaFz;GW>iHWX!ho`%@^GTVG~dLdh%;R_KGH5-Y1jigiV;b zeuoon{f@8|DG7yryYHUwoS3aH{=?9 zHzdhl6I=V)`!7!g2iJ|Ot4mG1Y|-A~b9d3h?uQ|g_ydNIxF2LaPi38)4KK67JPvLA zw7jQwom=0ln|)W>T%tEi_vie=4idL@=PcRuAoVM&OLy3pC!Qbpv$M3&sb_m>^DEKI zI43k#bQCU{S#7vEZ^K1u*>Ba-BU_4^SMQF#w8-&%h4lr_e6Jss|6t6I%|7xGrzD_q zX8tkGX0l_3_MHEdnR7h8S=xK(Vk<)s)n3YsTRQf5dpXfLqTWDqOVJ_ z_bfy+EN!HeMKV?I?rdj4tLq2C0RQ|J%IJ^Y0BdGWy`zkqMr@UK7h z*6ys^)bAXQt$h_tthz$|ew$T66lvdIuxhPUqbKIMitwF$EYMg(y^#O?)icx>cWvk@ zG1WfjMXmJ4qxJDM7PmPr_SJR*uZT8}M}Fm2A;u5MwbYsu3oksjb9o{4`+Rb7br!9O~l47!gCdnhy(^k5Qw-=?{O*>H(<8aHjYq4NF)EWER zp`f#mC*;Uyz*%iK?<|T$46T9vqG-y-n!;jbY^ia4%-lAQXVj{EMuwA}-`L#y(x}S( z8_v7ztKl`k_?foLo^QD;vCob4vGF1c+S!{Ju@=eBP9>x}wa9BLg>QT2RonFa?tXVm z+rtTWEQ&mrn;-3nJn6pQaGmCXBTwKz8Y18jTc;&(B%JJ6f6yqljB(7X^GkEO(OeI0 zz;|(N9xXpdc`6f~Cz;^Yc-qzaYPQUNfi;#3U!gU+VTUPlXKiHMZ0b{wdDIe{tJ$rN zr@Z~n=_Zs-f^TDO;EA!ybHhHf0o-kHIuF|pUq|`y>`2eD${Wa7^+Dra$LIa${b_ko z#^rx&4F9g(*!jD$!qLzJUqdNVhl~IJ4C*J;mk&Ij-Z7QD+PYfcx72u+`iDbV7x~Fb zGV|vbC;Is=y^Q^ZKMpXTO)XpjJvH>C?-&=CAnhYtXSvS5;F5|Y9adYBhu1M7kChI+ zU$e$MZ?M&h;~rSNXZNq*Ut6q^f}CwX?4PX7r6i%Gc3;$SJsP)_(u~F_Uh#d6XUT4; zz$VYmZ@vxT3;ychafiyMk=VKy(3-FoA98b#{j|85#(QumC1e^xt9l6UK|H1**8@A@ zJ 0 + self._files_view.setVisible(files_exists) + self._empty_widget.setVisible(not files_exists) + + +class SingleFileWidget(QtWidgets.QWidget): + value_changed = QtCore.Signal() + + def __init__(self, parent): + super(SingleFileWidget, self).__init__(parent) + + self.setAcceptDrops(True) + + filepath_input = QtWidgets.QLineEdit(self) + + browse_btn = QtWidgets.QPushButton("Browse", self) + browse_btn.setVisible(False) + + layout = QtWidgets.QHBoxLayout(self) + layout.setContentsMargins(0, 0, 0, 0) + layout.addWidget(filepath_input, 1) + layout.addWidget(browse_btn, 0) + + browse_btn.clicked.connect(self._on_browse_clicked) + filepath_input.textChanged.connect(self._on_text_change) + + self._in_set_value = False + + self._filepath_input = filepath_input + self._folders_allowed = False + self._exts_filter = [] + + def set_value(self, value, multivalue): + self._in_set_value = True + + if multivalue: + set_value = set(value) + if len(set_value) == 1: + value = tuple(set_value)[0] + else: + value = "< Multiselection >" + self._filepath_input.setText(value) + + self._in_set_value = False + + def current_value(self): + return self._filepath_input.text() + + def set_filters(self, folders_allowed, exts_filter): + self._folders_allowed = folders_allowed + self._exts_filter = exts_filter + + def _on_text_change(self, text): + if not self._in_set_value: + self.value_changed.emit() + + def _on_browse_clicked(self): + # TODO implement file dialog logic in '_on_browse_clicked' + print("_on_browse_clicked") + + def dragEnterEvent(self, event): + mime_data = event.mimeData() + if not mime_data.hasUrls(): + return + + filepaths = [] + for url in mime_data.urls(): + filepath = url.toLocalFile() + if os.path.exists(filepath): + filepaths.append(filepath) + + # TODO add folder, extensions check + if len(filepaths) == 1: + event.setDropAction(QtCore.Qt.CopyAction) + event.accept() + + def dragLeaveEvent(self, event): + event.accept() + + def dropEvent(self, event): + mime_data = event.mimeData() + if mime_data.hasUrls(): + filepaths = [] + for url in mime_data.urls(): + filepath = url.toLocalFile() + if os.path.exists(filepath): + filepaths.append(filepath) + # TODO filter check + if len(filepaths) == 1: + self.set_value(filepaths[0], False) + event.accept() diff --git a/openpype/widgets/attribute_defs/widgets.py b/openpype/widgets/attribute_defs/widgets.py index 1cfed08363..2eb22209db 100644 --- a/openpype/widgets/attribute_defs/widgets.py +++ b/openpype/widgets/attribute_defs/widgets.py @@ -1,14 +1,20 @@ +import os import uuid + +from Qt import QtWidgets, QtCore + from openpype.pipeline.lib import ( AbtractAttrDef, UnknownDef, NumberDef, TextDef, EnumDef, - BoolDef + BoolDef, + FileDef, + UISeparatorDef, + UILabelDef ) from openpype.widgets.nice_checkbox import NiceCheckbox -from Qt import QtWidgets, QtCore def create_widget_for_attr_def(attr_def, parent=None): @@ -32,12 +38,22 @@ def create_widget_for_attr_def(attr_def, parent=None): if isinstance(attr_def, UnknownDef): return UnknownAttrWidget(attr_def, parent) + if isinstance(attr_def, FileDef): + return FileAttrWidget(attr_def, parent) + + if isinstance(attr_def, UISeparatorDef): + return SeparatorAttrWidget(attr_def, parent) + + if isinstance(attr_def, UILabelDef): + return LabelAttrWidget(attr_def, parent) + raise ValueError("Unknown attribute definition \"{}\"".format( str(type(attr_def)) )) class _BaseAttrDefWidget(QtWidgets.QWidget): + # Type 'object' may not work with older PySide versions value_changed = QtCore.Signal(object, uuid.UUID) def __init__(self, attr_def, parent): @@ -68,12 +84,36 @@ class _BaseAttrDefWidget(QtWidgets.QWidget): def set_value(self, value, multivalue=False): raise NotImplementedError( - "Method 'current_value' is not implemented. {}".format( + "Method 'set_value' is not implemented. {}".format( self.__class__.__name__ ) ) +class SeparatorAttrWidget(_BaseAttrDefWidget): + def _ui_init(self): + input_widget = QtWidgets.QWidget(self) + input_widget.setObjectName("Separator") + input_widget.setMinimumHeight(2) + input_widget.setMaximumHeight(2) + + self._input_widget = input_widget + + self.main_layout.addWidget(input_widget, 0) + + +class LabelAttrWidget(_BaseAttrDefWidget): + def _ui_init(self): + input_widget = QtWidgets.QLabel(self) + label = self.attr_def.label + if label: + input_widget.setText(str(label)) + + self._input_widget = input_widget + + self.main_layout.addWidget(input_widget, 0) + + class NumberAttrWidget(_BaseAttrDefWidget): def _ui_init(self): decimals = self.attr_def.decimals @@ -83,6 +123,9 @@ class NumberAttrWidget(_BaseAttrDefWidget): else: input_widget = QtWidgets.QSpinBox(self) + if self.attr_def.tooltip: + input_widget.setToolTip(self.attr_def.tooltip) + input_widget.setMinimum(self.attr_def.minimum) input_widget.setMaximum(self.attr_def.maximum) input_widget.setValue(self.attr_def.default) @@ -136,6 +179,9 @@ class TextAttrWidget(_BaseAttrDefWidget): ): input_widget.setPlaceholderText(self.attr_def.placeholder) + if self.attr_def.tooltip: + input_widget.setToolTip(self.attr_def.tooltip) + if self.attr_def.default: if self.multiline: input_widget.setPlainText(self.attr_def.default) @@ -184,6 +230,9 @@ class BoolAttrWidget(_BaseAttrDefWidget): input_widget = NiceCheckbox(parent=self) input_widget.setChecked(self.attr_def.default) + if self.attr_def.tooltip: + input_widget.setToolTip(self.attr_def.tooltip) + input_widget.stateChanged.connect(self._on_value_change) self._input_widget = input_widget @@ -220,6 +269,9 @@ class EnumAttrWidget(_BaseAttrDefWidget): combo_delegate = QtWidgets.QStyledItemDelegate(input_widget) input_widget.setItemDelegate(combo_delegate) + if self.attr_def.tooltip: + input_widget.setToolTip(self.attr_def.tooltip) + items = self.attr_def.items for key, label in items.items(): input_widget.addItem(label, key) @@ -281,3 +333,40 @@ class UnknownAttrWidget(_BaseAttrDefWidget): if str_value != self._value: self._value = str_value self._input_widget.setText(str_value) + + +class FileAttrWidget(_BaseAttrDefWidget): + def _ui_init(self): + self.multipath = self.attr_def.multipath + if self.multipath: + from .files_widget import MultiFilesWidget + + input_widget = MultiFilesWidget(self) + + else: + from .files_widget import SingleFileWidget + + input_widget = SingleFileWidget(self) + + if self.attr_def.tooltip: + input_widget.setToolTip(self.attr_def.tooltip) + + input_widget.set_filters( + self.attr_def.folders, self.attr_def.extensions + ) + + input_widget.value_changed.connect(self._on_value_change) + + self._input_widget = input_widget + + self.main_layout.addWidget(input_widget, 0) + + def _on_value_change(self): + new_value = self.current_value() + self.value_changed.emit(new_value, self.attr_def.id) + + def current_value(self): + return self._input_widget.current_value() + + def set_value(self, value, multivalue=False): + self._input_widget.set_value(value, multivalue) From fbdd1d8ab5cc43c5bf00ff6122e68c5aaac5f739 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 18 Jan 2022 17:22:08 +0100 Subject: [PATCH 02/74] moved few widgets to tools/utils and modified asset/task widgets to easily change source model --- openpype/tools/publisher/widgets/__init__.py | 4 - .../publisher/widgets/card_view_widgets.py | 8 +- .../publisher/widgets/validations_widget.py | 6 +- openpype/tools/publisher/widgets/widgets.py | 109 +++--------------- openpype/tools/publisher/window.py | 7 +- openpype/tools/utils/__init__.py | 9 ++ openpype/tools/utils/assets_widget.py | 28 ++++- openpype/tools/utils/models.py | 30 +++-- openpype/tools/utils/tasks_widget.py | 8 ++ openpype/tools/utils/widgets.py | 59 ++++++++++ 10 files changed, 146 insertions(+), 122 deletions(-) diff --git a/openpype/tools/publisher/widgets/__init__.py b/openpype/tools/publisher/widgets/__init__.py index 9b22a6cf25..55afc349ff 100644 --- a/openpype/tools/publisher/widgets/__init__.py +++ b/openpype/tools/publisher/widgets/__init__.py @@ -9,8 +9,6 @@ from .border_label_widget import ( from .widgets import ( SubsetAttributesWidget, - PixmapLabel, - StopBtn, ResetBtn, ValidateBtn, @@ -44,8 +42,6 @@ __all__ = ( "SubsetAttributesWidget", "BorderedLabelWidget", - "PixmapLabel", - "StopBtn", "ResetBtn", "ValidateBtn", diff --git a/openpype/tools/publisher/widgets/card_view_widgets.py b/openpype/tools/publisher/widgets/card_view_widgets.py index 271d06e94c..5b59cccd25 100644 --- a/openpype/tools/publisher/widgets/card_view_widgets.py +++ b/openpype/tools/publisher/widgets/card_view_widgets.py @@ -27,12 +27,12 @@ from Qt import QtWidgets, QtCore from openpype.widgets.nice_checkbox import NiceCheckbox +from openpype.tools.utils import BaseClickableFrame from .widgets import ( AbstractInstanceView, ContextWarningLabel, - ClickableFrame, IconValuePixmapLabel, - TransparentPixmapLabel + PublishPixmapLabel ) from ..constants import ( CONTEXT_ID, @@ -140,7 +140,7 @@ class GroupWidget(QtWidgets.QWidget): widget_idx += 1 -class CardWidget(ClickableFrame): +class CardWidget(BaseClickableFrame): """Clickable card used as bigger button.""" selected = QtCore.Signal(str, str) # Group identifier of card @@ -184,7 +184,7 @@ class ContextCardWidget(CardWidget): self._id = CONTEXT_ID self._group_identifier = "" - icon_widget = TransparentPixmapLabel(self) + icon_widget = PublishPixmapLabel(None, self) icon_widget.setObjectName("FamilyIconLabel") label_widget = QtWidgets.QLabel(CONTEXT_LABEL, self) diff --git a/openpype/tools/publisher/widgets/validations_widget.py b/openpype/tools/publisher/widgets/validations_widget.py index 09e56d64cc..4af098413a 100644 --- a/openpype/tools/publisher/widgets/validations_widget.py +++ b/openpype/tools/publisher/widgets/validations_widget.py @@ -6,8 +6,8 @@ except Exception: from Qt import QtWidgets, QtCore, QtGui +from openpype.tools.utils import BaseClickableFrame from .widgets import ( - ClickableFrame, IconValuePixmapLabel ) @@ -55,7 +55,7 @@ class ValidationErrorTitleWidget(QtWidgets.QWidget): self._error_info = error_info self._selected = False - title_frame = ClickableFrame(self) + title_frame = BaseClickableFrame(self) title_frame.setObjectName("ValidationErrorTitleFrame") title_frame._mouse_release_callback = self._mouse_release_callback @@ -168,7 +168,7 @@ class ValidationErrorTitleWidget(QtWidgets.QWidget): self._toggle_instance_btn.setArrowType(QtCore.Qt.RightArrow) -class ActionButton(ClickableFrame): +class ActionButton(BaseClickableFrame): """Plugin's action callback button. Action may have label or icon or both. diff --git a/openpype/tools/publisher/widgets/widgets.py b/openpype/tools/publisher/widgets/widgets.py index 2ebcf73d4e..073e5f4bc2 100644 --- a/openpype/tools/publisher/widgets/widgets.py +++ b/openpype/tools/publisher/widgets/widgets.py @@ -8,14 +8,20 @@ from Qt import QtWidgets, QtCore, QtGui from avalon.vendor import qtawesome from openpype.widgets.attribute_defs import create_widget_for_attr_def +from openpype.tools import resources from openpype.tools.flickcharm import FlickCharm -from openpype.tools.utils import PlaceholderLineEdit -from openpype.pipeline.create import SUBSET_NAME_ALLOWED_SYMBOLS from .models import ( AssetsHierarchyModel, TasksModel, RecursiveSortFilterProxyModel, ) +from openpype.tools.utils import ( + PlaceholderLineEdit, + IconButton, + PixmapLabel, + BaseClickableFrame +) +from openpype.pipeline.create import SUBSET_NAME_ALLOWED_SYMBOLS from .icons import ( get_pixmap, get_icon_path @@ -26,49 +32,14 @@ from ..constants import ( ) -class PixmapLabel(QtWidgets.QLabel): - """Label resizing image to height of font.""" - def __init__(self, pixmap, parent): - super(PixmapLabel, self).__init__(parent) - self._source_pixmap = pixmap - - def set_source_pixmap(self, pixmap): - """Change source image.""" - self._source_pixmap = pixmap - self._set_resized_pix() - - def _set_resized_pix(self): +class PublishPixmapLabel(PixmapLabel): + def _get_pix_size(self): size = self.fontMetrics().height() size += size % 2 - self.setPixmap( - self._source_pixmap.scaled( - size, - size, - QtCore.Qt.KeepAspectRatio, - QtCore.Qt.SmoothTransformation - ) - ) - - def resizeEvent(self, event): - self._set_resized_pix() - super(PixmapLabel, self).resizeEvent(event) + return size, size -class TransparentPixmapLabel(QtWidgets.QLabel): - """Transparent label resizing to width and height of font.""" - def __init__(self, *args, **kwargs): - super(TransparentPixmapLabel, self).__init__(*args, **kwargs) - - def resizeEvent(self, event): - size = self.fontMetrics().height() - size += size % 2 - pix = QtGui.QPixmap(size, size) - pix.fill(QtCore.Qt.transparent) - self.setPixmap(pix) - super(TransparentPixmapLabel, self).resizeEvent(event) - - -class IconValuePixmapLabel(PixmapLabel): +class IconValuePixmapLabel(PublishPixmapLabel): """Label resizing to width and height of font. Handle icon parsing from creators/instances. Using of QAwesome module @@ -125,7 +96,7 @@ class IconValuePixmapLabel(PixmapLabel): return self._default_pixmap() -class ContextWarningLabel(PixmapLabel): +class ContextWarningLabel(PublishPixmapLabel): """Pixmap label with warning icon.""" def __init__(self, parent): pix = get_pixmap("warning") @@ -138,29 +109,6 @@ class ContextWarningLabel(PixmapLabel): self.setObjectName("FamilyIconLabel") -class IconButton(QtWidgets.QPushButton): - """PushButton with icon and size of font. - - Using font metrics height as icon size reference. - """ - - def __init__(self, *args, **kwargs): - super(IconButton, self).__init__(*args, **kwargs) - self.setObjectName("IconButton") - - def sizeHint(self): - result = super(IconButton, self).sizeHint() - icon_h = self.iconSize().height() - font_height = self.fontMetrics().height() - text_set = bool(self.text()) - if not text_set and icon_h < font_height: - new_size = result.height() - icon_h + font_height - result.setHeight(new_size) - result.setWidth(new_size) - - return result - - class PublishIconBtn(IconButton): """Button using alpha of source image to redraw with different color. @@ -314,7 +262,7 @@ class ShowPublishReportBtn(PublishIconBtn): class RemoveInstanceBtn(PublishIconBtn): """Create remove button.""" def __init__(self, parent=None): - icon_path = get_icon_path("delete") + icon_path = resources.get_icon_path("delete") super(RemoveInstanceBtn, self).__init__(icon_path, parent) self.setToolTip("Remove selected instances") @@ -359,33 +307,6 @@ class AbstractInstanceView(QtWidgets.QWidget): ).format(self.__class__.__name__)) -class ClickableFrame(QtWidgets.QFrame): - """Widget that catch left mouse click and can trigger a callback. - - Callback is defined by overriding `_mouse_release_callback`. - """ - def __init__(self, parent): - super(ClickableFrame, self).__init__(parent) - - self._mouse_pressed = False - - def _mouse_release_callback(self): - pass - - def mousePressEvent(self, event): - if event.button() == QtCore.Qt.LeftButton: - self._mouse_pressed = True - super(ClickableFrame, self).mousePressEvent(event) - - def mouseReleaseEvent(self, event): - if self._mouse_pressed: - self._mouse_pressed = False - if self.rect().contains(event.pos()): - self._mouse_release_callback() - - super(ClickableFrame, self).mouseReleaseEvent(event) - - class AssetsDialog(QtWidgets.QDialog): """Dialog to select asset for a context of instance.""" def __init__(self, controller, parent): @@ -554,7 +475,7 @@ class ClickableLineEdit(QtWidgets.QLineEdit): event.accept() -class AssetsField(ClickableFrame): +class AssetsField(BaseClickableFrame): """Field where asset name of selected instance/s is showed. Click on the field will trigger `AssetsDialog`. diff --git a/openpype/tools/publisher/window.py b/openpype/tools/publisher/window.py index bb58813e55..b668888281 100644 --- a/openpype/tools/publisher/window.py +++ b/openpype/tools/publisher/window.py @@ -4,7 +4,10 @@ from openpype import ( resources, style ) -from openpype.tools.utils import PlaceholderLineEdit +from openpype.tools.utils import ( + PlaceholderLineEdit, + PixmapLabel +) from .control import PublisherController from .widgets import ( BorderedLabelWidget, @@ -14,8 +17,6 @@ from .widgets import ( InstanceListView, CreateDialog, - PixmapLabel, - StopBtn, ResetBtn, ValidateBtn, diff --git a/openpype/tools/utils/__init__.py b/openpype/tools/utils/__init__.py index eb0cb1eef5..ac93595682 100644 --- a/openpype/tools/utils/__init__.py +++ b/openpype/tools/utils/__init__.py @@ -3,6 +3,8 @@ from .widgets import ( BaseClickableFrame, ClickableFrame, ExpandBtn, + PixmapLabel, + IconButton, ) from .error_dialog import ErrorMessageBox @@ -11,15 +13,22 @@ from .lib import ( paint_image_with_color ) +from .models import ( + RecursiveSortFilterProxyModel, +) __all__ = ( "PlaceholderLineEdit", "BaseClickableFrame", "ClickableFrame", "ExpandBtn", + "PixmapLabel", + "IconButton", "ErrorMessageBox", "WrappedCallbackItem", "paint_image_with_color", + + "RecursiveSortFilterProxyModel", ) diff --git a/openpype/tools/utils/assets_widget.py b/openpype/tools/utils/assets_widget.py index 1495586b04..55e34285fc 100644 --- a/openpype/tools/utils/assets_widget.py +++ b/openpype/tools/utils/assets_widget.py @@ -635,9 +635,10 @@ class AssetsWidget(QtWidgets.QWidget): selection_model = view.selectionModel() selection_model.selectionChanged.connect(self._on_selection_change) refresh_btn.clicked.connect(self.refresh) - current_asset_btn.clicked.connect(self.set_current_session_asset) + current_asset_btn.clicked.connect(self._on_current_asset_click) view.doubleClicked.connect(self.double_clicked) + self._refresh_btn = refresh_btn self._current_asset_btn = current_asset_btn self._model = model self._proxy = proxy @@ -668,11 +669,30 @@ class AssetsWidget(QtWidgets.QWidget): def stop_refresh(self): self._model.stop_refresh() + def _get_current_session_asset(self): + return self.dbcon.Session.get("AVALON_ASSET") + + def _on_current_asset_click(self): + """Trigger change of asset to current context asset. + This separation gives ability to override this method and use it + in differnt way. + """ + self.set_current_session_asset() + def set_current_session_asset(self): - asset_name = self.dbcon.Session.get("AVALON_ASSET") + asset_name = self._get_current_session_asset() if asset_name: self.select_asset_by_name(asset_name) + def set_refresh_btn_visibility(self, visible=None): + """Hide set refresh button. + Some tools may have their global refresh button or do not support + refresh at all. + """ + if visible is None: + visible = not self._refresh_btn.isVisible() + self._refresh_btn.setVisible(visible) + def set_current_asset_btn_visibility(self, visible=None): """Hide set current asset button. @@ -727,6 +747,10 @@ class AssetsWidget(QtWidgets.QWidget): def _set_loading_state(self, loading, empty): self._view.set_loading_state(loading, empty) + def _clear_selection(self): + selection_model = self._view.selectionModel() + selection_model.clearSelection() + def _select_indexes(self, indexes): valid_indexes = [ index diff --git a/openpype/tools/utils/models.py b/openpype/tools/utils/models.py index df3eee41a2..2b5b156eeb 100644 --- a/openpype/tools/utils/models.py +++ b/openpype/tools/utils/models.py @@ -199,31 +199,37 @@ class Item(dict): class RecursiveSortFilterProxyModel(QtCore.QSortFilterProxyModel): - """Filters to the regex if any of the children matches allow parent""" - def filterAcceptsRow(self, row, parent): + """Recursive proxy model. + Item is not filtered if any children match the filter. + Use case: Filtering by string - parent won't be filtered if does not match + the filter string but first checks if any children does. + """ + def filterAcceptsRow(self, row, parent_index): regex = self.filterRegExp() if not regex.isEmpty(): - pattern = regex.pattern() model = self.sourceModel() - source_index = model.index(row, self.filterKeyColumn(), parent) + source_index = model.index( + row, self.filterKeyColumn(), parent_index + ) if source_index.isValid(): + pattern = regex.pattern() + # Check current index itself - key = model.data(source_index, self.filterRole()) - if re.search(pattern, key, re.IGNORECASE): + value = model.data(source_index, self.filterRole()) + if re.search(pattern, value, re.IGNORECASE): return True - # Check children rows = model.rowCount(source_index) - for i in range(rows): - if self.filterAcceptsRow(i, source_index): + for idx in range(rows): + if self.filterAcceptsRow(idx, source_index): return True # Otherwise filter it return False - return super( - RecursiveSortFilterProxyModel, self - ).filterAcceptsRow(row, parent) + return super(RecursiveSortFilterProxyModel, self).filterAcceptsRow( + row, parent_index + ) class ProjectModel(QtGui.QStandardItemModel): diff --git a/openpype/tools/utils/tasks_widget.py b/openpype/tools/utils/tasks_widget.py index 6e6cd17ffd..6c7787d06a 100644 --- a/openpype/tools/utils/tasks_widget.py +++ b/openpype/tools/utils/tasks_widget.py @@ -255,6 +255,10 @@ class TasksWidget(QtWidgets.QWidget): # Force a task changed emit. self.task_changed.emit() + def _clear_selection(self): + selection_model = self._tasks_view.selectionModel() + selection_model.clearSelection() + def select_task_name(self, task_name): """Select a task by name. @@ -285,6 +289,10 @@ class TasksWidget(QtWidgets.QWidget): self._tasks_view.setCurrentIndex(index) break + last_selected_task_name = self.get_selected_task_name() + if last_selected_task_name: + self._last_selected_task_name = last_selected_task_name + def get_selected_task_name(self): """Return name of task at current index (selected) diff --git a/openpype/tools/utils/widgets.py b/openpype/tools/utils/widgets.py index c32eae043e..ea09968e40 100644 --- a/openpype/tools/utils/widgets.py +++ b/openpype/tools/utils/widgets.py @@ -148,6 +148,65 @@ class ImageButton(QtWidgets.QPushButton): return self.iconSize() +class IconButton(QtWidgets.QPushButton): + """PushButton with icon and size of font. + + Using font metrics height as icon size reference. + """ + + def __init__(self, *args, **kwargs): + super(IconButton, self).__init__(*args, **kwargs) + self.setObjectName("IconButton") + + def sizeHint(self): + result = super(IconButton, self).sizeHint() + icon_h = self.iconSize().height() + font_height = self.fontMetrics().height() + text_set = bool(self.text()) + if not text_set and icon_h < font_height: + new_size = result.height() - icon_h + font_height + result.setHeight(new_size) + result.setWidth(new_size) + + return result + + +class PixmapLabel(QtWidgets.QLabel): + """Label resizing image to height of font.""" + def __init__(self, pixmap, parent): + super(PixmapLabel, self).__init__(parent) + self._empty_pixmap = QtGui.QPixmap(0, 0) + self._source_pixmap = pixmap + + def set_source_pixmap(self, pixmap): + """Change source image.""" + self._source_pixmap = pixmap + self._set_resized_pix() + + def _get_pix_size(self): + size = self.fontMetrics().height() + size += size % 2 + return size, size + + def _set_resized_pix(self): + if self._source_pixmap is None: + self.setPixmap(self._empty_pixmap) + return + width, height = self._get_pix_size() + self.setPixmap( + self._source_pixmap.scaled( + width, + height, + QtCore.Qt.KeepAspectRatio, + QtCore.Qt.SmoothTransformation + ) + ) + + def resizeEvent(self, event): + self._set_resized_pix() + super(PixmapLabel, self).resizeEvent(event) + + class OptionalMenu(QtWidgets.QMenu): """A subclass of `QtWidgets.QMenu` to work with `OptionalAction` From fffdef5030f74cb0c0428cfb657234465d2d3a09 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 18 Jan 2022 17:22:41 +0100 Subject: [PATCH 03/74] added publisher specific asset and task widgets --- .../tools/publisher/widgets/assets_widget.py | 275 ++++++++++++++++++ .../tools/publisher/widgets/tasks_widget.py | 169 +++++++++++ 2 files changed, 444 insertions(+) create mode 100644 openpype/tools/publisher/widgets/assets_widget.py create mode 100644 openpype/tools/publisher/widgets/tasks_widget.py diff --git a/openpype/tools/publisher/widgets/assets_widget.py b/openpype/tools/publisher/widgets/assets_widget.py new file mode 100644 index 0000000000..5d5372cbce --- /dev/null +++ b/openpype/tools/publisher/widgets/assets_widget.py @@ -0,0 +1,275 @@ +import collections + +import avalon.api + +from Qt import QtWidgets, QtCore, QtGui +from openpype.tools.utils import ( + PlaceholderLineEdit, + RecursiveSortFilterProxyModel +) +from openpype.tools.utils.assets_widget import ( + SingleSelectAssetsWidget, + ASSET_ID_ROLE, + ASSET_NAME_ROLE +) + + +class CreateDialogAssetsWidget(SingleSelectAssetsWidget): + current_context_required = QtCore.Signal() + + def __init__(self, controller, parent): + self._controller = controller + super(CreateDialogAssetsWidget, self).__init__(None, parent) + + self.set_refresh_btn_visibility(False) + self.set_current_asset_btn_visibility(False) + + self._current_asset_name = None + self._last_selection = None + self._enabled = None + + def _on_current_asset_click(self): + self.current_context_required.emit() + + def set_enabled(self, enabled): + if self._enabled == enabled: + return + self._enabled = enabled + if not enabled: + self._last_selection = self.get_selected_asset_id() + self._clear_selection() + elif self._last_selection is not None: + self.select_asset(self._last_selection) + + def _select_indexes(self, *args, **kwargs): + super(CreateDialogAssetsWidget, self)._select_indexes(*args, **kwargs) + if self._enabled: + return + self._last_selection = self.get_selected_asset_id() + self._clear_selection() + + def set_current_asset_name(self, asset_name): + self._current_asset_name = asset_name + # Hide set current asset if there is no one + self.set_current_asset_btn_visibility(asset_name is not None) + + def _get_current_session_asset(self): + return self._current_asset_name + + def _create_source_model(self): + return AssetsHierarchyModel(self._controller) + + def _refresh_model(self): + self._model.reset() + self._on_model_refresh(self._model.rowCount() > 0) + + +class AssetsHierarchyModel(QtGui.QStandardItemModel): + """Assets hiearrchy model. + + For selecting asset for which should beinstance created. + + Uses controller to load asset hierarchy. All asset documents are stored by + their parents. + """ + def __init__(self, controller): + super(AssetsHierarchyModel, self).__init__() + self._controller = controller + + self._items_by_name = {} + self._items_by_asset_id = {} + + def reset(self): + self.clear() + + self._items_by_name = {} + self._items_by_asset_id = {} + assets_by_parent_id = self._controller.get_asset_hierarchy() + + items_by_name = {} + items_by_asset_id = {} + _queue = collections.deque() + _queue.append((self.invisibleRootItem(), None)) + while _queue: + parent_item, parent_id = _queue.popleft() + children = assets_by_parent_id.get(parent_id) + if not children: + continue + + children_by_name = { + child["name"]: child + for child in children + } + items = [] + for name in sorted(children_by_name.keys()): + child = children_by_name[name] + child_id = child["_id"] + item = QtGui.QStandardItem(name) + item.setFlags( + QtCore.Qt.ItemIsEnabled + | QtCore.Qt.ItemIsSelectable + ) + item.setData(child_id, ASSET_ID_ROLE) + item.setData(name, ASSET_NAME_ROLE) + + items_by_name[name] = item + items_by_asset_id[child_id] = item + items.append(item) + _queue.append((item, child_id)) + + parent_item.appendRows(items) + + self._items_by_name = items_by_name + self._items_by_asset_id = items_by_asset_id + + def get_index_by_asset_id(self, asset_id): + item = self._items_by_asset_id.get(asset_id) + if item is not None: + return item.index() + return QtCore.QModelIndex() + + def get_index_by_asset_name(self, asset_name): + item = self._items_by_name.get(asset_name) + if item is None: + return QtCore.QModelIndex() + return item.index() + + def name_is_valid(self, item_name): + return item_name in self._items_by_name + + +class AssetsDialog(QtWidgets.QDialog): + """Dialog to select asset for a context of instance.""" + def __init__(self, controller, parent): + super(AssetsDialog, self).__init__(parent) + self.setWindowTitle("Select asset") + + model = AssetsHierarchyModel(controller) + proxy_model = RecursiveSortFilterProxyModel() + proxy_model.setSourceModel(model) + proxy_model.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive) + + filter_input = PlaceholderLineEdit(self) + filter_input.setPlaceholderText("Filter assets..") + + asset_view = QtWidgets.QTreeView(self) + asset_view.setModel(proxy_model) + asset_view.setHeaderHidden(True) + asset_view.setFrameShape(QtWidgets.QFrame.NoFrame) + asset_view.setEditTriggers(QtWidgets.QTreeView.NoEditTriggers) + asset_view.setAlternatingRowColors(True) + asset_view.setSelectionBehavior(QtWidgets.QTreeView.SelectRows) + asset_view.setAllColumnsShowFocus(True) + + ok_btn = QtWidgets.QPushButton("OK", self) + cancel_btn = QtWidgets.QPushButton("Cancel", self) + + btns_layout = QtWidgets.QHBoxLayout() + btns_layout.addStretch(1) + btns_layout.addWidget(ok_btn) + btns_layout.addWidget(cancel_btn) + + layout = QtWidgets.QVBoxLayout(self) + layout.addWidget(filter_input, 0) + layout.addWidget(asset_view, 1) + layout.addLayout(btns_layout, 0) + + filter_input.textChanged.connect(self._on_filter_change) + ok_btn.clicked.connect(self._on_ok_clicked) + cancel_btn.clicked.connect(self._on_cancel_clicked) + + self._filter_input = filter_input + self._ok_btn = ok_btn + self._cancel_btn = cancel_btn + + self._model = model + self._proxy_model = proxy_model + + self._asset_view = asset_view + + self._selected_asset = None + # Soft refresh is enabled + # - reset will happen at all cost if soft reset is enabled + # - adds ability to call reset on multiple places without repeating + self._soft_reset_enabled = True + + def showEvent(self, event): + """Refresh asset model on show.""" + super(AssetsDialog, self).showEvent(event) + # Refresh on show + self.reset(False) + + def reset(self, force=True): + """Reset asset model.""" + if not force and not self._soft_reset_enabled: + return + + if self._soft_reset_enabled: + self._soft_reset_enabled = False + + self._model.reset() + + def name_is_valid(self, name): + """Is asset name valid. + + Args: + name(str): Asset name that should be checked. + """ + # Make sure we're reset + self.reset(False) + # Valid the name by model + return self._model.name_is_valid(name) + + def _on_filter_change(self, text): + """Trigger change of filter of assets.""" + self._proxy_model.setFilterFixedString(text) + + def _on_cancel_clicked(self): + self.done(0) + + def _on_ok_clicked(self): + index = self._asset_view.currentIndex() + asset_name = None + if index.isValid(): + asset_name = index.data(QtCore.Qt.DisplayRole) + self._selected_asset = asset_name + self.done(1) + + def set_selected_assets(self, asset_names): + """Change preselected asset before showing the dialog. + + This also resets model and clean filter. + """ + self.reset(False) + self._asset_view.collapseAll() + self._filter_input.setText("") + + indexes = [] + for asset_name in asset_names: + index = self._model.get_index_by_asset_name(asset_name) + if index.isValid(): + indexes.append(index) + + if not indexes: + return + + index_deque = collections.deque() + for index in indexes: + index_deque.append(index) + + all_indexes = [] + while index_deque: + index = index_deque.popleft() + all_indexes.append(index) + + parent_index = index.parent() + if parent_index.isValid(): + index_deque.append(parent_index) + + for index in all_indexes: + proxy_index = self._proxy_model.mapFromSource(index) + self._asset_view.expand(proxy_index) + + def get_selected_asset(self): + """Get selected asset name.""" + return self._selected_asset diff --git a/openpype/tools/publisher/widgets/tasks_widget.py b/openpype/tools/publisher/widgets/tasks_widget.py new file mode 100644 index 0000000000..a0b3a340ae --- /dev/null +++ b/openpype/tools/publisher/widgets/tasks_widget.py @@ -0,0 +1,169 @@ +from Qt import QtCore, QtGui + +from openpype.tools.utils.tasks_widget import TasksWidget, TASK_NAME_ROLE + + +class TasksModel(QtGui.QStandardItemModel): + """Tasks model. + + Task model must have set context of asset documents. + + Items in model are based on 0-infinite asset documents. Always contain + an interserction of context asset tasks. When no assets are in context + them model is empty if 2 or more are in context assets that don't have + tasks with same names then model is empty too. + + Args: + controller (PublisherController): Controller which handles creation and + publishing. + """ + def __init__(self, controller): + super(TasksModel, self).__init__() + + self._controller = controller + self._items_by_name = {} + self._asset_names = [] + self._task_names_by_asset_name = {} + + def set_asset_names(self, asset_names): + """Set assets context.""" + self._asset_names = asset_names + self.reset() + + @staticmethod + def get_intersection_of_tasks(task_names_by_asset_name): + """Calculate intersection of task names from passed data. + + Example: + ``` + # Passed `task_names_by_asset_name` + { + "asset_1": ["compositing", "animation"], + "asset_2": ["compositing", "editorial"] + } + ``` + Result: + ``` + # Set + {"compositing"} + ``` + + Args: + task_names_by_asset_name (dict): Task names in iterable by parent. + """ + tasks = None + for task_names in task_names_by_asset_name.values(): + if tasks is None: + tasks = set(task_names) + else: + tasks &= set(task_names) + + if not tasks: + break + return tasks or set() + + def is_task_name_valid(self, asset_name, task_name): + """Is task name available for asset. + + Args: + asset_name (str): Name of asset where should look for task. + task_name (str): Name of task which should be available in asset's + tasks. + """ + task_names = self._task_names_by_asset_name.get(asset_name) + if task_names and task_name in task_names: + return True + return False + + def reset(self): + """Update model by current context.""" + if not self._asset_names: + self._items_by_name = {} + self._task_names_by_asset_name = {} + self.clear() + return + + task_names_by_asset_name = ( + self._controller.get_task_names_by_asset_names(self._asset_names) + ) + + self._task_names_by_asset_name = task_names_by_asset_name + + new_task_names = self.get_intersection_of_tasks( + task_names_by_asset_name + ) + old_task_names = set(self._items_by_name.keys()) + if new_task_names == old_task_names: + return + + root_item = self.invisibleRootItem() + for task_name in old_task_names: + if task_name not in new_task_names: + item = self._items_by_name.pop(task_name) + root_item.removeRow(item.row()) + + new_items = [] + for task_name in new_task_names: + if task_name in self._items_by_name: + continue + + item = QtGui.QStandardItem(task_name) + item.setData(task_name, TASK_NAME_ROLE) + self._items_by_name[task_name] = item + new_items.append(item) + root_item.appendRows(new_items) + + def headerData(self, section, orientation, role=None): + if role is None: + role = QtCore.Qt.EditRole + # Show nice labels in the header + if section == 0: + if ( + role in (QtCore.Qt.DisplayRole, QtCore.Qt.EditRole) + and orientation == QtCore.Qt.Horizontal + ): + return "Tasks" + + return super(TasksModel, self).headerData(section, orientation, role) + + +class CreateDialogTasksWidget(TasksWidget): + def __init__(self, controller, parent): + self._controller = controller + super(CreateDialogTasksWidget, self).__init__(None, parent) + + self._enabled = None + + def _create_source_model(self): + return TasksModel(self._controller) + + def set_asset_name(self, asset_name): + current = self.get_selected_task_name() + if current: + self._last_selected_task_name = current + + self._tasks_model.set_asset_names([asset_name]) + if self._last_selected_task_name and self._enabled: + self.select_task_name(self._last_selected_task_name) + + # Force a task changed emit. + self.task_changed.emit() + + def select_task_name(self, task_name): + super(CreateDialogTasksWidget, self).select_task_name(task_name) + if not self._enabled: + current = self.get_selected_task_name() + if current: + self._last_selected_task_name = current + self._clear_selection() + + def set_enabled(self, enabled): + self._enabled = enabled + if not enabled: + last_selected_task_name = self.get_selected_task_name() + if last_selected_task_name: + self._last_selected_task_name = last_selected_task_name + self._clear_selection() + + elif self._last_selected_task_name is not None: + self.select_task_name(self._last_selected_task_name) From 3878c5262a5293ed250c85a15be6aa5531da1da2 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 18 Jan 2022 17:22:57 +0100 Subject: [PATCH 04/74] added widgett for pre create attributes --- .../publisher/widgets/precreate_widget.py | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 openpype/tools/publisher/widgets/precreate_widget.py diff --git a/openpype/tools/publisher/widgets/precreate_widget.py b/openpype/tools/publisher/widgets/precreate_widget.py new file mode 100644 index 0000000000..7f0228946e --- /dev/null +++ b/openpype/tools/publisher/widgets/precreate_widget.py @@ -0,0 +1,61 @@ +from Qt import QtWidgets + +from openpype.widgets.attribute_defs import create_widget_for_attr_def + + +class AttributesWidget(QtWidgets.QWidget): + def __init__(self, parent=None): + super(AttributesWidget, self).__init__(parent) + + layout = QtWidgets.QGridLayout(self) + layout.setContentsMargins(0, 0, 0, 0) + + self._layout = layout + + self._widgets = [] + + def current_value(self): + output = {} + for widget in self._widgets: + attr_def = widget.attr_def + if attr_def.is_value_def: + output[attr_def.key] = widget.current_value() + return output + + def clear_attr_defs(self): + while self._layout.count(): + item = self._layout.takeAt(0) + widget = item.widget() + if widget: + widget.setVisible(False) + widget.deleteLater() + + self._widgets = [] + + def set_attr_defs(self, attr_defs): + self.clear_attr_defs() + + row = 0 + for attr_def in attr_defs: + widget = create_widget_for_attr_def(attr_def, self) + + expand_cols = 2 + if attr_def.is_value_def and attr_def.is_label_horizontal: + expand_cols = 1 + + col_num = 2 - expand_cols + + if attr_def.label: + label_widget = QtWidgets.QLabel(attr_def.label, self) + self._layout.addWidget( + label_widget, row, 0, 1, expand_cols + ) + if not attr_def.is_label_horizontal: + row += 1 + + self._layout.addWidget( + widget, row, col_num, 1, expand_cols + ) + self._widgets.append(widget) + + row += 1 From 9c6a57aa587fe7577d9214e55311029d36e34039 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 18 Jan 2022 17:23:37 +0100 Subject: [PATCH 05/74] creator can define precreate attribute definitions and allowing context change --- openpype/pipeline/create/creator_plugins.py | 26 ++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/openpype/pipeline/create/creator_plugins.py b/openpype/pipeline/create/creator_plugins.py index aa2e3333ce..8247581d94 100644 --- a/openpype/pipeline/create/creator_plugins.py +++ b/openpype/pipeline/create/creator_plugins.py @@ -80,7 +80,7 @@ class BaseCreator: self.create_context.creator_removed_instance(instance) @abstractmethod - def create(self, options=None): + def create(self): """Create new instance. Replacement of `process` method from avalon implementation. @@ -199,15 +199,22 @@ class Creator(BaseCreator): # - may not be used if `get_detail_description` is overriden detailed_description = None + # It does make sense to change context on creation + # - in some cases it may confuse artists because it would not be used + # e.g. for buld creators + create_allow_context_change = True + @abstractmethod - def create(self, subset_name, instance_data, options=None): + def create(self, subset_name, instance_data, pre_create_data): """Create new instance and store it. Ideally should be stored to workfile using host implementation. Args: subset_name(str): Subset name of created instance. - instance_data(dict): + instance_data(dict): Base data for instance. + pre_create_data(dict): Data based on pre creation attributes. + Those may affect how creator works. """ # instance = CreatedInstance( @@ -258,6 +265,19 @@ class Creator(BaseCreator): return None + def get_pre_create_attr_defs(self): + """Plugin attribute definitions needed for creation. + Attribute definitions of plugin that define how creation will work. + Values of these definitions are passed to `create` method. + NOTE: + Convert method should be implemented which should care about updating + keys/values when plugin attributes change. + Returns: + list: Attribute definitions that can be tweaked for + created instance. + """ + return [] + class AutoCreator(BaseCreator): """Creator which is automatically triggered without user interaction. From f0b7f72325ff51a9f7cf4681c2fa81c44562d18c Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 18 Jan 2022 17:25:34 +0100 Subject: [PATCH 06/74] creator dialog has context widget and creator's attributes --- .../tools/publisher/widgets/create_dialog.py | 202 ++++++++++++++++-- .../tools/publisher/widgets/images/delete.png | Bin 12343 -> 0 bytes openpype/tools/publisher/widgets/models.py | 201 ----------------- openpype/tools/publisher/widgets/widgets.py | 144 +------------ openpype/tools/publisher/window.py | 23 +- 5 files changed, 201 insertions(+), 369 deletions(-) delete mode 100644 openpype/tools/publisher/widgets/images/delete.png delete mode 100644 openpype/tools/publisher/widgets/models.py diff --git a/openpype/tools/publisher/widgets/create_dialog.py b/openpype/tools/publisher/widgets/create_dialog.py index 84fc6d4e97..05936265bb 100644 --- a/openpype/tools/publisher/widgets/create_dialog.py +++ b/openpype/tools/publisher/widgets/create_dialog.py @@ -15,6 +15,9 @@ from openpype.pipeline.create import ( ) from .widgets import IconValuePixmapLabel +from .assets_widget import CreateDialogAssetsWidget +from .tasks_widget import CreateDialogTasksWidget +from .precreate_widget import AttributesWidget from ..constants import ( VARIANT_TOOLTIP, CREATOR_IDENTIFIER_ROLE, @@ -202,7 +205,34 @@ class CreateDialog(QtWidgets.QDialog): self._name_pattern = name_pattern self._compiled_name_pattern = re.compile(name_pattern) + context_widget = QtWidgets.QWidget(self) + + assets_widget = CreateDialogAssetsWidget(controller, context_widget) + tasks_widget = CreateDialogTasksWidget(controller, context_widget) + + context_layout = QtWidgets.QVBoxLayout(context_widget) + context_layout.setContentsMargins(0, 0, 0, 0) + context_layout.setSpacing(0) + context_layout.addWidget(assets_widget, 2) + context_layout.addWidget(tasks_widget, 1) + + pre_create_scroll_area = QtWidgets.QScrollArea(self) + pre_create_contet_widget = QtWidgets.QWidget(pre_create_scroll_area) + pre_create_scroll_area.setWidget(pre_create_contet_widget) + pre_create_scroll_area.setWidgetResizable(True) + + pre_create_contet_layout = QtWidgets.QVBoxLayout( + pre_create_contet_widget + ) + pre_create_attributes_widget = AttributesWidget( + pre_create_contet_widget + ) + pre_create_contet_layout.addWidget(pre_create_attributes_widget, 0) + pre_create_contet_layout.addStretch(1) + creator_description_widget = CreatorDescriptionWidget(self) + # TODO add HELP button + creator_description_widget.setVisible(False) creators_view = QtWidgets.QListView(self) creators_model = QtGui.QStandardItemModel() @@ -235,6 +265,14 @@ class CreateDialog(QtWidgets.QDialog): form_layout.addRow("Name:", variant_layout) form_layout.addRow("Subset:", subset_name_input) + mid_widget = QtWidgets.QWidget(self) + mid_layout = QtWidgets.QVBoxLayout(mid_widget) + mid_layout.setContentsMargins(0, 0, 0, 0) + mid_layout.addWidget(QtWidgets.QLabel("Choose family:", self)) + mid_layout.addWidget(creators_view, 1) + mid_layout.addLayout(form_layout, 0) + mid_layout.addWidget(create_btn, 0) + left_layout = QtWidgets.QVBoxLayout() left_layout.addWidget(QtWidgets.QLabel("Choose family:", self)) left_layout.addWidget(creators_view, 1) @@ -242,20 +280,36 @@ class CreateDialog(QtWidgets.QDialog): left_layout.addWidget(create_btn, 0) layout = QtWidgets.QHBoxLayout(self) - layout.addLayout(left_layout, 0) - layout.addSpacing(5) - layout.addWidget(creator_description_widget, 1) + layout.setSpacing(10) + layout.addWidget(context_widget, 1) + layout.addWidget(mid_widget, 1) + layout.addWidget(pre_create_scroll_area, 1) + + prereq_timer = QtCore.QTimer() + prereq_timer.setInterval(50) + prereq_timer.setSingleShot(True) + + prereq_timer.timeout.connect(self._on_prereq_timer) create_btn.clicked.connect(self._on_create) variant_input.returnPressed.connect(self._on_create) variant_input.textChanged.connect(self._on_variant_change) creators_view.selectionModel().currentChanged.connect( - self._on_item_change + self._on_creator_item_change ) variant_hints_menu.triggered.connect(self._on_variant_action) + assets_widget.selection_changed.connect(self._on_asset_change) + assets_widget.current_context_required.connect( + self._on_current_session_context_request + ) + tasks_widget.task_changed.connect(self._on_task_change) controller.add_plugins_refresh_callback(self._on_plugins_refresh) + self._pre_create_attributes_widget = pre_create_attributes_widget + self._context_widget = context_widget + self._assets_widget = assets_widget + self._tasks_widget = tasks_widget self.creator_description_widget = creator_description_widget self.subset_name_input = subset_name_input @@ -269,12 +323,54 @@ class CreateDialog(QtWidgets.QDialog): self.creators_view = creators_view self.create_btn = create_btn + self._prereq_timer = prereq_timer + + def _context_change_is_enabled(self): + return self._context_widget.isEnabled() + + def _get_asset_name(self): + asset_name = None + if self._context_change_is_enabled(): + asset_name = self._assets_widget.get_selected_asset_name() + + if asset_name is None: + asset_name = self._asset_name + return asset_name + + def _get_task_name(self): + task_name = None + if self._context_change_is_enabled(): + # Don't use selection of task if asset is not set + asset_name = self._assets_widget.get_selected_asset_name() + if asset_name: + task_name = self._tasks_widget.get_selected_task_name() + + if not task_name: + task_name = self._task_name + return task_name + @property def dbcon(self): return self.controller.dbcon + def _set_context_enabled(self, enabled): + self._assets_widget.set_enabled(enabled) + self._tasks_widget.set_enabled(enabled) + self._context_widget.setEnabled(enabled) + def refresh(self): - self._prereq_available = True + # Get context before refresh to keep selection of asset and + # task widgets + asset_name = self._get_asset_name() + task_name = self._get_task_name() + + self._prereq_available = False + + # Disable context widget so refresh of asset will use context asset + # name + self._set_context_enabled(False) + + self._assets_widget.refresh() # Refresh data before update of creators self._refresh_asset() @@ -282,21 +378,36 @@ class CreateDialog(QtWidgets.QDialog): # data self._refresh_creators() + self._assets_widget.set_current_asset_name(self._asset_name) + self._assets_widget.select_asset_by_name(asset_name) + self._tasks_widget.set_asset_name(asset_name) + self._tasks_widget.select_task_name(task_name) + + self._invalidate_prereq() + + def _invalidate_prereq(self): + self._prereq_timer.start() + + def _on_prereq_timer(self): + prereq_available = True + if self.creators_model.rowCount() < 1: + prereq_available = False + if self._asset_doc is None: # QUESTION how to handle invalid asset? - self.subset_name_input.setText("< Asset is not set >") - self._prereq_available = False + prereq_available = False - if self.creators_model.rowCount() < 1: - self._prereq_available = False + if prereq_available != self._prereq_available: + self._prereq_available = prereq_available - self.create_btn.setEnabled(self._prereq_available) - self.creators_view.setEnabled(self._prereq_available) - self.variant_input.setEnabled(self._prereq_available) - self.variant_hints_btn.setEnabled(self._prereq_available) + self.create_btn.setEnabled(prereq_available) + self.creators_view.setEnabled(prereq_available) + self.variant_input.setEnabled(prereq_available) + self.variant_hints_btn.setEnabled(prereq_available) + self._on_variant_change() def _refresh_asset(self): - asset_name = self._asset_name + asset_name = self._get_asset_name() # Skip if asset did not change if self._asset_doc and self._asset_doc["name"] == asset_name: @@ -324,6 +435,9 @@ class CreateDialog(QtWidgets.QDialog): ) self._subset_names = set(subset_docs.distinct("name")) + if not asset_doc: + self.subset_name_input.setText("< Asset is not set >") + def _refresh_creators(self): # Refresh creators and add their families to list existing_items = {} @@ -366,25 +480,62 @@ class CreateDialog(QtWidgets.QDialog): if not indexes: index = self.creators_model.index(0, 0) self.creators_view.setCurrentIndex(index) + else: + index = indexes[0] + + identifier = index.data(CREATOR_IDENTIFIER_ROLE) + + self._set_creator(identifier) def _on_plugins_refresh(self): # Trigger refresh only if is visible if self.isVisible(): self.refresh() - def _on_item_change(self, new_index, _old_index): + def _on_asset_change(self): + self._refresh_asset() + + asset_name = self._assets_widget.get_selected_asset_name() + self._tasks_widget.set_asset_name(asset_name) + if self._context_change_is_enabled(): + self._invalidate_prereq() + + def _on_task_change(self): + if self._context_change_is_enabled(): + self._invalidate_prereq() + + def _on_current_session_context_request(self): + self._assets_widget.set_current_session_asset() + if self._task_name: + self._tasks_widget.select_task_name(self._task_name) + + def _on_creator_item_change(self, new_index, _old_index): identifier = None if new_index.isValid(): identifier = new_index.data(CREATOR_IDENTIFIER_ROLE) + self._set_creator(identifier) + def _set_creator(self, identifier): creator = self.controller.manual_creators.get(identifier) self.creator_description_widget.set_plugin(creator) self._selected_creator = creator if not creator: + self._pre_create_attributes_widget.set_attr_defs([]) + self._set_context_enabled(False) return + if ( + creator.create_allow_context_change + != self._context_change_is_enabled() + ): + self._set_context_enabled(creator.create_allow_context_change) + self._refresh_asset() + + attr_defs = creator.get_pre_create_attr_defs() + self._pre_create_attributes_widget.set_attr_defs(attr_defs) + default_variants = creator.get_default_variants() if not default_variants: default_variants = ["Main"] @@ -410,12 +561,19 @@ class CreateDialog(QtWidgets.QDialog): if self.variant_input.text() != value: self.variant_input.setText(value) - def _on_variant_change(self, variant_value): - if not self._prereq_available or not self._selected_creator: + def _on_variant_change(self, variant_value=None): + if not self._prereq_available: + return + + # This should probably never happen? + if not self._selected_creator: if self.subset_name_input.text(): self.subset_name_input.setText("") return + if variant_value is None: + variant_value = self.variant_input.text() + match = self._compiled_name_pattern.match(variant_value) valid = bool(match) self.create_btn.setEnabled(valid) @@ -425,7 +583,7 @@ class CreateDialog(QtWidgets.QDialog): return project_name = self.controller.project_name - task_name = self._task_name + task_name = self._get_task_name() asset_doc = copy.deepcopy(self._asset_doc) # Calculate subset name with Creator plugin @@ -522,9 +680,9 @@ class CreateDialog(QtWidgets.QDialog): family = index.data(FAMILY_ROLE) subset_name = self.subset_name_input.text() variant = self.variant_input.text() - asset_name = self._asset_name - task_name = self._task_name - options = {} + asset_name = self._get_asset_name() + task_name = self._get_task_name() + pre_create_data = self._pre_create_attributes_widget.current_value() # Where to define these data? # - what data show be stored? instance_data = { @@ -537,7 +695,7 @@ class CreateDialog(QtWidgets.QDialog): error_info = None try: self.controller.create( - creator_identifier, subset_name, instance_data, options + creator_identifier, subset_name, instance_data, pre_create_data ) except CreatorError as exc: diff --git a/openpype/tools/publisher/widgets/images/delete.png b/openpype/tools/publisher/widgets/images/delete.png deleted file mode 100644 index ab02768ba31460baedaaa4d965c6879e9781517e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12343 zcmd6Ni9gh9^zieY8AI8cTlTHcrYsp{XS$Kx78H_fr4U!hzLc*vN+{jP5-PVC*`mn$ zy=^KZZr7G9lWwZ9Crer8Jzw4T_r9O^FL?WW`iwbqp7We@p0hvC1?xQ)qDy6$B7{UO zcbM%(hys67kPsa{zJ;~^fDc;Wua>q#@GnZ}NF01$;=kiSAVR{+$^RHi&y)tBOpv)l z&^|wppwL4nj-t@eP>o~9eFEJN`5)ErJK>ozVkC>uN@Qua)ix}1xF@pw=zhCTS%+Fem>Z@nV6JYng@ zr7yNo%JYmK-H>fO3gb=T*+M2qyasvrZyfJB}If>%e#PM0$ zv1a!kX_R|Vl2Jjg6Ah#IWB!iA7lZ!Dh^e6Zq2B9h+3Q`BT8*f9kUV4j8X+7Lk2^nW z{ChyvfBo1Tr=~n&)7}CR^oFk7pGXMfcPWM!Q*RGf)54B>EZ9x{n%fSvRm`3$a>I$T zn0@i7x7+lDYA9h@x3Mo;RJ?ozBNRKOROveDs1vsVZ}1$*w%0WC{>!pW__E_NhB(~> zS6T=RiR9j3j2pKJUvYFp*3-)U>j^_#bA!vp^A&PoN6qHU%);jPb;x6RK8$gtnCt?V z*x%;1dzkzg!PqN7#j7M3N%Y>cH%hXM*E0G0CzW%T(oyhw<+`Oa%ej|$5As^KayO-Y zZ|9xc;m$;PhKztMW2d+yZ9X>3i?G+toJO{ka>C2@yAj`(&W&{(s-X8SWAuKpao&XT zHZaC_NKSuCO$^fH3KmGMN_fe@s~8L{N@yk>2wP@TN3Nu~-gAl5p&KIJ%g_(8^@+m| zi6nc?UuEMJQ1B|{J(vddb%9HK`a`KoPY)ND+GWSQLQrdb{P+{siXmIBOk4cr=ODDE z2HOQ+^Q7Zq6<3H=R`EMOT2ZesLOuObuI`nnukY}nFSqM!i<1W z?oHwh9vJfuRX8sg*7_ey)-jKaX{Kf$T$tTBhH>|Di{FSBFZV#5cRuQ#iI1@;o8i{G z4_{Qxm)nnxVhhW{j(WH_*JN30qu*`JqV>xU+a!e5#6N?K|PQEn_>=zJF?qPy2;R ztTBID8nyd2Da;9c~4#^qSLbubF$4 zj(>=Yi^pBj$lh8>%Qq=b)Hx~cpK0MG5u4Ouzm>`%$W+*gnqP>i-PO<|`LX_UB(5h|d8)m4S8PR^C6rc|zD_PN$xwwFdJ z%KdwY?2^h0Nvg+A6$#d@XY%hwtWwuPV}Cy6SI5lS6`LpPoIh<&=%Z>*l&1IUp zbG5RjbF1?OE2zD)3{N}FT*qk)g)Q;lI;pH`dHa#n*!j56KYBHs1@X8_{F(2`)s`p2 zrQ_vlf(zamBSwJQ*nXmi-Jxu$Rw^~abD5@o>&C*cQ!_jFHt!KQRT{yts~SRPPfx~( z_t(y^wj3*FP6W5bOCKy&z@@mcAlv(TJI$P5LluBLb1cBkV$xC7vS}uT6BRkB{Jhm& zkQ+Pp#5K9RJvz^Y=&a%at>fH%gfF?J_bZG$lJ@-q@7$$7E5wLrGw(Gm9sLBy%6aCO z@+;6-E>B=ba(Y{vrJc@3B{vZA|) znfyB^pM-hHp%VBWI2Ivkkzc@>dW!%X zEuz5P8U7ee9?_Rm436%ZZt)uZFLa^3;2sLliVQ939Hv`G%)YcPQ1TEOkaPj z1YYP@)3T|(2P)4VxIw?Z8+ql-^CQ#J&P{?*Uy~~w6)`F)S@^AK4YKZA2!-{c#StP} z8ULWbrRZApAB_Pds3>L=@%tVsM;Xj3jZhIz9dmrgPu59)CE5{sc#S)LfQEQ}3m-0Wr(iSe1|+U_ul|>-;;6M^QIHP> ziqu^TI)oF2buq)2?=UM&*f9c%A8+2VcXWYL8ErFMOx0M= zKKWP#y$jtk_V?o-$+?c#vbV1N{f!D*v(T8Ty1Oga^voSa^n3lzWOnx&<<~_nPeXPa zqi&~KWVyFv&8)u8B=X-jNl~?Qes{1IAJ#@YlFN;CJv}~ddb<2Dq={pZYi5U)L{PG- zZ$}+ZATuss5O22CWF@y2T1L}>)SL~uy64A-|9-5n``;_QY?Q6hnm4B8eNJR^OleB;Jtwj<1!(Aog&JV~X=!;#Kp7JE+r~T~?UwE6zL- zUE~rA0o>GZQat+lRzdFNxG>!@(YC?Ms!d&c>01A7PX)<@n14ApBd`j5H<w`otP5Z{T3Qn{6u26e6iBgWI>(Vugu{;JgwsN82fB{Sx$!U?DS zz>soCiJscb3T^SSZ(stI^0e60bBaaThk_6}1LQETlbCQCpq=*g5~v)XAlt z)qn9#Vw$mRx6=I4<&Dw&KhjbYDr!Pxko`tw4FN?*>mU7`sNGwgEtQo`=uzQYzr-FH zm|e=-(>r8^t(bAL>3JvFc1<;}nr`PDxV9OUL}Y8SBQtJQB^yXF?xMR=*L2bES24HA zA+&?HyG`oy{LEN|FB9F%!dQF#*hQwtaA~v$$K0N2Ptdtlx4tG~ zs&?xP1*~mDB}LE^e# zGjDwjStKS6WmK(RMtXDdQ!!%6CM5Et8vBiB-WL3c$LV&pjg$Qp^99h&yt>fFwZb8$l4EaFjPbR@n3x1#bdr|p;0@RNjiK-9)C9gLKx*KoDD z_c=9nCw!^nLR>T8;SlOP9jB*IDLv!DT_t~;DZ$7_y;zMAv(LD9>0M1_MKL2rn7n_3 z`&{;LQd}t2kLGeM?e%`$^~xinbIZp3xf_zkqf;2;hqw|OPu26a+kempmf#mo(6mG> zP{uNbp-R6#@sTK|h<}_ZemQ~PMXB4L&MNoYJSjfW1$ihgOlquw5I->_9_5zzY$X2fd6J&OOaRwUrGL=AsxmDuE?PVa zRmMGwowXmLWj*Vko~^Vi_B|4U*1SSmm)KGR#~7v6c~f`HpH`q$%JhN1k|NiP^~UM> z2$=dvrZk@oV~!0;%vA;+2y&_mT!h^y=)+tnnI}%0j))P1D*a#9*4@`0!LF~P5=eVO zmOF6k>+VoYxqlOJ&>`xH(=|bqYWB3yeulaB*jv%?(?Nn%54Mo+}l zRpM&wkGG9Y>H9t?;uo}$NW)2FK^DcMlx-&WXKuxXy}?cEk2Ui9>ivjc?qbD>aSGIS zFMBg1G;;;pnMs?oH;a0UZ$8fza=QiQyb0Z#JmPk#>4@gVIHpD3KYtt@3yHMS>Wi05B@YQ8#?~J6Vn@_NQO?yHBKiw6i8Ufl(s)2RJPyiIDKKG09Q&#T9bbL~Nhf05l2X6Uz~Z=>A6I-*F2osb>aF-^Ta`Yeq-NhobCuK^ zuXY!)i*#qT1O04<-)ey#7{sAIC+mqAfz1U@4%QQY!)JHWc>TvL(<|pOtwwC_6e>N&&nOaoBpY4)UD1h7bj{9wJoHZ8tGIgU(;b5CjKCiY+ z0&ER-%w$V_KG4W)EX?a#WfXh&o^N~6YhGd@?@ZWUhkb2SOJB29jEso@8Q6oYRI-W^xv6WGtRP-+(YyH~ET-cERQwK`Js*A2!(Lvc_u~EKX!%UfuG9ZR zIG-IMy18e;^{Wu~DRB336LF5+w2O{ztkXq`85U^mYoxW&0tts89XmSiK0zZE(bg{# ze#Ib4WzZTxxyP2`t!MoGrqI7uq2$ghF{0G&tQf^P1Kih_ zSho^(wX#EAC#fr?k;h+1OKeeF#&*Rw)(0UYx*nB|2k23NUW7abUF#l!J?d(sU?SS+ z(h~-bvHtlW6I6{jXQE8H5=3-mNYRCddc;aEuX2 zaH~hJh|@mXx@((QZ58RpqQP5r)DzK`0U@_FHCl;xr*GpOlmphfd9!Qo9s|{HvRGVY z)ggzaTAAOgx)6)8-n|DgLXgK}q@|cdsS;=X(+>dfyd_j3EJ6t*CG8jDu49xg*DK4b zQNSgb=+fOm1_1+_eS0UXj)l|w#o|wHb~i*$cGjWopxpq{s?5xut|y9aeQgRsdDU4_ ztC-@FZCUC-a|lTz9R<5#zFca<`GX(ngv=&%slgb5$g#ux1R%E^Xp~Y(%dEuwN#33U zZ_|s*;Kct!$p5XRTIH~n&G2m)2}%4E8WyU&2w_jwcN%;usMBD3r6ktwMiysscXAE>dyja55lZqyxZY8Ji;lYjmYU0k~R_pI{74&bH16{;-OCgVSWU-dpw+r zOw*wfGxAt#2{otb1c*J%mjQQb79+K~1p-&Zag@0VP$K%^_^k)!v3s8AItds;t#F)W z{|CT!Y58PkwxZ1h%&-tlJ1Y`-Kp?1NOMTnJ<$$ATqrBim)Lur_+D6B(sQXPGnB4An zNW@wKh3I}WGkeekyTPGqqt?$;>)bp>s8dqcDui=D_L3}>MfjNNB3n-Y5p3`UvVL+E zZ5BaYm)IQ_RB))pspR4iTFDV)-8h8gSHYaaQv!4>LgN0E=?N-nf7=>mFHftpwyuz) zt-6S2cc)W8`34Eevol6loOX)EF|I4~H|1^!VB9sVvcHQt;0yw#E|+ zU^43LlRMc(Kqf{8dFxR~O6uc^Xwc4Cw?>d4M9^kXE{PA0V+_uI6y@1WJ~r8`eB91< zb_X3jc!fym(zMZv7aUEBuEaIJo5G;!0we4{cK!J1{U?0*f{^Qk z0R%-KJ7>+JCXQUZcj%M&LpQQ4PzSactIpp&RzfX-`Hu_}wSEbKL}J+^02_SBk2qQ0 zg^kgOOEQS}&4_|mA+8BhNNT1yG%iO>50v-Mgb?Z$%G&}q2Wgx{v#lkX9Ze=`(lM4g zSX>I22?tq!`i-~c@dGWo7RoaRBe_r20tZ)43rCggyc&$vbzKF2(7gzB?8%}*+<0zg zhVFv90tL*CM#mk&JwU>ZcT1(OB&f#>3iFPi|4F*w(`_6SeFsW}p0B;quqjE~(U^=a zd7HD4-mhkvyLx7yAuS4(rEY;fFwtiRP``a!aQ_|7@7gPx60n?JbhYja_X^sQJ^vcyFb{$l3?|35X1cpmW-RO2MHBMmDwrxB?@<+s2pl5ZDt2^VY?U zxAC+`N}c;{do}Pa5cI)GQWWqj(ufzn!XJ3>g~snc+~%vKNM0)R|IJhf?C=uhqyXO+ zDl!9kH5624Ze?^=v|| zkaxfe67(o~obSt(P zv$)ycY?tL7o&yje8{E-n9LsUBYaA?(>vXoAz05||58mz^K0)PzBnECMFLZNBeO}0< z2{J_9=P);QL!_XERy1;Q`yw%0=Q$B%kiHhRYoj0nwVZburF#jo3Q5Doa;S8C%eOAb z?RgTQhHh#LMrFxG7%u@&+W;y*D!7ONG4d#C`FjX$G=F-G)wTrUT$~8<{XBUbx5L~* z&4$$2gS6{2ndx7gX}E zG)vu|<`3Qm1;v(c24wQ+;tFv~*n?1{9syYAqJ}I^(EJ_Rg8x#%RhY06iY^64TQNq( z9RXR(0^P`~oAJ4+_C1T1xzBcX*?({jQA`$E z-Z3ip6A*d{m1PJ?LmPeGk%+_sX^VgeJ#whEQpjS*axFKTzF1)8u#v@{I+-OR&9d}xE3t3JI_?8WJ-tv$M? z51xsUzZx7yUOPkGan3HD#@R#+0)>h`<#QaCqkfzwpQ?aBGb(SfMF3>>x7af19+N?L zi_28-)l^(f2H`LeS)8pb1;s#61;xO+ZLet|lC8VBuTEF>fKLAGK-@JfI|$R(!3ve^ z2X~dH9;22NHiH$6AiMqsjmjtfjZJ{arg9b0Bve7CEs&u*@K;QhscLUAhcO{HPcS&L zu0bu2;yMK~_uBTN60T4V$+4Z^S*CLTzqh);YHzSRh~0~|fqMY0MTW{cScl}-v7H}@ zLu^!g$QOsx1?aYv>1V|T;s^D~ztd#11 zT>*a$g1RH=B#dQ;<$z6KIZ#_neGAiNQE|3yEj^vQ1<5BMF)Cm`7guBU5T_c2vwuKz zxyhTa*JVyiwvA+AImSH+C`Fv|mW)-bK6z|o=fdb^5-fnPZa{1p4g7^#R#91z5k_>l zfp3FQ#)aZq1~?#9jn_f$D4{N5uzQy+));gu4$0O*3kAJEEm`c8PBHG#qFO}B<^_kf zvRBh|ZKe-(ez0Lt7dNdG%-II6Hd#q3XlWvn99mqwW|Xd{_!C1K85}`gS3{}tNmz~_ zV8~-6`8ALcHlZLjUJLL2Q^Ykb+ zN|jYPMJaHWJWw@smbZ=z!z%*uJn}8TmQQ@)qr-d-6h&YmYKA2JZ;(NR?M5R%@t?sW zD8U*~i>4tG&O)CdeeYIWWXjbpdbWKJl!gXJk=MSY22@ZdA%lJ#6?FSc1-}7-C|?bA zt0_;dXe;_*Uv8)zBGG0K1^#ITd=F^kkF*YouH-e%N75UU%zK<{6EBw)A29h{97 z1%gC!Hh~f5MKsHyi=h6GmiV|d`f&s~j7huQ1+)38N`#4^lduRZav%8VWY{mDO>&Vx ztpzHPYA8H_@w+4Boq=qgfxri$9Ef|)keh+fzd|`9^QVG6Ml{)ls{tAEIjBCnY7}wj z>V1G5R4+z!+(ZUt@p1GbSWBiLtP*thluja&!D|EDMp!UA^>CqqbKOKsGY>aM!5>XY2V^=V=g<%trVGBY)&kKf3qOo&p$d2(L z2<%UD6U>RE zl<#L&zj^hD5&xH#ihr`hDHea03A5z(%Xq6T7R-H=zd3LXG9V>4M%XF_(WCXm{X zpzG-8R!>ABRvkjuDd0S?^Ap5nu*k2|FbY5|Nkvv@V>r#4jxWjkjS~s834!1Ojbs?$ zw%+QJg{W_V!0~E0HL{hD^5#BEUEp+!56M-JBs=3K(vUBq^OiW8B%r|_lxA%^L9?Fj z4H0K;6G8uQw-Y2&Zi0juu7!4;v%ne-q0eV90<9E5``%kFvdk4C7>mFDl%OS85M~vE zd)BM@3FfS#0IW?T!>Aj8VcSw2SzP>F<}iR$S=-qpOuER+ZfcV0r;n0D>*ofBB*c z1;w`fA5-<3OmS%L(*J`WQ-Qv7+n3sT@kCS(=aQI}NRGDtVAlt17>@R*<*cR>K~UH9 zj>L7^*&h7x`3H>!Wwx`BHqv>Hv=n-VuooOToE>@ooxt@9klAj6|8s6*K!=szbfA~; z+eOF22T#(tbFQw3$t@OrLG<<@=?lR$Knr409JG;_P$Jo?$pRZz%)wf;@geKQO@&8^14HUjZ%NQ6` zYQ3msCE)2%q+zDe8v(;y(V=yDk;^LCIYq}~fTTPo(u}nHdSEQ$!*@+f6O8vB1jit! zK4CCIa5Pyu{Vz^@S1e>c!?_>WP2T(bgWpbLZP8mXI~dZ7`~j zYFwDp*=Q=JrL~?6gzI&y+E7v*&}T2dKW9DkrIdhyh}xtg_`Vmg^9}ALfz5Dm6R<+K zp!gQ{i(42>tM2w1LO3cvkGVw{EzvSEL=&x%2y_I5$Uz;sh8IFx#)!lZk}bLp+?5z7 zqVv$w-pzvgdYG@d<%E=(FBq^fOvpi_FOinXC%z~QjgunL`HF(Pkr2CXt^E7&G4I@H z0sVOgousXZzke{6;Jbl+%1S+|#Miv7@4>mgs}|@%BCrx6i$&eaS+h$MIrSds8D{^e zwy#Z0f>%lgbo@(x#I_sGW0x}6-$+l%xz+As9#IP+rgIhS*^uf z^iS08PjDJNtKNK|{^-B=3qdAF4@Kl+c;aoTYd!RqtU)-p{JU3?AI*fhw{Sy@t4w}7 zdtT&&LgVZ_XYSn<@4_yt((8>$?`zY(r>eA7tqwuupp5h?{Us&xR3p#a6Pm9$gBI)u zd(*zJ;so_6K zY<5Xbi#GO8xM_U#z15z%QO+Ef*t})6atP*0&bV}7n!4L~7}NXL5Kj{SR#q&KRo?BU ze<1C90QZ7O=!yOtM3Tt2G7ItD<$XEJpt1jQK#_Xd+ z8Lxd9+HW8!x1gAjrrzCr>ZA6AI6iygaKpN3%#`lb$&EDyXKZi-PDZvPi&q>t79DQy z#*iSthw8OTm9&}XoG9)A-lZ`kwbs zf793!o%xl{{gdcnPBh3Z7{A3@&cp34>)o4=LR_!Lvd?`Ch9@Rf(y8Jf$`#w#UL`dn zJr+u2Q|mL*_ODQ{*yT~j2y-{q$h)*BNN#N7j&;y#g@+ESURb%`^^J)$#v zxTlC(hnhRd&qlv6iN5up4GBThqc7;-}otRm07DxpC+Q_MjsE98_7rYYHBPoA-yGPMHTQU^;Ns z;_Tj|#P^zB&)#q>Ub+7vp%DLSzw_;KOK?$kmBOG(Jny%zDnIpm^M60?>LT+%Azd0P*$d8ef}An*pwn;#m!E7_h>zNGQPr9LOyQz^Qg>2mOcT`)qY z+`8 z4Lv3F`8~1EP+>qFaPTNXVaLpDN3>Id&c;i| z)VM+Jh&j9-3&mqsXnuqn^!zYUQh@SW;k;9nw_k{A<^C_v1}|4V=>B8Yg&WZ3gZ08& zN?&l+$J!J72qpVss@}P0dfYZfKq~Lqj@r051@al?8Dc&@HSh&L-v!^&fV57k*S^gX znmcJ$qpCdOR4aX~2-?QDuwUX0PcO*&+m9!UeJ|tOtFgH7kZ8cHoXj#soWwHs)uxC> zNrwrKDM~hH)XP_DpZwc0<6(Das31IQt(Wp&6@TzVw#%a;_nE&qbJuw0UV$*;TE@_% zXW7+?!Al+C?p4fshuUSni7I$_SU5bu2_D^iYQ`!a?wQC3B-wVw+xB*xdJuti$x?}^ z@^TsLy{;OKoM~IlUk^fXOzJyQ`uCpX=TrOORcX5n@=#_LKS{uopHCm>b`(h6ESy+D zaLk?_bdX=3oO`oJB+A!gA$aoF^576O@JWWKh-s+ShPpVg6K%yO~%H&;E`{)(J(qdz`9_SY;3ZyT!-t!%b0L zDZHRuGrWd-niFLKj6ntBp~3W{X;7lJSL6;G2t~m=zlp=>Gt0w;>V)Rp;Wf|hH%#Wl zX5hnH1{qvQ+mDhc3xASiKAubaz7ycQM}j#_MnE*zm(XwXxzbvb>M_6sc@A}ApLcnj z5~?&ETL5{y+Y^X?=EkyhsjOJ-iL1o6m{j{>^Syy4Vn%vQSNqy!qKypJC*}TXJQa%s z3G%x$@aU^)`}b>_Jt?EMJmN%2_?!420FJKdBO|HG7vlU=o!ByXU1<=%hX@5)Z}Kz* z>kP@arppo<#c+tiKFkSALKpQ8ZA-7;5Thh8@;){?dkA@LV~qQA>#5>JF7dh7s^~KZ zxX;KJrH5@BU}AhRPWS*VCfW`jqOScnf-8k*zvL9KrEW(+82Qc22n!R77d?}hnEPc$ zimMxw{c6`JjSW?m*G}dBMqD_i0rf4-w5e9Ml$#0UHW8}{LG1~*@rc%ya0jHW98y|& zv&B7yKXRa2Isaf}jOpR=oBRRJT+n!g4hDD5yUe;J^u#NleC-=fni-8<@XX%2(zi(z rp1^NN{L!q!pS6II-hB!0q#(k*5NUNf0pKZ%!+<>JN>@^>Ma{6 diff --git a/openpype/tools/publisher/widgets/models.py b/openpype/tools/publisher/widgets/models.py deleted file mode 100644 index 0cfd771ef1..0000000000 --- a/openpype/tools/publisher/widgets/models.py +++ /dev/null @@ -1,201 +0,0 @@ -import re -import collections - -from Qt import QtCore, QtGui - - -class AssetsHierarchyModel(QtGui.QStandardItemModel): - """Assets hiearrchy model. - - For selecting asset for which should beinstance created. - - Uses controller to load asset hierarchy. All asset documents are stored by - their parents. - """ - def __init__(self, controller): - super(AssetsHierarchyModel, self).__init__() - self._controller = controller - - self._items_by_name = {} - - def reset(self): - self.clear() - - self._items_by_name = {} - assets_by_parent_id = self._controller.get_asset_hierarchy() - - items_by_name = {} - _queue = collections.deque() - _queue.append((self.invisibleRootItem(), None)) - while _queue: - parent_item, parent_id = _queue.popleft() - children = assets_by_parent_id.get(parent_id) - if not children: - continue - - children_by_name = { - child["name"]: child - for child in children - } - items = [] - for name in sorted(children_by_name.keys()): - child = children_by_name[name] - item = QtGui.QStandardItem(name) - items_by_name[name] = item - items.append(item) - _queue.append((item, child["_id"])) - - parent_item.appendRows(items) - - self._items_by_name = items_by_name - - def name_is_valid(self, item_name): - return item_name in self._items_by_name - - def get_index_by_name(self, item_name): - item = self._items_by_name.get(item_name) - if item: - return item.index() - return QtCore.QModelIndex() - - -class TasksModel(QtGui.QStandardItemModel): - """Tasks model. - - Task model must have set context of asset documents. - - Items in model are based on 0-infinite asset documents. Always contain - an interserction of context asset tasks. When no assets are in context - them model is empty if 2 or more are in context assets that don't have - tasks with same names then model is empty too. - - Args: - controller (PublisherController): Controller which handles creation and - publishing. - """ - def __init__(self, controller): - super(TasksModel, self).__init__() - self._controller = controller - self._items_by_name = {} - self._asset_names = [] - self._task_names_by_asset_name = {} - - def set_asset_names(self, asset_names): - """Set assets context.""" - self._asset_names = asset_names - self.reset() - - @staticmethod - def get_intersection_of_tasks(task_names_by_asset_name): - """Calculate intersection of task names from passed data. - - Example: - ``` - # Passed `task_names_by_asset_name` - { - "asset_1": ["compositing", "animation"], - "asset_2": ["compositing", "editorial"] - } - ``` - Result: - ``` - # Set - {"compositing"} - ``` - - Args: - task_names_by_asset_name (dict): Task names in iterable by parent. - """ - tasks = None - for task_names in task_names_by_asset_name.values(): - if tasks is None: - tasks = set(task_names) - else: - tasks &= set(task_names) - - if not tasks: - break - return tasks or set() - - def is_task_name_valid(self, asset_name, task_name): - """Is task name available for asset. - - Args: - asset_name (str): Name of asset where should look for task. - task_name (str): Name of task which should be available in asset's - tasks. - """ - task_names = self._task_names_by_asset_name.get(asset_name) - if task_names and task_name in task_names: - return True - return False - - def reset(self): - """Update model by current context.""" - if not self._asset_names: - self._items_by_name = {} - self._task_names_by_asset_name = {} - self.clear() - return - - task_names_by_asset_name = ( - self._controller.get_task_names_by_asset_names(self._asset_names) - ) - self._task_names_by_asset_name = task_names_by_asset_name - - new_task_names = self.get_intersection_of_tasks( - task_names_by_asset_name - ) - old_task_names = set(self._items_by_name.keys()) - if new_task_names == old_task_names: - return - - root_item = self.invisibleRootItem() - for task_name in old_task_names: - if task_name not in new_task_names: - item = self._items_by_name.pop(task_name) - root_item.removeRow(item.row()) - - new_items = [] - for task_name in new_task_names: - if task_name in self._items_by_name: - continue - - item = QtGui.QStandardItem(task_name) - self._items_by_name[task_name] = item - new_items.append(item) - root_item.appendRows(new_items) - - -class RecursiveSortFilterProxyModel(QtCore.QSortFilterProxyModel): - """Recursive proxy model. - - Item is not filtered if any children match the filter. - - Use case: Filtering by string - parent won't be filtered if does not match - the filter string but first checks if any children does. - """ - def filterAcceptsRow(self, row, parent_index): - regex = self.filterRegExp() - if not regex.isEmpty(): - model = self.sourceModel() - source_index = model.index( - row, self.filterKeyColumn(), parent_index - ) - if source_index.isValid(): - pattern = regex.pattern() - - # Check current index itself - value = model.data(source_index, self.filterRole()) - if re.search(pattern, value, re.IGNORECASE): - return True - - rows = model.rowCount(source_index) - for idx in range(rows): - if self.filterAcceptsRow(idx, source_index): - return True - return False - - return super(RecursiveSortFilterProxyModel, self).filterAcceptsRow( - row, parent_index - ) diff --git a/openpype/tools/publisher/widgets/widgets.py b/openpype/tools/publisher/widgets/widgets.py index 073e5f4bc2..3af59507ca 100644 --- a/openpype/tools/publisher/widgets/widgets.py +++ b/openpype/tools/publisher/widgets/widgets.py @@ -10,11 +10,6 @@ from avalon.vendor import qtawesome from openpype.widgets.attribute_defs import create_widget_for_attr_def from openpype.tools import resources from openpype.tools.flickcharm import FlickCharm -from .models import ( - AssetsHierarchyModel, - TasksModel, - RecursiveSortFilterProxyModel, -) from openpype.tools.utils import ( PlaceholderLineEdit, IconButton, @@ -22,6 +17,8 @@ from openpype.tools.utils import ( BaseClickableFrame ) from openpype.pipeline.create import SUBSET_NAME_ALLOWED_SYMBOLS +from .assets_widget import AssetsDialog +from .tasks_widget import TasksModel from .icons import ( get_pixmap, get_icon_path @@ -307,143 +304,6 @@ class AbstractInstanceView(QtWidgets.QWidget): ).format(self.__class__.__name__)) -class AssetsDialog(QtWidgets.QDialog): - """Dialog to select asset for a context of instance.""" - def __init__(self, controller, parent): - super(AssetsDialog, self).__init__(parent) - self.setWindowTitle("Select asset") - - model = AssetsHierarchyModel(controller) - proxy_model = RecursiveSortFilterProxyModel() - proxy_model.setSourceModel(model) - proxy_model.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive) - - filter_input = PlaceholderLineEdit(self) - filter_input.setPlaceholderText("Filter assets..") - - asset_view = QtWidgets.QTreeView(self) - asset_view.setModel(proxy_model) - asset_view.setHeaderHidden(True) - asset_view.setFrameShape(QtWidgets.QFrame.NoFrame) - asset_view.setEditTriggers(QtWidgets.QTreeView.NoEditTriggers) - asset_view.setAlternatingRowColors(True) - asset_view.setSelectionBehavior(QtWidgets.QTreeView.SelectRows) - asset_view.setAllColumnsShowFocus(True) - - ok_btn = QtWidgets.QPushButton("OK", self) - cancel_btn = QtWidgets.QPushButton("Cancel", self) - - btns_layout = QtWidgets.QHBoxLayout() - btns_layout.addStretch(1) - btns_layout.addWidget(ok_btn) - btns_layout.addWidget(cancel_btn) - - layout = QtWidgets.QVBoxLayout(self) - layout.addWidget(filter_input, 0) - layout.addWidget(asset_view, 1) - layout.addLayout(btns_layout, 0) - - filter_input.textChanged.connect(self._on_filter_change) - ok_btn.clicked.connect(self._on_ok_clicked) - cancel_btn.clicked.connect(self._on_cancel_clicked) - - self._filter_input = filter_input - self._ok_btn = ok_btn - self._cancel_btn = cancel_btn - - self._model = model - self._proxy_model = proxy_model - - self._asset_view = asset_view - - self._selected_asset = None - # Soft refresh is enabled - # - reset will happen at all cost if soft reset is enabled - # - adds ability to call reset on multiple places without repeating - self._soft_reset_enabled = True - - def showEvent(self, event): - """Refresh asset model on show.""" - super(AssetsDialog, self).showEvent(event) - # Refresh on show - self.reset(False) - - def reset(self, force=True): - """Reset asset model.""" - if not force and not self._soft_reset_enabled: - return - - if self._soft_reset_enabled: - self._soft_reset_enabled = False - - self._model.reset() - - def name_is_valid(self, name): - """Is asset name valid. - - Args: - name(str): Asset name that should be checked. - """ - # Make sure we're reset - self.reset(False) - # Valid the name by model - return self._model.name_is_valid(name) - - def _on_filter_change(self, text): - """Trigger change of filter of assets.""" - self._proxy_model.setFilterFixedString(text) - - def _on_cancel_clicked(self): - self.done(0) - - def _on_ok_clicked(self): - index = self._asset_view.currentIndex() - asset_name = None - if index.isValid(): - asset_name = index.data(QtCore.Qt.DisplayRole) - self._selected_asset = asset_name - self.done(1) - - def set_selected_assets(self, asset_names): - """Change preselected asset before showing the dialog. - - This also resets model and clean filter. - """ - self.reset(False) - self._asset_view.collapseAll() - self._filter_input.setText("") - - indexes = [] - for asset_name in asset_names: - index = self._model.get_index_by_name(asset_name) - if index.isValid(): - indexes.append(index) - - if not indexes: - return - - index_deque = collections.deque() - for index in indexes: - index_deque.append(index) - - all_indexes = [] - while index_deque: - index = index_deque.popleft() - all_indexes.append(index) - - parent_index = index.parent() - if parent_index.isValid(): - index_deque.append(parent_index) - - for index in all_indexes: - proxy_index = self._proxy_model.mapFromSource(index) - self._asset_view.expand(proxy_index) - - def get_selected_asset(self): - """Get selected asset name.""" - return self._selected_asset - - class ClickableLineEdit(QtWidgets.QLineEdit): """QLineEdit capturing left mouse click. diff --git a/openpype/tools/publisher/window.py b/openpype/tools/publisher/window.py index b668888281..642bd17589 100644 --- a/openpype/tools/publisher/window.py +++ b/openpype/tools/publisher/window.py @@ -33,7 +33,7 @@ class PublisherWindow(QtWidgets.QDialog): default_width = 1000 default_height = 600 - def __init__(self, parent=None): + def __init__(self, parent=None, reset_on_show=None): super(PublisherWindow, self).__init__(parent) self.setWindowTitle("OpenPype publisher") @@ -41,6 +41,9 @@ class PublisherWindow(QtWidgets.QDialog): icon = QtGui.QIcon(resources.get_openpype_icon_filepath()) self.setWindowIcon(icon) + if reset_on_show is None: + reset_on_show = True + if parent is None: on_top_flag = QtCore.Qt.WindowStaysOnTopHint else: @@ -55,6 +58,7 @@ class PublisherWindow(QtWidgets.QDialog): | on_top_flag ) + self._reset_on_show = reset_on_show self._first_show = True self._refreshing_instances = False @@ -117,12 +121,16 @@ class PublisherWindow(QtWidgets.QDialog): subset_view_btns_layout.addWidget(change_view_btn) # Layout of view and buttons - subset_view_layout = QtWidgets.QVBoxLayout() + # - widget 'subset_view_widget' is necessary + # - only layout won't be resized automatically to minimum size hint + # on child resize request! + subset_view_widget = QtWidgets.QWidget(subset_views_widget) + subset_view_layout = QtWidgets.QVBoxLayout(subset_view_widget) subset_view_layout.setContentsMargins(0, 0, 0, 0) subset_view_layout.addLayout(subset_views_layout, 1) subset_view_layout.addLayout(subset_view_btns_layout, 0) - subset_views_widget.set_center_widget(subset_view_layout) + subset_views_widget.set_center_widget(subset_view_widget) # Whole subset layout with attributes and details subset_content_widget = QtWidgets.QWidget(subset_frame) @@ -249,7 +257,8 @@ class PublisherWindow(QtWidgets.QDialog): self._first_show = False self.resize(self.default_width, self.default_height) self.setStyleSheet(style.load_stylesheet()) - self.reset() + if self._reset_on_show: + self.reset() def closeEvent(self, event): self.controller.save_changes() @@ -382,6 +391,12 @@ class PublisherWindow(QtWidgets.QDialog): context_title = self.controller.get_context_title() self.set_context_label(context_title) + # Give a change to process Resize Request + QtWidgets.QApplication.processEvents() + # Trigger update geometry of + widget = self.subset_views_layout.currentWidget() + widget.updateGeometry() + def _on_subset_change(self, *_args): # Ignore changes if in middle of refreshing if self._refreshing_instances: From 2d7521289a088e4bf3f15f573be42b78ee1dd81c Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 18 Jan 2022 17:25:51 +0100 Subject: [PATCH 07/74] ui attribute definitions are skipped for storing data --- openpype/pipeline/create/context.py | 3 +-- openpype/tools/publisher/control.py | 4 +++- openpype/tools/publisher/widgets/widgets.py | 13 +++++++------ 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/openpype/pipeline/create/context.py b/openpype/pipeline/create/context.py index 7b0f50b1dc..f508e43315 100644 --- a/openpype/pipeline/create/context.py +++ b/openpype/pipeline/create/context.py @@ -94,6 +94,7 @@ class AttributeValues: attr_defs_by_key = { attr_def.key: attr_def for attr_def in attr_defs + if attr_def.is_value_def } for key, value in values.items(): if key not in attr_defs_by_key: @@ -306,8 +307,6 @@ class PublishAttributes: self._plugin_names_order = [] self._missing_plugins = [] self.attr_plugins = attr_plugins or [] - if not attr_plugins: - return origin_data = self._origin_data data = self._data diff --git a/openpype/tools/publisher/control.py b/openpype/tools/publisher/control.py index 860c009f15..a94fe34e79 100644 --- a/openpype/tools/publisher/control.py +++ b/openpype/tools/publisher/control.py @@ -605,7 +605,9 @@ class PublisherController: found_idx = idx break - value = instance.creator_attributes[attr_def.key] + value = None + if attr_def.is_value_def: + value = instance.creator_attributes[attr_def.key] if found_idx is None: idx = len(output) output.append((attr_def, [instance], [value])) diff --git a/openpype/tools/publisher/widgets/widgets.py b/openpype/tools/publisher/widgets/widgets.py index 3af59507ca..cedd5817c8 100644 --- a/openpype/tools/publisher/widgets/widgets.py +++ b/openpype/tools/publisher/widgets/widgets.py @@ -1175,12 +1175,13 @@ class CreatorAttrsWidget(QtWidgets.QWidget): content_layout = QtWidgets.QFormLayout(content_widget) for attr_def, attr_instances, values in result: widget = create_widget_for_attr_def(attr_def, content_widget) - if len(values) == 1: - value = values[0] - if value is not None: - widget.set_value(values[0]) - else: - widget.set_value(values, True) + if attr_def.is_value_def: + if len(values) == 1: + value = values[0] + if value is not None: + widget.set_value(values[0]) + else: + widget.set_value(values, True) label = attr_def.label or attr_def.key content_layout.addRow(label, widget) From 23c3bc8d0a31875da642aee0ea1298ee34e73831 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 18 Jan 2022 17:26:09 +0100 Subject: [PATCH 08/74] style changes of header view nad checkbox --- openpype/style/data.json | 2 +- openpype/style/style.css | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/openpype/style/data.json b/openpype/style/data.json index 1db0c732cf..b545f5de51 100644 --- a/openpype/style/data.json +++ b/openpype/style/data.json @@ -66,7 +66,7 @@ }, "nice-checkbox": { "bg-checked": "#56a06f", - "bg-unchecked": "#434b56", + "bg-unchecked": "#21252B", "bg-checker": "#D3D8DE", "bg-checker-hover": "#F0F2F5" }, diff --git a/openpype/style/style.css b/openpype/style/style.css index d9b0ff7421..f0ffe4dfc6 100644 --- a/openpype/style/style.css +++ b/openpype/style/style.css @@ -387,10 +387,16 @@ QHeaderView::section:only-one { QHeaderView::down-arrow { image: url(:/openpype/images/down_arrow.png); + padding-right: 4px; + subcontrol-origin: padding; + subcontrol-position: center right; } QHeaderView::up-arrow { image: url(:/openpype/images/up_arrow.png); + padding-right: 4px; + subcontrol-origin: padding; + subcontrol-position: center right; } /* Checkboxes */ @@ -1198,6 +1204,10 @@ QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { font-size: 36pt; } +#OverlayFrame { + background: rgba(0, 0, 0, 127); +} + #BreadcrumbsPathInput { padding: 2px; font-size: 9pt; From 95176b6e345e8d70a6e24c78e9bd052382b35481 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 18 Jan 2022 17:26:16 +0100 Subject: [PATCH 09/74] modified example creator --- .../testhost/plugins/create/test_creator_1.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/testhost/plugins/create/test_creator_1.py b/openpype/hosts/testhost/plugins/create/test_creator_1.py index 6ec4d16467..0ee5111979 100644 --- a/openpype/hosts/testhost/plugins/create/test_creator_1.py +++ b/openpype/hosts/testhost/plugins/create/test_creator_1.py @@ -13,6 +13,8 @@ class TestCreatorOne(Creator): family = "test" description = "Testing creator of testhost" + create_allow_context_change = False + def get_icon(self): return resources.get_openpype_splash_filepath() @@ -48,7 +50,17 @@ class TestCreatorOne(Creator): def get_attribute_defs(self): output = [ - lib.NumberDef("number_key", label="Number") + lib.NumberDef("number_key", label="Number"), + ] + return output + + def get_pre_create_attr_defs(self): + output = [ + lib.BoolDef("use_selection", label="Use selection"), + lib.UISeparatorDef(), + lib.UILabelDef("Testing label"), + lib.FileDef("filepath", folders=True, label="Filepath"), + lib.FileDef("filepath_2", multipath=True, folders=True, label="Filepath 2") ] return output From 20f5e8fc1b2263882adec624e1b961a0308a3fda Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 18 Jan 2022 17:51:25 +0100 Subject: [PATCH 10/74] hound fixes --- openpype/hosts/testhost/plugins/create/test_creator_1.py | 4 +++- openpype/tools/publisher/widgets/assets_widget.py | 2 -- openpype/widgets/attribute_defs/widgets.py | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/testhost/plugins/create/test_creator_1.py b/openpype/hosts/testhost/plugins/create/test_creator_1.py index 0ee5111979..3684f38592 100644 --- a/openpype/hosts/testhost/plugins/create/test_creator_1.py +++ b/openpype/hosts/testhost/plugins/create/test_creator_1.py @@ -60,7 +60,9 @@ class TestCreatorOne(Creator): lib.UISeparatorDef(), lib.UILabelDef("Testing label"), lib.FileDef("filepath", folders=True, label="Filepath"), - lib.FileDef("filepath_2", multipath=True, folders=True, label="Filepath 2") + lib.FileDef( + "filepath_2", multipath=True, folders=True, label="Filepath 2" + ) ] return output diff --git a/openpype/tools/publisher/widgets/assets_widget.py b/openpype/tools/publisher/widgets/assets_widget.py index 5d5372cbce..b8696a2665 100644 --- a/openpype/tools/publisher/widgets/assets_widget.py +++ b/openpype/tools/publisher/widgets/assets_widget.py @@ -1,7 +1,5 @@ import collections -import avalon.api - from Qt import QtWidgets, QtCore, QtGui from openpype.tools.utils import ( PlaceholderLineEdit, diff --git a/openpype/widgets/attribute_defs/widgets.py b/openpype/widgets/attribute_defs/widgets.py index 2eb22209db..a6f1b8d6c9 100644 --- a/openpype/widgets/attribute_defs/widgets.py +++ b/openpype/widgets/attribute_defs/widgets.py @@ -1,4 +1,3 @@ -import os import uuid from Qt import QtWidgets, QtCore From f8be5763b57af0e94b85af74ae95ba1579578349 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 18 Jan 2022 18:05:32 +0100 Subject: [PATCH 11/74] renamed method 'get_attribute_defs' to 'get_instance_attr_defs' --- openpype/hosts/testhost/plugins/create/auto_creator.py | 2 +- openpype/hosts/testhost/plugins/create/test_creator_1.py | 8 ++++++-- openpype/hosts/testhost/plugins/create/test_creator_2.py | 4 ++-- .../hosts/testhost/plugins/publish/collect_context.py | 2 +- .../hosts/testhost/plugins/publish/collect_instance_1.py | 2 +- openpype/pipeline/create/context.py | 2 +- openpype/pipeline/create/creator_plugins.py | 2 +- 7 files changed, 13 insertions(+), 9 deletions(-) diff --git a/openpype/hosts/testhost/plugins/create/auto_creator.py b/openpype/hosts/testhost/plugins/create/auto_creator.py index 0690164ae5..45c573e487 100644 --- a/openpype/hosts/testhost/plugins/create/auto_creator.py +++ b/openpype/hosts/testhost/plugins/create/auto_creator.py @@ -11,7 +11,7 @@ class MyAutoCreator(AutoCreator): identifier = "workfile" family = "workfile" - def get_attribute_defs(self): + def get_instance_attr_defs(self): output = [ lib.NumberDef("number_key", label="Number") ] diff --git a/openpype/hosts/testhost/plugins/create/test_creator_1.py b/openpype/hosts/testhost/plugins/create/test_creator_1.py index 3684f38592..45c30e8a27 100644 --- a/openpype/hosts/testhost/plugins/create/test_creator_1.py +++ b/openpype/hosts/testhost/plugins/create/test_creator_1.py @@ -1,3 +1,4 @@ +import json from openpype import resources from openpype.hosts.testhost.api import pipeline from openpype.pipeline import ( @@ -35,7 +36,10 @@ class TestCreatorOne(Creator): for instance in instances: self._remove_instance_from_context(instance) - def create(self, subset_name, data, options=None): + def create(self, subset_name, data, pre_create_data): + print("Data that can be used in create:\n{}".format( + json.dumps(pre_create_data, indent=4) + )) new_instance = CreatedInstance(self.family, subset_name, data, self) pipeline.HostContext.add_instance(new_instance.data_to_store()) self.log.info(new_instance.data) @@ -48,7 +52,7 @@ class TestCreatorOne(Creator): "different_variant" ] - def get_attribute_defs(self): + def get_instance_attr_defs(self): output = [ lib.NumberDef("number_key", label="Number"), ] diff --git a/openpype/hosts/testhost/plugins/create/test_creator_2.py b/openpype/hosts/testhost/plugins/create/test_creator_2.py index 4b1430a6a2..e66304a038 100644 --- a/openpype/hosts/testhost/plugins/create/test_creator_2.py +++ b/openpype/hosts/testhost/plugins/create/test_creator_2.py @@ -15,7 +15,7 @@ class TestCreatorTwo(Creator): def get_icon(self): return "cube" - def create(self, subset_name, data, options=None): + def create(self, subset_name, data, pre_create_data): new_instance = CreatedInstance(self.family, subset_name, data, self) pipeline.HostContext.add_instance(new_instance.data_to_store()) self.log.info(new_instance.data) @@ -38,7 +38,7 @@ class TestCreatorTwo(Creator): for instance in instances: self._remove_instance_from_context(instance) - def get_attribute_defs(self): + def get_instance_attr_defs(self): output = [ lib.NumberDef("number_key"), lib.TextDef("text_key") diff --git a/openpype/hosts/testhost/plugins/publish/collect_context.py b/openpype/hosts/testhost/plugins/publish/collect_context.py index 0ab98fb84b..bbb8477cdf 100644 --- a/openpype/hosts/testhost/plugins/publish/collect_context.py +++ b/openpype/hosts/testhost/plugins/publish/collect_context.py @@ -19,7 +19,7 @@ class CollectContextDataTestHost( hosts = ["testhost"] @classmethod - def get_attribute_defs(cls): + def get_instance_attr_defs(cls): return [ attribute_definitions.BoolDef( "test_bool", diff --git a/openpype/hosts/testhost/plugins/publish/collect_instance_1.py b/openpype/hosts/testhost/plugins/publish/collect_instance_1.py index 3c035eccb6..979ab83f11 100644 --- a/openpype/hosts/testhost/plugins/publish/collect_instance_1.py +++ b/openpype/hosts/testhost/plugins/publish/collect_instance_1.py @@ -20,7 +20,7 @@ class CollectInstanceOneTestHost( hosts = ["testhost"] @classmethod - def get_attribute_defs(cls): + def get_instance_attr_defs(cls): return [ attribute_definitions.NumberDef( "version", diff --git a/openpype/pipeline/create/context.py b/openpype/pipeline/create/context.py index f508e43315..4454d31d83 100644 --- a/openpype/pipeline/create/context.py +++ b/openpype/pipeline/create/context.py @@ -419,7 +419,7 @@ class CreatedInstance: # Stored creator specific attribute values # {key: value} creator_values = copy.deepcopy(orig_creator_attributes) - creator_attr_defs = creator.get_attribute_defs() + creator_attr_defs = creator.get_instance_attr_defs() self._data["creator_attributes"] = CreatorAttributeValues( self, creator_attr_defs, creator_values, orig_creator_attributes diff --git a/openpype/pipeline/create/creator_plugins.py b/openpype/pipeline/create/creator_plugins.py index 8247581d94..1ac2c420a2 100644 --- a/openpype/pipeline/create/creator_plugins.py +++ b/openpype/pipeline/create/creator_plugins.py @@ -163,7 +163,7 @@ class BaseCreator: dynamic_data=dynamic_data ) - def get_attribute_defs(self): + def get_instance_attr_defs(self): """Plugin attribute definitions. Attribute definitions of plugin that hold data about created instance From 2695c218fb9d6345b845e021805d28dad5161032 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 21 Jan 2022 15:10:13 +0100 Subject: [PATCH 12/74] nuke: add color space check functionality to api --- openpype/hosts/nuke/api/__init__.py | 7 +++++ openpype/hosts/nuke/api/utils.py | 47 +++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/openpype/hosts/nuke/api/__init__.py b/openpype/hosts/nuke/api/__init__.py index f7ebcb41da..b571c4098c 100644 --- a/openpype/hosts/nuke/api/__init__.py +++ b/openpype/hosts/nuke/api/__init__.py @@ -29,6 +29,10 @@ from .lib import ( maintained_selection ) +from .utils import ( + colorspace_exists_on_node, + get_colorspace_list +) __all__ = ( "file_extensions", @@ -54,4 +58,7 @@ __all__ = ( "update_container", "maintained_selection", + + "colorspace_exists_on_node", + "get_colorspace_list" ) diff --git a/openpype/hosts/nuke/api/utils.py b/openpype/hosts/nuke/api/utils.py index 0ed84f9560..5b0c607292 100644 --- a/openpype/hosts/nuke/api/utils.py +++ b/openpype/hosts/nuke/api/utils.py @@ -82,3 +82,50 @@ def bake_gizmos_recursively(in_group=None): if node.Class() == "Group": bake_gizmos_recursively(node) + + +def colorspace_exists_on_node(node, colorspace_name): + """ Check if colorspace exists on node + + Look through all options in the colorpsace knob, and see if we have an + exact match to one of the items. + + Args: + node (nuke.Node): nuke node object + colorspace_name (str): color profile name + + Returns: + bool: True if exists + """ + try: + colorspace_knob = node['colorspace'] + except ValueError: + # knob is not available on input node + return False + all_clrs = get_colorspace_list(colorspace_knob) + + return colorspace_name in all_clrs + + +def get_colorspace_list(colorspace_knob): + """Get available colorspace profile names + + Args: + colorspace_knob (nuke.Knob): nuke knob object + + Returns: + list: list of strings names of profiles + """ + + all_clrs = list(colorspace_knob.values()) + reduced_clrs = [] + + if not colorspace_knob.getFlag(nuke.STRIP_CASCADE_PREFIX): + return all_clrs + + # strip colorspace with nested path + for clrs in all_clrs: + clrs = clrs.split('/')[-1] + reduced_clrs.append(clrs) + + return reduced_clrs From 9f5057aafe678fa41f67620a9c18252eac5902a6 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 21 Jan 2022 15:10:42 +0100 Subject: [PATCH 13/74] nuke: load clip with colorspace from representation data --- openpype/hosts/nuke/plugins/load/load_clip.py | 74 +++++++++++++------ 1 file changed, 52 insertions(+), 22 deletions(-) diff --git a/openpype/hosts/nuke/plugins/load/load_clip.py b/openpype/hosts/nuke/plugins/load/load_clip.py index 3a9c9ca691..621a464c69 100644 --- a/openpype/hosts/nuke/plugins/load/load_clip.py +++ b/openpype/hosts/nuke/plugins/load/load_clip.py @@ -9,7 +9,8 @@ from openpype.hosts.nuke.api.lib import ( from openpype.hosts.nuke.api import ( containerise, update_container, - viewer_update_and_undo_stop + viewer_update_and_undo_stop, + colorspace_exists_on_node ) from openpype.hosts.nuke.api import plugin @@ -65,12 +66,37 @@ class LoadClip(plugin.NukeLoader): + plugin.get_review_presets_config() ) - def load(self, context, name, namespace, options): + def _set_colorspace(self, node, version_data, repre_data, path=None): + output_color = None + path = path or self.fname.replace("\\", "/") + # get colorspace + colorspace = repre_data.get("colorspace") + colorspace = colorspace or version_data.get("colorspace") + # colorspace from `project_anatomy/imageio/nuke/regexInputs` + iio_colorspace = get_imageio_input_colorspace(path) + + # Set colorspace defined in version data + if ( + colorspace is not None + and colorspace_exists_on_node( + node, str(colorspace)) is not False + ): + node["colorspace"].setValue(str(colorspace)) + output_color = str(colorspace) + elif iio_colorspace is not None: + node["colorspace"].setValue(iio_colorspace) + output_color = iio_colorspace + + return output_color + + + def load(self, context, name, namespace, options): + repres = context["representation"] # reste container id so it is always unique for each instance self.reset_container_id() - is_sequence = len(context["representation"]["files"]) > 1 + is_sequence = len(repres["files"]) > 1 file = self.fname.replace("\\", "/") @@ -79,10 +105,9 @@ class LoadClip(plugin.NukeLoader): version = context['version'] version_data = version.get("data", {}) - repr_id = context["representation"]["_id"] - colorspace = version_data.get("colorspace") - iio_colorspace = get_imageio_input_colorspace(file) - repr_cont = context["representation"]["context"] + repr_id = repres["_id"] + + repr_cont = repres["context"] self.log.info("version_data: {}\n".format(version_data)) self.log.debug( @@ -116,7 +141,7 @@ class LoadClip(plugin.NukeLoader): "Representation id `{}` is failing to load".format(repr_id)) return - read_name = self._get_node_name(context["representation"]) + read_name = self._get_node_name(repres) # Create the Loader with the filename path set read_node = nuke.createNode( @@ -128,11 +153,8 @@ class LoadClip(plugin.NukeLoader): with viewer_update_and_undo_stop(): read_node["file"].setValue(file) - # Set colorspace defined in version data - if colorspace: - read_node["colorspace"].setValue(str(colorspace)) - elif iio_colorspace is not None: - read_node["colorspace"].setValue(iio_colorspace) + set_colorspace = self._set_colorspace( + read_node, version_data, repres["data"]) self._set_range_to_node(read_node, first, last, start_at_workfile) @@ -145,6 +167,13 @@ class LoadClip(plugin.NukeLoader): for k in add_keys: if k == 'version': data_imprint.update({k: context["version"]['name']}) + elif k == 'colorspace': + colorspace = repres["data"].get(k) + colorspace = colorspace or version_data.get(k) + data_imprint.update({ + "db_colorspace": colorspace, + "set_colorspace": set_colorspace + }) else: data_imprint.update( {k: context["version"]['data'].get(k, str(None))}) @@ -193,10 +222,13 @@ class LoadClip(plugin.NukeLoader): }) version_data = version.get("data", {}) repr_id = representation["_id"] - colorspace = version_data.get("colorspace") - iio_colorspace = get_imageio_input_colorspace(file) + repr_cont = representation["context"] + # colorspace profile + colorspace = representation["data"].get("colorspace") + colorspace = colorspace or version_data.get("colorspace") + self.handle_start = version_data.get("handleStart", 0) self.handle_end = version_data.get("handleEnd", 0) @@ -229,12 +261,9 @@ class LoadClip(plugin.NukeLoader): # to avoid multiple undo steps for rest of process # we will switch off undo-ing with viewer_update_and_undo_stop(): - - # Set colorspace defined in version data - if colorspace: - read_node["colorspace"].setValue(str(colorspace)) - elif iio_colorspace is not None: - read_node["colorspace"].setValue(iio_colorspace) + set_colorspace = self._set_colorspace( + read_node, version_data, representation["data"], + path=file) self._set_range_to_node(read_node, first, last, start_at_workfile) @@ -243,7 +272,8 @@ class LoadClip(plugin.NukeLoader): "frameStart": str(first), "frameEnd": str(last), "version": str(version.get("name")), - "colorspace": colorspace, + "db_colorspace": colorspace, + "set_colorspace": set_colorspace, "source": version_data.get("source"), "handleStart": str(self.handle_start), "handleEnd": str(self.handle_end), From 9746cb4eb87c459c0975e57e2c6b14ef6a325220 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 21 Jan 2022 15:18:06 +0100 Subject: [PATCH 14/74] nuke: load clip internal method moved to the end of class methods --- openpype/hosts/nuke/plugins/load/load_clip.py | 49 +++++++++---------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/openpype/hosts/nuke/plugins/load/load_clip.py b/openpype/hosts/nuke/plugins/load/load_clip.py index 621a464c69..c94fbd59b5 100644 --- a/openpype/hosts/nuke/plugins/load/load_clip.py +++ b/openpype/hosts/nuke/plugins/load/load_clip.py @@ -66,31 +66,6 @@ class LoadClip(plugin.NukeLoader): + plugin.get_review_presets_config() ) - def _set_colorspace(self, node, version_data, repre_data, path=None): - output_color = None - path = path or self.fname.replace("\\", "/") - # get colorspace - colorspace = repre_data.get("colorspace") - colorspace = colorspace or version_data.get("colorspace") - - # colorspace from `project_anatomy/imageio/nuke/regexInputs` - iio_colorspace = get_imageio_input_colorspace(path) - - # Set colorspace defined in version data - if ( - colorspace is not None - and colorspace_exists_on_node( - node, str(colorspace)) is not False - ): - node["colorspace"].setValue(str(colorspace)) - output_color = str(colorspace) - elif iio_colorspace is not None: - node["colorspace"].setValue(iio_colorspace) - output_color = iio_colorspace - - return output_color - - def load(self, context, name, namespace, options): repres = context["representation"] # reste container id so it is always unique for each instance @@ -406,3 +381,27 @@ class LoadClip(plugin.NukeLoader): } return self.node_name_template.format(**name_data) + + def _set_colorspace(self, node, version_data, repre_data, path=None): + output_color = None + path = path or self.fname.replace("\\", "/") + # get colorspace + colorspace = repre_data.get("colorspace") + colorspace = colorspace or version_data.get("colorspace") + + # colorspace from `project_anatomy/imageio/nuke/regexInputs` + iio_colorspace = get_imageio_input_colorspace(path) + + # Set colorspace defined in version data + if ( + colorspace is not None + and colorspace_exists_on_node( + node, str(colorspace)) is not False + ): + node["colorspace"].setValue(str(colorspace)) + output_color = str(colorspace) + elif iio_colorspace is not None: + node["colorspace"].setValue(iio_colorspace) + output_color = iio_colorspace + + return output_color \ No newline at end of file From 122e28660812519948db0707b32f03a24bd22aa7 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 25 Jan 2022 12:13:38 +0100 Subject: [PATCH 15/74] fixing otio frame offset --- openpype/plugins/publish/extract_otio_review.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/openpype/plugins/publish/extract_otio_review.py b/openpype/plugins/publish/extract_otio_review.py index 675e5e0ee0..7cde5ab97e 100644 --- a/openpype/plugins/publish/extract_otio_review.py +++ b/openpype/plugins/publish/extract_otio_review.py @@ -273,6 +273,8 @@ class ExtractOTIOReview(openpype.api.Extractor): src_start = int(avl_start + start) avl_durtation = int(avl_range.duration.value) + self.need_offset = bool(avl_start != 0 and src_start != 0) + # if media start is les then clip requires if src_start < avl_start: # calculate gap @@ -408,11 +410,17 @@ class ExtractOTIOReview(openpype.api.Extractor): """ padding = "{{:0{}d}}".format(self.padding) + + # create frame offset + offset = 0 + if self.need_offset: + offset = 1 + if end_offset: new_frames = list() start_frame = self.used_frames[-1] - for index in range((end_offset + 1), - (int(end_offset + duration) + 1)): + for index in range((end_offset + offset), + (int(end_offset + duration) + offset)): seq_number = padding.format(start_frame + index) self.log.debug( "index: `{}` | seq_number: `{}`".format(index, seq_number)) From 7ec4d501802135fd725e5f37682bc351ca38483f Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 25 Jan 2022 13:48:03 +0100 Subject: [PATCH 16/74] precreate widget is separated from create dialog completely --- .../tools/publisher/widgets/create_dialog.py | 38 +++------- .../publisher/widgets/precreate_widget.py | 76 ++++++++++++++++++- 2 files changed, 85 insertions(+), 29 deletions(-) diff --git a/openpype/tools/publisher/widgets/create_dialog.py b/openpype/tools/publisher/widgets/create_dialog.py index 05936265bb..f9f8310e09 100644 --- a/openpype/tools/publisher/widgets/create_dialog.py +++ b/openpype/tools/publisher/widgets/create_dialog.py @@ -17,7 +17,7 @@ from openpype.pipeline.create import ( from .widgets import IconValuePixmapLabel from .assets_widget import CreateDialogAssetsWidget from .tasks_widget import CreateDialogTasksWidget -from .precreate_widget import AttributesWidget +from .precreate_widget import PreCreateWidget from ..constants import ( VARIANT_TOOLTIP, CREATOR_IDENTIFIER_ROLE, @@ -216,22 +216,11 @@ class CreateDialog(QtWidgets.QDialog): context_layout.addWidget(assets_widget, 2) context_layout.addWidget(tasks_widget, 1) - pre_create_scroll_area = QtWidgets.QScrollArea(self) - pre_create_contet_widget = QtWidgets.QWidget(pre_create_scroll_area) - pre_create_scroll_area.setWidget(pre_create_contet_widget) - pre_create_scroll_area.setWidgetResizable(True) + # Precreate attributes widgets + pre_create_widget = PreCreateWidget(self) - pre_create_contet_layout = QtWidgets.QVBoxLayout( - pre_create_contet_widget - ) - pre_create_attributes_widget = AttributesWidget( - pre_create_contet_widget - ) - pre_create_contet_layout.addWidget(pre_create_attributes_widget, 0) - pre_create_contet_layout.addStretch(1) - - creator_description_widget = CreatorDescriptionWidget(self) # TODO add HELP button + creator_description_widget = CreatorDescriptionWidget(self) creator_description_widget.setVisible(False) creators_view = QtWidgets.QListView(self) @@ -273,17 +262,11 @@ class CreateDialog(QtWidgets.QDialog): mid_layout.addLayout(form_layout, 0) mid_layout.addWidget(create_btn, 0) - left_layout = QtWidgets.QVBoxLayout() - left_layout.addWidget(QtWidgets.QLabel("Choose family:", self)) - left_layout.addWidget(creators_view, 1) - left_layout.addLayout(form_layout, 0) - left_layout.addWidget(create_btn, 0) - layout = QtWidgets.QHBoxLayout(self) layout.setSpacing(10) layout.addWidget(context_widget, 1) layout.addWidget(mid_widget, 1) - layout.addWidget(pre_create_scroll_area, 1) + layout.addWidget(pre_create_widget, 1) prereq_timer = QtCore.QTimer() prereq_timer.setInterval(50) @@ -306,7 +289,8 @@ class CreateDialog(QtWidgets.QDialog): controller.add_plugins_refresh_callback(self._on_plugins_refresh) - self._pre_create_attributes_widget = pre_create_attributes_widget + self._pre_create_widget = pre_create_widget + self._context_widget = context_widget self._assets_widget = assets_widget self._tasks_widget = tasks_widget @@ -519,10 +503,11 @@ class CreateDialog(QtWidgets.QDialog): creator = self.controller.manual_creators.get(identifier) self.creator_description_widget.set_plugin(creator) + self._pre_create_widget.set_plugin(creator) self._selected_creator = creator + if not creator: - self._pre_create_attributes_widget.set_attr_defs([]) self._set_context_enabled(False) return @@ -533,9 +518,6 @@ class CreateDialog(QtWidgets.QDialog): self._set_context_enabled(creator.create_allow_context_change) self._refresh_asset() - attr_defs = creator.get_pre_create_attr_defs() - self._pre_create_attributes_widget.set_attr_defs(attr_defs) - default_variants = creator.get_default_variants() if not default_variants: default_variants = ["Main"] @@ -682,7 +664,7 @@ class CreateDialog(QtWidgets.QDialog): variant = self.variant_input.text() asset_name = self._get_asset_name() task_name = self._get_task_name() - pre_create_data = self._pre_create_attributes_widget.current_value() + pre_create_data = self._pre_create_widget.current_value() # Where to define these data? # - what data show be stored? instance_data = { diff --git a/openpype/tools/publisher/widgets/precreate_widget.py b/openpype/tools/publisher/widgets/precreate_widget.py index 7f0228946e..c7a215d178 100644 --- a/openpype/tools/publisher/widgets/precreate_widget.py +++ b/openpype/tools/publisher/widgets/precreate_widget.py @@ -1,8 +1,82 @@ -from Qt import QtWidgets +from Qt import QtWidgets, QtCore from openpype.widgets.attribute_defs import create_widget_for_attr_def +class PreCreateWidget(QtWidgets.QWidget): + def __init__(self, parent): + super(PreCreateWidget, self).__init__(parent) + + # Precreate attribute defininitions of Creator + scroll_area = QtWidgets.QScrollArea(self) + contet_widget = QtWidgets.QWidget(scroll_area) + scroll_area.setWidget(contet_widget) + scroll_area.setWidgetResizable(True) + + attributes_widget = AttributesWidget(contet_widget) + contet_layout = QtWidgets.QVBoxLayout(contet_widget) + contet_layout.setContentsMargins(0, 0, 0, 0) + contet_layout.addWidget(attributes_widget, 0) + contet_layout.addStretch(1) + + # Widget showed when there are no attribute definitions from creator + empty_widget = QtWidgets.QWidget(self) + empty_widget.setVisible(False) + + # Label showed when creator is not selected + no_creator_label = QtWidgets.QLabel( + "Creator is not selected", + empty_widget + ) + no_creator_label.setWordWrap(True) + + # Creator does not have precreate attributes + empty_label = QtWidgets.QLabel( + "This creator had no configurable options", + empty_widget + ) + empty_label.setWordWrap(True) + empty_label.setVisible(False) + + empty_layout = QtWidgets.QVBoxLayout(empty_widget) + empty_layout.setContentsMargins(0, 0, 0, 0) + empty_layout.addStretch(1) + empty_layout.addWidget(empty_label, 0, QtCore.Qt.AlignCenter) + empty_layout.addWidget(no_creator_label, 0, QtCore.Qt.AlignCenter) + empty_layout.addStretch(1) + + main_layout = QtWidgets.QHBoxLayout(self) + main_layout.setContentsMargins(0, 0, 0, 0) + main_layout.addWidget(scroll_area, 1) + main_layout.addWidget(empty_widget, 1) + + self._scroll_area = scroll_area + self._empty_widget = empty_widget + + self._empty_label = empty_label + self._no_creator_label = no_creator_label + self._attributes_widget = attributes_widget + + def current_value(self): + return self._attributes_widget.current_value() + + def set_plugin(self, creator): + attr_defs = [] + creator_selected = False + if creator is not None: + creator_selected = True + attr_defs = creator.get_pre_create_attr_defs() + + self._attributes_widget.set_attr_defs(attr_defs) + + attr_defs_available = len(attr_defs) > 0 + self._scroll_area.setVisible(attr_defs_available) + self._empty_widget.setVisible(not attr_defs_available) + + self._empty_label.setVisible(creator_selected) + self._no_creator_label.setVisible(not creator_selected) + + class AttributesWidget(QtWidgets.QWidget): def __init__(self, parent=None): super(AttributesWidget, self).__init__(parent) From d7393646a3a084e3502dec720abbf51aba1385ac Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 25 Jan 2022 13:48:18 +0100 Subject: [PATCH 17/74] handle default value of 'is_label_horizontal' --- openpype/pipeline/lib/attribute_definitions.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/openpype/pipeline/lib/attribute_definitions.py b/openpype/pipeline/lib/attribute_definitions.py index 111eb44429..189a5e7acd 100644 --- a/openpype/pipeline/lib/attribute_definitions.py +++ b/openpype/pipeline/lib/attribute_definitions.py @@ -46,6 +46,8 @@ class AbtractAttrDef: def __init__( self, key, default, label=None, tooltip=None, is_label_horizontal=None ): + if is_label_horizontal is None: + is_label_horizontal = True self.key = key self.label = label self.tooltip = tooltip @@ -342,8 +344,11 @@ class FileDef(AbtractAttrDef): # Change horizontal label is_label_horizontal = kwargs.get("is_label_horizontal") - if is_label_horizontal is None and multipath: - kwargs["is_label_horizontal"] = False + if is_label_horizontal is None: + is_label_horizontal = True + if multipath: + is_label_horizontal = False + kwargs["is_label_horizontal"] = is_label_horizontal self.multipath = multipath self.folders = folders From 3160199b044d63ffbc4b4d8bb3c7a852578dd355 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 25 Jan 2022 14:15:19 +0100 Subject: [PATCH 18/74] fix grammar --- openpype/tools/publisher/widgets/precreate_widget.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/openpype/tools/publisher/widgets/precreate_widget.py b/openpype/tools/publisher/widgets/precreate_widget.py index c7a215d178..eaadfe890b 100644 --- a/openpype/tools/publisher/widgets/precreate_widget.py +++ b/openpype/tools/publisher/widgets/precreate_widget.py @@ -32,7 +32,7 @@ class PreCreateWidget(QtWidgets.QWidget): # Creator does not have precreate attributes empty_label = QtWidgets.QLabel( - "This creator had no configurable options", + "This creator has no configurable options", empty_widget ) empty_label.setWordWrap(True) @@ -40,10 +40,8 @@ class PreCreateWidget(QtWidgets.QWidget): empty_layout = QtWidgets.QVBoxLayout(empty_widget) empty_layout.setContentsMargins(0, 0, 0, 0) - empty_layout.addStretch(1) empty_layout.addWidget(empty_label, 0, QtCore.Qt.AlignCenter) empty_layout.addWidget(no_creator_label, 0, QtCore.Qt.AlignCenter) - empty_layout.addStretch(1) main_layout = QtWidgets.QHBoxLayout(self) main_layout.setContentsMargins(0, 0, 0, 0) From c400c79c6a1cb46dc2714beaad8e28b7a75f8e8e Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 25 Jan 2022 15:13:11 +0100 Subject: [PATCH 19/74] nuke: keep consistent variable names --- openpype/hosts/nuke/plugins/load/load_clip.py | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/openpype/hosts/nuke/plugins/load/load_clip.py b/openpype/hosts/nuke/plugins/load/load_clip.py index c94fbd59b5..13fa4f84c5 100644 --- a/openpype/hosts/nuke/plugins/load/load_clip.py +++ b/openpype/hosts/nuke/plugins/load/load_clip.py @@ -67,11 +67,11 @@ class LoadClip(plugin.NukeLoader): ) def load(self, context, name, namespace, options): - repres = context["representation"] + repre = context["representation"] # reste container id so it is always unique for each instance self.reset_container_id() - is_sequence = len(repres["files"]) > 1 + is_sequence = len(repre["files"]) > 1 file = self.fname.replace("\\", "/") @@ -80,13 +80,13 @@ class LoadClip(plugin.NukeLoader): version = context['version'] version_data = version.get("data", {}) - repr_id = repres["_id"] + repre_id = repre["_id"] - repr_cont = repres["context"] + repre_cont = repre["context"] self.log.info("version_data: {}\n".format(version_data)) self.log.debug( - "Representation id `{}` ".format(repr_id)) + "Representation id `{}` ".format(repre_id)) self.handle_start = version_data.get("handleStart", 0) self.handle_end = version_data.get("handleEnd", 0) @@ -101,7 +101,7 @@ class LoadClip(plugin.NukeLoader): first = 1 last = first + duration elif "#" not in file: - frame = repr_cont.get("frame") + frame = repre_cont.get("frame") assert frame, "Representation is not sequence" padding = len(frame) @@ -113,10 +113,10 @@ class LoadClip(plugin.NukeLoader): if not file: self.log.warning( - "Representation id `{}` is failing to load".format(repr_id)) + "Representation id `{}` is failing to load".format(repre_id)) return - read_name = self._get_node_name(repres) + read_name = self._get_node_name(repre) # Create the Loader with the filename path set read_node = nuke.createNode( @@ -129,7 +129,7 @@ class LoadClip(plugin.NukeLoader): read_node["file"].setValue(file) set_colorspace = self._set_colorspace( - read_node, version_data, repres["data"]) + read_node, version_data, repre["data"]) self._set_range_to_node(read_node, first, last, start_at_workfile) @@ -143,7 +143,7 @@ class LoadClip(plugin.NukeLoader): if k == 'version': data_imprint.update({k: context["version"]['name']}) elif k == 'colorspace': - colorspace = repres["data"].get(k) + colorspace = repre["data"].get(k) colorspace = colorspace or version_data.get(k) data_imprint.update({ "db_colorspace": colorspace, @@ -196,9 +196,9 @@ class LoadClip(plugin.NukeLoader): "_id": representation["parent"] }) version_data = version.get("data", {}) - repr_id = representation["_id"] + repre_id = representation["_id"] - repr_cont = representation["context"] + repre_cont = representation["context"] # colorspace profile colorspace = representation["data"].get("colorspace") @@ -217,7 +217,7 @@ class LoadClip(plugin.NukeLoader): first = 1 last = first + duration elif "#" not in file: - frame = repr_cont.get("frame") + frame = repre_cont.get("frame") assert frame, "Representation is not sequence" padding = len(frame) @@ -225,7 +225,7 @@ class LoadClip(plugin.NukeLoader): if not file: self.log.warning( - "Representation id `{}` is failing to load".format(repr_id)) + "Representation id `{}` is failing to load".format(repre_id)) return read_name = self._get_node_name(representation) @@ -370,12 +370,12 @@ class LoadClip(plugin.NukeLoader): def _get_node_name(self, representation): - repr_cont = representation["context"] + repre_cont = representation["context"] name_data = { - "asset": repr_cont["asset"], - "subset": repr_cont["subset"], + "asset": repre_cont["asset"], + "subset": repre_cont["subset"], "representation": representation["name"], - "ext": repr_cont["representation"], + "ext": repre_cont["representation"], "id": representation["_id"], "class_name": self.__class__.__name__ } From 28128f3827e810886fac74238987af9e48156971 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 25 Jan 2022 15:14:12 +0100 Subject: [PATCH 20/74] flake8: new line at the end --- openpype/hosts/nuke/plugins/load/load_clip.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/nuke/plugins/load/load_clip.py b/openpype/hosts/nuke/plugins/load/load_clip.py index 13fa4f84c5..4fc49e4cee 100644 --- a/openpype/hosts/nuke/plugins/load/load_clip.py +++ b/openpype/hosts/nuke/plugins/load/load_clip.py @@ -404,4 +404,4 @@ class LoadClip(plugin.NukeLoader): node["colorspace"].setValue(iio_colorspace) output_color = iio_colorspace - return output_color \ No newline at end of file + return output_color From 584c8db1031c22a05cc404f71dde7ae0d779c56d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Marinov?= Date: Fri, 28 Jan 2022 00:21:52 +0100 Subject: [PATCH 21/74] Added missing family_mapping dict --- .../schema_project_ftrack.json | 1517 +++++++++-------- 1 file changed, 769 insertions(+), 748 deletions(-) diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json b/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json index e50e269695..86c8b14747 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json @@ -1,750 +1,771 @@ { - "type": "dict", - "key": "ftrack", - "label": "Ftrack", - "collapsible": true, - "is_file": true, - "children": [ - { - "type": "dict", - "key": "events", - "label": "Server Actions/Events", - "children": [ - { - "type": "dict", - "key": "sync_to_avalon", - "label": "Sync to avalon", - "children": [ - { - "type": "label", - "label": "Allow name and hierarchy change only if following statuses are on all children tasks" - }, - { - "type": "list", - "key": "statuses_name_change", - "label": "Statuses", - "object_type": { - "type": "text", - "multiline": false - } - } - ] - }, - { - "type": "dict", - "key": "prepare_project", - "label": "Prepare Project", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "list", - "key": "role_list", - "label": "Roles", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "key": "sync_hier_entity_attributes", - "label": "Sync Hierarchical and Entity Attributes", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "list", - "key": "interest_entity_types", - "label": "Entity types of interest", - "object_type": { - "type": "text", - "multiline": false - } - }, - { - "type": "list", - "key": "interest_attributes", - "label": "Attributes to sync", - "object_type": { - "type": "text", - "multiline": false - } - }, - { - "type": "separator" - }, - { - "type": "boolean", - "key": "action_enabled", - "label": "Enable Action" - }, - { - "type": "list", - "key": "role_list", - "label": "Roles for action", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "key": "clone_review_session", - "label": "Clone Review Session", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "list", - "key": "role_list", - "label": "Roles for action", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "key": "thumbnail_updates", - "label": "Update Hierarchy thumbnails", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "label", - "label": "Push thumbnail from version, up through multiple hierarchy levels." - }, - { - "type": "number", - "key": "levels", - "label": "Levels" - } - ] - }, - { - "type": "dict", - "key": "user_assignment", - "label": "Run script on user assignments", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - } - ] - }, - { - "type": "dict", - "key": "status_update", - "label": "Update status on task action", - "is_group": true, - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "key": "mapping", - "type": "dict-modifiable", - "object_type": { - "type": "list", - "object_type": "text" - } - } - ] - }, - { - "type": "dict", - "key": "status_task_to_parent", - "label": "Sync status from Task to Parent", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "label", - "label": "List of parent object types where this is triggered (\"Shot\", \"Asset Build\", etc.). Skipped if list is empty." - }, - { - "type": "list", - "object_type": "text", - "key": "parent_object_types", - "label": "Object types" - }, - { - "key": "parent_status_match_all_task_statuses", - "type": "dict-modifiable", - "label": "Change parent if all tasks match", - "object_type": { - "type": "list", - "object_type": "text" - } - }, - { - "type": "list", - "key": "parent_status_by_task_status", - "label": "Change parent status if a single task matches", - "use_label_wrap": true, - "object_type": { - "type": "dict", - "children": [ - { - "type": "text", - "label": "New parent status", - "key": "new_status" - }, - { - "type": "separator" - }, - { - "type": "list", - "label": "Task status", - "key": "task_statuses", - "object_type": "text" - } - ] - } - } - ] - }, - { - "type": "dict", - "key": "status_task_to_version", - "label": "Sync status from Task to Version", - "is_group": true, - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "dict-modifiable", - "key": "mapping", - "object_type": - { - "type": "list", - "object_type": "text" - } - }, - { - "type": "label", - "label": "Limit status changes to entered asset types. Limitation is ignored if nothing is entered." - }, - { - "type": "list", - "key": "asset_types_filter", - "label": "Asset types (short)", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "key": "status_version_to_task", - "label": "Sync status from Version to Task", - "is_group": true, - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "label", - "label": "Change Task status based on a changed Version status.
Version's new status on the left will trigger a change of a task status to the first available from the list on right.
- if no status from the list is available it will use the same status as the version." - }, - { - "type": "dict-modifiable", - "key": "mapping", - "object_type": { - "type": "list", - "object_type": "text" - } - }, - { - "type": "separator" - }, - { - "type": "label", - "label": "Disable event if status was changed on specific Asset type." - }, - { - "type": "list", - "label": "Asset types (short)", - "key": "asset_types_to_skip", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "key": "first_version_status", - "label": "Set status on first created version", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "text", - "key": "status", - "label": "Status" - } - ] - }, - { - "type": "dict", - "key": "next_task_update", - "is_group": true, - "label": "Update status on next task", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "label", - "label": "Change status on next task by task types order when task status state changed to \"Done\". All tasks with same Task type must be \"Done\"." - }, - { - "type": "label", - "label": "Mapping of next task status changes From -> To." - }, - { - "type": "dict-modifiable", - "key": "mapping", - "object_type": { - "type": "text" - } - }, - { - "type": "separator" - }, - { - "type": "label", - "label": "Status names that are ignored on \"Done\" check (e.g. \"Omitted\")." - }, - { - "type": "list", - "key": "ignored_statuses", - "object_type": "text" - }, - { - "type": "separator" - }, - { - "type": "label", - "label": "Allow to break rule that all tasks with same Task type must be \"Done\" and change statuses with same type tasks ordered by name." - }, - { - "label": "Name sorting", - "type": "boolean", - "key": "name_sorting" - } - ] - } - ] - }, - { - "type": "dict", - "key": "user_handlers", - "label": "User Actions/Events", - "children": [ - { - "type": "dict", - "key": "application_launch_statuses", - "is_group": true, - "label": "Application - Status change on launch", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "label", - "label": "Do not change status if current status is:" - }, - { - "type": "list", - "key": "ignored_statuses", - "object_type": "text" - }, - { - "type": "label", - "label": "Change task's status to left side if current task status is in list on right side." - }, - { - "type": "dict-modifiable", - "key": "status_change", - "object_type": { - "type": "list", - "object_type": "text" - } - } - ] - }, - { - "type": "dict", - "key": "create_update_attributes", - "label": "Create/Update Avalon Attributes", - "children": [ - { - "type": "list", - "key": "role_list", - "label": "Roles", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "key": "prepare_project", - "label": "Prepare Project", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "list", - "key": "role_list", - "label": "Roles", - "object_type": "text" - }, - { - "type": "separator" - }, - { - "type": "label", - "label": "Check \"Create project structure\" by default" - }, - { - "type": "boolean", - "key": "create_project_structure_checked", - "label": "Checked" - } - ] - }, - { - "type": "dict", - "key": "clean_hierarchical_attr", - "label": "Clean hierarchical custom attributes", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "list", - "key": "role_list", - "label": "Roles", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "key": "delete_asset_subset", - "label": "Delete Asset/Subsets", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "list", - "key": "role_list", - "label": "Roles", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "key": "delete_old_versions", - "label": "Delete old versions", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "list", - "key": "role_list", - "label": "Roles", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "key": "delivery_action", - "label": "Delivery", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "list", - "key": "role_list", - "label": "Roles", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "key": "store_thubmnail_to_avalon", - "label": "Store Thumbnails to avalon", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "list", - "key": "role_list", - "label": "Roles", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "key": "job_killer", - "label": "Job Killer", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "list", - "key": "role_list", - "label": "Roles", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "key": "sync_to_avalon_local", - "label": "Sync to avalon (local) - For development", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "list", - "key": "role_list", - "label": "Roles", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "key": "seed_project", - "label": "Seed Debug Project", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "list", - "key": "role_list", - "label": "Roles", - "object_type": "text" - } - ] - } - ] - }, - { - "type": "dict", - "collapsible": true, - "key": "publish", - "label": "Publish plugins", - "children": [ - { - "type": "dict", - "collapsible": true, - "checkbox_key": "enabled", - "key": "CollectFtrackFamily", - "label": "Collect Ftrack Family", - "is_group": true, - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "list", - "collapsible": true, - "key": "profiles", - "label": "Profiles", - "use_label_wrap": true, - "object_type": { - "type": "dict", - "children": [ - { - "key": "hosts", - "label": "Host names", - "type": "list", - "object_type": "text" - }, - { - "key": "families", - "label": "Families", - "type": "list", - "object_type": "text" - }, - { - "key": "task_types", - "label": "Task types", - "type": "task-types-enum" - }, - { - "key": "tasks", - "label": "Task names", - "type": "list", - "object_type": "text" - }, - { - "type": "separator" - }, - { - "key": "add_ftrack_family", - "label": "Add Ftrack Family", - "type": "boolean" - }, - { - "type": "list", - "collapsible": true, - "key": "advanced_filtering", - "label": "Advanced adding if additional families present", - "use_label_wrap": true, - "object_type": { - "type": "dict", - "children": [ - { - "key": "families", - "label": "Additional Families", - "type": "list", - "object_type": "text" - }, - { - "key": "add_ftrack_family", - "label": "Add Ftrack Family", - "type": "boolean" - } - ] - } - } - ] - } - } - ] - }, - { - "type": "dict", - "collapsible": true, - "checkbox_key": "enabled", - "key": "IntegrateFtrackNote", - "label": "IntegrateFtrackNote", - "is_group": true, - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "text", - "key": "note_with_intent_template", - "label": "Note with intent template" - }, - { - "type": "list", - "object_type": "text", - "key": "note_labels", - "label": "Note labels" - } - ] - }, - - { - "type": "dict", - "collapsible": true, - "checkbox_key": "enabled", - "key": "ValidateFtrackAttributes", - "label": "ValidateFtrackAttributes", - "is_group": true, - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "raw-json", - "key": "ftrack_custom_attributes", - "label": "Custom attributes to validate" - } - ] - } - ] - } - ] + "type" : "dict", + "key" : "ftrack", + "label" : "Ftrack", + "collapsible" : true, + "is_file" : true, + "children" : [ + { + "type" : "dict", + "key" : "events", + "label" : "Server Actions/Events", + "children" : [ + { + "type" : "dict", + "key" : "sync_to_avalon", + "label" : "Sync to avalon", + "children" : [ + { + "type" : "label", + "label" : "Allow name and hierarchy change only if following statuses are on all children tasks" + }, + { + "type" : "list", + "key" : "statuses_name_change", + "label" : "Statuses", + "object_type" : { + "type" : "text", + "multiline" : false + } + } + ] + }, + { + "type" : "dict", + "key" : "prepare_project", + "label" : "Prepare Project", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "list", + "key" : "role_list", + "label" : "Roles", + "object_type" : "text" + } + ] + }, + { + "type" : "dict", + "key" : "sync_hier_entity_attributes", + "label" : "Sync Hierarchical and Entity Attributes", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "list", + "key" : "interest_entity_types", + "label" : "Entity types of interest", + "object_type" : { + "type" : "text", + "multiline" : false + } + }, + { + "type" : "list", + "key" : "interest_attributes", + "label" : "Attributes to sync", + "object_type" : { + "type" : "text", + "multiline" : false + } + }, + { + "type" : "separator" + }, + { + "type" : "boolean", + "key" : "action_enabled", + "label" : "Enable Action" + }, + { + "type" : "list", + "key" : "role_list", + "label" : "Roles for action", + "object_type" : "text" + } + ] + }, + { + "type" : "dict", + "key" : "clone_review_session", + "label" : "Clone Review Session", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "list", + "key" : "role_list", + "label" : "Roles for action", + "object_type" : "text" + } + ] + }, + { + "type" : "dict", + "key" : "thumbnail_updates", + "label" : "Update Hierarchy thumbnails", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "label", + "label" : "Push thumbnail from version, up through multiple hierarchy levels." + }, + { + "type" : "number", + "key" : "levels", + "label" : "Levels" + } + ] + }, + { + "type" : "dict", + "key" : "user_assignment", + "label" : "Run script on user assignments", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + } + ] + }, + { + "type" : "dict", + "key" : "status_update", + "label" : "Update status on task action", + "is_group" : true, + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "key" : "mapping", + "type" : "dict-modifiable", + "object_type" : { + "type" : "list", + "object_type" : "text" + } + } + ] + }, + { + "type" : "dict", + "key" : "status_task_to_parent", + "label" : "Sync status from Task to Parent", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "label", + "label" : "List of parent object types where this is triggered (\"Shot\", \"Asset Build\", etc.). Skipped if list is empty." + }, + { + "type" : "list", + "object_type" : "text", + "key" : "parent_object_types", + "label" : "Object types" + }, + { + "key" : "parent_status_match_all_task_statuses", + "type" : "dict-modifiable", + "label" : "Change parent if all tasks match", + "object_type" : { + "type" : "list", + "object_type" : "text" + } + }, + { + "type" : "list", + "key" : "parent_status_by_task_status", + "label" : "Change parent status if a single task matches", + "use_label_wrap" : true, + "object_type" : { + "type" : "dict", + "children" : [ + { + "type" : "text", + "label" : "New parent status", + "key" : "new_status" + }, + { + "type" : "separator" + }, + { + "type" : "list", + "label" : "Task status", + "key" : "task_statuses", + "object_type" : "text" + } + ] + } + } + ] + }, + { + "type" : "dict", + "key" : "status_task_to_version", + "label" : "Sync status from Task to Version", + "is_group" : true, + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "dict-modifiable", + "key" : "mapping", + "object_type" : { + "type" : "list", + "object_type" : "text" + } + }, + { + "type" : "label", + "label" : "Limit status changes to entered asset types. Limitation is ignored if nothing is entered." + }, + { + "type" : "list", + "key" : "asset_types_filter", + "label" : "Asset types (short)", + "object_type" : "text" + } + ] + }, + { + "type" : "dict", + "key" : "status_version_to_task", + "label" : "Sync status from Version to Task", + "is_group" : true, + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "label", + "label" : "Change Task status based on a changed Version status.
Version's new status on the left will trigger a change of a task status to the first available from the list on right.
- if no status from the list is available it will use the same status as the version." + }, + { + "type" : "dict-modifiable", + "key" : "mapping", + "object_type" : { + "type" : "list", + "object_type" : "text" + } + }, + { + "type" : "separator" + }, + { + "type" : "label", + "label" : "Disable event if status was changed on specific Asset type." + }, + { + "type" : "list", + "label" : "Asset types (short)", + "key" : "asset_types_to_skip", + "object_type" : "text" + } + ] + }, + { + "type" : "dict", + "key" : "first_version_status", + "label" : "Set status on first created version", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "text", + "key" : "status", + "label" : "Status" + } + ] + }, + { + "type" : "dict", + "key" : "next_task_update", + "is_group" : true, + "label" : "Update status on next task", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "label", + "label" : "Change status on next task by task types order when task status state changed to \"Done\". All tasks with same Task type must be \"Done\"." + }, + { + "type" : "label", + "label" : "Mapping of next task status changes From -> To." + }, + { + "type" : "dict-modifiable", + "key" : "mapping", + "object_type" : { + "type" : "text" + } + }, + { + "type" : "separator" + }, + { + "type" : "label", + "label" : "Status names that are ignored on \"Done\" check (e.g. \"Omitted\")." + }, + { + "type" : "list", + "key" : "ignored_statuses", + "object_type" : "text" + }, + { + "type" : "separator" + }, + { + "type" : "label", + "label" : "Allow to break rule that all tasks with same Task type must be \"Done\" and change statuses with same type tasks ordered by name." + }, + { + "label" : "Name sorting", + "type" : "boolean", + "key" : "name_sorting" + } + ] + } + ] + }, + { + "type" : "dict", + "key" : "user_handlers", + "label" : "User Actions/Events", + "children" : [ + { + "type" : "dict", + "key" : "application_launch_statuses", + "is_group" : true, + "label" : "Application - Status change on launch", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "label", + "label" : "Do not change status if current status is:" + }, + { + "type" : "list", + "key" : "ignored_statuses", + "object_type" : "text" + }, + { + "type" : "label", + "label" : "Change task's status to left side if current task status is in list on right side." + }, + { + "type" : "dict-modifiable", + "key" : "status_change", + "object_type" : { + "type" : "list", + "object_type" : "text" + } + } + ] + }, + { + "type" : "dict", + "key" : "create_update_attributes", + "label" : "Create/Update Avalon Attributes", + "children" : [ + { + "type" : "list", + "key" : "role_list", + "label" : "Roles", + "object_type" : "text" + } + ] + }, + { + "type" : "dict", + "key" : "prepare_project", + "label" : "Prepare Project", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "list", + "key" : "role_list", + "label" : "Roles", + "object_type" : "text" + }, + { + "type" : "separator" + }, + { + "type" : "label", + "label" : "Check \"Create project structure\" by default" + }, + { + "type" : "boolean", + "key" : "create_project_structure_checked", + "label" : "Checked" + } + ] + }, + { + "type" : "dict", + "key" : "clean_hierarchical_attr", + "label" : "Clean hierarchical custom attributes", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "list", + "key" : "role_list", + "label" : "Roles", + "object_type" : "text" + } + ] + }, + { + "type" : "dict", + "key" : "delete_asset_subset", + "label" : "Delete Asset/Subsets", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "list", + "key" : "role_list", + "label" : "Roles", + "object_type" : "text" + } + ] + }, + { + "type" : "dict", + "key" : "delete_old_versions", + "label" : "Delete old versions", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "list", + "key" : "role_list", + "label" : "Roles", + "object_type" : "text" + } + ] + }, + { + "type" : "dict", + "key" : "delivery_action", + "label" : "Delivery", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "list", + "key" : "role_list", + "label" : "Roles", + "object_type" : "text" + } + ] + }, + { + "type" : "dict", + "key" : "store_thubmnail_to_avalon", + "label" : "Store Thumbnails to avalon", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "list", + "key" : "role_list", + "label" : "Roles", + "object_type" : "text" + } + ] + }, + { + "type" : "dict", + "key" : "job_killer", + "label" : "Job Killer", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "list", + "key" : "role_list", + "label" : "Roles", + "object_type" : "text" + } + ] + }, + { + "type" : "dict", + "key" : "sync_to_avalon_local", + "label" : "Sync to avalon (local) - For development", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "list", + "key" : "role_list", + "label" : "Roles", + "object_type" : "text" + } + ] + }, + { + "type" : "dict", + "key" : "seed_project", + "label" : "Seed Debug Project", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "list", + "key" : "role_list", + "label" : "Roles", + "object_type" : "text" + } + ] + } + ] + }, + { + "type" : "dict", + "collapsible" : true, + "key" : "publish", + "label" : "Publish plugins", + "children" : [ + { + "type" : "dict", + "collapsible" : true, + "checkbox_key" : "enabled", + "key" : "CollectFtrackFamily", + "label" : "Collect Ftrack Family", + "is_group" : true, + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "list", + "collapsible" : true, + "key" : "profiles", + "label" : "Profiles", + "use_label_wrap" : true, + "object_type" : { + "type" : "dict", + "children" : [ + { + "key" : "hosts", + "label" : "Host names", + "type" : "list", + "object_type" : "text" + }, + { + "key" : "families", + "label" : "Families", + "type" : "list", + "object_type" : "text" + }, + { + "key" : "task_types", + "label" : "Task types", + "type" : "task-types-enum" + }, + { + "key" : "tasks", + "label" : "Task names", + "type" : "list", + "object_type" : "text" + }, + { + "type" : "separator" + }, + { + "key" : "add_ftrack_family", + "label" : "Add Ftrack Family", + "type" : "boolean" + }, + { + "type" : "list", + "collapsible" : true, + "key" : "advanced_filtering", + "label" : "Advanced adding if additional families present", + "use_label_wrap" : true, + "object_type" : { + "type" : "dict", + "children" : [ + { + "key" : "families", + "label" : "Additional Families", + "type" : "list", + "object_type" : "text" + }, + { + "key" : "add_ftrack_family", + "label" : "Add Ftrack Family", + "type" : "boolean" + } + ] + } + } + ] + } + } + ] + }, + { + "type" : "dict", + "collapsible" : true, + "checkbox_key" : "enabled", + "key" : "IntegrateFtrackNote", + "label" : "IntegrateFtrackNote", + "is_group" : true, + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "text", + "key" : "note_with_intent_template", + "label" : "Note with intent template" + }, + { + "type" : "list", + "object_type" : "text", + "key" : "note_labels", + "label" : "Note labels" + } + ] + }, + { + "type" : "dict", + "collapsible" : true, + "checkbox_key" : "enabled", + "key" : "ValidateFtrackAttributes", + "label" : "ValidateFtrackAttributes", + "is_group" : true, + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "raw-json", + "key" : "ftrack_custom_attributes", + "label" : "Custom attributes to validate" + } + ] + }, + { + "type" : "dict", + "collapsible" : true, + "checkbox_key" : "enabled", + "key" : "IntegrateFtrackInstance", + "label" : "IntegrateFtrackInstance", + "is_group" : true, + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "dict-modifiable", + "key" : "family_mapping", + "label" : "Family Mapping", + "object_type" : { + "type" : "text" + } + } + ] + } + ] + } + ] } From 2a00a6fd47c761ba7da2116df090b9b4e7f08ef6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Marinov?= Date: Fri, 28 Jan 2022 00:22:49 +0100 Subject: [PATCH 22/74] Added family_mapping defaults --- .../defaults/project_settings/ftrack.json | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/openpype/settings/defaults/project_settings/ftrack.json b/openpype/settings/defaults/project_settings/ftrack.json index 513611ebfb..0114bd163e 100644 --- a/openpype/settings/defaults/project_settings/ftrack.json +++ b/openpype/settings/defaults/project_settings/ftrack.json @@ -342,6 +342,30 @@ "ValidateFtrackAttributes": { "enabled": false, "ftrack_custom_attributes": {} + }, + "IntegrateFtrackInstance": { + "enabled": true, + "family_mapping": { + "camera": "cam", + "look": "look", + "mayaascii": "scene", + "model": "geo", + "rig": "rig", + "setdress": "setdress", + "pointcache": "cache", + "render": "render", + "render2d": "render", + "nukescript": "comp", + "write": "render", + "review": "mov", + "plate": "img", + "audio": "audio", + "workfile": "scene", + "animation": "cache", + "image": "img", + "reference": "reference", + "ass": "cache" + } } } -} \ No newline at end of file +} From 4b54c094e0086eb142b6182f10622c8c4175d514 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Marinov?= Date: Sat, 29 Jan 2022 20:03:17 +0100 Subject: [PATCH 23/74] Removed checkbox from IntegrateFtrackInstance --- .../schemas/projects_schema/schema_project_ftrack.json | 7 ------- 1 file changed, 7 deletions(-) diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json b/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json index 86c8b14747..6ab29699ee 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json @@ -744,17 +744,10 @@ }, { "type" : "dict", - "collapsible" : true, - "checkbox_key" : "enabled", "key" : "IntegrateFtrackInstance", "label" : "IntegrateFtrackInstance", "is_group" : true, "children" : [ - { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" - }, { "type" : "dict-modifiable", "key" : "family_mapping", From 5c22c45fa2d5d106d0b476b181ea38a51c12cfc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Marinov?= Date: Sat, 29 Jan 2022 21:00:20 +0100 Subject: [PATCH 24/74] Adding more defaults --- .../defaults/project_settings/ftrack.json | 52 +++++++++++-------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/openpype/settings/defaults/project_settings/ftrack.json b/openpype/settings/defaults/project_settings/ftrack.json index 0114bd163e..5975086872 100644 --- a/openpype/settings/defaults/project_settings/ftrack.json +++ b/openpype/settings/defaults/project_settings/ftrack.json @@ -344,27 +344,37 @@ "ftrack_custom_attributes": {} }, "IntegrateFtrackInstance": { - "enabled": true, - "family_mapping": { - "camera": "cam", - "look": "look", - "mayaascii": "scene", - "model": "geo", - "rig": "rig", - "setdress": "setdress", - "pointcache": "cache", - "render": "render", - "render2d": "render", - "nukescript": "comp", - "write": "render", - "review": "mov", - "plate": "img", - "audio": "audio", - "workfile": "scene", - "animation": "cache", - "image": "img", - "reference": "reference", - "ass": "cache" + "family_mapping" : { + "camera" : "cam", + "look" : "look", + "mayaascii" : "scene", + "model" : "geo", + "rig" : "rig", + "setdress" : "setdress", + "pointcache" : "cache", + "render" : "render", + "render2d" : "render", + "nukescript" : "comp", + "write" : "render", + "review" : "mov", + "plate" : "img", + "audio" : "audio", + "workfile" : "scene", + "animation" : "cache", + "image" : "img", + "reference" : "reference", + "ass" : "cache", + "mayaScene" : "scene", + "camerarig" : "rig", + "yeticache" : "cache", + "yetiRig" : "rig", + "xgen" : "xgen", + "rendersetup" : "rendersetup", + "assembly" : "assembly", + "layout" : "layout", + "unrealStaticMesh" : "geo", + "vrayproxy" : "cache", + "redshiftproxy" : "cache" } } } From 6c842c4f769b56117e113b1c4819b476f07db98f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Marinov?= Date: Mon, 31 Jan 2022 12:03:55 +0100 Subject: [PATCH 25/74] Update schema_project_ftrack.json tabs -> spaces --- .../schema_project_ftrack.json | 1524 ++++++++--------- 1 file changed, 762 insertions(+), 762 deletions(-) diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json b/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json index 6ab29699ee..14b7038cbe 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json @@ -1,764 +1,764 @@ { - "type" : "dict", - "key" : "ftrack", - "label" : "Ftrack", - "collapsible" : true, - "is_file" : true, - "children" : [ - { - "type" : "dict", - "key" : "events", - "label" : "Server Actions/Events", - "children" : [ - { - "type" : "dict", - "key" : "sync_to_avalon", - "label" : "Sync to avalon", - "children" : [ - { - "type" : "label", - "label" : "Allow name and hierarchy change only if following statuses are on all children tasks" - }, - { - "type" : "list", - "key" : "statuses_name_change", - "label" : "Statuses", - "object_type" : { - "type" : "text", - "multiline" : false - } - } - ] - }, - { - "type" : "dict", - "key" : "prepare_project", - "label" : "Prepare Project", - "checkbox_key" : "enabled", - "children" : [ - { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" - }, - { - "type" : "list", - "key" : "role_list", - "label" : "Roles", - "object_type" : "text" - } - ] - }, - { - "type" : "dict", - "key" : "sync_hier_entity_attributes", - "label" : "Sync Hierarchical and Entity Attributes", - "checkbox_key" : "enabled", - "children" : [ - { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" - }, - { - "type" : "list", - "key" : "interest_entity_types", - "label" : "Entity types of interest", - "object_type" : { - "type" : "text", - "multiline" : false - } - }, - { - "type" : "list", - "key" : "interest_attributes", - "label" : "Attributes to sync", - "object_type" : { - "type" : "text", - "multiline" : false - } - }, - { - "type" : "separator" - }, - { - "type" : "boolean", - "key" : "action_enabled", - "label" : "Enable Action" - }, - { - "type" : "list", - "key" : "role_list", - "label" : "Roles for action", - "object_type" : "text" - } - ] - }, - { - "type" : "dict", - "key" : "clone_review_session", - "label" : "Clone Review Session", - "checkbox_key" : "enabled", - "children" : [ - { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" - }, - { - "type" : "list", - "key" : "role_list", - "label" : "Roles for action", - "object_type" : "text" - } - ] - }, - { - "type" : "dict", - "key" : "thumbnail_updates", - "label" : "Update Hierarchy thumbnails", - "checkbox_key" : "enabled", - "children" : [ - { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" - }, - { - "type" : "label", - "label" : "Push thumbnail from version, up through multiple hierarchy levels." - }, - { - "type" : "number", - "key" : "levels", - "label" : "Levels" - } - ] - }, - { - "type" : "dict", - "key" : "user_assignment", - "label" : "Run script on user assignments", - "checkbox_key" : "enabled", - "children" : [ - { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" - } - ] - }, - { - "type" : "dict", - "key" : "status_update", - "label" : "Update status on task action", - "is_group" : true, - "checkbox_key" : "enabled", - "children" : [ - { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" - }, - { - "key" : "mapping", - "type" : "dict-modifiable", - "object_type" : { - "type" : "list", - "object_type" : "text" - } - } - ] - }, - { - "type" : "dict", - "key" : "status_task_to_parent", - "label" : "Sync status from Task to Parent", - "checkbox_key" : "enabled", - "children" : [ - { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" - }, - { - "type" : "label", - "label" : "List of parent object types where this is triggered (\"Shot\", \"Asset Build\", etc.). Skipped if list is empty." - }, - { - "type" : "list", - "object_type" : "text", - "key" : "parent_object_types", - "label" : "Object types" - }, - { - "key" : "parent_status_match_all_task_statuses", - "type" : "dict-modifiable", - "label" : "Change parent if all tasks match", - "object_type" : { - "type" : "list", - "object_type" : "text" - } - }, - { - "type" : "list", - "key" : "parent_status_by_task_status", - "label" : "Change parent status if a single task matches", - "use_label_wrap" : true, - "object_type" : { - "type" : "dict", - "children" : [ - { - "type" : "text", - "label" : "New parent status", - "key" : "new_status" - }, - { - "type" : "separator" - }, - { - "type" : "list", - "label" : "Task status", - "key" : "task_statuses", - "object_type" : "text" - } - ] - } - } - ] - }, - { - "type" : "dict", - "key" : "status_task_to_version", - "label" : "Sync status from Task to Version", - "is_group" : true, - "checkbox_key" : "enabled", - "children" : [ - { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" - }, - { - "type" : "dict-modifiable", - "key" : "mapping", - "object_type" : { - "type" : "list", - "object_type" : "text" - } - }, - { - "type" : "label", - "label" : "Limit status changes to entered asset types. Limitation is ignored if nothing is entered." - }, - { - "type" : "list", - "key" : "asset_types_filter", - "label" : "Asset types (short)", - "object_type" : "text" - } - ] - }, - { - "type" : "dict", - "key" : "status_version_to_task", - "label" : "Sync status from Version to Task", - "is_group" : true, - "checkbox_key" : "enabled", - "children" : [ - { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" - }, - { - "type" : "label", - "label" : "Change Task status based on a changed Version status.
Version's new status on the left will trigger a change of a task status to the first available from the list on right.
- if no status from the list is available it will use the same status as the version." - }, - { - "type" : "dict-modifiable", - "key" : "mapping", - "object_type" : { - "type" : "list", - "object_type" : "text" - } - }, - { - "type" : "separator" - }, - { - "type" : "label", - "label" : "Disable event if status was changed on specific Asset type." - }, - { - "type" : "list", - "label" : "Asset types (short)", - "key" : "asset_types_to_skip", - "object_type" : "text" - } - ] - }, - { - "type" : "dict", - "key" : "first_version_status", - "label" : "Set status on first created version", - "checkbox_key" : "enabled", - "children" : [ - { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" - }, - { - "type" : "text", - "key" : "status", - "label" : "Status" - } - ] - }, - { - "type" : "dict", - "key" : "next_task_update", - "is_group" : true, - "label" : "Update status on next task", - "checkbox_key" : "enabled", - "children" : [ - { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" - }, - { - "type" : "label", - "label" : "Change status on next task by task types order when task status state changed to \"Done\". All tasks with same Task type must be \"Done\"." - }, - { - "type" : "label", - "label" : "Mapping of next task status changes From -> To." - }, - { - "type" : "dict-modifiable", - "key" : "mapping", - "object_type" : { - "type" : "text" - } - }, - { - "type" : "separator" - }, - { - "type" : "label", - "label" : "Status names that are ignored on \"Done\" check (e.g. \"Omitted\")." - }, - { - "type" : "list", - "key" : "ignored_statuses", - "object_type" : "text" - }, - { - "type" : "separator" - }, - { - "type" : "label", - "label" : "Allow to break rule that all tasks with same Task type must be \"Done\" and change statuses with same type tasks ordered by name." - }, - { - "label" : "Name sorting", - "type" : "boolean", - "key" : "name_sorting" - } - ] - } - ] - }, - { - "type" : "dict", - "key" : "user_handlers", - "label" : "User Actions/Events", - "children" : [ - { - "type" : "dict", - "key" : "application_launch_statuses", - "is_group" : true, - "label" : "Application - Status change on launch", - "checkbox_key" : "enabled", - "children" : [ - { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" - }, - { - "type" : "label", - "label" : "Do not change status if current status is:" - }, - { - "type" : "list", - "key" : "ignored_statuses", - "object_type" : "text" - }, - { - "type" : "label", - "label" : "Change task's status to left side if current task status is in list on right side." - }, - { - "type" : "dict-modifiable", - "key" : "status_change", - "object_type" : { - "type" : "list", - "object_type" : "text" - } - } - ] - }, - { - "type" : "dict", - "key" : "create_update_attributes", - "label" : "Create/Update Avalon Attributes", - "children" : [ - { - "type" : "list", - "key" : "role_list", - "label" : "Roles", - "object_type" : "text" - } - ] - }, - { - "type" : "dict", - "key" : "prepare_project", - "label" : "Prepare Project", - "checkbox_key" : "enabled", - "children" : [ - { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" - }, - { - "type" : "list", - "key" : "role_list", - "label" : "Roles", - "object_type" : "text" - }, - { - "type" : "separator" - }, - { - "type" : "label", - "label" : "Check \"Create project structure\" by default" - }, - { - "type" : "boolean", - "key" : "create_project_structure_checked", - "label" : "Checked" - } - ] - }, - { - "type" : "dict", - "key" : "clean_hierarchical_attr", - "label" : "Clean hierarchical custom attributes", - "checkbox_key" : "enabled", - "children" : [ - { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" - }, - { - "type" : "list", - "key" : "role_list", - "label" : "Roles", - "object_type" : "text" - } - ] - }, - { - "type" : "dict", - "key" : "delete_asset_subset", - "label" : "Delete Asset/Subsets", - "checkbox_key" : "enabled", - "children" : [ - { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" - }, - { - "type" : "list", - "key" : "role_list", - "label" : "Roles", - "object_type" : "text" - } - ] - }, - { - "type" : "dict", - "key" : "delete_old_versions", - "label" : "Delete old versions", - "checkbox_key" : "enabled", - "children" : [ - { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" - }, - { - "type" : "list", - "key" : "role_list", - "label" : "Roles", - "object_type" : "text" - } - ] - }, - { - "type" : "dict", - "key" : "delivery_action", - "label" : "Delivery", - "checkbox_key" : "enabled", - "children" : [ - { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" - }, - { - "type" : "list", - "key" : "role_list", - "label" : "Roles", - "object_type" : "text" - } - ] - }, - { - "type" : "dict", - "key" : "store_thubmnail_to_avalon", - "label" : "Store Thumbnails to avalon", - "checkbox_key" : "enabled", - "children" : [ - { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" - }, - { - "type" : "list", - "key" : "role_list", - "label" : "Roles", - "object_type" : "text" - } - ] - }, - { - "type" : "dict", - "key" : "job_killer", - "label" : "Job Killer", - "checkbox_key" : "enabled", - "children" : [ - { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" - }, - { - "type" : "list", - "key" : "role_list", - "label" : "Roles", - "object_type" : "text" - } - ] - }, - { - "type" : "dict", - "key" : "sync_to_avalon_local", - "label" : "Sync to avalon (local) - For development", - "checkbox_key" : "enabled", - "children" : [ - { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" - }, - { - "type" : "list", - "key" : "role_list", - "label" : "Roles", - "object_type" : "text" - } - ] - }, - { - "type" : "dict", - "key" : "seed_project", - "label" : "Seed Debug Project", - "checkbox_key" : "enabled", - "children" : [ - { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" - }, - { - "type" : "list", - "key" : "role_list", - "label" : "Roles", - "object_type" : "text" - } - ] - } - ] - }, - { - "type" : "dict", - "collapsible" : true, - "key" : "publish", - "label" : "Publish plugins", - "children" : [ - { - "type" : "dict", - "collapsible" : true, - "checkbox_key" : "enabled", - "key" : "CollectFtrackFamily", - "label" : "Collect Ftrack Family", - "is_group" : true, - "children" : [ - { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" - }, - { - "type" : "list", - "collapsible" : true, - "key" : "profiles", - "label" : "Profiles", - "use_label_wrap" : true, - "object_type" : { - "type" : "dict", - "children" : [ - { - "key" : "hosts", - "label" : "Host names", - "type" : "list", - "object_type" : "text" - }, - { - "key" : "families", - "label" : "Families", - "type" : "list", - "object_type" : "text" - }, - { - "key" : "task_types", - "label" : "Task types", - "type" : "task-types-enum" - }, - { - "key" : "tasks", - "label" : "Task names", - "type" : "list", - "object_type" : "text" - }, - { - "type" : "separator" - }, - { - "key" : "add_ftrack_family", - "label" : "Add Ftrack Family", - "type" : "boolean" - }, - { - "type" : "list", - "collapsible" : true, - "key" : "advanced_filtering", - "label" : "Advanced adding if additional families present", - "use_label_wrap" : true, - "object_type" : { - "type" : "dict", - "children" : [ - { - "key" : "families", - "label" : "Additional Families", - "type" : "list", - "object_type" : "text" - }, - { - "key" : "add_ftrack_family", - "label" : "Add Ftrack Family", - "type" : "boolean" - } - ] - } - } - ] - } - } - ] - }, - { - "type" : "dict", - "collapsible" : true, - "checkbox_key" : "enabled", - "key" : "IntegrateFtrackNote", - "label" : "IntegrateFtrackNote", - "is_group" : true, - "children" : [ - { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" - }, - { - "type" : "text", - "key" : "note_with_intent_template", - "label" : "Note with intent template" - }, - { - "type" : "list", - "object_type" : "text", - "key" : "note_labels", - "label" : "Note labels" - } - ] - }, - { - "type" : "dict", - "collapsible" : true, - "checkbox_key" : "enabled", - "key" : "ValidateFtrackAttributes", - "label" : "ValidateFtrackAttributes", - "is_group" : true, - "children" : [ - { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" - }, - { - "type" : "raw-json", - "key" : "ftrack_custom_attributes", - "label" : "Custom attributes to validate" - } - ] - }, - { - "type" : "dict", - "key" : "IntegrateFtrackInstance", - "label" : "IntegrateFtrackInstance", - "is_group" : true, - "children" : [ - { - "type" : "dict-modifiable", - "key" : "family_mapping", - "label" : "Family Mapping", - "object_type" : { - "type" : "text" - } - } - ] - } - ] - } - ] + "type" : "dict", + "key" : "ftrack", + "label" : "Ftrack", + "collapsible" : true, + "is_file" : true, + "children" : [ + { + "type" : "dict", + "key" : "events", + "label" : "Server Actions/Events", + "children" : [ + { + "type" : "dict", + "key" : "sync_to_avalon", + "label" : "Sync to avalon", + "children" : [ + { + "type" : "label", + "label" : "Allow name and hierarchy change only if following statuses are on all children tasks" + }, + { + "type" : "list", + "key" : "statuses_name_change", + "label" : "Statuses", + "object_type" : { + "type" : "text", + "multiline" : false + } + } + ] + }, + { + "type" : "dict", + "key" : "prepare_project", + "label" : "Prepare Project", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "list", + "key" : "role_list", + "label" : "Roles", + "object_type" : "text" + } + ] + }, + { + "type" : "dict", + "key" : "sync_hier_entity_attributes", + "label" : "Sync Hierarchical and Entity Attributes", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "list", + "key" : "interest_entity_types", + "label" : "Entity types of interest", + "object_type" : { + "type" : "text", + "multiline" : false + } + }, + { + "type" : "list", + "key" : "interest_attributes", + "label" : "Attributes to sync", + "object_type" : { + "type" : "text", + "multiline" : false + } + }, + { + "type" : "separator" + }, + { + "type" : "boolean", + "key" : "action_enabled", + "label" : "Enable Action" + }, + { + "type" : "list", + "key" : "role_list", + "label" : "Roles for action", + "object_type" : "text" + } + ] + }, + { + "type" : "dict", + "key" : "clone_review_session", + "label" : "Clone Review Session", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "list", + "key" : "role_list", + "label" : "Roles for action", + "object_type" : "text" + } + ] + }, + { + "type" : "dict", + "key" : "thumbnail_updates", + "label" : "Update Hierarchy thumbnails", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "label", + "label" : "Push thumbnail from version, up through multiple hierarchy levels." + }, + { + "type" : "number", + "key" : "levels", + "label" : "Levels" + } + ] + }, + { + "type" : "dict", + "key" : "user_assignment", + "label" : "Run script on user assignments", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + } + ] + }, + { + "type" : "dict", + "key" : "status_update", + "label" : "Update status on task action", + "is_group" : true, + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "key" : "mapping", + "type" : "dict-modifiable", + "object_type" : { + "type" : "list", + "object_type" : "text" + } + } + ] + }, + { + "type" : "dict", + "key" : "status_task_to_parent", + "label" : "Sync status from Task to Parent", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "label", + "label" : "List of parent object types where this is triggered (\"Shot\", \"Asset Build\", etc.). Skipped if list is empty." + }, + { + "type" : "list", + "object_type" : "text", + "key" : "parent_object_types", + "label" : "Object types" + }, + { + "key" : "parent_status_match_all_task_statuses", + "type" : "dict-modifiable", + "label" : "Change parent if all tasks match", + "object_type" : { + "type" : "list", + "object_type" : "text" + } + }, + { + "type" : "list", + "key" : "parent_status_by_task_status", + "label" : "Change parent status if a single task matches", + "use_label_wrap" : true, + "object_type" : { + "type" : "dict", + "children" : [ + { + "type" : "text", + "label" : "New parent status", + "key" : "new_status" + }, + { + "type" : "separator" + }, + { + "type" : "list", + "label" : "Task status", + "key" : "task_statuses", + "object_type" : "text" + } + ] + } + } + ] + }, + { + "type" : "dict", + "key" : "status_task_to_version", + "label" : "Sync status from Task to Version", + "is_group" : true, + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "dict-modifiable", + "key" : "mapping", + "object_type" : { + "type" : "list", + "object_type" : "text" + } + }, + { + "type" : "label", + "label" : "Limit status changes to entered asset types. Limitation is ignored if nothing is entered." + }, + { + "type" : "list", + "key" : "asset_types_filter", + "label" : "Asset types (short)", + "object_type" : "text" + } + ] + }, + { + "type" : "dict", + "key" : "status_version_to_task", + "label" : "Sync status from Version to Task", + "is_group" : true, + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "label", + "label" : "Change Task status based on a changed Version status.
Version's new status on the left will trigger a change of a task status to the first available from the list on right.
- if no status from the list is available it will use the same status as the version." + }, + { + "type" : "dict-modifiable", + "key" : "mapping", + "object_type" : { + "type" : "list", + "object_type" : "text" + } + }, + { + "type" : "separator" + }, + { + "type" : "label", + "label" : "Disable event if status was changed on specific Asset type." + }, + { + "type" : "list", + "label" : "Asset types (short)", + "key" : "asset_types_to_skip", + "object_type" : "text" + } + ] + }, + { + "type" : "dict", + "key" : "first_version_status", + "label" : "Set status on first created version", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "text", + "key" : "status", + "label" : "Status" + } + ] + }, + { + "type" : "dict", + "key" : "next_task_update", + "is_group" : true, + "label" : "Update status on next task", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "label", + "label" : "Change status on next task by task types order when task status state changed to \"Done\". All tasks with same Task type must be \"Done\"." + }, + { + "type" : "label", + "label" : "Mapping of next task status changes From -> To." + }, + { + "type" : "dict-modifiable", + "key" : "mapping", + "object_type" : { + "type" : "text" + } + }, + { + "type" : "separator" + }, + { + "type" : "label", + "label" : "Status names that are ignored on \"Done\" check (e.g. \"Omitted\")." + }, + { + "type" : "list", + "key" : "ignored_statuses", + "object_type" : "text" + }, + { + "type" : "separator" + }, + { + "type" : "label", + "label" : "Allow to break rule that all tasks with same Task type must be \"Done\" and change statuses with same type tasks ordered by name." + }, + { + "label" : "Name sorting", + "type" : "boolean", + "key" : "name_sorting" + } + ] + } + ] + }, + { + "type" : "dict", + "key" : "user_handlers", + "label" : "User Actions/Events", + "children" : [ + { + "type" : "dict", + "key" : "application_launch_statuses", + "is_group" : true, + "label" : "Application - Status change on launch", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "label", + "label" : "Do not change status if current status is:" + }, + { + "type" : "list", + "key" : "ignored_statuses", + "object_type" : "text" + }, + { + "type" : "label", + "label" : "Change task's status to left side if current task status is in list on right side." + }, + { + "type" : "dict-modifiable", + "key" : "status_change", + "object_type" : { + "type" : "list", + "object_type" : "text" + } + } + ] + }, + { + "type" : "dict", + "key" : "create_update_attributes", + "label" : "Create/Update Avalon Attributes", + "children" : [ + { + "type" : "list", + "key" : "role_list", + "label" : "Roles", + "object_type" : "text" + } + ] + }, + { + "type" : "dict", + "key" : "prepare_project", + "label" : "Prepare Project", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "list", + "key" : "role_list", + "label" : "Roles", + "object_type" : "text" + }, + { + "type" : "separator" + }, + { + "type" : "label", + "label" : "Check \"Create project structure\" by default" + }, + { + "type" : "boolean", + "key" : "create_project_structure_checked", + "label" : "Checked" + } + ] + }, + { + "type" : "dict", + "key" : "clean_hierarchical_attr", + "label" : "Clean hierarchical custom attributes", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "list", + "key" : "role_list", + "label" : "Roles", + "object_type" : "text" + } + ] + }, + { + "type" : "dict", + "key" : "delete_asset_subset", + "label" : "Delete Asset/Subsets", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "list", + "key" : "role_list", + "label" : "Roles", + "object_type" : "text" + } + ] + }, + { + "type" : "dict", + "key" : "delete_old_versions", + "label" : "Delete old versions", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "list", + "key" : "role_list", + "label" : "Roles", + "object_type" : "text" + } + ] + }, + { + "type" : "dict", + "key" : "delivery_action", + "label" : "Delivery", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "list", + "key" : "role_list", + "label" : "Roles", + "object_type" : "text" + } + ] + }, + { + "type" : "dict", + "key" : "store_thubmnail_to_avalon", + "label" : "Store Thumbnails to avalon", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "list", + "key" : "role_list", + "label" : "Roles", + "object_type" : "text" + } + ] + }, + { + "type" : "dict", + "key" : "job_killer", + "label" : "Job Killer", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "list", + "key" : "role_list", + "label" : "Roles", + "object_type" : "text" + } + ] + }, + { + "type" : "dict", + "key" : "sync_to_avalon_local", + "label" : "Sync to avalon (local) - For development", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "list", + "key" : "role_list", + "label" : "Roles", + "object_type" : "text" + } + ] + }, + { + "type" : "dict", + "key" : "seed_project", + "label" : "Seed Debug Project", + "checkbox_key" : "enabled", + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "list", + "key" : "role_list", + "label" : "Roles", + "object_type" : "text" + } + ] + } + ] + }, + { + "type" : "dict", + "collapsible" : true, + "key" : "publish", + "label" : "Publish plugins", + "children" : [ + { + "type" : "dict", + "collapsible" : true, + "checkbox_key" : "enabled", + "key" : "CollectFtrackFamily", + "label" : "Collect Ftrack Family", + "is_group" : true, + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "list", + "collapsible" : true, + "key" : "profiles", + "label" : "Profiles", + "use_label_wrap" : true, + "object_type" : { + "type" : "dict", + "children" : [ + { + "key" : "hosts", + "label" : "Host names", + "type" : "list", + "object_type" : "text" + }, + { + "key" : "families", + "label" : "Families", + "type" : "list", + "object_type" : "text" + }, + { + "key" : "task_types", + "label" : "Task types", + "type" : "task-types-enum" + }, + { + "key" : "tasks", + "label" : "Task names", + "type" : "list", + "object_type" : "text" + }, + { + "type" : "separator" + }, + { + "key" : "add_ftrack_family", + "label" : "Add Ftrack Family", + "type" : "boolean" + }, + { + "type" : "list", + "collapsible" : true, + "key" : "advanced_filtering", + "label" : "Advanced adding if additional families present", + "use_label_wrap" : true, + "object_type" : { + "type" : "dict", + "children" : [ + { + "key" : "families", + "label" : "Additional Families", + "type" : "list", + "object_type" : "text" + }, + { + "key" : "add_ftrack_family", + "label" : "Add Ftrack Family", + "type" : "boolean" + } + ] + } + } + ] + } + } + ] + }, + { + "type" : "dict", + "collapsible" : true, + "checkbox_key" : "enabled", + "key" : "IntegrateFtrackNote", + "label" : "IntegrateFtrackNote", + "is_group" : true, + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "text", + "key" : "note_with_intent_template", + "label" : "Note with intent template" + }, + { + "type" : "list", + "object_type" : "text", + "key" : "note_labels", + "label" : "Note labels" + } + ] + }, + { + "type" : "dict", + "collapsible" : true, + "checkbox_key" : "enabled", + "key" : "ValidateFtrackAttributes", + "label" : "ValidateFtrackAttributes", + "is_group" : true, + "children" : [ + { + "type" : "boolean", + "key" : "enabled", + "label" : "Enabled" + }, + { + "type" : "raw-json", + "key" : "ftrack_custom_attributes", + "label" : "Custom attributes to validate" + } + ] + }, + { + "type" : "dict", + "key" : "IntegrateFtrackInstance", + "label" : "IntegrateFtrackInstance", + "is_group" : true, + "children" : [ + { + "type" : "dict-modifiable", + "key" : "family_mapping", + "label" : "Family Mapping", + "object_type" : { + "type" : "text" + } + } + ] + } + ] + } + ] } From 213ee7e0777071463200d824e0b4c4c9f764da4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Marinov?= Date: Mon, 31 Jan 2022 12:18:12 +0100 Subject: [PATCH 26/74] Saved json from settings instead of direct editing --- .../defaults/project_settings/ftrack.json | 60 +++++++++---------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/openpype/settings/defaults/project_settings/ftrack.json b/openpype/settings/defaults/project_settings/ftrack.json index 5975086872..0917de9562 100644 --- a/openpype/settings/defaults/project_settings/ftrack.json +++ b/openpype/settings/defaults/project_settings/ftrack.json @@ -344,37 +344,35 @@ "ftrack_custom_attributes": {} }, "IntegrateFtrackInstance": { - "family_mapping" : { - "camera" : "cam", - "look" : "look", - "mayaascii" : "scene", - "model" : "geo", - "rig" : "rig", - "setdress" : "setdress", - "pointcache" : "cache", - "render" : "render", - "render2d" : "render", - "nukescript" : "comp", - "write" : "render", - "review" : "mov", - "plate" : "img", - "audio" : "audio", - "workfile" : "scene", - "animation" : "cache", - "image" : "img", - "reference" : "reference", - "ass" : "cache", - "mayaScene" : "scene", - "camerarig" : "rig", - "yeticache" : "cache", - "yetiRig" : "rig", - "xgen" : "xgen", - "rendersetup" : "rendersetup", - "assembly" : "assembly", - "layout" : "layout", - "unrealStaticMesh" : "geo", - "vrayproxy" : "cache", - "redshiftproxy" : "cache" + "family_mapping": { + "camera": "cam", + "look": "look", + "mayaascii": "scene", + "model": "geo", + "rig": "rig", + "setdress": "setdress", + "pointcache": "cache", + "render": "render", + "render2d": "render", + "nukescript": "comp", + "write": "render", + "review": "mov", + "plate": "img", + "audio": "audio", + "workfile": "scene", + "animation": "cache", + "image": "img", + "reference": "reference", + "ass": "cache", + "mayaScene": "scene", + "camerarig": "rig", + "yeticache": "cache", + "yetiRig": "rig", + "xgen": "xgen", + "rendersetup": "rendersetup", + "assembly": "assembly", + "layout": "layout", + "unrealStaticMesh": "geo" } } } From e5ddac1101dd42a09162263546ccaf47accbed4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Marinov?= Date: Mon, 31 Jan 2022 12:24:08 +0100 Subject: [PATCH 27/74] Added two missing defaults --- openpype/settings/defaults/project_settings/ftrack.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openpype/settings/defaults/project_settings/ftrack.json b/openpype/settings/defaults/project_settings/ftrack.json index 0917de9562..a684946758 100644 --- a/openpype/settings/defaults/project_settings/ftrack.json +++ b/openpype/settings/defaults/project_settings/ftrack.json @@ -372,7 +372,9 @@ "rendersetup": "rendersetup", "assembly": "assembly", "layout": "layout", - "unrealStaticMesh": "geo" + "unrealStaticMesh": "geo", + "vrayproxy": "cache", + "redshiftproxy": "cache" } } } From 29c4adb50788323fd07fb314b5846734acf4a1a6 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 31 Jan 2022 12:55:41 +0100 Subject: [PATCH 28/74] Fix - safer pulling of task name for webpublishing from PS --- .../publish/collect_remote_instances.py | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/openpype/hosts/photoshop/plugins/publish/collect_remote_instances.py b/openpype/hosts/photoshop/plugins/publish/collect_remote_instances.py index 3994048f7d..2a07c684da 100644 --- a/openpype/hosts/photoshop/plugins/publish/collect_remote_instances.py +++ b/openpype/hosts/photoshop/plugins/publish/collect_remote_instances.py @@ -4,7 +4,7 @@ import re import pyblish.api from openpype.lib import prepare_template_data -from openpype.lib.plugin_tools import parse_json +from openpype.lib.plugin_tools import parse_json, get_batch_asset_task_info from openpype.hosts.photoshop import api as photoshop @@ -29,26 +29,32 @@ class CollectRemoteInstances(pyblish.api.ContextPlugin): def process(self, context): self.log.info("CollectRemoteInstances") - self.log.info("mapping:: {}".format(self.color_code_mapping)) + self.log.debug("mapping:: {}".format(self.color_code_mapping)) # parse variant if used in webpublishing, comes from webpublisher batch batch_dir = os.environ.get("OPENPYPE_PUBLISH_DATA") - variant = "Main" + task_data = None if batch_dir and os.path.exists(batch_dir): # TODO check if batch manifest is same as tasks manifests task_data = parse_json(os.path.join(batch_dir, "manifest.json")) - if not task_data: - raise ValueError( - "Cannot parse batch meta in {} folder".format(batch_dir)) - variant = task_data["variant"] + if not task_data: + raise ValueError( + "Cannot parse batch meta in {} folder".format(batch_dir)) + variant = task_data["variant"] stub = photoshop.stub() layers = stub.get_layers() + asset, task_name, task_type = get_batch_asset_task_info( + task_data["context"]) + + if not task_name: + task_name = task_type + instance_names = [] for layer in layers: - self.log.info("Layer:: {}".format(layer)) + self.log.debug("Layer:: {}".format(layer)) resolved_family, resolved_subset_template = self._resolve_mapping( layer ) @@ -57,7 +63,7 @@ class CollectRemoteInstances(pyblish.api.ContextPlugin): resolved_subset_template)) if not resolved_subset_template or not resolved_family: - self.log.debug("!!! Not marked, skip") + self.log.debug("!!! Not found family or template, skip") continue if layer.parents: @@ -68,8 +74,8 @@ class CollectRemoteInstances(pyblish.api.ContextPlugin): instance.append(layer) instance.data["family"] = resolved_family instance.data["publish"] = layer.visible - instance.data["asset"] = context.data["assetEntity"]["name"] - instance.data["task"] = context.data["task"] + instance.data["asset"] = asset + instance.data["task"] = task_name fill_pairs = { "variant": variant, @@ -114,7 +120,6 @@ class CollectRemoteInstances(pyblish.api.ContextPlugin): family_list.append(mapping["family"]) subset_name_list.append(mapping["subset_template_name"]) - if len(subset_name_list) > 1: self.log.warning("Multiple mappings found for '{}'". format(layer.name)) From 2e2d8009ae281835f5400449898a1bca160f106c Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 31 Jan 2022 23:35:48 +0100 Subject: [PATCH 29/74] Fix common typos in openpype/website --- website/docs/admin_distribute.md | 2 +- website/docs/admin_hosts_resolve.md | 2 +- website/docs/admin_hosts_tvpaint.md | 2 +- website/docs/admin_openpype_commands.md | 2 +- website/docs/admin_settings.md | 6 +++--- .../docs/admin_settings_project_anatomy.md | 2 +- website/docs/admin_settings_system.md | 2 +- .../docs/admin_webserver_for_webpublisher.md | 2 +- website/docs/artist_concepts.md | 2 +- website/docs/artist_getting_started.md | 4 ++-- website/docs/artist_hosts_aftereffects.md | 6 +++--- website/docs/artist_hosts_hiero.md | 14 ++++++------- website/docs/artist_hosts_maya.md | 8 ++++---- website/docs/artist_hosts_nuke_tut.md | 4 ++-- website/docs/artist_hosts_photoshop.md | 2 +- website/docs/artist_hosts_resolve.md | 4 ++-- website/docs/artist_hosts_unreal.md | 4 ++-- website/docs/artist_publish.md | 2 +- website/docs/artist_tools.md | 4 ++-- website/docs/changelog.md | 2 +- website/docs/dev_build.md | 4 ++-- website/docs/dev_contribute.md | 4 ++-- website/docs/features.md | 2 +- website/docs/module_ftrack.md | 2 +- website/docs/module_site_sync.md | 20 +++++++++---------- .../settings_project_global.md | 6 +++--- .../project_settings/settings_project_nuke.md | 6 +++--- .../settings_project_standalone.md | 2 +- website/docs/pype2/admin_anatomy.md | 2 +- website/docs/pype2/admin_config.md | 8 ++++---- website/docs/pype2/admin_ftrack.md | 6 +++--- website/docs/pype2/admin_install.md | 2 +- website/docs/pype2/admin_introduction.md | 2 +- website/docs/pype2/admin_presets_ftrack.md | 2 +- .../docs/pype2/admin_presets_nukestudio.md | 4 ++-- website/docs/pype2/admin_presets_plugins.md | 10 +++++----- website/docs/pype2/admin_presets_tools.md | 4 ++-- website/docs/pype2/admin_pype_commands.md | 6 +++--- .../docs/pype2/admin_setup_troubleshooting.md | 4 ++-- website/docs/upgrade_notes.md | 2 +- website/docusaurus.config.js | 2 +- 41 files changed, 88 insertions(+), 88 deletions(-) diff --git a/website/docs/admin_distribute.md b/website/docs/admin_distribute.md index b574a21cb2..207e43563b 100644 --- a/website/docs/admin_distribute.md +++ b/website/docs/admin_distribute.md @@ -32,7 +32,7 @@ You have two ways of making this happen #### Automatic Updates -Everytime and Artist launches OpenPype on their workstation, it will look to a pre-defined +Every time and Artist launches OpenPype on their workstation, it will look to a pre-defined [openPype update location](#self) for any versions that are newer than the latest, locally installed version. If such version is found, it will be downloaded, automatically extracted to the correct place and launched. This will become the default diff --git a/website/docs/admin_hosts_resolve.md b/website/docs/admin_hosts_resolve.md index d2e027205d..09e7df1d9f 100644 --- a/website/docs/admin_hosts_resolve.md +++ b/website/docs/admin_hosts_resolve.md @@ -89,7 +89,7 @@ paste to any terminal of your choice
-As it is shown in bellow picture you have to go to Fusion Tab and then in Fusion menu find Fusion Settings. Go to Fusion/Script and find Default Python Version and swith to Python 3.6 +As it is shown in below picture you have to go to Fusion Tab and then in Fusion menu find Fusion Settings. Go to Fusion/Script and find Default Python Version and switch to Python 3.6
diff --git a/website/docs/admin_hosts_tvpaint.md b/website/docs/admin_hosts_tvpaint.md index a99cd19010..a900ce96a8 100644 --- a/website/docs/admin_hosts_tvpaint.md +++ b/website/docs/admin_hosts_tvpaint.md @@ -8,7 +8,7 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; ## Subset name templates -Definition of possibile subset name templates in TVPaint integration. +Definition of possible subset name templates in TVPaint integration. ### [Render Layer](artist_hosts_tvpaint#render-layer) Render layer has additional keys for subset name template. It is possible to use **render_layer** and **render_pass**. diff --git a/website/docs/admin_openpype_commands.md b/website/docs/admin_openpype_commands.md index 0831cf4f5a..c17bca70ad 100644 --- a/website/docs/admin_openpype_commands.md +++ b/website/docs/admin_openpype_commands.md @@ -100,7 +100,7 @@ pype launch --app python --project my_project --asset my_asset --task my_task | Argument | Description | | --- | --- | -| `--debug` | print more verbose infomation | +| `--debug` | print more verbose information | ```shell pype publish diff --git a/website/docs/admin_settings.md b/website/docs/admin_settings.md index 0cd10f81dc..abc64a1cc9 100644 --- a/website/docs/admin_settings.md +++ b/website/docs/admin_settings.md @@ -34,7 +34,7 @@ availability. ### [Project](admin_settings_project) -Project tab contains most of OpenPype settings and all of them can be configured and overriden on a per-project basis if need be. This includes most of the workflow behaviors +Project tab contains most of OpenPype settings and all of them can be configured and overridden on a per-project basis if need be. This includes most of the workflow behaviors like what formats to export, naming conventions, publishing validations, automatic assets loaders and a lot more. We recommend to try to keep as many configurations as possible on a studio level and only override selectively, because micromanaging all of the project settings might become cumbersome down the line. Most of the settings can be safely adjusted and locked on a project @@ -42,7 +42,7 @@ after the production started. ## Understanding Overrides -Most of the individual settings can be set and overriden on multiple levels. +Most of the individual settings can be set and overridden on multiple levels. ### OpenPype defaults When you first open settings all of the values and categories will be marked with a @@ -72,7 +72,7 @@ You can also reset any settings to OpenPype default by doing `right click` and ` ### Project Overrides -Many settings are usefull to be adjusted on a per-project basis. To identify project +Many settings are useful to be adjusted on a per-project basis. To identify project overrides, they are marked with **orange edge** and **orange labels** in the settings GUI. To set project overrides proceed the same way as with the Studio defaults, but first select diff --git a/website/docs/admin_settings_project_anatomy.md b/website/docs/admin_settings_project_anatomy.md index 1f742c31ed..98003dc381 100644 --- a/website/docs/admin_settings_project_anatomy.md +++ b/website/docs/admin_settings_project_anatomy.md @@ -64,7 +64,7 @@ We have a few required anatomy templates for OpenPype to work properly, however | `version` | Version number | | `subset` | Subset name | | `family` | Main family name | -| `ext` | File extention | +| `ext` | File extension | | `representation` | Representation name | | `frame` | Frame number for sequence files. | | `output` | | diff --git a/website/docs/admin_settings_system.md b/website/docs/admin_settings_system.md index 78be9fb01e..7310de9562 100644 --- a/website/docs/admin_settings_system.md +++ b/website/docs/admin_settings_system.md @@ -124,7 +124,7 @@ also called a `Host` and these two terms might be used interchangeably in the do Each Host is made of two levels. 1. **Application group** - This is the main name of the application and you can define extra environments that are applicable to all versions of the given application. For example any extra Maya scripts that are not -version dependant, can be added to `Maya` environment here. +version dependent, can be added to `Maya` environment here. 2. **Application versions** - Here you can define executables (per platform) for each supported version of the DCC and any default arguments (`--nukex` for instance). You can also further extend it's environment. diff --git a/website/docs/admin_webserver_for_webpublisher.md b/website/docs/admin_webserver_for_webpublisher.md index 6e72ccaf32..dbc67233b5 100644 --- a/website/docs/admin_webserver_for_webpublisher.md +++ b/website/docs/admin_webserver_for_webpublisher.md @@ -10,7 +10,7 @@ import TabItem from '@theme/TabItem'; Running Openpype webserver is needed as a backend part for Web publishing. Any OS supported by Openpype could be used as a host server. -Webpublishing consists of two sides, Front end (FE) and Openpype backend. This documenation is only targeted on OP side. +Webpublishing consists of two sides, Front end (FE) and Openpype backend. This documentation is only targeted on OP side. It is expected that FE and OP will live on two separate servers, FE publicly available, OP safely in customer network. diff --git a/website/docs/artist_concepts.md b/website/docs/artist_concepts.md index 6046ba6214..9a0096efde 100644 --- a/website/docs/artist_concepts.md +++ b/website/docs/artist_concepts.md @@ -12,7 +12,7 @@ In our pipeline all the main entities the project is made from are internally co ### Subset -Usually, an asset needs to be created in multiple *'flavours'*. A character might have multiple different looks, model needs to be published in different resolutions, a standard animation rig might not be useable in a crowd system and so on. 'Subsets' are here to accommodate all this variety that might be needed within a single asset. A model might have subset: *'main'*, *'proxy'*, *'sculpt'*, while data of *'look'* family could have subsets *'main'*, *'dirty'*, *'damaged'*. Subsets have some recommendations for their names, but ultimately it's up to the artist to use them for separation of publishes when needed. +Usually, an asset needs to be created in multiple *'flavours'*. A character might have multiple different looks, model needs to be published in different resolutions, a standard animation rig might not be usable in a crowd system and so on. 'Subsets' are here to accommodate all this variety that might be needed within a single asset. A model might have subset: *'main'*, *'proxy'*, *'sculpt'*, while data of *'look'* family could have subsets *'main'*, *'dirty'*, *'damaged'*. Subsets have some recommendations for their names, but ultimately it's up to the artist to use them for separation of publishes when needed. ### Version diff --git a/website/docs/artist_getting_started.md b/website/docs/artist_getting_started.md index be1960a38c..4e448fbd02 100644 --- a/website/docs/artist_getting_started.md +++ b/website/docs/artist_getting_started.md @@ -24,7 +24,7 @@ To use it, you have two options **openpype_gui.exe** is the most common for artists. It runs OpenPype GUI in system tray. From there you can run all the available tools. To use any of the features, OpenPype must be running in the tray. -**openpype_console.exe** in usefull for debugging and error reporting. It opens console window where all the necessary information will appear during user's work. +**openpype_console.exe** in useful for debugging and error reporting. It opens console window where all the necessary information will appear during user's work.
@@ -95,8 +95,8 @@ With OpenPype, you can use Hiero/NKS as a starting point for creating a project'



### Preparing timeline for conversion to instances -Because we don't support on-fly data conversion so in case of working with raw camera sources or some other formats which need to be converted for 2D/3D work. We suggest to convert those before and reconform the timeline. Before any clips in timeline could be converted to publishable instances we recomend following. -1. Merge all tracks which supposed to be one and they are multipy only because of editor's style +Because we don't support on-fly data conversion so in case of working with raw camera sources or some other formats which need to be converted for 2D/3D work. We suggest to convert those before and reconform the timeline. Before any clips in timeline could be converted to publishable instances we recommend following. +1. Merge all tracks which supposed to be one and they are multiply only because of editor's style 2. Rename tracks to follow basic structure > if only one layer then `main` in case of multiple layer (elements) for one shot then `main`, and other elements for example: `bg`, `greenscreen`, `fg01`, `fg02`, `display01`, etc. please avoid using [-/_.,%&*] or spaces. These names will be later used in *subset* name creation as `{family}{trackName}` so for example **plateMain** or **plateFg01** 3. Define correct `Set Media Color Transform` at all clips as those will be also published to metadata and used for later loading with correct color transformation. 4. Reviewable video material which you wish to be used as preview videos on any supported Projec manager platform (Ftrack) has to be added ideally to track named **review**. This can be offline edit used as reference video for 2D/3D artists. This video material can be edited to fit length of **main** timeline track or it cand be one long video clip under all clips in **main** track, because OpenPype will trim this to appropriate length with use of FFMPEG. Please be avare we only support MP4(h264) or JPG sequence at the moment. @@ -110,7 +110,7 @@ Because we don't support on-fly data conversion so in case of working with raw c ### Converting timeline clips to instances -Every clip on timeline which is inteded to be published has to be converted to publishable instance. +Every clip on timeline which is intended to be published has to be converted to publishable instance.
@@ -169,7 +169,7 @@ I case you wish to publish reviewable video as explained above then find the app Hover above each input field for help.

-Handles can be defined here to. In case you wish to have individual clip set differently we recomend to set here the default value and later change those in the created OpenPype tag's metadata under `handleStart` and `handleEnd` properties (look bellow for details) +Handles can be defined here to. In case you wish to have individual clip set differently we recommend to set here the default value and later change those in the created OpenPype tag's metadata under `handleStart` and `handleEnd` properties (look below for details)
@@ -182,7 +182,7 @@ Handles can be defined here to. In case you wish to have individual clip set dif After you hit **Ok** tags are added to selected clips (except clips in **review** tracks).

-If you wish to change any individual propertie of the shot then you are able to do it here. In this example we can change `handleStart` and `handleEnd` to some other values. +If you wish to change any individual properties of the shot then you are able to do it here. In this example we can change `handleStart` and `handleEnd` to some other values.
diff --git a/website/docs/artist_hosts_maya.md b/website/docs/artist_hosts_maya.md index 6387da4adc..ae6d963b8d 100644 --- a/website/docs/artist_hosts_maya.md +++ b/website/docs/artist_hosts_maya.md @@ -94,7 +94,7 @@ or publishing phase. Empty one with gray text is disabled. See that in this case we are publishing from scene file `model_test_v01.mb` in Maya model named `modelMain (ben)` (next item). Publishing of workfile is -currenly disabled (last item). +currently disabled (last item). Right column lists all tasks that are run during collection, validation, extraction and integration phase. White items are optional and you can disable @@ -628,7 +628,7 @@ Yeti cache set and opening *Extra attributes* in Maya **Attribute Editor**. Those attributes there are self-explanatory, but: - `Preroll` is number of frames simulation will run before cache frames are stored. -This is usefull to "steady" simulation for example. +This is useful to "steady" simulation for example. - `Frame Start` from what frame we start to store cache files - `Frame End` to what frame we are storing cache files - `Fps` of cache @@ -715,7 +715,7 @@ For actual publishing of your groom to go **OpenPype → Publish** and then pres :::tip adding more descriptions -You can add multiple xgen desctiption into the subset you are about to publish, simply by +You can add multiple xgen description into the subset you are about to publish, simply by adding them to the maya set that was created for you. Please make sure that only xgen description nodes are present inside of the set and not the scalp geometry. ::: @@ -753,7 +753,7 @@ parameters to it - Redshift will then represent proxy with bounding box. ## Using VRay Proxies -OpenPype support publishing, loading and using of VRay Proxy in look management. Their underlaying format +OpenPype support publishing, loading and using of VRay Proxy in look management. Their underlying format can be either vrmesh or alembic. :::warning vrmesh or alembic and look management diff --git a/website/docs/artist_hosts_nuke_tut.md b/website/docs/artist_hosts_nuke_tut.md index 4d116bd958..8d9558130d 100644 --- a/website/docs/artist_hosts_nuke_tut.md +++ b/website/docs/artist_hosts_nuke_tut.md @@ -254,7 +254,7 @@ Gathering all the info and validating usually takes just a few seconds. Creating ##### Pyblish Note and Intent ![Note and Intent](assets/nuke_tut/nuke_PyblishDialogNukeNoteIntent.png) -Artist can add Note and Intent before firing the publish button. The Note and Intent is ment for easy communication between artist and supervisor. After publish, Note and Intent can be seen in Ftrack notes. +Artist can add Note and Intent before firing the publish button. The Note and Intent is meant for easy communication between artist and supervisor. After publish, Note and Intent can be seen in Ftrack notes. ##### Pyblish Checkbox @@ -334,4 +334,4 @@ If your Pyblish dialog fails on Validate Containers, you might have an old asset ### Fixing Validate Version If your Pyblish dialog fails on Validate Version, you might be trying to publish already published version. Rise your version in the OpenPype WorkFiles SaveAs. -Or maybe you accidentaly copied write node from different shot to your current one. Check the write publishes on the left side of the Pyblish dialog. Typically you publish only one write. Locate and delete the stray write from other shot. \ No newline at end of file +Or maybe you accidentally copied write node from different shot to your current one. Check the write publishes on the left side of the Pyblish dialog. Typically you publish only one write. Locate and delete the stray write from other shot. \ No newline at end of file diff --git a/website/docs/artist_hosts_photoshop.md b/website/docs/artist_hosts_photoshop.md index 7e84349565..16539bcf79 100644 --- a/website/docs/artist_hosts_photoshop.md +++ b/website/docs/artist_hosts_photoshop.md @@ -14,7 +14,7 @@ sidebar_label: Photoshop ## Setup -To install the extension, download, install [Anastasyi's Extention Manager](https://install.anastasiy.com/). Open Anastasyi's Extension Manager and select Photoshop in menu. Then go to `{path to pype}/repos/avalon-core/avalon/photoshop/extension.zxp`. Drag extension.zxp and drop it to Anastasyi's Extension Manager. The extension will install itself. +To install the extension, download, install [Anastasyi's Extension Manager](https://install.anastasiy.com/). Open Anastasyi's Extension Manager and select Photoshop in menu. Then go to `{path to pype}/repos/avalon-core/avalon/photoshop/extension.zxp`. Drag extension.zxp and drop it to Anastasyi's Extension Manager. The extension will install itself. ## Usage diff --git a/website/docs/artist_hosts_resolve.md b/website/docs/artist_hosts_resolve.md index be069eea79..afd050648f 100644 --- a/website/docs/artist_hosts_resolve.md +++ b/website/docs/artist_hosts_resolve.md @@ -141,7 +141,7 @@ As you can see the in `{shot}` key within *Shot Template Keywords* section, you
-Notice the relationship of following sections. Keys from **Shot Template Keywords** sections will be used for formating of templates in **Shot Hierarchy And Rename Settings** section. +Notice the relationship of following sections. Keys from **Shot Template Keywords** sections will be used for formatting of templates in **Shot Hierarchy And Rename Settings** section. **Shot parent hierarchy** will be forming parents of the asset (shot) *the hidden root for this is project folder*. So for example of this template we will get resulging string `shots/sq01` @@ -149,7 +149,7 @@ Notice the relationship of following sections. Keys from **Shot Template Keyword - `{_sequence_}`: timeline name - `{_clip_}`: clip name - `{_trackIndex_}`: position of track on timeline from bottom -- `{_clipIndex_}`: clip positon on timeline from left +- `{_clipIndex_}`: clip position on timeline from left
diff --git a/website/docs/artist_hosts_unreal.md b/website/docs/artist_hosts_unreal.md index 1c2c22937c..1ff09893e3 100644 --- a/website/docs/artist_hosts_unreal.md +++ b/website/docs/artist_hosts_unreal.md @@ -29,7 +29,7 @@ OpenPype global tools can be found in *Window* main menu: ### Loading -To import Static Mesh model, just choose **OpenPype → Load ...** and select your mesh. Static meshes are transfered as FBX files as specified in [Unreal Engine 4 Static Mesh Pipeline](https://docs.unrealengine.com/en-US/Engine/Content/Importing/FBX/StaticMeshes/index.html). This action will create new folder with subset name (`unrealStaticMeshMain_CON` for example) and put all data into it. Inside, you can find: +To import Static Mesh model, just choose **OpenPype → Load ...** and select your mesh. Static meshes are transferred as FBX files as specified in [Unreal Engine 4 Static Mesh Pipeline](https://docs.unrealengine.com/en-US/Engine/Content/Importing/FBX/StaticMeshes/index.html). This action will create new folder with subset name (`unrealStaticMeshMain_CON` for example) and put all data into it. Inside, you can find: ![Unreal Container Content](assets/unreal-container.jpg) @@ -37,4 +37,4 @@ In this case there is **lambert1**, material pulled from Maya when this static m ### Publishing -Publishing of Static Mesh works in similar ways. Select your mesh in *Content Browser* and **OpenPype → Create ...**. This will create folder named by subset you've choosen - for example **unrealStaticMeshDefault_INS**. It this folder is that mesh and *Avalon Publish Instance* asset marking this folder as publishable instance and holding important metadata on it. If you want to publish this instance, go **OpenPype → Publish ...** \ No newline at end of file +Publishing of Static Mesh works in similar ways. Select your mesh in *Content Browser* and **OpenPype → Create ...**. This will create folder named by subset you've chosen - for example **unrealStaticMeshDefault_INS**. It this folder is that mesh and *Avalon Publish Instance* asset marking this folder as publishable instance and holding important metadata on it. If you want to publish this instance, go **OpenPype → Publish ...** \ No newline at end of file diff --git a/website/docs/artist_publish.md b/website/docs/artist_publish.md index a7cb7a1bad..321eb5c56a 100644 --- a/website/docs/artist_publish.md +++ b/website/docs/artist_publish.md @@ -65,7 +65,7 @@ Here's a list of supported families | Gizmo | | | | Nukenodes | | | | Harmony.template | | | -| Harmony.pallette | | | +| Harmony.palette | | | diff --git a/website/docs/artist_tools.md b/website/docs/artist_tools.md index ae7fbbca49..273edfe0ca 100644 --- a/website/docs/artist_tools.md +++ b/website/docs/artist_tools.md @@ -32,7 +32,7 @@ Notice that the window doesn't close after hitting `Accept` and confirming the c Despite the name, Creator isn't for making new content in your scene, but rather taking what's already in it and creating all the metadata your content needs to be published. -In Maya this means creating a set with everything you want to publish and assigning custom attributes to it so it get's picked up during publishing stage. +In Maya this means creating a set with everything you want to publish and assigning custom attributes to it so it gets picked up during publishing stage. In Nuke it's either converting an existing write node to a publishable one, or simply creating a write node with all the correct settings and outputs already set. @@ -424,7 +424,7 @@ One or more items (instances) could be published any time Publish process is sta item must be created by Creator tool previously. Subset Manager provides easy way how to check which items, and how many, will be published. -It also provides clean and preferrable way how to remove unwanted item from publishing. +It also provides clean and preferable way how to remove unwanted item from publishing. ### Usage diff --git a/website/docs/changelog.md b/website/docs/changelog.md index 57048b9398..448592b930 100644 --- a/website/docs/changelog.md +++ b/website/docs/changelog.md @@ -12,7 +12,7 @@ _**release date:** (2021-05-18)_ **Enhancements:** - Use SubsetLoader and multiple contexts for delete_old_versions [\#1484](ttps://github.com/pypeclub/OpenPype/pull/1484)) -- TVPaint: Increment workfile version on successfull publish. [\#1489](https://github.com/pypeclub/OpenPype/pull/1489) +- TVPaint: Increment workfile version on successful publish. [\#1489](https://github.com/pypeclub/OpenPype/pull/1489) - Maya: Use of multiple deadline servers [\#1483](https://github.com/pypeclub/OpenPype/pull/1483) **Fixed bugs:** diff --git a/website/docs/dev_build.md b/website/docs/dev_build.md index bf606ae7c0..ab420bd959 100644 --- a/website/docs/dev_build.md +++ b/website/docs/dev_build.md @@ -138,7 +138,7 @@ $ exec $SHELL # install Python 3.7.10 # python will be downloaded and build so please make sure -# you have all necessary requirements installed (see bellow). +# you have all necessary requirements installed (see below). $ pyenv install -v 3.7.10 # change path to pype 3 @@ -193,7 +193,7 @@ For more information about setting your build environment please refer to [pyenv ### MacOS -To build pype on MacOS you wil need: +To build pype on MacOS you will need: - **[Homebrew](https://brew.sh)** - easy way of installing everything necessary. - **[CMake](https://cmake.org/)** to build some external OpenPype dependencies. diff --git a/website/docs/dev_contribute.md b/website/docs/dev_contribute.md index 6655ec88c1..c25e2f5d38 100644 --- a/website/docs/dev_contribute.md +++ b/website/docs/dev_contribute.md @@ -42,7 +42,7 @@ These are the important branches to remember. **`develop`** - Development branch where we merge all PRs during the development -**`release/3.x.x`** - Testing branch for a release, once a release branch is crated, no new features +**`release/3.x.x`** - Testing branch for a release, once a release branch is created, no new features are accepted for the given release. Bugfixes, however, are expected. Once the branch is stable it is merged to `main` and `develop` and `main` is tagged with a new release @@ -77,7 +77,7 @@ Inside each PR, put a link to the corresponding PR. Of course if you want to contribute, feel free to make a PR to only 2.x/develop or develop, based on what you are using. While reviewing the PRs, we might convert the code to corresponding PR for the other release ourselves. -We might also change the target of you PR to and intermediate branch, rather than `develop` if we feel it requires some extra work on our end. That way, we preserve all your commits so you don't loos out on the contribution credits. +We might also change the target of you PR to and intermediate branch, rather than `develop` if we feel it requires some extra work on our end. That way, we preserve all your commits so you don't lose out on the contribution credits. diff --git a/website/docs/features.md b/website/docs/features.md index c6413a7aa7..fd6196f71f 100644 --- a/website/docs/features.md +++ b/website/docs/features.md @@ -18,7 +18,7 @@ Idle manager Timers manager -Statics server +Statistics server ## System Admin diff --git a/website/docs/module_ftrack.md b/website/docs/module_ftrack.md index 8e3806828d..c597a9fc4a 100644 --- a/website/docs/module_ftrack.md +++ b/website/docs/module_ftrack.md @@ -212,7 +212,7 @@ This event makes sure statuses Asset Version get synced to it's task. After chan This event handler allows setting of different status to a first created Asset Version in Ftrack. -This is usefull for example if first version publish doesn't contain any actual reviewable work, but is only used for roundtrip conform check, in which case this version could receive status `pending conform` instead of standard `pending review` +This is useful for example if first version publish doesn't contain any actual reviewable work, but is only used for roundtrip conform check, in which case this version could receive status `pending conform` instead of standard `pending review` ### Update status on next task Change status on next task by task types order when task status state changed to "Done". All tasks with the same Task mapping of next task status changes From → To. Some status can be ignored. diff --git a/website/docs/module_site_sync.md b/website/docs/module_site_sync.md index 571da60ceb..78f482352e 100644 --- a/website/docs/module_site_sync.md +++ b/website/docs/module_site_sync.md @@ -37,7 +37,7 @@ Artists can explore their site ID by opening OpenPype Info tool by clicking on a Many different sites can be created and configured on the system level, and some or all can be assigned to each project. -Each OpenPype Tray app works with two sites at one time. (Sites can be the same, and no synching is done in this setup). +Each OpenPype Tray app works with two sites at one time. (Sites can be the same, and no syncing is done in this setup). Sites could be configured differently per project basis. @@ -49,7 +49,7 @@ This attribute is meant for special use cases only. One of the use cases is sftp site vendoring (exposing) same data as regular site (studio). Each site is accessible for different audience. 'studio' for artists in a studio via shared disk, 'sftp' for externals via sftp server with mounted 'studio' drive. -Change of file status on one site actually means same change on 'alternate' site occured too. (eg. artists publish to 'studio', 'sftp' is using +Change of file status on one site actually means same change on 'alternate' site occurred too. (eg. artists publish to 'studio', 'sftp' is using same location >> file is accessible on 'sftp' site right away, no need to sync it anyhow.) ##### Example @@ -62,7 +62,7 @@ Alternative sites work both way: ## Project Settings -Sites need to be made available for each project. Of course this is possible to do on the default project as well, in which case all other projects will inherit these settings until overriden explicitly. +Sites need to be made available for each project. Of course this is possible to do on the default project as well, in which case all other projects will inherit these settings until overridden explicitly. You'll find the setting in **Settings/Project/Global/Site Sync** @@ -103,7 +103,7 @@ Let's imagine a small globally distributed studio which wants all published work For this use case admin needs to configure: - how many times it tries to synchronize file in case of some issue (network, permissions) - how often should synchronization check for new assets -- sites for synchronization - 'local' and 'gdrive' (this can be overriden in local settings) +- sites for synchronization - 'local' and 'gdrive' (this can be overridden in local settings) - user credentials - root folder location on Google Drive side @@ -137,19 +137,19 @@ Beware that ssh key expects OpenSSH format (`.pem`) not a Putty format (`.ppk`)! - Enable Site Sync module in Settings - Add side with SFTP provider -![Enable synching and create site](assets/site_sync_sftp_system.png) +![Enable syncing and create site](assets/site_sync_sftp_system.png) - In Projects setting enable Site Sync (on default project - all project will be synched, or on specific project) - Configure SFTP connection and destination folder on a SFTP server (in screenshot `/upload`) ![SFTP connection](assets/site_sync_project_sftp_settings.png) -- if you want to force synching between local and sftp site for all users, use combination `active site: local`, `remote site: NAME_OF_SFTP_SITE` -- if you want to allow only specific users to use SFTP synching (external users, not located in the office), use `active site: studio`, `remote site: studio`. +- if you want to force syncing between local and sftp site for all users, use combination `active site: local`, `remote site: NAME_OF_SFTP_SITE` +- if you want to allow only specific users to use SFTP syncing (external users, not located in the office), use `active site: studio`, `remote site: studio`. ![Select active and remote site on a project](assets/site_sync_sftp_project_setting_not_forced.png) -- Each artist can decide and configure synching from his/her local to SFTP via `Local Settings` +- Each artist can decide and configure syncing from his/her local to SFTP via `Local Settings` ![Select active and remote site on a project](assets/site_sync_sftp_settings_local.png) @@ -164,7 +164,7 @@ Site Sync server synchronizes new published files from artist machine into confi There might be a use case where you need to synchronize between "non-artist" sites, for example between studio site and cloud. In this case you need to run Site Sync as a background process from a command line (via service etc) 24/7. -To configure all sites where all published files should be synced eventually you need to configure `project_settings/global/sync_server/config/always_accessible_on` property in Settins (per project) first. +To configure all sites where all published files should be synced eventually you need to configure `project_settings/global/sync_server/config/always_accessible_on` property in Settings (per project) first. ![Set another non artist remote site](assets/site_sync_always_on.png) @@ -190,7 +190,7 @@ To do this: - run OP from a command line with `syncserver` and `--active_site` arguments -This is an example how to trigger background synching process where active (source) site is `studio`. +This is an example how to trigger background syncing process where active (source) site is `studio`. (It is expected that OP is installed on a machine, `openpype_console` is on PATH. If not, add full path to executable. ) ```shell diff --git a/website/docs/project_settings/settings_project_global.md b/website/docs/project_settings/settings_project_global.md index e6336c36e2..24ea09b6fb 100644 --- a/website/docs/project_settings/settings_project_global.md +++ b/website/docs/project_settings/settings_project_global.md @@ -7,7 +7,7 @@ sidebar_label: Global import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -Project settings can have project specific values. Each new project is using studio values defined in **default** project but these values can be modified or overriden per project. +Project settings can have project specific values. Each new project is using studio values defined in **default** project but these values can be modified or overridden per project. :::warning Default studio values Projects always use default project values unless they have [project override](../admin_settings#project-overrides) (orage colour). Any changes in default project may affect all existing projects. @@ -77,7 +77,7 @@ Profile may generate multiple outputs from a single input. Each output must defi - All values that cause output resolution smaller than 1 pixel are invalid. - Value without sign (+/-) in is always explicit and value with sign is - relative. Output size for values "200px" and "+200px" are not the same "+200px" will add 200 pixels to source and "200px" will keep only 200px from source. Value of "0", "0px" or "0%" are automatically converted to "+0px" as 0px is invalid ouput. + relative. Output size for values "200px" and "+200px" are not the same "+200px" will add 200 pixels to source and "200px" will keep only 200px from source. Value of "0", "0px" or "0%" are automatically converted to "+0px" as 0px is invalid output. - Cropped value is related to center. It is better to avoid odd numbers if possible. @@ -88,7 +88,7 @@ Profile may generate multiple outputs from a single input. Each output must defi |---|---|---| | ` ` | 2200px | Empty string keep resolution unchanged. | | `50%` | 1100px | Crop 25% of input width on left and right side. | - | `300px` | 300px | Keep 300px in center of input and crop rest on left adn right. | + | `300px` | 300px | Keep 300px in center of input and crop rest on left and right. | | `300` | 300px | Values without units are used as pixels (`px`). | | `+0px` | 2200px | Keep resolution unchanged. | | `0px` | 2200px | Same as `+0px`. | diff --git a/website/docs/project_settings/settings_project_nuke.md b/website/docs/project_settings/settings_project_nuke.md index 561311317f..b3ee5f77a6 100644 --- a/website/docs/project_settings/settings_project_nuke.md +++ b/website/docs/project_settings/settings_project_nuke.md @@ -7,7 +7,7 @@ sidebar_label: Nuke import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -Project settings can have project specific values. Each new project is using studio values defined in **default** project but these values can be modified or overriden per project. +Project settings can have project specific values. Each new project is using studio values defined in **default** project but these values can be modified or overridden per project. :::warning Default studio values Projects always use default project values unless they have [project override](../admin_settings#project-overrides) (orage colour). Any changes in default project may affect all existing projects. @@ -40,7 +40,7 @@ Custom templates are added into nuke's node graph as nodes. List of task types c ![nuke_workfile_builder_template_task_type](assets/nuke_workfile_builder_template_task_type.png) - - multi platform path can be used in a variety of ways. Along the absolut path to a template file also an python formating could be used. At the moment these keys are supported (image example bellow): + - multi platform path can be used in a variety of ways. Along the absolute path to a template file also an python formatting could be used. At the moment these keys are supported (image example below): - `root[key]`: definitions from anatomy roots - `project[name, code]`: project in context - `asset`: name of asset/shot in context @@ -49,7 +49,7 @@ Custom templates are added into nuke's node graph as nodes. List of task types c ![nuke_workfile_builder_template_anatomy](assets/nuke_workfile_builder_template_anatomy.png) #### Run Builder profiles on first launch -Enabling this feature will look into available Builder's Prorfiles (look bellow for more informations about this feature) and load available versions into node graph. +Enabling this feature will look into available Builder's Prorfiles (look below for more information about this feature) and load available versions into node graph. ### Profiles (Builder) Builder profiles are set of rules allowing artist Load any available versions for the context of the asset, which it is run from. Preset is having following attributes: diff --git a/website/docs/project_settings/settings_project_standalone.md b/website/docs/project_settings/settings_project_standalone.md index b359dc70d0..778aba2942 100644 --- a/website/docs/project_settings/settings_project_standalone.md +++ b/website/docs/project_settings/settings_project_standalone.md @@ -7,7 +7,7 @@ sidebar_label: Standalone Publisher import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -Project settings can have project specific values. Each new project is using studio values defined in **default** project but these values can be modified or overriden per project. +Project settings can have project specific values. Each new project is using studio values defined in **default** project but these values can be modified or overridden per project. :::warning Default studio values Projects always use default project values unless they have [project override](../admin_settings#project-overrides) (orage colour). Any changes in default project may affect all existing projects. diff --git a/website/docs/pype2/admin_anatomy.md b/website/docs/pype2/admin_anatomy.md index 7f6342ff78..a7b3c16033 100644 --- a/website/docs/pype2/admin_anatomy.md +++ b/website/docs/pype2/admin_anatomy.md @@ -22,7 +22,7 @@ Project ``` :::note Shot naming -We do strongly recommend to name shots with their full hierarchical name. Avalon doesn't allow two assets with same name in project. Therefor if you have for example: +We do strongly recommend to name shots with their full hierarchical name. Avalon doesn't allow two assets with same name in project. Therefore if you have for example: ```text sequence01 / shot001 diff --git a/website/docs/pype2/admin_config.md b/website/docs/pype2/admin_config.md index c753ee85a4..c895c0b6b0 100644 --- a/website/docs/pype2/admin_config.md +++ b/website/docs/pype2/admin_config.md @@ -77,7 +77,7 @@ Template groups `work` and `publish` must be set in all circumstances. Both must | version | Version number. | | subset | Subset name. | | family | Main family name. | -| ext | File extention. (Possible to use only in `work` template atm.) | +| ext | File extension. (Possible to use only in `work` template atm.) | | representation | Representation name. (Is used instead of `ext` except `work` template atm.) | | frame | Frame number for sequence files. | | output | | @@ -160,7 +160,7 @@ group_1: group_2: # `global_key` is iverrided - global_key: "overriden global value" + global_key: "overridden global value" ``` **Result** ```yaml @@ -173,7 +173,7 @@ group_1: group_2: # `global_key` kept it's value for `group_2` - global_key: "overriden global value" + global_key: "overridden global value" ``` ### Combine Inner keys with Global keys @@ -273,7 +273,7 @@ Presets are categorized in folders based on what they control or what host (DCC ### colorspace -Defines all available color spaces in the studio. These configs not only tell the system what OCIO to use, but also how exactly it needs to be applied in the give application. From loading the data, trough previewing it all the way to rendered +Defines all available color spaces in the studio. These configs not only tell the system what OCIO to use, but also how exactly it needs to be applied in the give application. From loading the data, through previewing it all the way to rendered ### Dataflow diff --git a/website/docs/pype2/admin_ftrack.md b/website/docs/pype2/admin_ftrack.md index d321caf870..a81147bece 100644 --- a/website/docs/pype2/admin_ftrack.md +++ b/website/docs/pype2/admin_ftrack.md @@ -8,7 +8,7 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -Ftrack is currently the main project management option for Pype. This documentaion assumes that you are familiar with Ftrack and it's basic principles. If you're new to Ftrack, we recommend having a thorough look at [Ftrack Official Documentation](http://ftrack.rtd.ftrack.com/en/stable/). +Ftrack is currently the main project management option for Pype. This documentation assumes that you are familiar with Ftrack and it's basic principles. If you're new to Ftrack, we recommend having a thorough look at [Ftrack Official Documentation](http://ftrack.rtd.ftrack.com/en/stable/). ## Prepare Ftrack for Pype @@ -19,7 +19,7 @@ The only action that is strictly required is [Pype Admin - Create/Update Avalon If you want to switch projects that are already in production, you might also need to run [Pype Doctor - Custom attr doc](manager_ftrack_actions#custom-attr-doc). :::caution -Keep in mind that **Custom attr doc** action will migrate certain attributes from ftrack default ones to our custom attributes. Some attributes will also be renamed. We make backup of the values, but be very carefull with this option and consults us before running it. +Keep in mind that **Custom attr doc** action will migrate certain attributes from ftrack default ones to our custom attributes. Some attributes will also be renamed. We make backup of the values, but be very careful with this option and consults us before running it. ::: ## Event Server @@ -180,7 +180,7 @@ This event makes sure statuses Asset Version get synced to it's task. After chan This event handler allows setting of different status to a first created Asset Version in ftrack. -This is usefull for example if first version publish doesn't contain any actual reviewable work, but is only used for roundtrip conform check, in which case this version could receive status `pending conform` instead of standard `pending review` +This is useful for example if first version publish doesn't contain any actual reviewable work, but is only used for roundtrip conform check, in which case this version could receive status `pending conform` instead of standard `pending review` Behaviour can be filtered by `name` or `type` of the task assigned to the Asset Version. Configuration can be found in [ftrack presets](admin_presets_ftrack#first_version_status-dict) diff --git a/website/docs/pype2/admin_install.md b/website/docs/pype2/admin_install.md index dad0d19b50..c534a60945 100644 --- a/website/docs/pype2/admin_install.md +++ b/website/docs/pype2/admin_install.md @@ -11,7 +11,7 @@ import TabItem from '@theme/TabItem'; The general approach to pype deployment is installing central repositories on a shared network storage which can be accessed by all artists in the studio. Simple shortcuts to launchers are then distributed to all workstations for artists to use. This approach ensures easy maintenance and updates. -When artist first runs pype all the required python packages get installed automatically to his local workstation and updated everytime there is a change in the central installation. +When artist first runs pype all the required python packages get installed automatically to his local workstation and updated every time there is a change in the central installation. :::note Automatic workstation installation and updates will not work in offline scenarios. In these case `pype install --force --offline` command must be triggered explicitly on the workstation diff --git a/website/docs/pype2/admin_introduction.md b/website/docs/pype2/admin_introduction.md index 7a3b8f51d8..b40f35697a 100644 --- a/website/docs/pype2/admin_introduction.md +++ b/website/docs/pype2/admin_introduction.md @@ -66,6 +66,6 @@ Thanks to a very flexible and extensible system of presets, we're almost always ### Studio-Project-Configs -On top of studio wide pype config, we support project level overrides for any and all avriables and presets available in the main studio config. +On top of studio wide pype config, we support project level overrides for any and all variables and presets available in the main studio config. ### Studio-Project-Scrips diff --git a/website/docs/pype2/admin_presets_ftrack.md b/website/docs/pype2/admin_presets_ftrack.md index 793812dc2c..fb3d332418 100644 --- a/website/docs/pype2/admin_presets_ftrack.md +++ b/website/docs/pype2/admin_presets_ftrack.md @@ -61,7 +61,7 @@ Key specifies the resulting status and value is a list of statuses from which we ```json { "status_update": { - "_ignore_": ["in progress", "ommited", "on hold"], + "_ignore_": ["in progress", "omitted", "on hold"], "Ready": ["not ready"], "In Progress" : ["_any_"] } diff --git a/website/docs/pype2/admin_presets_nukestudio.md b/website/docs/pype2/admin_presets_nukestudio.md index 256c6e5ef4..63ea709880 100644 --- a/website/docs/pype2/admin_presets_nukestudio.md +++ b/website/docs/pype2/admin_presets_nukestudio.md @@ -45,9 +45,9 @@ This plugin is set to `true` by default so it will synchronize version of publis path: `pype-config/presets/plugins/nukestudio/publish.json` -Plugin is responsible for cuting shorter or longer source material for review. Here you can add any aditional tags you wish to be added into extract review process. +Plugin is responsible for cuting shorter or longer source material for review. Here you can add any additional tags you wish to be added into extract review process. -The plugin generates reedited intermediate video with handless even if it has to add empty black frames. Some productions prefer to use review material without handless so in the example, `no-handles` are added as tags. This allow furter review extractor to publish review without handles, without affecting other outputs. +The plugin generates reedited intermediate video with handless even if it has to add empty black frames. Some productions prefer to use review material without handless so in the example, `no-handles` are added as tags. This allow further review extractor to publish review without handles, without affecting other outputs. ```python { diff --git a/website/docs/pype2/admin_presets_plugins.md b/website/docs/pype2/admin_presets_plugins.md index 9c838d4a64..fcdc09439b 100644 --- a/website/docs/pype2/admin_presets_plugins.md +++ b/website/docs/pype2/admin_presets_plugins.md @@ -53,7 +53,7 @@ Profile may have multiple outputs from one input and that's why **outputs** is d | **filter** | Filters definition. | dict | [here](#output-filters-filter) | :::note -As metioned above **all keys are optional**. If they are not filled at all, then **"ext"** is filled with input's file extension and resolution keys **"width"** and **"heigh"** are filled from instance data, or from input resolution if instance doesn't have set them. +As mentioned above **all keys are optional**. If they are not filled at all, then **"ext"** is filled with input's file extension and resolution keys **"width"** and **"height"** are filled from instance data, or from input resolution if instance doesn't have set them. ::: :::important resolution @@ -61,7 +61,7 @@ It is not possible to enter only **"width"** or only **"height"**. In that case ::: #### New representation tags (`tags`) -You can add tags to representation created during extracting process. This might help to define what should happen with representation in upcomming plugins. +You can add tags to representation created during extracting process. This might help to define what should happen with representation in upcoming plugins. | Tag | Description | | --- | --- | @@ -69,7 +69,7 @@ You can add tags to representation created during extracting process. This might | **preview** | Will be used as preview in Ftrack. | | **reformat** | Rescale to format based on width and height keys. | | **bake-lut** | Bake LUT into the output (if is available path in data). | -| **slate-frame** | Add slate frame at the beggining of video. | +| **slate-frame** | Add slate frame at the beginning of video. | | **no-handles** | Remove the shot handles from the output. | | **sequence** | Generate a sequence of images instead of single frame.
Is applied only if **"ext"** of output is image extension e.g.: png or jpg/jpeg. | @@ -331,7 +331,7 @@ If source representation has suffix **"h264"** and burnin suffix is **"client"** #### Default content values (`fields`) -If you want to set position content values for all or most of burnin definitions, you can set them in **"fields"**. They will be added to every burnin definition in all profiles. Value can be overriden if same position key is filled in burnin definiton. +If you want to set position content values for all or most of burnin definitions, you can set them in **"fields"**. They will be added to every burnin definition in all profiles. Value can be overridden if same position key is filled in burnin definition. ```json { @@ -348,7 +348,7 @@ If you want to set position content values for all or most of burnin definitions /* example2 has 2 overrides. */ "example2": { - /* Top left value is overriden with asset name. */ + /* Top left value is overridden with asset name. */ "TOP_LEFT": "{asset}", /* Top center will be skipped. */ "TOP_CENTERED": null diff --git a/website/docs/pype2/admin_presets_tools.md b/website/docs/pype2/admin_presets_tools.md index bcd992a1eb..15d9d6a65a 100644 --- a/website/docs/pype2/admin_presets_tools.md +++ b/website/docs/pype2/admin_presets_tools.md @@ -98,7 +98,7 @@ This preset tells the creator tools what family should be pre-selected in differ path: `pype-config/presets/tools/project_folder_structure.json` -Defines the base folder structure for a project. This is supposed to act as a starting point to quickly creat the base of the project. You can add `[ftrack.entityType]` after any of the folders here and they will automatically be also created in ftrack project. +Defines the base folder structure for a project. This is supposed to act as a starting point to quickly create the base of the project. You can add `[ftrack.entityType]` after any of the folders here and they will automatically be also created in ftrack project. ### `__project_root__` [dict] @@ -175,7 +175,7 @@ Keys are renderer names and values are templates IDs. "arnold": 46, "arnold_sf": 57, "gelato": 30, -"harware": 3, +"hardware": 3, "krakatoa": 51, "file_layers": 7, "mentalray": 2, diff --git a/website/docs/pype2/admin_pype_commands.md b/website/docs/pype2/admin_pype_commands.md index 245e8a23e2..6267138f79 100644 --- a/website/docs/pype2/admin_pype_commands.md +++ b/website/docs/pype2/admin_pype_commands.md @@ -199,7 +199,7 @@ pype publish - run Pyblish GUI ### `--debug` -- print more verbose infomation +- print more verbose information -------------------- @@ -260,9 +260,9 @@ pype tray --debug ## `update-requirements` -Synchronize dependecies in your virtual environment with requirement.txt file. +Synchronize dependencies in your virtual environment with requirement.txt file. Equivalent of running `pip freeze > pypeapp/requirements.txt` from your virtual -environmnet. This is useful for development purposes. +environment. This is useful for development purposes. ```sh pype update-requirements diff --git a/website/docs/pype2/admin_setup_troubleshooting.md b/website/docs/pype2/admin_setup_troubleshooting.md index 2ffdd9b5f3..7143405ae1 100644 --- a/website/docs/pype2/admin_setup_troubleshooting.md +++ b/website/docs/pype2/admin_setup_troubleshooting.md @@ -7,11 +7,11 @@ sidebar_label: Setup Troubleshooting ## SSL Server certificates Python is strict about certificates when connecting to server with SSL. If -certificate cannot be validated, connection will fail. Therefor care must be +certificate cannot be validated, connection will fail. Therefore care must be taken when using self-signed certificates to add their certification authority to trusted certificates. Also please note that even when using certificates from trusted CA, you need to update your trusted CA certificates bundle as those certificates can change. -So if you receieve SSL error `cannot validate certificate` or similar, please update root CA certificate bundle on machines and possibly **certifi** python package in Pype virtual environment - just edit `pypeapp/requirements.txt` and update its version. You can find current versions on [PyPI](https://pypi.org). +So if you receive SSL error `cannot validate certificate` or similar, please update root CA certificate bundle on machines and possibly **certifi** python package in Pype virtual environment - just edit `pypeapp/requirements.txt` and update its version. You can find current versions on [PyPI](https://pypi.org). diff --git a/website/docs/upgrade_notes.md b/website/docs/upgrade_notes.md index dbc90e948d..8231cf997d 100644 --- a/website/docs/upgrade_notes.md +++ b/website/docs/upgrade_notes.md @@ -14,7 +14,7 @@ sidebar_label: Update Notes Due to changes in how tasks are stored in the database (we added task types and possibility of more arbitrary data.), we must take a few precautions when updating. 1. Make sure that ftrack event server with sync to avalon is NOT running during the update. -2. Any project that is to be worked on with 2.13 must be synced from ftrack to avalon with the udpated sync to avalon action, or using and updated event server sync to avalon event. +2. Any project that is to be worked on with 2.13 must be synced from ftrack to avalon with the updated sync to avalon action, or using and updated event server sync to avalon event. If 2.12 event servers runs when trying to update the project sync with 2.13, it will override any changes. diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index ddbcfd9ce7..ba9c983121 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -111,7 +111,7 @@ module.exports = { algolia: { apiKey: '5e01ee3bfbb744ca6f25d4b281ce38a9', indexName: 'openpype', - // Optional: see doc section bellow + // Optional: see doc section below contextualSearch: true, // Optional: Algolia search parameters searchParameters: {}, From 88cde63aa87b90f6615a4c5ac7312abd242c8e55 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 31 Jan 2022 23:37:12 +0100 Subject: [PATCH 30/74] Fix typo --- website/docs/admin_distribute.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/admin_distribute.md b/website/docs/admin_distribute.md index 207e43563b..f3778249f8 100644 --- a/website/docs/admin_distribute.md +++ b/website/docs/admin_distribute.md @@ -32,7 +32,7 @@ You have two ways of making this happen #### Automatic Updates -Every time and Artist launches OpenPype on their workstation, it will look to a pre-defined +Every time an Artist launches OpenPype on their workstation, it will look to a pre-defined [openPype update location](#self) for any versions that are newer than the latest, locally installed version. If such version is found, it will be downloaded, automatically extracted to the correct place and launched. This will become the default From 304d85510314636516b7a26e32e2ee4d2264cb19 Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Tue, 1 Feb 2022 10:57:15 +0100 Subject: [PATCH 31/74] add extension on windows --- openpype/lib/vendor_bin_utils.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/openpype/lib/vendor_bin_utils.py b/openpype/lib/vendor_bin_utils.py index a5d4153b2a..4c2cf93dfa 100644 --- a/openpype/lib/vendor_bin_utils.py +++ b/openpype/lib/vendor_bin_utils.py @@ -34,11 +34,17 @@ def get_vendor_bin_path(bin_app): def get_oiio_tools_path(tool="oiiotool"): """Path to vendorized OpenImageIO tool executables. + On Window it adds .exe extension if missing from tool argument. + Args: tool (string): Tool name (oiiotool, maketx, ...). Default is "oiiotool". """ oiio_dir = get_vendor_bin_path("oiio") + if platform.system().lower() == "windows" and not tool.lower().endswith( + ".exe" + ): + tool = "{}.exe".format(tool) return os.path.join(oiio_dir, tool) From 1b6b39051faac296e9af4fa1f6aac2d16d9df9bb Mon Sep 17 00:00:00 2001 From: OpenPype Date: Tue, 1 Feb 2022 11:43:50 +0000 Subject: [PATCH 32/74] [Automated] Bump version --- CHANGELOG.md | 12 ++++++++++-- openpype/version.py | 2 +- pyproject.toml | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a90f2ce01..88d2976b5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## [3.8.1-nightly.2](https://github.com/pypeclub/OpenPype/tree/HEAD) +## [3.8.1-nightly.3](https://github.com/pypeclub/OpenPype/tree/HEAD) [Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.8.0...HEAD) @@ -8,9 +8,13 @@ - Webpublisher: Thumbnail extractor [\#2600](https://github.com/pypeclub/OpenPype/pull/2600) - Loader: Allow to toggle default family filters between "include" or "exclude" filtering [\#2541](https://github.com/pypeclub/OpenPype/pull/2541) +- Launcher: Added context menu to to skip opening last workfile [\#2536](https://github.com/pypeclub/OpenPype/pull/2536) **🐛 Bug fixes** +- Release/3.8.0 [\#2619](https://github.com/pypeclub/OpenPype/pull/2619) +- hotfix: OIIO tool path - add extension on windows [\#2618](https://github.com/pypeclub/OpenPype/pull/2618) +- Settings: Enum does not store empty string if has single item to select [\#2615](https://github.com/pypeclub/OpenPype/pull/2615) - switch distutils to sysconfig for `get\_platform\(\)` [\#2594](https://github.com/pypeclub/OpenPype/pull/2594) - Fix poetry index and speedcopy update [\#2589](https://github.com/pypeclub/OpenPype/pull/2589) - Webpublisher: Fix - subset names from processed .psd used wrong value for task [\#2586](https://github.com/pypeclub/OpenPype/pull/2586) @@ -21,6 +25,7 @@ **Merged pull requests:** - Bump pillow from 8.4.0 to 9.0.0 [\#2595](https://github.com/pypeclub/OpenPype/pull/2595) +- Webpublisher: Skip version collect [\#2591](https://github.com/pypeclub/OpenPype/pull/2591) - build\(deps\): bump pillow from 8.4.0 to 9.0.0 [\#2523](https://github.com/pypeclub/OpenPype/pull/2523) ## [3.8.0](https://github.com/pypeclub/OpenPype/tree/3.8.0) (2022-01-24) @@ -74,7 +79,6 @@ - Fix published frame content for sequence starting with 0 [\#2513](https://github.com/pypeclub/OpenPype/pull/2513) - Maya: reset empty string attributes correctly to "" instead of "None" [\#2506](https://github.com/pypeclub/OpenPype/pull/2506) - Improve FusionPreLaunch hook errors [\#2505](https://github.com/pypeclub/OpenPype/pull/2505) -- Maya: Validate Shape Zero do not keep fixed geometry vertices selected/active after repair [\#2456](https://github.com/pypeclub/OpenPype/pull/2456) **Merged pull requests:** @@ -92,6 +96,10 @@ - General: Workdir extra folders [\#2462](https://github.com/pypeclub/OpenPype/pull/2462) +**🐛 Bug fixes** + +- TVPaint: Create render layer dialog is in front [\#2471](https://github.com/pypeclub/OpenPype/pull/2471) + ## [3.6.4](https://github.com/pypeclub/OpenPype/tree/3.6.4) (2021-11-23) [Full Changelog](https://github.com/pypeclub/OpenPype/compare/CI/3.7.0-nightly.1...3.6.4) diff --git a/openpype/version.py b/openpype/version.py index 7e19430e70..85480d1fd7 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.8.1-nightly.2" +__version__ = "3.8.1-nightly.3" diff --git a/pyproject.toml b/pyproject.toml index 8ef0c1b52e..5c19b6da8d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "OpenPype" -version = "3.8.1-nightly.2" # OpenPype +version = "3.8.1-nightly.3" # OpenPype description = "Open VFX and Animation pipeline with support." authors = ["OpenPype Team "] license = "MIT License" From c49c9ef26ec7b8695b87222acfae78b56e07a0a2 Mon Sep 17 00:00:00 2001 From: OpenPype Date: Tue, 1 Feb 2022 11:50:35 +0000 Subject: [PATCH 33/74] [Automated] Release --- CHANGELOG.md | 19 ++++++++++--------- openpype/version.py | 2 +- pyproject.toml | 2 +- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 88d2976b5f..ad2f001b45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,13 @@ # Changelog -## [3.8.1-nightly.3](https://github.com/pypeclub/OpenPype/tree/HEAD) +## [3.8.1](https://github.com/pypeclub/OpenPype/tree/3.8.1) (2022-02-01) -[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.8.0...HEAD) +[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.8.0...3.8.1) **🚀 Enhancements** - Webpublisher: Thumbnail extractor [\#2600](https://github.com/pypeclub/OpenPype/pull/2600) - Loader: Allow to toggle default family filters between "include" or "exclude" filtering [\#2541](https://github.com/pypeclub/OpenPype/pull/2541) -- Launcher: Added context menu to to skip opening last workfile [\#2536](https://github.com/pypeclub/OpenPype/pull/2536) **🐛 Bug fixes** @@ -20,22 +19,20 @@ - Webpublisher: Fix - subset names from processed .psd used wrong value for task [\#2586](https://github.com/pypeclub/OpenPype/pull/2586) - `vrscene` creator Deadline webservice URL handling [\#2580](https://github.com/pypeclub/OpenPype/pull/2580) - global: track name was failing if duplicated root word in name [\#2568](https://github.com/pypeclub/OpenPype/pull/2568) +- General: Do not validate version if build does not support it [\#2557](https://github.com/pypeclub/OpenPype/pull/2557) - Validate Maya Rig produces no cycle errors [\#2484](https://github.com/pypeclub/OpenPype/pull/2484) **Merged pull requests:** - Bump pillow from 8.4.0 to 9.0.0 [\#2595](https://github.com/pypeclub/OpenPype/pull/2595) - Webpublisher: Skip version collect [\#2591](https://github.com/pypeclub/OpenPype/pull/2591) +- build\(deps\): bump follow-redirects from 1.14.4 to 1.14.7 in /website [\#2534](https://github.com/pypeclub/OpenPype/pull/2534) - build\(deps\): bump pillow from 8.4.0 to 9.0.0 [\#2523](https://github.com/pypeclub/OpenPype/pull/2523) ## [3.8.0](https://github.com/pypeclub/OpenPype/tree/3.8.0) (2022-01-24) [Full Changelog](https://github.com/pypeclub/OpenPype/compare/CI/3.8.0-nightly.7...3.8.0) -### 📖 Documentation - -- Variable in docs renamed to proper name [\#2546](https://github.com/pypeclub/OpenPype/pull/2546) - **🆕 New features** - Flame: extracting segments with trans-coding [\#2547](https://github.com/pypeclub/OpenPype/pull/2547) @@ -52,6 +49,7 @@ - Settings: PathInput strip passed string [\#2550](https://github.com/pypeclub/OpenPype/pull/2550) - Global: Exctract Review anatomy fill data with output name [\#2548](https://github.com/pypeclub/OpenPype/pull/2548) - Cosmetics: Clean up some cosmetics / typos [\#2542](https://github.com/pypeclub/OpenPype/pull/2542) +- Launcher: Added context menu to to skip opening last workfile [\#2536](https://github.com/pypeclub/OpenPype/pull/2536) - General: Validate if current process OpenPype version is requested version [\#2529](https://github.com/pypeclub/OpenPype/pull/2529) - General: Be able to use anatomy data in ffmpeg output arguments [\#2525](https://github.com/pypeclub/OpenPype/pull/2525) - Expose toggle publish plug-in settings for Maya Look Shading Engine Naming [\#2521](https://github.com/pypeclub/OpenPype/pull/2521) @@ -66,7 +64,6 @@ - General: OpenPype version updates [\#2575](https://github.com/pypeclub/OpenPype/pull/2575) - Ftrack: Delete action revision [\#2563](https://github.com/pypeclub/OpenPype/pull/2563) - Webpublisher: ftrack shows incorrect user names [\#2560](https://github.com/pypeclub/OpenPype/pull/2560) -- General: Do not validate version if build does not support it [\#2557](https://github.com/pypeclub/OpenPype/pull/2557) - Webpublisher: Fixed progress reporting [\#2553](https://github.com/pypeclub/OpenPype/pull/2553) - Fix Maya AssProxyLoader version switch [\#2551](https://github.com/pypeclub/OpenPype/pull/2551) - General: Fix install thread in igniter [\#2549](https://github.com/pypeclub/OpenPype/pull/2549) @@ -79,13 +76,17 @@ - Fix published frame content for sequence starting with 0 [\#2513](https://github.com/pypeclub/OpenPype/pull/2513) - Maya: reset empty string attributes correctly to "" instead of "None" [\#2506](https://github.com/pypeclub/OpenPype/pull/2506) - Improve FusionPreLaunch hook errors [\#2505](https://github.com/pypeclub/OpenPype/pull/2505) +- General: Modules import function output fix [\#2492](https://github.com/pypeclub/OpenPype/pull/2492) + +### 📖 Documentation + +- Variable in docs renamed to proper name [\#2546](https://github.com/pypeclub/OpenPype/pull/2546) **Merged pull requests:** - AfterEffects: Move implementation to OpenPype [\#2543](https://github.com/pypeclub/OpenPype/pull/2543) - Maya: Remove Maya Look Assigner check on startup [\#2540](https://github.com/pypeclub/OpenPype/pull/2540) - build\(deps\): bump shelljs from 0.8.4 to 0.8.5 in /website [\#2538](https://github.com/pypeclub/OpenPype/pull/2538) -- build\(deps\): bump follow-redirects from 1.14.4 to 1.14.7 in /website [\#2534](https://github.com/pypeclub/OpenPype/pull/2534) - Nuke: Merge avalon's implementation into OpenPype [\#2514](https://github.com/pypeclub/OpenPype/pull/2514) ## [3.7.0](https://github.com/pypeclub/OpenPype/tree/3.7.0) (2022-01-04) diff --git a/openpype/version.py b/openpype/version.py index 85480d1fd7..c573c57637 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.8.1-nightly.3" +__version__ = "3.8.1" diff --git a/pyproject.toml b/pyproject.toml index 5c19b6da8d..56d059e447 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "OpenPype" -version = "3.8.1-nightly.3" # OpenPype +version = "3.8.1" # OpenPype description = "Open VFX and Animation pipeline with support." authors = ["OpenPype Team "] license = "MIT License" From d48eb8d047fa3b16c0e94323cc813f9e1300a75a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Marinov?= Date: Tue, 1 Feb 2022 16:54:38 +0100 Subject: [PATCH 34/74] formatting changes --- openpype/settings/defaults/project_settings/ftrack.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/settings/defaults/project_settings/ftrack.json b/openpype/settings/defaults/project_settings/ftrack.json index a684946758..1c1256caab 100644 --- a/openpype/settings/defaults/project_settings/ftrack.json +++ b/openpype/settings/defaults/project_settings/ftrack.json @@ -343,7 +343,7 @@ "enabled": false, "ftrack_custom_attributes": {} }, - "IntegrateFtrackInstance": { + "IntegrateFtrackInstance": { "family_mapping": { "camera": "cam", "look": "look", From 09f40f15ad55e312affad5b991becffc5c14b5f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Marinov?= Date: Tue, 1 Feb 2022 16:57:18 +0100 Subject: [PATCH 35/74] formatting changes --- .../schema_project_ftrack.json | 945 +++++++++--------- 1 file changed, 473 insertions(+), 472 deletions(-) diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json b/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json index 14b7038cbe..1e904e6fdb 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json @@ -1,226 +1,226 @@ { - "type" : "dict", - "key" : "ftrack", - "label" : "Ftrack", - "collapsible" : true, - "is_file" : true, - "children" : [ + "type": "dict", + "key": "ftrack", + "label": "Ftrack", + "collapsible": true, + "is_file": true, + "children": [ { - "type" : "dict", - "key" : "events", - "label" : "Server Actions/Events", - "children" : [ + "type": "dict", + "key": "events", + "label": "Server Actions/Events", + "children": [ { - "type" : "dict", - "key" : "sync_to_avalon", - "label" : "Sync to avalon", - "children" : [ + "type": "dict", + "key": "sync_to_avalon", + "label": "Sync to avalon", + "children": [ { - "type" : "label", - "label" : "Allow name and hierarchy change only if following statuses are on all children tasks" + "type": "label", + "label": "Allow name and hierarchy change only if following statuses are on all children tasks" }, { - "type" : "list", - "key" : "statuses_name_change", - "label" : "Statuses", - "object_type" : { - "type" : "text", - "multiline" : false + "type": "list", + "key": "statuses_name_change", + "label": "Statuses", + "object_type": { + "type": "text", + "multiline": false } } ] }, { - "type" : "dict", - "key" : "prepare_project", - "label" : "Prepare Project", - "checkbox_key" : "enabled", - "children" : [ + "type": "dict", + "key": "prepare_project", + "label": "Prepare Project", + "checkbox_key": "enabled", + "children": [ { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" + "type": "boolean", + "key": "enabled", + "label": "Enabled" }, { - "type" : "list", - "key" : "role_list", - "label" : "Roles", - "object_type" : "text" + "type": "list", + "key": "role_list", + "label": "Roles", + "object_type": "text" } ] }, { - "type" : "dict", - "key" : "sync_hier_entity_attributes", - "label" : "Sync Hierarchical and Entity Attributes", - "checkbox_key" : "enabled", - "children" : [ + "type": "dict", + "key": "sync_hier_entity_attributes", + "label": "Sync Hierarchical and Entity Attributes", + "checkbox_key": "enabled", + "children": [ { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" + "type": "boolean", + "key": "enabled", + "label": "Enabled" }, { - "type" : "list", - "key" : "interest_entity_types", - "label" : "Entity types of interest", - "object_type" : { - "type" : "text", - "multiline" : false + "type": "list", + "key": "interest_entity_types", + "label": "Entity types of interest", + "object_type": { + "type": "text", + "multiline": false } }, { - "type" : "list", - "key" : "interest_attributes", - "label" : "Attributes to sync", - "object_type" : { - "type" : "text", - "multiline" : false + "type": "list", + "key": "interest_attributes", + "label": "Attributes to sync", + "object_type": { + "type": "text", + "multiline": false } }, { - "type" : "separator" + "type": "separator" }, { - "type" : "boolean", - "key" : "action_enabled", - "label" : "Enable Action" + "type": "boolean", + "key": "action_enabled", + "label": "Enable Action" }, { - "type" : "list", - "key" : "role_list", - "label" : "Roles for action", - "object_type" : "text" + "type": "list", + "key": "role_list", + "label": "Roles for action", + "object_type": "text" } ] }, { - "type" : "dict", - "key" : "clone_review_session", - "label" : "Clone Review Session", - "checkbox_key" : "enabled", - "children" : [ + "type": "dict", + "key": "clone_review_session", + "label": "Clone Review Session", + "checkbox_key": "enabled", + "children": [ { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" + "type": "boolean", + "key": "enabled", + "label": "Enabled" }, { - "type" : "list", - "key" : "role_list", - "label" : "Roles for action", - "object_type" : "text" + "type": "list", + "key": "role_list", + "label": "Roles for action", + "object_type": "text" } ] }, { - "type" : "dict", - "key" : "thumbnail_updates", - "label" : "Update Hierarchy thumbnails", - "checkbox_key" : "enabled", - "children" : [ + "type": "dict", + "key": "thumbnail_updates", + "label": "Update Hierarchy thumbnails", + "checkbox_key": "enabled", + "children": [ { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" + "type": "boolean", + "key": "enabled", + "label": "Enabled" }, { - "type" : "label", - "label" : "Push thumbnail from version, up through multiple hierarchy levels." + "type": "label", + "label": "Push thumbnail from version, up through multiple hierarchy levels." }, { - "type" : "number", - "key" : "levels", - "label" : "Levels" + "type": "number", + "key": "levels", + "label": "Levels" } ] }, { - "type" : "dict", - "key" : "user_assignment", - "label" : "Run script on user assignments", - "checkbox_key" : "enabled", - "children" : [ + "type": "dict", + "key": "user_assignment", + "label": "Run script on user assignments", + "checkbox_key": "enabled", + "children": [ { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" + "type": "boolean", + "key": "enabled", + "label": "Enabled" } ] }, { - "type" : "dict", - "key" : "status_update", - "label" : "Update status on task action", - "is_group" : true, - "checkbox_key" : "enabled", - "children" : [ + "type": "dict", + "key": "status_update", + "label": "Update status on task action", + "is_group": true, + "checkbox_key": "enabled", + "children": [ { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" + "type": "boolean", + "key": "enabled", + "label": "Enabled" }, { - "key" : "mapping", - "type" : "dict-modifiable", - "object_type" : { - "type" : "list", - "object_type" : "text" + "key": "mapping", + "type": "dict-modifiable", + "object_type": { + "type": "list", + "object_type": "text" } } ] }, { - "type" : "dict", - "key" : "status_task_to_parent", - "label" : "Sync status from Task to Parent", - "checkbox_key" : "enabled", - "children" : [ + "type": "dict", + "key": "status_task_to_parent", + "label": "Sync status from Task to Parent", + "checkbox_key": "enabled", + "children": [ { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" + "type": "boolean", + "key": "enabled", + "label": "Enabled" }, { - "type" : "label", - "label" : "List of parent object types where this is triggered (\"Shot\", \"Asset Build\", etc.). Skipped if list is empty." + "type": "label", + "label": "List of parent object types where this is triggered (\"Shot\", \"Asset Build\", etc.). Skipped if list is empty." }, { - "type" : "list", - "object_type" : "text", - "key" : "parent_object_types", - "label" : "Object types" + "type": "list", + "object_type": "text", + "key": "parent_object_types", + "label": "Object types" }, { - "key" : "parent_status_match_all_task_statuses", - "type" : "dict-modifiable", - "label" : "Change parent if all tasks match", - "object_type" : { - "type" : "list", - "object_type" : "text" + "key": "parent_status_match_all_task_statuses", + "type": "dict-modifiable", + "label": "Change parent if all tasks match", + "object_type": { + "type": "list", + "object_type": "text" } }, { - "type" : "list", - "key" : "parent_status_by_task_status", - "label" : "Change parent status if a single task matches", - "use_label_wrap" : true, - "object_type" : { - "type" : "dict", - "children" : [ + "type": "list", + "key": "parent_status_by_task_status", + "label": "Change parent status if a single task matches", + "use_label_wrap": true, + "object_type": { + "type": "dict", + "children": [ { - "type" : "text", - "label" : "New parent status", - "key" : "new_status" + "type": "text", + "label": "New parent status", + "key": "new_status" }, { - "type" : "separator" + "type": "separator" }, { - "type" : "list", - "label" : "Task status", - "key" : "task_statuses", - "object_type" : "text" + "type": "list", + "label": "Task status", + "key": "task_statuses", + "object_type": "text" } ] } @@ -228,465 +228,466 @@ ] }, { - "type" : "dict", - "key" : "status_task_to_version", - "label" : "Sync status from Task to Version", - "is_group" : true, - "checkbox_key" : "enabled", - "children" : [ + "type": "dict", + "key": "status_task_to_version", + "label": "Sync status from Task to Version", + "is_group": true, + "checkbox_key": "enabled", + "children": [ { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" + "type": "boolean", + "key": "enabled", + "label": "Enabled" }, { - "type" : "dict-modifiable", - "key" : "mapping", - "object_type" : { - "type" : "list", - "object_type" : "text" + "type": "dict-modifiable", + "key": "mapping", + "object_type": + { + "type": "list", + "object_type": "text" } }, { - "type" : "label", - "label" : "Limit status changes to entered asset types. Limitation is ignored if nothing is entered." + "type": "label", + "label": "Limit status changes to entered asset types. Limitation is ignored if nothing is entered." }, { - "type" : "list", - "key" : "asset_types_filter", - "label" : "Asset types (short)", - "object_type" : "text" + "type": "list", + "key": "asset_types_filter", + "label": "Asset types (short)", + "object_type": "text" } ] }, { - "type" : "dict", - "key" : "status_version_to_task", - "label" : "Sync status from Version to Task", - "is_group" : true, - "checkbox_key" : "enabled", - "children" : [ + "type": "dict", + "key": "status_version_to_task", + "label": "Sync status from Version to Task", + "is_group": true, + "checkbox_key": "enabled", + "children": [ { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" + "type": "boolean", + "key": "enabled", + "label": "Enabled" }, { - "type" : "label", - "label" : "Change Task status based on a changed Version status.
Version's new status on the left will trigger a change of a task status to the first available from the list on right.
- if no status from the list is available it will use the same status as the version." + "type": "label", + "label": "Change Task status based on a changed Version status.
Version's new status on the left will trigger a change of a task status to the first available from the list on right.
- if no status from the list is available it will use the same status as the version." }, { - "type" : "dict-modifiable", - "key" : "mapping", - "object_type" : { - "type" : "list", - "object_type" : "text" + "type": "dict-modifiable", + "key": "mapping", + "object_type": { + "type": "list", + "object_type": "text" } }, { - "type" : "separator" + "type": "separator" }, { - "type" : "label", - "label" : "Disable event if status was changed on specific Asset type." + "type": "label", + "label": "Disable event if status was changed on specific Asset type." }, { - "type" : "list", - "label" : "Asset types (short)", - "key" : "asset_types_to_skip", - "object_type" : "text" + "type": "list", + "label": "Asset types (short)", + "key": "asset_types_to_skip", + "object_type": "text" } ] }, { - "type" : "dict", - "key" : "first_version_status", - "label" : "Set status on first created version", - "checkbox_key" : "enabled", - "children" : [ + "type": "dict", + "key": "first_version_status", + "label": "Set status on first created version", + "checkbox_key": "enabled", + "children": [ { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" + "type": "boolean", + "key": "enabled", + "label": "Enabled" }, { - "type" : "text", - "key" : "status", - "label" : "Status" + "type": "text", + "key": "status", + "label": "Status" } ] }, { - "type" : "dict", - "key" : "next_task_update", - "is_group" : true, - "label" : "Update status on next task", - "checkbox_key" : "enabled", - "children" : [ + "type": "dict", + "key": "next_task_update", + "is_group": true, + "label": "Update status on next task", + "checkbox_key": "enabled", + "children": [ { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" + "type": "boolean", + "key": "enabled", + "label": "Enabled" }, { - "type" : "label", - "label" : "Change status on next task by task types order when task status state changed to \"Done\". All tasks with same Task type must be \"Done\"." + "type": "label", + "label": "Change status on next task by task types order when task status state changed to \"Done\". All tasks with same Task type must be \"Done\"." }, { - "type" : "label", - "label" : "Mapping of next task status changes From -> To." + "type": "label", + "label": "Mapping of next task status changes From -> To." }, { - "type" : "dict-modifiable", - "key" : "mapping", - "object_type" : { - "type" : "text" + "type": "dict-modifiable", + "key": "mapping", + "object_type": { + "type": "text" } }, { - "type" : "separator" + "type": "separator" }, { - "type" : "label", - "label" : "Status names that are ignored on \"Done\" check (e.g. \"Omitted\")." + "type": "label", + "label": "Status names that are ignored on \"Done\" check (e.g. \"Omitted\")." }, { - "type" : "list", - "key" : "ignored_statuses", - "object_type" : "text" + "type": "list", + "key": "ignored_statuses", + "object_type": "text" }, { - "type" : "separator" + "type": "separator" }, { - "type" : "label", - "label" : "Allow to break rule that all tasks with same Task type must be \"Done\" and change statuses with same type tasks ordered by name." + "type": "label", + "label": "Allow to break rule that all tasks with same Task type must be \"Done\" and change statuses with same type tasks ordered by name." }, { - "label" : "Name sorting", - "type" : "boolean", - "key" : "name_sorting" + "label": "Name sorting", + "type": "boolean", + "key": "name_sorting" } ] } ] }, { - "type" : "dict", - "key" : "user_handlers", - "label" : "User Actions/Events", - "children" : [ + "type": "dict", + "key": "user_handlers", + "label": "User Actions/Events", + "children": [ { - "type" : "dict", - "key" : "application_launch_statuses", - "is_group" : true, - "label" : "Application - Status change on launch", - "checkbox_key" : "enabled", - "children" : [ + "type": "dict", + "key": "application_launch_statuses", + "is_group": true, + "label": "Application - Status change on launch", + "checkbox_key": "enabled", + "children": [ { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" + "type": "boolean", + "key": "enabled", + "label": "Enabled" }, { - "type" : "label", - "label" : "Do not change status if current status is:" + "type": "label", + "label": "Do not change status if current status is:" }, { - "type" : "list", - "key" : "ignored_statuses", - "object_type" : "text" + "type": "list", + "key": "ignored_statuses", + "object_type": "text" }, { - "type" : "label", - "label" : "Change task's status to left side if current task status is in list on right side." + "type": "label", + "label": "Change task's status to left side if current task status is in list on right side." }, { - "type" : "dict-modifiable", - "key" : "status_change", - "object_type" : { - "type" : "list", - "object_type" : "text" + "type": "dict-modifiable", + "key": "status_change", + "object_type": { + "type": "list", + "object_type": "text" } } ] }, { - "type" : "dict", - "key" : "create_update_attributes", - "label" : "Create/Update Avalon Attributes", - "children" : [ + "type": "dict", + "key": "create_update_attributes", + "label": "Create/Update Avalon Attributes", + "children": [ { - "type" : "list", - "key" : "role_list", - "label" : "Roles", - "object_type" : "text" + "type": "list", + "key": "role_list", + "label": "Roles", + "object_type": "text" } ] }, { - "type" : "dict", - "key" : "prepare_project", - "label" : "Prepare Project", - "checkbox_key" : "enabled", - "children" : [ + "type": "dict", + "key": "prepare_project", + "label": "Prepare Project", + "checkbox_key": "enabled", + "children": [ { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" + "type": "boolean", + "key": "enabled", + "label": "Enabled" }, { - "type" : "list", - "key" : "role_list", - "label" : "Roles", - "object_type" : "text" + "type": "list", + "key": "role_list", + "label": "Roles", + "object_type": "text" }, { - "type" : "separator" + "type": "separator" }, { - "type" : "label", - "label" : "Check \"Create project structure\" by default" + "type": "label", + "label": "Check \"Create project structure\" by default" }, { - "type" : "boolean", - "key" : "create_project_structure_checked", - "label" : "Checked" + "type": "boolean", + "key": "create_project_structure_checked", + "label": "Checked" } ] }, { - "type" : "dict", - "key" : "clean_hierarchical_attr", - "label" : "Clean hierarchical custom attributes", - "checkbox_key" : "enabled", - "children" : [ + "type": "dict", + "key": "clean_hierarchical_attr", + "label": "Clean hierarchical custom attributes", + "checkbox_key": "enabled", + "children": [ { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" + "type": "boolean", + "key": "enabled", + "label": "Enabled" }, { - "type" : "list", - "key" : "role_list", - "label" : "Roles", - "object_type" : "text" + "type": "list", + "key": "role_list", + "label": "Roles", + "object_type": "text" } ] }, { - "type" : "dict", - "key" : "delete_asset_subset", - "label" : "Delete Asset/Subsets", - "checkbox_key" : "enabled", - "children" : [ + "type": "dict", + "key": "delete_asset_subset", + "label": "Delete Asset/Subsets", + "checkbox_key": "enabled", + "children": [ { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" + "type": "boolean", + "key": "enabled", + "label": "Enabled" }, { - "type" : "list", - "key" : "role_list", - "label" : "Roles", - "object_type" : "text" + "type": "list", + "key": "role_list", + "label": "Roles", + "object_type": "text" } ] }, { - "type" : "dict", - "key" : "delete_old_versions", - "label" : "Delete old versions", - "checkbox_key" : "enabled", - "children" : [ + "type": "dict", + "key": "delete_old_versions", + "label": "Delete old versions", + "checkbox_key": "enabled", + "children": [ { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" + "type": "boolean", + "key": "enabled", + "label": "Enabled" }, { - "type" : "list", - "key" : "role_list", - "label" : "Roles", - "object_type" : "text" + "type": "list", + "key": "role_list", + "label": "Roles", + "object_type": "text" } ] }, { - "type" : "dict", - "key" : "delivery_action", - "label" : "Delivery", - "checkbox_key" : "enabled", - "children" : [ + "type": "dict", + "key": "delivery_action", + "label": "Delivery", + "checkbox_key": "enabled", + "children": [ { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" + "type": "boolean", + "key": "enabled", + "label": "Enabled" }, { - "type" : "list", - "key" : "role_list", - "label" : "Roles", - "object_type" : "text" + "type": "list", + "key": "role_list", + "label": "Roles", + "object_type": "text" } ] }, { - "type" : "dict", - "key" : "store_thubmnail_to_avalon", - "label" : "Store Thumbnails to avalon", - "checkbox_key" : "enabled", - "children" : [ + "type": "dict", + "key": "store_thubmnail_to_avalon", + "label": "Store Thumbnails to avalon", + "checkbox_key": "enabled", + "children": [ { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" + "type": "boolean", + "key": "enabled", + "label": "Enabled" }, { - "type" : "list", - "key" : "role_list", - "label" : "Roles", - "object_type" : "text" + "type": "list", + "key": "role_list", + "label": "Roles", + "object_type": "text" } ] }, { - "type" : "dict", - "key" : "job_killer", - "label" : "Job Killer", - "checkbox_key" : "enabled", - "children" : [ + "type": "dict", + "key": "job_killer", + "label": "Job Killer", + "checkbox_key": "enabled", + "children": [ { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" + "type": "boolean", + "key": "enabled", + "label": "Enabled" }, { - "type" : "list", - "key" : "role_list", - "label" : "Roles", - "object_type" : "text" + "type": "list", + "key": "role_list", + "label": "Roles", + "object_type": "text" } ] }, { - "type" : "dict", - "key" : "sync_to_avalon_local", - "label" : "Sync to avalon (local) - For development", - "checkbox_key" : "enabled", - "children" : [ + "type": "dict", + "key": "sync_to_avalon_local", + "label": "Sync to avalon (local) - For development", + "checkbox_key": "enabled", + "children": [ { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" + "type": "boolean", + "key": "enabled", + "label": "Enabled" }, { - "type" : "list", - "key" : "role_list", - "label" : "Roles", - "object_type" : "text" + "type": "list", + "key": "role_list", + "label": "Roles", + "object_type": "text" } ] }, { - "type" : "dict", - "key" : "seed_project", - "label" : "Seed Debug Project", - "checkbox_key" : "enabled", - "children" : [ + "type": "dict", + "key": "seed_project", + "label": "Seed Debug Project", + "checkbox_key": "enabled", + "children": [ { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" + "type": "boolean", + "key": "enabled", + "label": "Enabled" }, { - "type" : "list", - "key" : "role_list", - "label" : "Roles", - "object_type" : "text" + "type": "list", + "key": "role_list", + "label": "Roles", + "object_type": "text" } ] } ] }, { - "type" : "dict", - "collapsible" : true, - "key" : "publish", - "label" : "Publish plugins", - "children" : [ + "type": "dict", + "collapsible": true, + "key": "publish", + "label": "Publish plugins", + "children": [ { - "type" : "dict", - "collapsible" : true, - "checkbox_key" : "enabled", - "key" : "CollectFtrackFamily", - "label" : "Collect Ftrack Family", - "is_group" : true, - "children" : [ + "type": "dict", + "collapsible": true, + "checkbox_key": "enabled", + "key": "CollectFtrackFamily", + "label": "Collect Ftrack Family", + "is_group": true, + "children": [ { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" + "type": "boolean", + "key": "enabled", + "label": "Enabled" }, { - "type" : "list", - "collapsible" : true, - "key" : "profiles", - "label" : "Profiles", - "use_label_wrap" : true, - "object_type" : { - "type" : "dict", - "children" : [ + "type": "list", + "collapsible": true, + "key": "profiles", + "label": "Profiles", + "use_label_wrap": true, + "object_type": { + "type": "dict", + "children": [ { - "key" : "hosts", - "label" : "Host names", - "type" : "list", - "object_type" : "text" + "key": "hosts", + "label": "Host names", + "type": "list", + "object_type": "text" }, { - "key" : "families", - "label" : "Families", - "type" : "list", - "object_type" : "text" + "key": "families", + "label": "Families", + "type": "list", + "object_type": "text" }, { - "key" : "task_types", - "label" : "Task types", - "type" : "task-types-enum" + "key": "task_types", + "label": "Task types", + "type": "task-types-enum" }, { - "key" : "tasks", - "label" : "Task names", - "type" : "list", - "object_type" : "text" + "key": "tasks", + "label": "Task names", + "type": "list", + "object_type": "text" }, { - "type" : "separator" + "type": "separator" }, { - "key" : "add_ftrack_family", - "label" : "Add Ftrack Family", - "type" : "boolean" + "key": "add_ftrack_family", + "label": "Add Ftrack Family", + "type": "boolean" }, { - "type" : "list", - "collapsible" : true, - "key" : "advanced_filtering", - "label" : "Advanced adding if additional families present", - "use_label_wrap" : true, - "object_type" : { - "type" : "dict", - "children" : [ + "type": "list", + "collapsible": true, + "key": "advanced_filtering", + "label": "Advanced adding if additional families present", + "use_label_wrap": true, + "object_type": { + "type": "dict", + "children": [ { - "key" : "families", - "label" : "Additional Families", - "type" : "list", - "object_type" : "text" + "key": "families", + "label": "Additional Families", + "type": "list", + "object_type": "text" }, { - "key" : "add_ftrack_family", - "label" : "Add Ftrack Family", - "type" : "boolean" + "key": "add_ftrack_family", + "label": "Add Ftrack Family", + "type": "boolean" } ] } @@ -697,63 +698,63 @@ ] }, { - "type" : "dict", - "collapsible" : true, - "checkbox_key" : "enabled", - "key" : "IntegrateFtrackNote", - "label" : "IntegrateFtrackNote", - "is_group" : true, - "children" : [ + "type": "dict", + "collapsible": true, + "checkbox_key": "enabled", + "key": "IntegrateFtrackNote", + "label": "IntegrateFtrackNote", + "is_group": true, + "children": [ { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" + "type": "boolean", + "key": "enabled", + "label": "Enabled" }, { - "type" : "text", - "key" : "note_with_intent_template", - "label" : "Note with intent template" + "type": "text", + "key": "note_with_intent_template", + "label": "Note with intent template" }, { - "type" : "list", - "object_type" : "text", - "key" : "note_labels", - "label" : "Note labels" + "type": "list", + "object_type": "text", + "key": "note_labels", + "label": "Note labels" } ] }, { - "type" : "dict", - "collapsible" : true, - "checkbox_key" : "enabled", - "key" : "ValidateFtrackAttributes", - "label" : "ValidateFtrackAttributes", - "is_group" : true, - "children" : [ + "type": "dict", + "collapsible": true, + "checkbox_key": "enabled", + "key": "ValidateFtrackAttributes", + "label": "ValidateFtrackAttributes", + "is_group": true, + "children": [ { - "type" : "boolean", - "key" : "enabled", - "label" : "Enabled" + "type": "boolean", + "key": "enabled", + "label": "Enabled" }, { - "type" : "raw-json", - "key" : "ftrack_custom_attributes", - "label" : "Custom attributes to validate" + "type": "raw-json", + "key": "ftrack_custom_attributes", + "label": "Custom attributes to validate" } ] }, - { - "type" : "dict", - "key" : "IntegrateFtrackInstance", - "label" : "IntegrateFtrackInstance", - "is_group" : true, - "children" : [ + { + "type": "dict", + "key": "IntegrateFtrackInstance", + "label": "IntegrateFtrackInstance", + "is_group": true, + "children": [ { - "type" : "dict-modifiable", - "key" : "family_mapping", - "label" : "Family Mapping", - "object_type" : { - "type" : "text" + "type": "dict-modifiable", + "key": "family_mapping", + "label": "Family Mapping", + "object_type": { + "type": "text" } } ] From ce7d759860252b98738eb18ec11c7801f493d0bd Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Feb 2022 17:17:52 +0100 Subject: [PATCH 36/74] more formatting fixes --- openpype/settings/defaults/project_settings/ftrack.json | 2 +- .../entities/schemas/projects_schema/schema_project_ftrack.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/settings/defaults/project_settings/ftrack.json b/openpype/settings/defaults/project_settings/ftrack.json index 1c1256caab..2f4fd6a790 100644 --- a/openpype/settings/defaults/project_settings/ftrack.json +++ b/openpype/settings/defaults/project_settings/ftrack.json @@ -378,4 +378,4 @@ } } } -} +} \ No newline at end of file diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json b/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json index 1e904e6fdb..e6c8282981 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json @@ -762,4 +762,4 @@ ] } ] -} +} \ No newline at end of file From 39751e6cff2effda6ec641c6a1a8072d0cf0f98a Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Feb 2022 17:24:27 +0100 Subject: [PATCH 37/74] even more formatting fixes --- openpype/settings/defaults/project_settings/ftrack.json | 2 +- .../entities/schemas/projects_schema/schema_project_ftrack.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/settings/defaults/project_settings/ftrack.json b/openpype/settings/defaults/project_settings/ftrack.json index 2f4fd6a790..1474ad103d 100644 --- a/openpype/settings/defaults/project_settings/ftrack.json +++ b/openpype/settings/defaults/project_settings/ftrack.json @@ -343,7 +343,7 @@ "enabled": false, "ftrack_custom_attributes": {} }, - "IntegrateFtrackInstance": { + "IntegrateFtrackInstance": { "family_mapping": { "camera": "cam", "look": "look", diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json b/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json index e6c8282981..eae4ee5536 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json @@ -743,7 +743,7 @@ } ] }, - { + { "type": "dict", "key": "IntegrateFtrackInstance", "label": "IntegrateFtrackInstance", From 1684ea0dc3b535ce28a85d90b9fa80e55fb9f867 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Feb 2022 17:25:45 +0100 Subject: [PATCH 38/74] even more formatting fixes --- .../entities/schemas/projects_schema/schema_project_ftrack.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json b/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json index eae4ee5536..6d0e2693d4 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json @@ -762,4 +762,4 @@ ] } ] -} \ No newline at end of file +} From b27ebb6fbe0c3e0350f9958f4f19c309d90a0b60 Mon Sep 17 00:00:00 2001 From: OpenPype Date: Wed, 2 Feb 2022 03:37:27 +0000 Subject: [PATCH 39/74] [Automated] Bump version --- CHANGELOG.md | 29 ++++++++++++++++++++--------- openpype/version.py | 2 +- pyproject.toml | 2 +- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad2f001b45..70089e4868 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,26 @@ # Changelog +## [3.8.2-nightly.1](https://github.com/pypeclub/OpenPype/tree/HEAD) + +[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.8.1...HEAD) + +**🐛 Bug fixes** + +- Global: fix broken otio review extractor [\#2590](https://github.com/pypeclub/OpenPype/pull/2590) + +**Merged pull requests:** + +- Fix - safer pulling of task name for webpublishing from PS [\#2613](https://github.com/pypeclub/OpenPype/pull/2613) + ## [3.8.1](https://github.com/pypeclub/OpenPype/tree/3.8.1) (2022-02-01) -[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.8.0...3.8.1) +[Full Changelog](https://github.com/pypeclub/OpenPype/compare/CI/3.8.1-nightly.3...3.8.1) **🚀 Enhancements** - Webpublisher: Thumbnail extractor [\#2600](https://github.com/pypeclub/OpenPype/pull/2600) - Loader: Allow to toggle default family filters between "include" or "exclude" filtering [\#2541](https://github.com/pypeclub/OpenPype/pull/2541) +- Launcher: Added context menu to to skip opening last workfile [\#2536](https://github.com/pypeclub/OpenPype/pull/2536) **🐛 Bug fixes** @@ -19,20 +32,22 @@ - Webpublisher: Fix - subset names from processed .psd used wrong value for task [\#2586](https://github.com/pypeclub/OpenPype/pull/2586) - `vrscene` creator Deadline webservice URL handling [\#2580](https://github.com/pypeclub/OpenPype/pull/2580) - global: track name was failing if duplicated root word in name [\#2568](https://github.com/pypeclub/OpenPype/pull/2568) -- General: Do not validate version if build does not support it [\#2557](https://github.com/pypeclub/OpenPype/pull/2557) - Validate Maya Rig produces no cycle errors [\#2484](https://github.com/pypeclub/OpenPype/pull/2484) **Merged pull requests:** - Bump pillow from 8.4.0 to 9.0.0 [\#2595](https://github.com/pypeclub/OpenPype/pull/2595) - Webpublisher: Skip version collect [\#2591](https://github.com/pypeclub/OpenPype/pull/2591) -- build\(deps\): bump follow-redirects from 1.14.4 to 1.14.7 in /website [\#2534](https://github.com/pypeclub/OpenPype/pull/2534) - build\(deps\): bump pillow from 8.4.0 to 9.0.0 [\#2523](https://github.com/pypeclub/OpenPype/pull/2523) ## [3.8.0](https://github.com/pypeclub/OpenPype/tree/3.8.0) (2022-01-24) [Full Changelog](https://github.com/pypeclub/OpenPype/compare/CI/3.8.0-nightly.7...3.8.0) +### 📖 Documentation + +- Variable in docs renamed to proper name [\#2546](https://github.com/pypeclub/OpenPype/pull/2546) + **🆕 New features** - Flame: extracting segments with trans-coding [\#2547](https://github.com/pypeclub/OpenPype/pull/2547) @@ -49,7 +64,6 @@ - Settings: PathInput strip passed string [\#2550](https://github.com/pypeclub/OpenPype/pull/2550) - Global: Exctract Review anatomy fill data with output name [\#2548](https://github.com/pypeclub/OpenPype/pull/2548) - Cosmetics: Clean up some cosmetics / typos [\#2542](https://github.com/pypeclub/OpenPype/pull/2542) -- Launcher: Added context menu to to skip opening last workfile [\#2536](https://github.com/pypeclub/OpenPype/pull/2536) - General: Validate if current process OpenPype version is requested version [\#2529](https://github.com/pypeclub/OpenPype/pull/2529) - General: Be able to use anatomy data in ffmpeg output arguments [\#2525](https://github.com/pypeclub/OpenPype/pull/2525) - Expose toggle publish plug-in settings for Maya Look Shading Engine Naming [\#2521](https://github.com/pypeclub/OpenPype/pull/2521) @@ -64,6 +78,7 @@ - General: OpenPype version updates [\#2575](https://github.com/pypeclub/OpenPype/pull/2575) - Ftrack: Delete action revision [\#2563](https://github.com/pypeclub/OpenPype/pull/2563) - Webpublisher: ftrack shows incorrect user names [\#2560](https://github.com/pypeclub/OpenPype/pull/2560) +- General: Do not validate version if build does not support it [\#2557](https://github.com/pypeclub/OpenPype/pull/2557) - Webpublisher: Fixed progress reporting [\#2553](https://github.com/pypeclub/OpenPype/pull/2553) - Fix Maya AssProxyLoader version switch [\#2551](https://github.com/pypeclub/OpenPype/pull/2551) - General: Fix install thread in igniter [\#2549](https://github.com/pypeclub/OpenPype/pull/2549) @@ -76,17 +91,13 @@ - Fix published frame content for sequence starting with 0 [\#2513](https://github.com/pypeclub/OpenPype/pull/2513) - Maya: reset empty string attributes correctly to "" instead of "None" [\#2506](https://github.com/pypeclub/OpenPype/pull/2506) - Improve FusionPreLaunch hook errors [\#2505](https://github.com/pypeclub/OpenPype/pull/2505) -- General: Modules import function output fix [\#2492](https://github.com/pypeclub/OpenPype/pull/2492) - -### 📖 Documentation - -- Variable in docs renamed to proper name [\#2546](https://github.com/pypeclub/OpenPype/pull/2546) **Merged pull requests:** - AfterEffects: Move implementation to OpenPype [\#2543](https://github.com/pypeclub/OpenPype/pull/2543) - Maya: Remove Maya Look Assigner check on startup [\#2540](https://github.com/pypeclub/OpenPype/pull/2540) - build\(deps\): bump shelljs from 0.8.4 to 0.8.5 in /website [\#2538](https://github.com/pypeclub/OpenPype/pull/2538) +- build\(deps\): bump follow-redirects from 1.14.4 to 1.14.7 in /website [\#2534](https://github.com/pypeclub/OpenPype/pull/2534) - Nuke: Merge avalon's implementation into OpenPype [\#2514](https://github.com/pypeclub/OpenPype/pull/2514) ## [3.7.0](https://github.com/pypeclub/OpenPype/tree/3.7.0) (2022-01-04) diff --git a/openpype/version.py b/openpype/version.py index c573c57637..4fa91e280b 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.8.1" +__version__ = "3.8.2-nightly.1" diff --git a/pyproject.toml b/pyproject.toml index 56d059e447..a3d2ecabd9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "OpenPype" -version = "3.8.1" # OpenPype +version = "3.8.2-nightly.1" # OpenPype description = "Open VFX and Animation pipeline with support." authors = ["OpenPype Team "] license = "MIT License" From 03f48830bc1c3b99938156e3ca4d03ed966bab9d Mon Sep 17 00:00:00 2001 From: "clement.hector" Date: Tue, 18 Jan 2022 13:23:38 +0100 Subject: [PATCH 40/74] fix subset name --- .../hosts/photoshop/plugins/create/create_image.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/openpype/hosts/photoshop/plugins/create/create_image.py b/openpype/hosts/photoshop/plugins/create/create_image.py index cf41bb4020..afcfd599c8 100644 --- a/openpype/hosts/photoshop/plugins/create/create_image.py +++ b/openpype/hosts/photoshop/plugins/create/create_image.py @@ -17,9 +17,7 @@ class CreateImage(openpype.api.Creator): create_group = False stub = photoshop.stub() - useSelection = False if (self.options or {}).get("useSelection"): - useSelection = True multiple_instances = False selection = stub.get_selected_layers() self.log.info("selection {}".format(selection)) @@ -82,19 +80,13 @@ class CreateImage(openpype.api.Creator): group.name = group.name.replace(stub.PUBLISH_ICON, ''). \ replace(stub.LOADED_ICON, '') - if useSelection: - subset_name = self.data["subset"] + group.name - else: - # use value provided by user from Creator - subset_name = self.data["subset"] - if group.long_name: for directory in group.long_name[::-1]: name = directory.replace(stub.PUBLISH_ICON, '').\ replace(stub.LOADED_ICON, '') long_names.append(name) - self.data.update({"subset": subset_name}) + self.data.update({"subset": self.data["subset"]}) self.data.update({"uuid": str(group.id)}) self.data.update({"long_name": "_".join(long_names)}) stub.imprint(group, self.data) From 59e87ef79634f8e9ee1b167f1f7b19e5d0ee14ed Mon Sep 17 00:00:00 2001 From: "clement.hector" Date: Tue, 18 Jan 2022 14:07:16 +0100 Subject: [PATCH 41/74] add group name in case of multi subset creation --- openpype/hosts/photoshop/plugins/create/create_image.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/photoshop/plugins/create/create_image.py b/openpype/hosts/photoshop/plugins/create/create_image.py index afcfd599c8..b36b0d76be 100644 --- a/openpype/hosts/photoshop/plugins/create/create_image.py +++ b/openpype/hosts/photoshop/plugins/create/create_image.py @@ -75,18 +75,23 @@ class CreateImage(openpype.api.Creator): group = stub.group_selected_layers(layer.name) groups.append(group) + creator_subset_name = self.data["subset"] for group in groups: long_names = [] group.name = group.name.replace(stub.PUBLISH_ICON, ''). \ replace(stub.LOADED_ICON, '') + subset_name = creator_subset_name + if len(groups) > 1: + subset_name += group.name.title().replace(" ", "") + if group.long_name: for directory in group.long_name[::-1]: name = directory.replace(stub.PUBLISH_ICON, '').\ replace(stub.LOADED_ICON, '') long_names.append(name) - self.data.update({"subset": self.data["subset"]}) + self.data.update({"subset": subset_name}) self.data.update({"uuid": str(group.id)}) self.data.update({"long_name": "_".join(long_names)}) stub.imprint(group, self.data) From f9daff0379de4750d9067e04176513aaa5e918ba Mon Sep 17 00:00:00 2001 From: "clement.hector" Date: Tue, 18 Jan 2022 14:22:21 +0100 Subject: [PATCH 42/74] create with no "use selection" create empty subset group --- openpype/hosts/photoshop/plugins/create/create_image.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openpype/hosts/photoshop/plugins/create/create_image.py b/openpype/hosts/photoshop/plugins/create/create_image.py index b36b0d76be..344a53f47e 100644 --- a/openpype/hosts/photoshop/plugins/create/create_image.py +++ b/openpype/hosts/photoshop/plugins/create/create_image.py @@ -62,8 +62,7 @@ class CreateImage(openpype.api.Creator): # No selection creates an empty group. create_group = True else: - stub.select_layers(stub.get_layers()) - group = stub.group_selected_layers(self.name) + group = stub.create_group(self.name) groups.append(group) if create_group: From 8bbf9eb7068d1f12af142480b6ede453e95c6c74 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 2 Feb 2022 12:18:36 +0100 Subject: [PATCH 43/74] nuke: improving logic --- openpype/hosts/nuke/plugins/load/load_clip.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/openpype/hosts/nuke/plugins/load/load_clip.py b/openpype/hosts/nuke/plugins/load/load_clip.py index 4fc49e4cee..16df3e27d5 100644 --- a/openpype/hosts/nuke/plugins/load/load_clip.py +++ b/openpype/hosts/nuke/plugins/load/load_clip.py @@ -128,7 +128,7 @@ class LoadClip(plugin.NukeLoader): with viewer_update_and_undo_stop(): read_node["file"].setValue(file) - set_colorspace = self._set_colorspace( + used_colorspace = self._set_colorspace( read_node, version_data, repre["data"]) self._set_range_to_node(read_node, first, last, start_at_workfile) @@ -145,10 +145,9 @@ class LoadClip(plugin.NukeLoader): elif k == 'colorspace': colorspace = repre["data"].get(k) colorspace = colorspace or version_data.get(k) - data_imprint.update({ - "db_colorspace": colorspace, - "set_colorspace": set_colorspace - }) + data_imprint["db_colorspace"] = colorspace + if used_colorspace: + data_imprint["used_colorspace"] = used_colorspace else: data_imprint.update( {k: context["version"]['data'].get(k, str(None))}) @@ -236,7 +235,7 @@ class LoadClip(plugin.NukeLoader): # to avoid multiple undo steps for rest of process # we will switch off undo-ing with viewer_update_and_undo_stop(): - set_colorspace = self._set_colorspace( + used_colorspace = self._set_colorspace( read_node, version_data, representation["data"], path=file) @@ -248,7 +247,6 @@ class LoadClip(plugin.NukeLoader): "frameEnd": str(last), "version": str(version.get("name")), "db_colorspace": colorspace, - "set_colorspace": set_colorspace, "source": version_data.get("source"), "handleStart": str(self.handle_start), "handleEnd": str(self.handle_end), @@ -256,6 +254,10 @@ class LoadClip(plugin.NukeLoader): "author": version_data.get("author") } + # add used colorspace if found any + if used_colorspace: + updated_dict["used_colorspace"] = used_colorspace + # change color of read_node # get all versions in list versions = io.find({ From 6b47d5085cf79797e070e1a4f8eda6976a303bd3 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 2 Feb 2022 13:16:06 +0100 Subject: [PATCH 44/74] nuke: adding clear button to write nodes --- openpype/hosts/nuke/api/lib.py | 15 ++++++++++++++- openpype/hosts/nuke/startup/clear_rendered.py | 11 +++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 openpype/hosts/nuke/startup/clear_rendered.py diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index 26dab9a2bc..15cbb2dd62 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -753,7 +753,7 @@ def script_name(): def add_button_write_to_read(node): name = "createReadNode" - label = "Create Read From Rendered" + label = "Read From Rendered" value = "import write_to_read;\ write_to_read.write_to_read(nuke.thisNode(), allow_relative=False)" knob = nuke.PyScript_Knob(name, label, value) @@ -761,6 +761,16 @@ def add_button_write_to_read(node): node.addKnob(knob) + +def add_button_clear_rendered(node, path): + name = "clearRendered" + label = "Clear Rendered" + value = "import clear_rendered;\ + clear_rendered.clear_rendered(\"{}\")".format(path) + knob = nuke.PyScript_Knob(name, label, value) + node.addKnob(knob) + + def create_write_node(name, data, input=None, prenodes=None, review=True, linked_knobs=None, farm=True): ''' Creating write node which is group node @@ -988,6 +998,9 @@ def create_write_node(name, data, input=None, prenodes=None, # adding write to read button add_button_write_to_read(GN) + # adding write to read button + add_button_clear_rendered(GN, os.path.dirname(fpath)) + # Deadline tab. add_deadline_tab(GN) diff --git a/openpype/hosts/nuke/startup/clear_rendered.py b/openpype/hosts/nuke/startup/clear_rendered.py new file mode 100644 index 0000000000..cf1d8ce170 --- /dev/null +++ b/openpype/hosts/nuke/startup/clear_rendered.py @@ -0,0 +1,11 @@ +import os + +from openpype.api import Logger +log = Logger().get_logger(__name__) + + +def clear_rendered(dir_path): + for _f in os.listdir(dir_path): + _f_path = os.path.join(dir_path, _f) + log.info("Removing: `{}`".format(_f_path)) + os.remove(_f_path) From ce510d26dc5f7505d29b8074704d5c54e8707b54 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 2 Feb 2022 13:32:34 +0100 Subject: [PATCH 45/74] hound: suggestion --- openpype/hosts/nuke/api/lib.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index 15cbb2dd62..6faf6cd108 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -761,7 +761,6 @@ def add_button_write_to_read(node): node.addKnob(knob) - def add_button_clear_rendered(node, path): name = "clearRendered" label = "Clear Rendered" From 4b2034f0b129a92175e900c6f101bc36f556ca35 Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Wed, 2 Feb 2022 15:16:06 +0100 Subject: [PATCH 46/74] fix pulling of cx_freeze 6.10 --- poetry.lock | 1678 +++++++++++++++++++++++-------------------- pyproject.toml | 2 +- tools/create_env.sh | 1 - 3 files changed, 895 insertions(+), 786 deletions(-) diff --git a/poetry.lock b/poetry.lock index 4d5ba5407b..b6eba33e0a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -15,22 +15,25 @@ resolved_reference = "55a7c331e6dc5f81639af50ca4a8cc9d73e9273d" [[package]] name = "aiohttp" -version = "3.7.4.post0" +version = "3.8.1" description = "Async http client/server framework (asyncio)" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -async-timeout = ">=3.0,<4.0" +aiosignal = ">=1.1.2" +async-timeout = ">=4.0.0a3,<5.0" +asynctest = {version = "0.13.0", markers = "python_version < \"3.8\""} attrs = ">=17.3.0" -chardet = ">=2.0,<5.0" +charset-normalizer = ">=2.0,<3.0" +frozenlist = ">=1.1.1" multidict = ">=4.5,<7.0" -typing-extensions = ">=3.6.5" +typing-extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""} yarl = ">=1.0,<2.0" [package.extras] -speedups = ["aiodns", "brotlipy", "cchardet"] +speedups = ["aiodns", "brotli", "cchardet"] [[package]] name = "aiohttp-json-rpc" @@ -43,6 +46,17 @@ python-versions = ">=3.5" [package.dependencies] aiohttp = ">=3,<4" +[[package]] +name = "aiosignal" +version = "1.2.0" +description = "aiosignal: a list of registered asynchronous callbacks" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +frozenlist = ">=1.1.0" + [[package]] name = "alabaster" version = "0.7.12" @@ -80,25 +94,36 @@ python-dateutil = ">=2.7.0" [[package]] name = "astroid" -version = "2.8.4" +version = "2.9.3" description = "An abstract syntax tree for Python with inference support." category = "dev" optional = false -python-versions = "~=3.6" +python-versions = ">=3.6.2" [package.dependencies] lazy-object-proxy = ">=1.4.0" -typed-ast = {version = ">=1.4.0,<1.5", markers = "implementation_name == \"cpython\" and python_version < \"3.8\""} +typed-ast = {version = ">=1.4.0,<2.0", markers = "implementation_name == \"cpython\" and python_version < \"3.8\""} typing-extensions = {version = ">=3.10", markers = "python_version < \"3.10\""} wrapt = ">=1.11,<1.14" [[package]] name = "async-timeout" -version = "3.0.1" +version = "4.0.2" description = "Timeout context manager for asyncio programs" category = "main" optional = false -python-versions = ">=3.5.3" +python-versions = ">=3.6" + +[package.dependencies] +typing-extensions = {version = ">=3.6.5", markers = "python_version < \"3.8\""} + +[[package]] +name = "asynctest" +version = "0.13.0" +description = "Enhance the standard unittest package with features for testing asyncio libraries" +category = "main" +optional = false +python-versions = ">=3.5" [[package]] name = "atomicwrites" @@ -110,17 +135,17 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "attrs" -version = "21.2.0" +version = "21.4.0" description = "Classes Without Boilerplate" category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [package.extras] -dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit"] +dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] -tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface"] -tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"] +tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] +tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"] [[package]] name = "autopep8" @@ -163,7 +188,7 @@ typecheck = ["mypy"] [[package]] name = "blessed" -version = "1.19.0" +version = "1.19.1" description = "Easy, practical library for making terminal apps, by providing an elegant, well-documented interface to Colors, Keyboard input, and screen Positioning capabilities." category = "main" optional = false @@ -176,11 +201,11 @@ wcwidth = ">=0.1.4" [[package]] name = "cachetools" -version = "4.2.4" +version = "5.0.0" description = "Extensible memoizing collections and decorators" category = "main" optional = false -python-versions = "~=3.5" +python-versions = "~=3.7" [[package]] name = "certifi" @@ -209,6 +234,17 @@ category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +[[package]] +name = "charset-normalizer" +version = "2.0.11" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "main" +optional = false +python-versions = ">=3.5.0" + +[package.extras] +unicode_backport = ["unicodedata2"] + [[package]] name = "click" version = "7.1.2" @@ -259,11 +295,11 @@ python-versions = "*" [[package]] name = "coverage" -version = "6.0.2" +version = "6.3.1" description = "Code coverage measurement for Python" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] tomli = {version = "*", optional = true, markers = "extra == \"toml\""} @@ -273,7 +309,7 @@ toml = ["tomli"] [[package]] name = "cryptography" -version = "35.0.0" +version = "36.0.1" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." category = "main" optional = false @@ -284,7 +320,7 @@ cffi = ">=1.12" [package.extras] docs = ["sphinx (>=1.6.5,!=1.8.0,!=3.1.0,!=3.1.1)", "sphinx-rtd-theme"] -docstest = ["doc8", "pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"] +docstest = ["pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"] pep8test = ["black", "flake8", "flake8-import-order", "pep8-naming"] sdist = ["setuptools_rust (>=0.11.4)"] ssh = ["bcrypt (>=3.1.5)"] @@ -292,7 +328,7 @@ test = ["pytest (>=6.2.0)", "pytest-cov", "pytest-subtests", "pytest-xdist", "pr [[package]] name = "cx-freeze" -version = "6.7" +version = "6.9" description = "Create standalone executables from Python scripts" category = "dev" optional = false @@ -312,22 +348,23 @@ python-versions = "*" [[package]] name = "dnspython" -version = "2.1.0" +version = "2.2.0" description = "DNS toolkit" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.6,<4.0" [package.extras] -dnssec = ["cryptography (>=2.6)"] -doh = ["requests", "requests-toolbelt"] -idna = ["idna (>=2.1)"] -curio = ["curio (>=1.2)", "sniffio (>=1.1)"] -trio = ["trio (>=0.14.0)", "sniffio (>=1.1)"] +dnssec = ["cryptography (>=2.6,<37.0)"] +curio = ["curio (>=1.2,<2.0)", "sniffio (>=1.1,<2.0)"] +doh = ["h2 (>=4.1.0)", "httpx (>=0.21.1)", "requests (>=2.23.0,<3.0.0)", "requests-toolbelt (>=0.9.1,<0.10.0)"] +idna = ["idna (>=2.1,<4.0)"] +trio = ["trio (>=0.14,<0.20)"] +wmi = ["wmi (>=1.5.1,<2.0.0)"] [[package]] name = "docutils" -version = "0.18" +version = "0.18.1" description = "Docutils -- Python Documentation Utilities" category = "dev" optional = false @@ -335,7 +372,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "dropbox" -version = "11.22.0" +version = "11.26.0" description = "Official Dropbox API Client" category = "main" optional = false @@ -348,7 +385,7 @@ stone = ">=2" [[package]] name = "enlighten" -version = "1.10.1" +version = "1.10.2" description = "Enlighten Progress Bar" category = "main" optional = false @@ -380,6 +417,14 @@ mccabe = ">=0.6.0,<0.7.0" pycodestyle = ">=2.7.0,<2.8.0" pyflakes = ">=2.3.0,<2.4.0" +[[package]] +name = "frozenlist" +version = "1.3.0" +description = "A list-like structure which implements collections.abc.MutableSequence" +category = "main" +optional = false +python-versions = ">=3.7" + [[package]] name = "ftrack-python-api" version = "2.0.0" @@ -419,7 +464,7 @@ smmap = ">=3.0.1,<6" [[package]] name = "gitpython" -version = "3.1.24" +version = "3.1.26" description = "GitPython is a python library used to interact with Git repositories" category = "dev" optional = false @@ -427,41 +472,38 @@ python-versions = ">=3.7" [package.dependencies] gitdb = ">=4.0.1,<5" -typing-extensions = {version = ">=3.7.4.3", markers = "python_version < \"3.10\""} +typing-extensions = {version = ">=3.7.4.3", markers = "python_version < \"3.8\""} [[package]] name = "google-api-core" -version = "1.31.3" +version = "2.4.0" description = "Google API client core library" category = "main" optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*" +python-versions = ">=3.6" [package.dependencies] -google-auth = ">=1.25.0,<2.0dev" -googleapis-common-protos = ">=1.6.0,<2.0dev" -packaging = ">=14.3" -protobuf = ">=3.12.0,<3.18.0" -pytz = "*" +google-auth = ">=1.25.0,<3.0dev" +googleapis-common-protos = ">=1.52.0,<2.0dev" +protobuf = ">=3.12.0" requests = ">=2.18.0,<3.0.0dev" -six = ">=1.13.0" [package.extras] -grpc = ["grpcio (>=1.29.0,<2.0dev)"] +grpc = ["grpcio (>=1.33.2,<2.0dev)", "grpcio-status (>=1.33.2,<2.0dev)"] grpcgcp = ["grpcio-gcp (>=0.2.2)"] grpcio-gcp = ["grpcio-gcp (>=0.2.2)"] [[package]] name = "google-api-python-client" -version = "1.12.8" +version = "1.12.10" description = "Google API Client Library for Python" category = "main" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" [package.dependencies] -google-api-core = ">=1.21.0,<2dev" -google-auth = ">=1.16.0" +google-api-core = {version = ">=1.21.0,<3dev", markers = "python_version >= \"3\""} +google-auth = {version = ">=1.16.0,<3dev", markers = "python_version >= \"3\""} google-auth-httplib2 = ">=0.0.3" httplib2 = ">=0.15.0,<1dev" six = ">=1.13.0,<2dev" @@ -469,14 +511,14 @@ uritemplate = ">=3.0.0,<4dev" [[package]] name = "google-auth" -version = "1.35.0" +version = "2.6.0" description = "Google Authentication Library" category = "main" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*" [package.dependencies] -cachetools = ">=2.0.0,<5.0" +cachetools = ">=2.0.0,<6.0" pyasn1-modules = ">=0.2.1" rsa = {version = ">=3.1.4,<5", markers = "python_version >= \"3.6\""} six = ">=1.9.0" @@ -501,7 +543,7 @@ six = "*" [[package]] name = "googleapis-common-protos" -version = "1.53.0" +version = "1.54.0" description = "Common protobufs used in Google APIs" category = "main" optional = false @@ -515,14 +557,14 @@ grpc = ["grpcio (>=1.0.0)"] [[package]] name = "httplib2" -version = "0.20.1" +version = "0.20.2" description = "A comprehensive HTTP client library." category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [package.dependencies] -pyparsing = ">=2.4.2,<3" +pyparsing = {version = ">=2.4.2,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.0.2 || >3.0.2,<3.0.3 || >3.0.3,<4", markers = "python_version > \"3.0\""} [[package]] name = "idna" @@ -534,7 +576,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "imagesize" -version = "1.2.0" +version = "1.3.0" description = "Getting image size from png/jpeg/jpeg2000/gif file" category = "dev" optional = false @@ -542,11 +584,11 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "importlib-metadata" -version = "4.8.1" +version = "4.10.1" description = "Read metadata from Python packages" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} @@ -555,7 +597,7 @@ zipp = ">=0.5" [package.extras] docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] perf = ["ipython"] -testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] [[package]] name = "iniconfig" @@ -567,7 +609,7 @@ python-versions = "*" [[package]] name = "isort" -version = "5.9.3" +version = "5.10.1" description = "A Python utility / library to sort Python imports." category = "dev" optional = false @@ -668,11 +710,11 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pyt [[package]] name = "lazy-object-proxy" -version = "1.6.0" +version = "1.7.1" description = "A fast and thorough lazy object proxy." category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = ">=3.6" [[package]] name = "log4mongo" @@ -703,11 +745,11 @@ python-versions = "*" [[package]] name = "multidict" -version = "5.2.0" +version = "6.0.2" description = "multidict implementation" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [[package]] name = "opentimelineio" @@ -731,18 +773,18 @@ reference = "openpype" [[package]] name = "packaging" -version = "21.2" +version = "21.3" description = "Core utilities for Python packages" -category = "main" +category = "dev" optional = false python-versions = ">=3.6" [package.dependencies] -pyparsing = ">=2.0.2,<3" +pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" [[package]] name = "paramiko" -version = "2.8.0" +version = "2.9.2" description = "SSH2 protocol library" category = "main" optional = false @@ -761,7 +803,7 @@ invoke = ["invoke (>=1.3)"] [[package]] name = "parso" -version = "0.8.2" +version = "0.8.3" description = "A Python Parser" category = "dev" optional = false @@ -792,11 +834,11 @@ python-versions = ">=3.7" [[package]] name = "platformdirs" -version = "2.4.0" +version = "2.4.1" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.extras] docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"] @@ -835,22 +877,19 @@ python-versions = "*" [[package]] name = "protobuf" -version = "3.17.3" +version = "3.19.4" description = "Protocol Buffers" category = "main" optional = false -python-versions = "*" - -[package.dependencies] -six = ">=1.9" +python-versions = ">=3.5" [[package]] name = "py" -version = "1.10.0" +version = "1.11.0" description = "library with cross-python path, ini-parsing, io, code, log facilities" category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "pyaaf2" @@ -897,7 +936,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "pycparser" -version = "2.20" +version = "2.21" description = "C parser in Python" category = "main" optional = false @@ -925,7 +964,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "pygments" -version = "2.10.0" +version = "2.11.2" description = "Pygments is a syntax highlighting package written in Python." category = "dev" optional = false @@ -933,24 +972,24 @@ python-versions = ">=3.5" [[package]] name = "pylint" -version = "2.11.1" +version = "2.12.2" description = "python code static checker" category = "dev" optional = false -python-versions = "~=3.6" +python-versions = ">=3.6.2" [package.dependencies] -astroid = ">=2.8.0,<2.9" +astroid = ">=2.9.0,<2.10" colorama = {version = "*", markers = "sys_platform == \"win32\""} isort = ">=4.2.5,<6" mccabe = ">=0.6,<0.7" platformdirs = ">=2.2.0" -toml = ">=0.7.1" +toml = ">=0.9.2" typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} [[package]] name = "pymongo" -version = "3.12.1" +version = "3.12.3" description = "Python driver for MongoDB " category = "main" optional = false @@ -968,15 +1007,14 @@ zstd = ["zstandard"] [[package]] name = "pynacl" -version = "1.4.0" +version = "1.5.0" description = "Python binding to the Networking and Cryptography (NaCl) library" category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=3.6" [package.dependencies] cffi = ">=1.4.1" -six = "*" [package.extras] docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"] @@ -984,7 +1022,7 @@ tests = ["pytest (>=3.2.1,!=3.3.0)", "hypothesis (>=3.27.0)"] [[package]] name = "pynput" -version = "1.7.4" +version = "1.7.6" description = "Monitor and control user input devices" category = "main" optional = false @@ -992,14 +1030,14 @@ python-versions = "*" [package.dependencies] evdev = {version = ">=1.3", markers = "sys_platform in \"linux\""} -pyobjc-framework-ApplicationServices = {version = ">=7.3", markers = "sys_platform == \"darwin\""} -pyobjc-framework-Quartz = {version = ">=7.3", markers = "sys_platform == \"darwin\""} +pyobjc-framework-ApplicationServices = {version = ">=8.0", markers = "sys_platform == \"darwin\""} +pyobjc-framework-Quartz = {version = ">=8.0", markers = "sys_platform == \"darwin\""} python-xlib = {version = ">=0.17", markers = "sys_platform in \"linux\""} six = "*" [[package]] name = "pyobjc-core" -version = "7.3" +version = "8.2" description = "Python<->ObjC Interoperability Module" category = "main" optional = false @@ -1007,39 +1045,39 @@ python-versions = ">=3.6" [[package]] name = "pyobjc-framework-applicationservices" -version = "7.3" +version = "8.2" description = "Wrappers for the framework ApplicationServices on macOS" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -pyobjc-core = ">=7.3" -pyobjc-framework-Cocoa = ">=7.3" -pyobjc-framework-Quartz = ">=7.3" +pyobjc-core = ">=8.2" +pyobjc-framework-Cocoa = ">=8.2" +pyobjc-framework-Quartz = ">=8.2" [[package]] name = "pyobjc-framework-cocoa" -version = "7.3" +version = "8.2" description = "Wrappers for the Cocoa frameworks on macOS" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -pyobjc-core = ">=7.3" +pyobjc-core = ">=8.2" [[package]] name = "pyobjc-framework-quartz" -version = "7.3" +version = "8.2" description = "Wrappers for the Quartz frameworks on macOS" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -pyobjc-core = ">=7.3" -pyobjc-framework-Cocoa = ">=7.3" +pyobjc-core = ">=8.2" +pyobjc-framework-Cocoa = ">=8.2" [[package]] name = "pyparsing" @@ -1051,11 +1089,11 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "pyrsistent" -version = "0.18.0" +version = "0.18.1" description = "Persistent/Functional/Immutable data structures" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [[package]] name = "pysftp" @@ -1107,11 +1145,11 @@ testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtuale [[package]] name = "pytest-print" -version = "0.3.0" +version = "0.3.1" description = "pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout)" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] pytest = ">=6" @@ -1153,7 +1191,7 @@ python-versions = "*" name = "pytz" version = "2021.3" description = "World timezone definitions, modern and historical" -category = "main" +category = "dev" optional = false python-versions = "*" @@ -1214,11 +1252,11 @@ socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] [[package]] name = "rsa" -version = "4.7.2" +version = "4.8" description = "Pure-Python RSA implementation" category = "main" optional = false -python-versions = ">=3.5, <4" +python-versions = ">=3.6,<4" [package.dependencies] pyasn1 = ">=0.1.3" @@ -1253,15 +1291,15 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "slack-sdk" -version = "3.11.2" +version = "3.13.0" description = "The Slack API Platform SDK for Python" category = "main" optional = false python-versions = ">=3.6.0" [package.extras] -optional = ["aiodns (>1.0)", "aiohttp (>=3.7.3,<4)", "boto3 (<=2)", "SQLAlchemy (>=1,<2)", "websockets (>=9.1,<10)", "websocket-client (>=1,<2)"] -testing = ["pytest (>=5.4,<6)", "pytest-asyncio (<1)", "Flask-Sockets (>=0.2,<1)", "Flask (>=1,<2)", "Werkzeug (<2)", "pytest-cov (>=2,<3)", "codecov (>=2,<3)", "flake8 (>=3,<4)", "black (==21.9b0)", "psutil (>=5,<6)", "databases (>=0.3)", "boto3 (<=2)", "moto (<2)"] +optional = ["aiodns (>1.0)", "aiohttp (>=3.7.3,<4)", "boto3 (<=2)", "SQLAlchemy (>=1,<2)", "websockets (>=10,<11)", "websocket-client (>=1,<2)"] +testing = ["pytest (>=6.2.5,<7)", "pytest-asyncio (<1)", "Flask-Sockets (>=0.2,<1)", "Flask (>=1,<2)", "Werkzeug (<2)", "pytest-cov (>=2,<3)", "codecov (>=2,<3)", "flake8 (>=4,<5)", "black (==21.12b0)", "psutil (>=5,<6)", "databases (>=0.3)", "boto3 (<=2)", "moto (<2)"] [[package]] name = "smmap" @@ -1273,7 +1311,7 @@ python-versions = ">=3.6" [[package]] name = "snowballstemmer" -version = "2.1.0" +version = "2.2.0" description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." category = "dev" optional = false @@ -1432,7 +1470,7 @@ test = ["pytest", "sqlalchemy", "whoosh", "sphinx"] [[package]] name = "stone" -version = "3.2.1" +version = "3.3.1" description = "Stone is an interface description language (IDL) for APIs." category = "main" optional = false @@ -1440,7 +1478,7 @@ python-versions = "*" [package.dependencies] ply = ">=3.4" -six = ">=1.3.0" +six = ">=1.12.0" [[package]] name = "termcolor" @@ -1460,27 +1498,27 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "tomli" -version = "1.2.2" +version = "2.0.0" description = "A lil' TOML parser" category = "dev" optional = false +python-versions = ">=3.7" + +[[package]] +name = "typed-ast" +version = "1.5.2" +description = "a fork of Python 2 and 3 ast modules with type comment support" +category = "dev" +optional = false python-versions = ">=3.6" -[[package]] -name = "typed-ast" -version = "1.4.3" -description = "a fork of Python 2 and 3 ast modules with type comment support" -category = "dev" -optional = false -python-versions = "*" - [[package]] name = "typing-extensions" -version = "3.10.0.2" -description = "Backported and Experimental Type Hints for Python 3.5+" +version = "4.0.1" +description = "Backported and Experimental Type Hints for Python 3.6+" category = "main" optional = false -python-versions = "*" +python-versions = ">=3.6" [[package]] name = "uritemplate" @@ -1492,7 +1530,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "urllib3" -version = "1.26.7" +version = "1.26.8" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false @@ -1524,7 +1562,7 @@ six = "*" [[package]] name = "wrapt" -version = "1.13.2" +version = "1.13.3" description = "Module for decorators, wrappers and monkey patching." category = "dev" optional = false @@ -1549,7 +1587,7 @@ ujson = ["ujson"] [[package]] name = "yarl" -version = "1.7.0" +version = "1.7.2" description = "Yet another URL library" category = "main" optional = false @@ -1562,66 +1600,105 @@ typing-extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""} [[package]] name = "zipp" -version = "3.6.0" +version = "3.7.0" description = "Backport of pathlib-compatible object wrapper for zip files" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.extras] docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] [metadata] lock-version = "1.1" python-versions = "3.7.*" -content-hash = "c933f867533b4ca36b9af3002395bdf6c0de6904a8bbcc38578840b266c54872" +content-hash = "2f78d48a6aad2d8a88b7dd7f31a76d907bec9fb65f0086fba6b6d2e1605f0f88" [metadata.files] acre = [] aiohttp = [ - {file = "aiohttp-3.7.4.post0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:3cf75f7cdc2397ed4442594b935a11ed5569961333d49b7539ea741be2cc79d5"}, - {file = "aiohttp-3.7.4.post0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:4b302b45040890cea949ad092479e01ba25911a15e648429c7c5aae9650c67a8"}, - {file = "aiohttp-3.7.4.post0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:fe60131d21b31fd1a14bd43e6bb88256f69dfc3188b3a89d736d6c71ed43ec95"}, - {file = "aiohttp-3.7.4.post0-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:393f389841e8f2dfc86f774ad22f00923fdee66d238af89b70ea314c4aefd290"}, - {file = "aiohttp-3.7.4.post0-cp36-cp36m-manylinux2014_ppc64le.whl", hash = "sha256:c6e9dcb4cb338d91a73f178d866d051efe7c62a7166653a91e7d9fb18274058f"}, - {file = "aiohttp-3.7.4.post0-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:5df68496d19f849921f05f14f31bd6ef53ad4b00245da3195048c69934521809"}, - {file = "aiohttp-3.7.4.post0-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:0563c1b3826945eecd62186f3f5c7d31abb7391fedc893b7e2b26303b5a9f3fe"}, - {file = "aiohttp-3.7.4.post0-cp36-cp36m-win32.whl", hash = "sha256:3d78619672183be860b96ed96f533046ec97ca067fd46ac1f6a09cd9b7484287"}, - {file = "aiohttp-3.7.4.post0-cp36-cp36m-win_amd64.whl", hash = "sha256:f705e12750171c0ab4ef2a3c76b9a4024a62c4103e3a55dd6f99265b9bc6fcfc"}, - {file = "aiohttp-3.7.4.post0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:230a8f7e24298dea47659251abc0fd8b3c4e38a664c59d4b89cca7f6c09c9e87"}, - {file = "aiohttp-3.7.4.post0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:2e19413bf84934d651344783c9f5e22dee452e251cfd220ebadbed2d9931dbf0"}, - {file = "aiohttp-3.7.4.post0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:e4b2b334e68b18ac9817d828ba44d8fcb391f6acb398bcc5062b14b2cbeac970"}, - {file = "aiohttp-3.7.4.post0-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:d012ad7911653a906425d8473a1465caa9f8dea7fcf07b6d870397b774ea7c0f"}, - {file = "aiohttp-3.7.4.post0-cp37-cp37m-manylinux2014_ppc64le.whl", hash = "sha256:40eced07f07a9e60e825554a31f923e8d3997cfc7fb31dbc1328c70826e04cde"}, - {file = "aiohttp-3.7.4.post0-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:209b4a8ee987eccc91e2bd3ac36adee0e53a5970b8ac52c273f7f8fd4872c94c"}, - {file = "aiohttp-3.7.4.post0-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:14762875b22d0055f05d12abc7f7d61d5fd4fe4642ce1a249abdf8c700bf1fd8"}, - {file = "aiohttp-3.7.4.post0-cp37-cp37m-win32.whl", hash = "sha256:7615dab56bb07bff74bc865307aeb89a8bfd9941d2ef9d817b9436da3a0ea54f"}, - {file = "aiohttp-3.7.4.post0-cp37-cp37m-win_amd64.whl", hash = "sha256:d9e13b33afd39ddeb377eff2c1c4f00544e191e1d1dee5b6c51ddee8ea6f0cf5"}, - {file = "aiohttp-3.7.4.post0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:547da6cacac20666422d4882cfcd51298d45f7ccb60a04ec27424d2f36ba3eaf"}, - {file = "aiohttp-3.7.4.post0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:af9aa9ef5ba1fd5b8c948bb11f44891968ab30356d65fd0cc6707d989cd521df"}, - {file = "aiohttp-3.7.4.post0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:64322071e046020e8797117b3658b9c2f80e3267daec409b350b6a7a05041213"}, - {file = "aiohttp-3.7.4.post0-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:bb437315738aa441251214dad17428cafda9cdc9729499f1d6001748e1d432f4"}, - {file = "aiohttp-3.7.4.post0-cp38-cp38-manylinux2014_ppc64le.whl", hash = "sha256:e54962802d4b8b18b6207d4a927032826af39395a3bd9196a5af43fc4e60b009"}, - {file = "aiohttp-3.7.4.post0-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:a00bb73540af068ca7390e636c01cbc4f644961896fa9363154ff43fd37af2f5"}, - {file = "aiohttp-3.7.4.post0-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:79ebfc238612123a713a457d92afb4096e2148be17df6c50fb9bf7a81c2f8013"}, - {file = "aiohttp-3.7.4.post0-cp38-cp38-win32.whl", hash = "sha256:515dfef7f869a0feb2afee66b957cc7bbe9ad0cdee45aec7fdc623f4ecd4fb16"}, - {file = "aiohttp-3.7.4.post0-cp38-cp38-win_amd64.whl", hash = "sha256:114b281e4d68302a324dd33abb04778e8557d88947875cbf4e842c2c01a030c5"}, - {file = "aiohttp-3.7.4.post0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:7b18b97cf8ee5452fa5f4e3af95d01d84d86d32c5e2bfa260cf041749d66360b"}, - {file = "aiohttp-3.7.4.post0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:15492a6368d985b76a2a5fdd2166cddfea5d24e69eefed4630cbaae5c81d89bd"}, - {file = "aiohttp-3.7.4.post0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:bdb230b4943891321e06fc7def63c7aace16095be7d9cf3b1e01be2f10fba439"}, - {file = "aiohttp-3.7.4.post0-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:cffe3ab27871bc3ea47df5d8f7013945712c46a3cc5a95b6bee15887f1675c22"}, - {file = "aiohttp-3.7.4.post0-cp39-cp39-manylinux2014_ppc64le.whl", hash = "sha256:f881853d2643a29e643609da57b96d5f9c9b93f62429dcc1cbb413c7d07f0e1a"}, - {file = "aiohttp-3.7.4.post0-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:a5ca29ee66f8343ed336816c553e82d6cade48a3ad702b9ffa6125d187e2dedb"}, - {file = "aiohttp-3.7.4.post0-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:17c073de315745a1510393a96e680d20af8e67e324f70b42accbd4cb3315c9fb"}, - {file = "aiohttp-3.7.4.post0-cp39-cp39-win32.whl", hash = "sha256:932bb1ea39a54e9ea27fc9232163059a0b8855256f4052e776357ad9add6f1c9"}, - {file = "aiohttp-3.7.4.post0-cp39-cp39-win_amd64.whl", hash = "sha256:02f46fc0e3c5ac58b80d4d56eb0a7c7d97fcef69ace9326289fb9f1955e65cfe"}, - {file = "aiohttp-3.7.4.post0.tar.gz", hash = "sha256:493d3299ebe5f5a7c66b9819eacdcfbbaaf1a8e84911ddffcdc48888497afecf"}, + {file = "aiohttp-3.8.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1ed0b6477896559f17b9eaeb6d38e07f7f9ffe40b9f0f9627ae8b9926ae260a8"}, + {file = "aiohttp-3.8.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7dadf3c307b31e0e61689cbf9e06be7a867c563d5a63ce9dca578f956609abf8"}, + {file = "aiohttp-3.8.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a79004bb58748f31ae1cbe9fa891054baaa46fb106c2dc7af9f8e3304dc30316"}, + {file = "aiohttp-3.8.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:12de6add4038df8f72fac606dff775791a60f113a725c960f2bab01d8b8e6b15"}, + {file = "aiohttp-3.8.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6f0d5f33feb5f69ddd57a4a4bd3d56c719a141080b445cbf18f238973c5c9923"}, + {file = "aiohttp-3.8.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eaba923151d9deea315be1f3e2b31cc39a6d1d2f682f942905951f4e40200922"}, + {file = "aiohttp-3.8.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:099ebd2c37ac74cce10a3527d2b49af80243e2a4fa39e7bce41617fbc35fa3c1"}, + {file = "aiohttp-3.8.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2e5d962cf7e1d426aa0e528a7e198658cdc8aa4fe87f781d039ad75dcd52c516"}, + {file = "aiohttp-3.8.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:fa0ffcace9b3aa34d205d8130f7873fcfefcb6a4dd3dd705b0dab69af6712642"}, + {file = "aiohttp-3.8.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:61bfc23df345d8c9716d03717c2ed5e27374e0fe6f659ea64edcd27b4b044cf7"}, + {file = "aiohttp-3.8.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:31560d268ff62143e92423ef183680b9829b1b482c011713ae941997921eebc8"}, + {file = "aiohttp-3.8.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:01d7bdb774a9acc838e6b8f1d114f45303841b89b95984cbb7d80ea41172a9e3"}, + {file = "aiohttp-3.8.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:97ef77eb6b044134c0b3a96e16abcb05ecce892965a2124c566af0fd60f717e2"}, + {file = "aiohttp-3.8.1-cp310-cp310-win32.whl", hash = "sha256:c2aef4703f1f2ddc6df17519885dbfa3514929149d3ff900b73f45998f2532fa"}, + {file = "aiohttp-3.8.1-cp310-cp310-win_amd64.whl", hash = "sha256:713ac174a629d39b7c6a3aa757b337599798da4c1157114a314e4e391cd28e32"}, + {file = "aiohttp-3.8.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:473d93d4450880fe278696549f2e7aed8cd23708c3c1997981464475f32137db"}, + {file = "aiohttp-3.8.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99b5eeae8e019e7aad8af8bb314fb908dd2e028b3cdaad87ec05095394cce632"}, + {file = "aiohttp-3.8.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3af642b43ce56c24d063325dd2cf20ee012d2b9ba4c3c008755a301aaea720ad"}, + {file = "aiohttp-3.8.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3630c3ef435c0a7c549ba170a0633a56e92629aeed0e707fec832dee313fb7a"}, + {file = "aiohttp-3.8.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:4a4a4e30bf1edcad13fb0804300557aedd07a92cabc74382fdd0ba6ca2661091"}, + {file = "aiohttp-3.8.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6f8b01295e26c68b3a1b90efb7a89029110d3a4139270b24fda961893216c440"}, + {file = "aiohttp-3.8.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:a25fa703a527158aaf10dafd956f7d42ac6d30ec80e9a70846253dd13e2f067b"}, + {file = "aiohttp-3.8.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:5bfde62d1d2641a1f5173b8c8c2d96ceb4854f54a44c23102e2ccc7e02f003ec"}, + {file = "aiohttp-3.8.1-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:51467000f3647d519272392f484126aa716f747859794ac9924a7aafa86cd411"}, + {file = "aiohttp-3.8.1-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:03a6d5349c9ee8f79ab3ff3694d6ce1cfc3ced1c9d36200cb8f08ba06bd3b782"}, + {file = "aiohttp-3.8.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:102e487eeb82afac440581e5d7f8f44560b36cf0bdd11abc51a46c1cd88914d4"}, + {file = "aiohttp-3.8.1-cp36-cp36m-win32.whl", hash = "sha256:4aed991a28ea3ce320dc8ce655875e1e00a11bdd29fe9444dd4f88c30d558602"}, + {file = "aiohttp-3.8.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b0e20cddbd676ab8a64c774fefa0ad787cc506afd844de95da56060348021e96"}, + {file = "aiohttp-3.8.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:37951ad2f4a6df6506750a23f7cbabad24c73c65f23f72e95897bb2cecbae676"}, + {file = "aiohttp-3.8.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c23b1ad869653bc818e972b7a3a79852d0e494e9ab7e1a701a3decc49c20d51"}, + {file = "aiohttp-3.8.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:15b09b06dae900777833fe7fc4b4aa426556ce95847a3e8d7548e2d19e34edb8"}, + {file = "aiohttp-3.8.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:477c3ea0ba410b2b56b7efb072c36fa91b1e6fc331761798fa3f28bb224830dd"}, + {file = "aiohttp-3.8.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2f2f69dca064926e79997f45b2f34e202b320fd3782f17a91941f7eb85502ee2"}, + {file = "aiohttp-3.8.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ef9612483cb35171d51d9173647eed5d0069eaa2ee812793a75373447d487aa4"}, + {file = "aiohttp-3.8.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6d69f36d445c45cda7b3b26afef2fc34ef5ac0cdc75584a87ef307ee3c8c6d00"}, + {file = "aiohttp-3.8.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:55c3d1072704d27401c92339144d199d9de7b52627f724a949fc7d5fc56d8b93"}, + {file = "aiohttp-3.8.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:b9d00268fcb9f66fbcc7cd9fe423741d90c75ee029a1d15c09b22d23253c0a44"}, + {file = "aiohttp-3.8.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:07b05cd3305e8a73112103c834e91cd27ce5b4bd07850c4b4dbd1877d3f45be7"}, + {file = "aiohttp-3.8.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c34dc4958b232ef6188c4318cb7b2c2d80521c9a56c52449f8f93ab7bc2a8a1c"}, + {file = "aiohttp-3.8.1-cp37-cp37m-win32.whl", hash = "sha256:d2f9b69293c33aaa53d923032fe227feac867f81682f002ce33ffae978f0a9a9"}, + {file = "aiohttp-3.8.1-cp37-cp37m-win_amd64.whl", hash = "sha256:6ae828d3a003f03ae31915c31fa684b9890ea44c9c989056fea96e3d12a9fa17"}, + {file = "aiohttp-3.8.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0c7ebbbde809ff4e970824b2b6cb7e4222be6b95a296e46c03cf050878fc1785"}, + {file = "aiohttp-3.8.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8b7ef7cbd4fec9a1e811a5de813311ed4f7ac7d93e0fda233c9b3e1428f7dd7b"}, + {file = "aiohttp-3.8.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c3d6a4d0619e09dcd61021debf7059955c2004fa29f48788a3dfaf9c9901a7cd"}, + {file = "aiohttp-3.8.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:718626a174e7e467f0558954f94af117b7d4695d48eb980146016afa4b580b2e"}, + {file = "aiohttp-3.8.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:589c72667a5febd36f1315aa6e5f56dd4aa4862df295cb51c769d16142ddd7cd"}, + {file = "aiohttp-3.8.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2ed076098b171573161eb146afcb9129b5ff63308960aeca4b676d9d3c35e700"}, + {file = "aiohttp-3.8.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:086f92daf51a032d062ec5f58af5ca6a44d082c35299c96376a41cbb33034675"}, + {file = "aiohttp-3.8.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:11691cf4dc5b94236ccc609b70fec991234e7ef8d4c02dd0c9668d1e486f5abf"}, + {file = "aiohttp-3.8.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:31d1e1c0dbf19ebccbfd62eff461518dcb1e307b195e93bba60c965a4dcf1ba0"}, + {file = "aiohttp-3.8.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:11a67c0d562e07067c4e86bffc1553f2cf5b664d6111c894671b2b8712f3aba5"}, + {file = "aiohttp-3.8.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:bb01ba6b0d3f6c68b89fce7305080145d4877ad3acaed424bae4d4ee75faa950"}, + {file = "aiohttp-3.8.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:44db35a9e15d6fe5c40d74952e803b1d96e964f683b5a78c3cc64eb177878155"}, + {file = "aiohttp-3.8.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:844a9b460871ee0a0b0b68a64890dae9c415e513db0f4a7e3cab41a0f2fedf33"}, + {file = "aiohttp-3.8.1-cp38-cp38-win32.whl", hash = "sha256:7d08744e9bae2ca9c382581f7dce1273fe3c9bae94ff572c3626e8da5b193c6a"}, + {file = "aiohttp-3.8.1-cp38-cp38-win_amd64.whl", hash = "sha256:04d48b8ce6ab3cf2097b1855e1505181bdd05586ca275f2505514a6e274e8e75"}, + {file = "aiohttp-3.8.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f5315a2eb0239185af1bddb1abf472d877fede3cc8d143c6cddad37678293237"}, + {file = "aiohttp-3.8.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a996d01ca39b8dfe77440f3cd600825d05841088fd6bc0144cc6c2ec14cc5f74"}, + {file = "aiohttp-3.8.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:13487abd2f761d4be7c8ff9080de2671e53fff69711d46de703c310c4c9317ca"}, + {file = "aiohttp-3.8.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea302f34477fda3f85560a06d9ebdc7fa41e82420e892fc50b577e35fc6a50b2"}, + {file = "aiohttp-3.8.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a2f635ce61a89c5732537a7896b6319a8fcfa23ba09bec36e1b1ac0ab31270d2"}, + {file = "aiohttp-3.8.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e999f2d0e12eea01caeecb17b653f3713d758f6dcc770417cf29ef08d3931421"}, + {file = "aiohttp-3.8.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0770e2806a30e744b4e21c9d73b7bee18a1cfa3c47991ee2e5a65b887c49d5cf"}, + {file = "aiohttp-3.8.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d15367ce87c8e9e09b0f989bfd72dc641bcd04ba091c68cd305312d00962addd"}, + {file = "aiohttp-3.8.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:6c7cefb4b0640703eb1069835c02486669312bf2f12b48a748e0a7756d0de33d"}, + {file = "aiohttp-3.8.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:71927042ed6365a09a98a6377501af5c9f0a4d38083652bcd2281a06a5976724"}, + {file = "aiohttp-3.8.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:28d490af82bc6b7ce53ff31337a18a10498303fe66f701ab65ef27e143c3b0ef"}, + {file = "aiohttp-3.8.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:b6613280ccedf24354406caf785db748bebbddcf31408b20c0b48cb86af76866"}, + {file = "aiohttp-3.8.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:81e3d8c34c623ca4e36c46524a3530e99c0bc95ed068fd6e9b55cb721d408fb2"}, + {file = "aiohttp-3.8.1-cp39-cp39-win32.whl", hash = "sha256:7187a76598bdb895af0adbd2fb7474d7f6025d170bc0a1130242da817ce9e7d1"}, + {file = "aiohttp-3.8.1-cp39-cp39-win_amd64.whl", hash = "sha256:1c182cb873bc91b411e184dab7a2b664d4fea2743df0e4d57402f7f3fa644bac"}, + {file = "aiohttp-3.8.1.tar.gz", hash = "sha256:fc5471e1a54de15ef71c1bc6ebe80d4dc681ea600e68bfd1cbce40427f0b7578"}, ] aiohttp-json-rpc = [ {file = "aiohttp-json-rpc-0.13.3.tar.gz", hash = "sha256:6237a104478c22c6ef96c7227a01d6832597b414e4b79a52d85593356a169e99"}, {file = "aiohttp_json_rpc-0.13.3-py3-none-any.whl", hash = "sha256:4fbd197aced61bd2df7ae3237ead7d3e08833c2ccf48b8581e1828c95ebee680"}, ] +aiosignal = [ + {file = "aiosignal-1.2.0-py3-none-any.whl", hash = "sha256:26e62109036cd181df6e6ad646f91f0dcfd05fe16d0cb924138ff2ab75d64e3a"}, + {file = "aiosignal-1.2.0.tar.gz", hash = "sha256:78ed67db6c7b7ced4f98e495e572106d5c432a93e1ddd1bf475e1dc05f5b7df2"}, +] alabaster = [ {file = "alabaster-0.7.12-py2.py3-none-any.whl", hash = "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359"}, {file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"}, @@ -1639,20 +1716,24 @@ arrow = [ {file = "arrow-0.17.0.tar.gz", hash = "sha256:ff08d10cda1d36c68657d6ad20d74fbea493d980f8b2d45344e00d6ed2bf6ed4"}, ] astroid = [ - {file = "astroid-2.8.4-py3-none-any.whl", hash = "sha256:0755c998e7117078dcb7d0bda621391dd2a85da48052d948c7411ab187325346"}, - {file = "astroid-2.8.4.tar.gz", hash = "sha256:1e83a69fd51b013ebf5912d26b9338d6643a55fec2f20c787792680610eed4a2"}, + {file = "astroid-2.9.3-py3-none-any.whl", hash = "sha256:506daabe5edffb7e696ad82483ad0228245a9742ed7d2d8c9cdb31537decf9f6"}, + {file = "astroid-2.9.3.tar.gz", hash = "sha256:1efdf4e867d4d8ba4a9f6cf9ce07cd182c4c41de77f23814feb27ca93ca9d877"}, ] async-timeout = [ - {file = "async-timeout-3.0.1.tar.gz", hash = "sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f"}, - {file = "async_timeout-3.0.1-py3-none-any.whl", hash = "sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"}, + {file = "async-timeout-4.0.2.tar.gz", hash = "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15"}, + {file = "async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"}, +] +asynctest = [ + {file = "asynctest-0.13.0-py3-none-any.whl", hash = "sha256:5da6118a7e6d6b54d83a8f7197769d046922a44d2a99c21382f0a6e4fadae676"}, + {file = "asynctest-0.13.0.tar.gz", hash = "sha256:c27862842d15d83e6a34eb0b2866c323880eb3a75e4485b079ea11748fd77fac"}, ] atomicwrites = [ {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, ] attrs = [ - {file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"}, - {file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"}, + {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, + {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, ] autopep8 = [ {file = "autopep8-1.5.7-py2.py3-none-any.whl", hash = "sha256:aa213493c30dcdac99537249ee65b24af0b2c29f2e83cd8b3f68760441ed0db9"}, @@ -1675,12 +1756,12 @@ bcrypt = [ {file = "bcrypt-3.2.0.tar.gz", hash = "sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29"}, ] blessed = [ - {file = "blessed-1.19.0-py2.py3-none-any.whl", hash = "sha256:1f2d462631b2b6d2d4c3c65b54ef79ad87a6ca2dd55255df2f8d739fcc8a1ddb"}, - {file = "blessed-1.19.0.tar.gz", hash = "sha256:4db0f94e5761aea330b528e84a250027ffe996b5a94bf03e502600c9a5ad7a61"}, + {file = "blessed-1.19.1-py2.py3-none-any.whl", hash = "sha256:63b8554ae2e0e7f43749b6715c734cc8f3883010a809bf16790102563e6cf25b"}, + {file = "blessed-1.19.1.tar.gz", hash = "sha256:9a0d099695bf621d4680dd6c73f6ad547f6a3442fbdbe80c4b1daa1edbc492fc"}, ] cachetools = [ - {file = "cachetools-4.2.4-py3-none-any.whl", hash = "sha256:92971d3cb7d2a97efff7c7bb1657f21a8f5fb309a37530537c71b1774189f2d1"}, - {file = "cachetools-4.2.4.tar.gz", hash = "sha256:89ea6f1b638d5a73a4f9226be57ac5e4f399d22770b92355f92dcb0f7f001693"}, + {file = "cachetools-5.0.0-py3-none-any.whl", hash = "sha256:8fecd4203a38af17928be7b90689d8083603073622229ca7077b72d8e5a976e4"}, + {file = "cachetools-5.0.0.tar.gz", hash = "sha256:486471dfa8799eb7ec503a8059e263db000cdda20075ce5e48903087f79d5fd6"}, ] certifi = [ {file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"}, @@ -1742,6 +1823,10 @@ chardet = [ {file = "chardet-4.0.0-py2.py3-none-any.whl", hash = "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"}, {file = "chardet-4.0.0.tar.gz", hash = "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa"}, ] +charset-normalizer = [ + {file = "charset-normalizer-2.0.11.tar.gz", hash = "sha256:98398a9d69ee80548c762ba991a4728bfc3836768ed226b3945908d1a688371c"}, + {file = "charset_normalizer-2.0.11-py3-none-any.whl", hash = "sha256:2842d8f5e82a1f6aa437380934d5e1cd4fcf2003b06fed6940769c164a480a45"}, +] click = [ {file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"}, {file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"}, @@ -1763,72 +1848,82 @@ coolname = [ {file = "coolname-1.1.0.tar.gz", hash = "sha256:410fe6ea9999bf96f2856ef0c726d5f38782bbefb7bb1aca0e91e0dc98ed09e3"}, ] coverage = [ - {file = "coverage-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1549e1d08ce38259de2bc3e9a0d5f3642ff4a8f500ffc1b2df73fd621a6cdfc0"}, - {file = "coverage-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcae10fccb27ca2a5f456bf64d84110a5a74144be3136a5e598f9d9fb48c0caa"}, - {file = "coverage-6.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:53a294dc53cfb39c74758edaa6305193fb4258a30b1f6af24b360a6c8bd0ffa7"}, - {file = "coverage-6.0.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8251b37be1f2cd9c0e5ccd9ae0380909c24d2a5ed2162a41fcdbafaf59a85ebd"}, - {file = "coverage-6.0.2-cp310-cp310-win32.whl", hash = "sha256:db42baa892cba723326284490283a68d4de516bfb5aaba369b4e3b2787a778b7"}, - {file = "coverage-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:bbffde2a68398682623d9dd8c0ca3f46fda074709b26fcf08ae7a4c431a6ab2d"}, - {file = "coverage-6.0.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:60e51a3dd55540bec686d7fff61b05048ca31e804c1f32cbb44533e6372d9cc3"}, - {file = "coverage-6.0.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a6a9409223a27d5ef3cca57dd7cd4dfcb64aadf2fad5c3b787830ac9223e01a"}, - {file = "coverage-6.0.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:4b34ae4f51bbfa5f96b758b55a163d502be3dcb24f505d0227858c2b3f94f5b9"}, - {file = "coverage-6.0.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3bbda1b550e70fa6ac40533d3f23acd4f4e9cb4e6e77251ce77fdf41b3309fb2"}, - {file = "coverage-6.0.2-cp36-cp36m-win32.whl", hash = "sha256:4e28d2a195c533b58fc94a12826f4431726d8eb029ac21d874345f943530c122"}, - {file = "coverage-6.0.2-cp36-cp36m-win_amd64.whl", hash = "sha256:a82d79586a0a4f5fd1cf153e647464ced402938fbccb3ffc358c7babd4da1dd9"}, - {file = "coverage-6.0.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3be1206dc09fb6298de3fce70593e27436862331a85daee36270b6d0e1c251c4"}, - {file = "coverage-6.0.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9cd3828bbe1a40070c11fe16a51df733fd2f0cb0d745fb83b7b5c1f05967df7"}, - {file = "coverage-6.0.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:d036dc1ed8e1388e995833c62325df3f996675779541f682677efc6af71e96cc"}, - {file = "coverage-6.0.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:04560539c19ec26995ecfb3d9307ff154fbb9a172cb57e3b3cfc4ced673103d1"}, - {file = "coverage-6.0.2-cp37-cp37m-win32.whl", hash = "sha256:e4fb7ced4d9dec77d6cf533acfbf8e1415fe799430366affb18d69ee8a3c6330"}, - {file = "coverage-6.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:77b1da5767ed2f44611bc9bc019bc93c03fa495728ec389759b6e9e5039ac6b1"}, - {file = "coverage-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:61b598cbdbaae22d9e34e3f675997194342f866bb1d781da5d0be54783dce1ff"}, - {file = "coverage-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36e9040a43d2017f2787b28d365a4bb33fcd792c7ff46a047a04094dc0e2a30d"}, - {file = "coverage-6.0.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9f1627e162e3864a596486774876415a7410021f4b67fd2d9efdf93ade681afc"}, - {file = "coverage-6.0.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e7a0b42db2a47ecb488cde14e0f6c7679a2c5a9f44814393b162ff6397fcdfbb"}, - {file = "coverage-6.0.2-cp38-cp38-win32.whl", hash = "sha256:a1b73c7c4d2a42b9d37dd43199c5711d91424ff3c6c22681bc132db4a4afec6f"}, - {file = "coverage-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:1db67c497688fd4ba85b373b37cc52c50d437fd7267520ecd77bddbd89ea22c9"}, - {file = "coverage-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f2f184bf38e74f152eed7f87e345b51f3ab0b703842f447c22efe35e59942c24"}, - {file = "coverage-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd1cf1deb3d5544bd942356364a2fdc8959bad2b6cf6eb17f47d301ea34ae822"}, - {file = "coverage-6.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ad9b8c1206ae41d46ec7380b78ba735ebb77758a650643e841dd3894966c31d0"}, - {file = "coverage-6.0.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:381d773d896cc7f8ba4ff3b92dee4ed740fb88dfe33b6e42efc5e8ab6dfa1cfe"}, - {file = "coverage-6.0.2-cp39-cp39-win32.whl", hash = "sha256:424c44f65e8be58b54e2b0bd1515e434b940679624b1b72726147cfc6a9fc7ce"}, - {file = "coverage-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:abbff240f77347d17306d3201e14431519bf64495648ca5a49571f988f88dee9"}, - {file = "coverage-6.0.2-pp36-none-any.whl", hash = "sha256:7092eab374346121805fb637572483270324407bf150c30a3b161fc0c4ca5164"}, - {file = "coverage-6.0.2-pp37-none-any.whl", hash = "sha256:30922626ce6f7a5a30bdba984ad21021529d3d05a68b4f71ea3b16bda35b8895"}, - {file = "coverage-6.0.2.tar.gz", hash = "sha256:6807947a09510dc31fa86f43595bf3a14017cd60bf633cc746d52141bfa6b149"}, + {file = "coverage-6.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeffd96882d8c06d31b65dddcf51db7c612547babc1c4c5db6a011abe9798525"}, + {file = "coverage-6.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:621f6ea7260ea2ffdaec64fe5cb521669984f567b66f62f81445221d4754df4c"}, + {file = "coverage-6.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84f2436d6742c01136dd940ee158bfc7cf5ced3da7e4c949662b8703b5cd8145"}, + {file = "coverage-6.3.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de73fca6fb403dd72d4da517cfc49fcf791f74eee697d3219f6be29adf5af6ce"}, + {file = "coverage-6.3.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78fbb2be068a13a5d99dce9e1e7d168db880870f7bc73f876152130575bd6167"}, + {file = "coverage-6.3.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f5a4551dfd09c3bd12fca8144d47fe7745275adf3229b7223c2f9e29a975ebda"}, + {file = "coverage-6.3.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7bff3a98f63b47464480de1b5bdd80c8fade0ba2832c9381253c9b74c4153c27"}, + {file = "coverage-6.3.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a06c358f4aed05fa1099c39decc8022261bb07dfadc127c08cfbd1391b09689e"}, + {file = "coverage-6.3.1-cp310-cp310-win32.whl", hash = "sha256:9fff3ff052922cb99f9e52f63f985d4f7a54f6b94287463bc66b7cdf3eb41217"}, + {file = "coverage-6.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:276b13cc085474e482566c477c25ed66a097b44c6e77132f3304ac0b039f83eb"}, + {file = "coverage-6.3.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:56c4a409381ddd7bbff134e9756077860d4e8a583d310a6f38a2315b9ce301d0"}, + {file = "coverage-6.3.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9eb494070aa060ceba6e4bbf44c1bc5fa97bfb883a0d9b0c9049415f9e944793"}, + {file = "coverage-6.3.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5e15d424b8153756b7c903bde6d4610be0c3daca3986173c18dd5c1a1625e4cd"}, + {file = "coverage-6.3.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61d47a897c1e91f33f177c21de897267b38fbb45f2cd8e22a710bcef1df09ac1"}, + {file = "coverage-6.3.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:25e73d4c81efa8ea3785274a2f7f3bfbbeccb6fcba2a0bdd3be9223371c37554"}, + {file = "coverage-6.3.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:fac0bcc5b7e8169bffa87f0dcc24435446d329cbc2b5486d155c2e0f3b493ae1"}, + {file = "coverage-6.3.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:72128176fea72012063200b7b395ed8a57849282b207321124d7ff14e26988e8"}, + {file = "coverage-6.3.1-cp37-cp37m-win32.whl", hash = "sha256:1bc6d709939ff262fd1432f03f080c5042dc6508b6e0d3d20e61dd045456a1a0"}, + {file = "coverage-6.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:618eeba986cea7f621d8607ee378ecc8c2504b98b3fdc4952b30fe3578304687"}, + {file = "coverage-6.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d5ed164af5c9078596cfc40b078c3b337911190d3faeac830c3f1274f26b8320"}, + {file = "coverage-6.3.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:352c68e233409c31048a3725c446a9e48bbff36e39db92774d4f2380d630d8f8"}, + {file = "coverage-6.3.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:448d7bde7ceb6c69e08474c2ddbc5b4cd13c9e4aa4a717467f716b5fc938a734"}, + {file = "coverage-6.3.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9fde6b90889522c220dd56a670102ceef24955d994ff7af2cb786b4ba8fe11e4"}, + {file = "coverage-6.3.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e647a0be741edbb529a72644e999acb09f2ad60465f80757da183528941ff975"}, + {file = "coverage-6.3.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6a5cdc3adb4f8bb8d8f5e64c2e9e282bc12980ef055ec6da59db562ee9bdfefa"}, + {file = "coverage-6.3.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2dd70a167843b4b4b2630c0c56f1b586fe965b4f8ac5da05b6690344fd065c6b"}, + {file = "coverage-6.3.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:9ad0a117b8dc2061ce9461ea4c1b4799e55edceb236522c5b8f958ce9ed8fa9a"}, + {file = "coverage-6.3.1-cp38-cp38-win32.whl", hash = "sha256:e92c7a5f7d62edff50f60a045dc9542bf939758c95b2fcd686175dd10ce0ed10"}, + {file = "coverage-6.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:482fb42eea6164894ff82abbcf33d526362de5d1a7ed25af7ecbdddd28fc124f"}, + {file = "coverage-6.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c5b81fb37db76ebea79aa963b76d96ff854e7662921ce742293463635a87a78d"}, + {file = "coverage-6.3.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a4f923b9ab265136e57cc14794a15b9dcea07a9c578609cd5dbbfff28a0d15e6"}, + {file = "coverage-6.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56d296cbc8254a7dffdd7bcc2eb70be5a233aae7c01856d2d936f5ac4e8ac1f1"}, + {file = "coverage-6.3.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1245ab82e8554fa88c4b2ab1e098ae051faac5af829efdcf2ce6b34dccd5567c"}, + {file = "coverage-6.3.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f2b05757c92ad96b33dbf8e8ec8d4ccb9af6ae3c9e9bd141c7cc44d20c6bcba"}, + {file = "coverage-6.3.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9e3dd806f34de38d4c01416344e98eab2437ac450b3ae39c62a0ede2f8b5e4ed"}, + {file = "coverage-6.3.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d651fde74a4d3122e5562705824507e2f5b2d3d57557f1916c4b27635f8fbe3f"}, + {file = "coverage-6.3.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:704f89b87c4f4737da2860695a18c852b78ec7279b24eedacab10b29067d3a38"}, + {file = "coverage-6.3.1-cp39-cp39-win32.whl", hash = "sha256:2aed4761809640f02e44e16b8b32c1a5dee5e80ea30a0ff0912158bde9c501f2"}, + {file = "coverage-6.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:9976fb0a5709988778ac9bc44f3d50fccd989987876dfd7716dee28beed0a9fa"}, + {file = "coverage-6.3.1-pp36.pp37.pp38-none-any.whl", hash = "sha256:463e52616ea687fd323888e86bf25e864a3cc6335a043fad6bbb037dbf49bbe2"}, + {file = "coverage-6.3.1.tar.gz", hash = "sha256:6c3f6158b02ac403868eea390930ae64e9a9a2a5bbfafefbb920d29258d9f2f8"}, ] cryptography = [ - {file = "cryptography-35.0.0-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:d57e0cdc1b44b6cdf8af1d01807db06886f10177469312fbde8f44ccbb284bc9"}, - {file = "cryptography-35.0.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:ced40344e811d6abba00295ced98c01aecf0c2de39481792d87af4fa58b7b4d6"}, - {file = "cryptography-35.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:54b2605e5475944e2213258e0ab8696f4f357a31371e538ef21e8d61c843c28d"}, - {file = "cryptography-35.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:7b7ceeff114c31f285528ba8b390d3e9cfa2da17b56f11d366769a807f17cbaa"}, - {file = "cryptography-35.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d69645f535f4b2c722cfb07a8eab916265545b3475fdb34e0be2f4ee8b0b15e"}, - {file = "cryptography-35.0.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a2d0e0acc20ede0f06ef7aa58546eee96d2592c00f450c9acb89c5879b61992"}, - {file = "cryptography-35.0.0-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:07bb7fbfb5de0980590ddfc7f13081520def06dc9ed214000ad4372fb4e3c7f6"}, - {file = "cryptography-35.0.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7eba2cebca600a7806b893cb1d541a6e910afa87e97acf2021a22b32da1df52d"}, - {file = "cryptography-35.0.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:18d90f4711bf63e2fb21e8c8e51ed8189438e6b35a6d996201ebd98a26abbbe6"}, - {file = "cryptography-35.0.0-cp36-abi3-win32.whl", hash = "sha256:c10c797ac89c746e488d2ee92bd4abd593615694ee17b2500578b63cad6b93a8"}, - {file = "cryptography-35.0.0-cp36-abi3-win_amd64.whl", hash = "sha256:7075b304cd567694dc692ffc9747f3e9cb393cc4aa4fb7b9f3abd6f5c4e43588"}, - {file = "cryptography-35.0.0-pp36-pypy36_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a688ebcd08250eab5bb5bca318cc05a8c66de5e4171a65ca51db6bd753ff8953"}, - {file = "cryptography-35.0.0-pp36-pypy36_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d99915d6ab265c22873f1b4d6ea5ef462ef797b4140be4c9d8b179915e0985c6"}, - {file = "cryptography-35.0.0-pp36-pypy36_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:928185a6d1ccdb816e883f56ebe92e975a262d31cc536429041921f8cb5a62fd"}, - {file = "cryptography-35.0.0-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:ebeddd119f526bcf323a89f853afb12e225902a24d29b55fe18dd6fcb2838a76"}, - {file = "cryptography-35.0.0-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:22a38e96118a4ce3b97509443feace1d1011d0571fae81fc3ad35f25ba3ea999"}, - {file = "cryptography-35.0.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb80e8a1f91e4b7ef8b33041591e6d89b2b8e122d787e87eeb2b08da71bb16ad"}, - {file = "cryptography-35.0.0-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:abb5a361d2585bb95012a19ed9b2c8f412c5d723a9836418fab7aaa0243e67d2"}, - {file = "cryptography-35.0.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:1ed82abf16df40a60942a8c211251ae72858b25b7421ce2497c2eb7a1cee817c"}, - {file = "cryptography-35.0.0.tar.gz", hash = "sha256:9933f28f70d0517686bd7de36166dda42094eac49415459d9bdf5e7df3e0086d"}, + {file = "cryptography-36.0.1-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:73bc2d3f2444bcfeac67dd130ff2ea598ea5f20b40e36d19821b4df8c9c5037b"}, + {file = "cryptography-36.0.1-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:2d87cdcb378d3cfed944dac30596da1968f88fb96d7fc34fdae30a99054b2e31"}, + {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:74d6c7e80609c0f4c2434b97b80c7f8fdfaa072ca4baab7e239a15d6d70ed73a"}, + {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:6c0c021f35b421ebf5976abf2daacc47e235f8b6082d3396a2fe3ccd537ab173"}, + {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d59a9d55027a8b88fd9fd2826c4392bd487d74bf628bb9d39beecc62a644c12"}, + {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a817b961b46894c5ca8a66b599c745b9a3d9f822725221f0e0fe49dc043a3a3"}, + {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:94ae132f0e40fe48f310bba63f477f14a43116f05ddb69d6fa31e93f05848ae2"}, + {file = "cryptography-36.0.1-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7be0eec337359c155df191d6ae00a5e8bbb63933883f4f5dffc439dac5348c3f"}, + {file = "cryptography-36.0.1-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:e0344c14c9cb89e76eb6a060e67980c9e35b3f36691e15e1b7a9e58a0a6c6dc3"}, + {file = "cryptography-36.0.1-cp36-abi3-win32.whl", hash = "sha256:4caa4b893d8fad33cf1964d3e51842cd78ba87401ab1d2e44556826df849a8ca"}, + {file = "cryptography-36.0.1-cp36-abi3-win_amd64.whl", hash = "sha256:391432971a66cfaf94b21c24ab465a4cc3e8bf4a939c1ca5c3e3a6e0abebdbcf"}, + {file = "cryptography-36.0.1-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bb5829d027ff82aa872d76158919045a7c1e91fbf241aec32cb07956e9ebd3c9"}, + {file = "cryptography-36.0.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebc15b1c22e55c4d5566e3ca4db8689470a0ca2babef8e3a9ee057a8b82ce4b1"}, + {file = "cryptography-36.0.1-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:596f3cd67e1b950bc372c33f1a28a0692080625592ea6392987dba7f09f17a94"}, + {file = "cryptography-36.0.1-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:30ee1eb3ebe1644d1c3f183d115a8c04e4e603ed6ce8e394ed39eea4a98469ac"}, + {file = "cryptography-36.0.1-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ec63da4e7e4a5f924b90af42eddf20b698a70e58d86a72d943857c4c6045b3ee"}, + {file = "cryptography-36.0.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca238ceb7ba0bdf6ce88c1b74a87bffcee5afbfa1e41e173b1ceb095b39add46"}, + {file = "cryptography-36.0.1-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:ca28641954f767f9822c24e927ad894d45d5a1e501767599647259cbf030b903"}, + {file = "cryptography-36.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:39bdf8e70eee6b1c7b289ec6e5d84d49a6bfa11f8b8646b5b3dfe41219153316"}, + {file = "cryptography-36.0.1.tar.gz", hash = "sha256:53e5c1dc3d7a953de055d77bef2ff607ceef7a2aac0353b5d630ab67f7423638"}, ] cx-freeze = [ - {file = "cx_Freeze-6.7-cp36-cp36m-win32.whl", hash = "sha256:befd5a2fb915eae03bfb237ffebeb7a5dfe8f58bc8c93c18f19a47c1fc800d8a"}, - {file = "cx_Freeze-6.7-cp36-cp36m-win_amd64.whl", hash = "sha256:7718801da4a3ad499b0d648c507759f3b7ffef24ba4e9fd8ff3b129b77dda0e3"}, - {file = "cx_Freeze-6.7-cp37-cp37m-win32.whl", hash = "sha256:361f27b1575b508a52fe3eb0afe83f2594c44235d084e04815924ea48742f0ea"}, - {file = "cx_Freeze-6.7-cp37-cp37m-win_amd64.whl", hash = "sha256:65aec3b37b91b0a41ccf61b9794d8660b809d665a529479489ab410a201736fc"}, - {file = "cx_Freeze-6.7-cp38-cp38-win32.whl", hash = "sha256:ec3bb21bc74c4fea458563f6e47191daa5486f089aebb1d00a922b5aa9834c87"}, - {file = "cx_Freeze-6.7-cp38-cp38-win_amd64.whl", hash = "sha256:1b76c72f8a2c0e1a416b7bced9d5fd247a0120f6b1b35d4678568beb1ccf9380"}, - {file = "cx_Freeze-6.7-cp39-cp39-win32.whl", hash = "sha256:beb38b2df37af44d08a1e62f09f0e1c5b991ded751f7cc3ab0ac93fba013ba54"}, - {file = "cx_Freeze-6.7-cp39-cp39-win_amd64.whl", hash = "sha256:967c86416b8dea3b00c0f1e2c94f5118004c9297afc8b1ae88002aec28a9097c"}, - {file = "cx_Freeze-6.7.tar.gz", hash = "sha256:050f1dd133a04810bd7f38ac7ae3b290054acb2ff4f6e73f7a286266d153495d"}, + {file = "cx_Freeze-6.9-cp310-cp310-win32.whl", hash = "sha256:776d4fb68a4831691acbd3c374362b9b48ce2e568514a73c3d4cb14d5dcf1470"}, + {file = "cx_Freeze-6.9-cp310-cp310-win_amd64.whl", hash = "sha256:243f36d35a034a409cd6247d8cb5d1fbfd7374e3e668e813d0811f64d6bd5ed3"}, + {file = "cx_Freeze-6.9-cp36-cp36m-win32.whl", hash = "sha256:ffc855eabc735b693e2d604d71dce6d52d78a6ba1070c55d51e786dd68ed232c"}, + {file = "cx_Freeze-6.9-cp36-cp36m-win_amd64.whl", hash = "sha256:fe4e32a0c75b2b54491882926bf3ba12f8a3d589822a68a8be7c09f1dcca5546"}, + {file = "cx_Freeze-6.9-cp37-cp37m-win32.whl", hash = "sha256:99c292e7a31cb343efc0cf47f82220a44a4a3b8776651624cd8ee03c23104940"}, + {file = "cx_Freeze-6.9-cp37-cp37m-win_amd64.whl", hash = "sha256:738ab22f3a3f6bc220b16dccf2aa0603c3cd271b2a7a9d9480dab82311308b23"}, + {file = "cx_Freeze-6.9-cp38-cp38-win32.whl", hash = "sha256:c1c75df572858e623d0aa39771cd984c0abd8aacb43b2aca2d12d0bc95f25566"}, + {file = "cx_Freeze-6.9-cp38-cp38-win_amd64.whl", hash = "sha256:0788c895c47fdcf375151ce78ff42336c01aca7bc43daecb8f8f8356cdc42b43"}, + {file = "cx_Freeze-6.9-cp39-cp39-win32.whl", hash = "sha256:a31f5ddbc80b29e297370d868791470b0e3e9062db45038c23293a76ed039018"}, + {file = "cx_Freeze-6.9-cp39-cp39-win_amd64.whl", hash = "sha256:30708f603076713c0a839cdfb34f4126d68e9d61afb3d9a59daa9cf252033872"}, + {file = "cx_Freeze-6.9.tar.gz", hash = "sha256:673aa3199af2ef87fc03a43a30e5d78b27ced2cedde925da89c55b5657da267b"}, ] cx-logging = [ {file = "cx_Logging-3.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:9fcd297e5c51470521c47eff0f86ba844aeca6be97e13c3e2114ebdf03fa3c96"}, @@ -1846,21 +1941,21 @@ cx-logging = [ {file = "cx_Logging-3.0.tar.gz", hash = "sha256:ba8a7465facf7b98d8f494030fb481a2e8aeee29dc191e10383bb54ed42bdb34"}, ] dnspython = [ - {file = "dnspython-2.1.0-py3-none-any.whl", hash = "sha256:95d12f6ef0317118d2a1a6fc49aac65ffec7eb8087474158f42f26a639135216"}, - {file = "dnspython-2.1.0.zip", hash = "sha256:e4a87f0b573201a0f3727fa18a516b055fd1107e0e5477cded4a2de497df1dd4"}, + {file = "dnspython-2.2.0-py3-none-any.whl", hash = "sha256:081649da27ced5e75709a1ee542136eaba9842a0fe4c03da4fb0a3d3ed1f3c44"}, + {file = "dnspython-2.2.0.tar.gz", hash = "sha256:e79351e032d0b606b98d38a4b0e6e2275b31a5b85c873e587cc11b73aca026d6"}, ] docutils = [ - {file = "docutils-0.18-py2.py3-none-any.whl", hash = "sha256:a31688b2ea858517fa54293e5d5df06fbb875fb1f7e4c64529271b77781ca8fc"}, - {file = "docutils-0.18.tar.gz", hash = "sha256:c1d5dab2b11d16397406a282e53953fe495a46d69ae329f55aa98a5c4e3c5fbb"}, + {file = "docutils-0.18.1-py2.py3-none-any.whl", hash = "sha256:23010f129180089fbcd3bc08cfefccb3b890b0050e1ca00c867036e9d161b98c"}, + {file = "docutils-0.18.1.tar.gz", hash = "sha256:679987caf361a7539d76e584cbeddc311e3aee937877c87346f31debc63e9d06"}, ] dropbox = [ - {file = "dropbox-11.22.0-py2-none-any.whl", hash = "sha256:f2efc924529be2e2e2a1d6f49246b25966c201b23dda231dfb148a6f5ae1a149"}, - {file = "dropbox-11.22.0-py3-none-any.whl", hash = "sha256:0a9cc253391cae7fccf1954da75edf8459d6567ba764e21b471019f0fa001ab4"}, - {file = "dropbox-11.22.0.tar.gz", hash = "sha256:ab84c9c78606faa0dc94cdb95c6b2bdb579beb5f34fff42091c98a1e0fbeb16c"}, + {file = "dropbox-11.26.0-py2-none-any.whl", hash = "sha256:abd29587fa692bde0c3a48ce8efb56c24d8df92c5f402bbcdd78f3089d5ced5c"}, + {file = "dropbox-11.26.0-py3-none-any.whl", hash = "sha256:84becf043a63007ae67620946acb0fa164669ce691c7f1dbfdabb6712a258b29"}, + {file = "dropbox-11.26.0.tar.gz", hash = "sha256:dd79e3dfc216688020959462aefac54ffce7c07a45e89f4fb258348885195a73"}, ] enlighten = [ - {file = "enlighten-1.10.1-py2.py3-none-any.whl", hash = "sha256:3d6c3eec8cf3eb626ee7b65eddc1b3e904d01f4547a2b9fe7f1da8892a0297e8"}, - {file = "enlighten-1.10.1.tar.gz", hash = "sha256:3391916586364aedced5d6926482b48745e4948f822de096d32258ba238ea984"}, + {file = "enlighten-1.10.2-py2.py3-none-any.whl", hash = "sha256:b237fe562b320bf9f1d4bb76d0c98e0daf914372a76ab87c35cd02f57aa9d8c1"}, + {file = "enlighten-1.10.2.tar.gz", hash = "sha256:7a5b83cd0f4d095e59d80c648ebb5f7ffca0cd8bcf7ae6639828ee1ad000632a"}, ] evdev = [ {file = "evdev-1.4.0.tar.gz", hash = "sha256:8782740eb1a86b187334c07feb5127d3faa0b236e113206dfe3ae8f77fb1aaf1"}, @@ -1869,6 +1964,67 @@ flake8 = [ {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"}, {file = "flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"}, ] +frozenlist = [ + {file = "frozenlist-1.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d2257aaba9660f78c7b1d8fea963b68f3feffb1a9d5d05a18401ca9eb3e8d0a3"}, + {file = "frozenlist-1.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4a44ebbf601d7bac77976d429e9bdb5a4614f9f4027777f9e54fd765196e9d3b"}, + {file = "frozenlist-1.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:45334234ec30fc4ea677f43171b18a27505bfb2dba9aca4398a62692c0ea8868"}, + {file = "frozenlist-1.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:47be22dc27ed933d55ee55845d34a3e4e9f6fee93039e7f8ebadb0c2f60d403f"}, + {file = "frozenlist-1.3.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:03a7dd1bfce30216a3f51a84e6dd0e4a573d23ca50f0346634916ff105ba6e6b"}, + {file = "frozenlist-1.3.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:691ddf6dc50480ce49f68441f1d16a4c3325887453837036e0fb94736eae1e58"}, + {file = "frozenlist-1.3.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bde99812f237f79eaf3f04ebffd74f6718bbd216101b35ac7955c2d47c17da02"}, + {file = "frozenlist-1.3.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a202458d1298ced3768f5a7d44301e7c86defac162ace0ab7434c2e961166e8"}, + {file = "frozenlist-1.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b9e3e9e365991f8cc5f5edc1fd65b58b41d0514a6a7ad95ef5c7f34eb49b3d3e"}, + {file = "frozenlist-1.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:04cb491c4b1c051734d41ea2552fde292f5f3a9c911363f74f39c23659c4af78"}, + {file = "frozenlist-1.3.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:436496321dad302b8b27ca955364a439ed1f0999311c393dccb243e451ff66aa"}, + {file = "frozenlist-1.3.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:754728d65f1acc61e0f4df784456106e35afb7bf39cfe37227ab00436fb38676"}, + {file = "frozenlist-1.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6eb275c6385dd72594758cbe96c07cdb9bd6becf84235f4a594bdf21e3596c9d"}, + {file = "frozenlist-1.3.0-cp310-cp310-win32.whl", hash = "sha256:e30b2f9683812eb30cf3f0a8e9f79f8d590a7999f731cf39f9105a7c4a39489d"}, + {file = "frozenlist-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:f7353ba3367473d1d616ee727945f439e027f0bb16ac1a750219a8344d1d5d3c"}, + {file = "frozenlist-1.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:88aafd445a233dbbf8a65a62bc3249a0acd0d81ab18f6feb461cc5a938610d24"}, + {file = "frozenlist-1.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4406cfabef8f07b3b3af0f50f70938ec06d9f0fc26cbdeaab431cbc3ca3caeaa"}, + {file = "frozenlist-1.3.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8cf829bd2e2956066dd4de43fd8ec881d87842a06708c035b37ef632930505a2"}, + {file = "frozenlist-1.3.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:603b9091bd70fae7be28bdb8aa5c9990f4241aa33abb673390a7f7329296695f"}, + {file = "frozenlist-1.3.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:25af28b560e0c76fa41f550eacb389905633e7ac02d6eb3c09017fa1c8cdfde1"}, + {file = "frozenlist-1.3.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94c7a8a9fc9383b52c410a2ec952521906d355d18fccc927fca52ab575ee8b93"}, + {file = "frozenlist-1.3.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:65bc6e2fece04e2145ab6e3c47428d1bbc05aede61ae365b2c1bddd94906e478"}, + {file = "frozenlist-1.3.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:3f7c935c7b58b0d78c0beea0c7358e165f95f1fd8a7e98baa40d22a05b4a8141"}, + {file = "frozenlist-1.3.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd89acd1b8bb4f31b47072615d72e7f53a948d302b7c1d1455e42622de180eae"}, + {file = "frozenlist-1.3.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:6983a31698490825171be44ffbafeaa930ddf590d3f051e397143a5045513b01"}, + {file = "frozenlist-1.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:adac9700675cf99e3615eb6a0eb5e9f5a4143c7d42c05cea2e7f71c27a3d0846"}, + {file = "frozenlist-1.3.0-cp37-cp37m-win32.whl", hash = "sha256:0c36e78b9509e97042ef869c0e1e6ef6429e55817c12d78245eb915e1cca7468"}, + {file = "frozenlist-1.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:57f4d3f03a18facacb2a6bcd21bccd011e3b75d463dc49f838fd699d074fabd1"}, + {file = "frozenlist-1.3.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8c905a5186d77111f02144fab5b849ab524f1e876a1e75205cd1386a9be4b00a"}, + {file = "frozenlist-1.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b5009062d78a8c6890d50b4e53b0ddda31841b3935c1937e2ed8c1bda1c7fb9d"}, + {file = "frozenlist-1.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2fdc3cd845e5a1f71a0c3518528bfdbfe2efaf9886d6f49eacc5ee4fd9a10953"}, + {file = "frozenlist-1.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:92e650bd09b5dda929523b9f8e7f99b24deac61240ecc1a32aeba487afcd970f"}, + {file = "frozenlist-1.3.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:40dff8962b8eba91fd3848d857203f0bd704b5f1fa2b3fc9af64901a190bba08"}, + {file = "frozenlist-1.3.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:768efd082074bb203c934e83a61654ed4931ef02412c2fbdecea0cff7ecd0274"}, + {file = "frozenlist-1.3.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:006d3595e7d4108a12025ddf415ae0f6c9e736e726a5db0183326fd191b14c5e"}, + {file = "frozenlist-1.3.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:871d42623ae15eb0b0e9df65baeee6976b2e161d0ba93155411d58ff27483ad8"}, + {file = "frozenlist-1.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aff388be97ef2677ae185e72dc500d19ecaf31b698986800d3fc4f399a5e30a5"}, + {file = "frozenlist-1.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:9f892d6a94ec5c7b785e548e42722e6f3a52f5f32a8461e82ac3e67a3bd073f1"}, + {file = "frozenlist-1.3.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:e982878792c971cbd60ee510c4ee5bf089a8246226dea1f2138aa0bb67aff148"}, + {file = "frozenlist-1.3.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:c6c321dd013e8fc20735b92cb4892c115f5cdb82c817b1e5b07f6b95d952b2f0"}, + {file = "frozenlist-1.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:30530930410855c451bea83f7b272fb1c495ed9d5cc72895ac29e91279401db3"}, + {file = "frozenlist-1.3.0-cp38-cp38-win32.whl", hash = "sha256:40ec383bc194accba825fbb7d0ef3dda5736ceab2375462f1d8672d9f6b68d07"}, + {file = "frozenlist-1.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:f20baa05eaa2bcd5404c445ec51aed1c268d62600362dc6cfe04fae34a424bd9"}, + {file = "frozenlist-1.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0437fe763fb5d4adad1756050cbf855bbb2bf0d9385c7bb13d7a10b0dd550486"}, + {file = "frozenlist-1.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b684c68077b84522b5c7eafc1dc735bfa5b341fb011d5552ebe0968e22ed641c"}, + {file = "frozenlist-1.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:93641a51f89473837333b2f8100f3f89795295b858cd4c7d4a1f18e299dc0a4f"}, + {file = "frozenlist-1.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6d32ff213aef0fd0bcf803bffe15cfa2d4fde237d1d4838e62aec242a8362fa"}, + {file = "frozenlist-1.3.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31977f84828b5bb856ca1eb07bf7e3a34f33a5cddce981d880240ba06639b94d"}, + {file = "frozenlist-1.3.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3c62964192a1c0c30b49f403495911298810bada64e4f03249ca35a33ca0417a"}, + {file = "frozenlist-1.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4eda49bea3602812518765810af732229b4291d2695ed24a0a20e098c45a707b"}, + {file = "frozenlist-1.3.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acb267b09a509c1df5a4ca04140da96016f40d2ed183cdc356d237286c971b51"}, + {file = "frozenlist-1.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e1e26ac0a253a2907d654a37e390904426d5ae5483150ce3adedb35c8c06614a"}, + {file = "frozenlist-1.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f96293d6f982c58ebebb428c50163d010c2f05de0cde99fd681bfdc18d4b2dc2"}, + {file = "frozenlist-1.3.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e84cb61b0ac40a0c3e0e8b79c575161c5300d1d89e13c0e02f76193982f066ed"}, + {file = "frozenlist-1.3.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:ff9310f05b9d9c5c4dd472983dc956901ee6cb2c3ec1ab116ecdde25f3ce4951"}, + {file = "frozenlist-1.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d26b650b71fdc88065b7a21f8ace70175bcf3b5bdba5ea22df4bfd893e795a3b"}, + {file = "frozenlist-1.3.0-cp39-cp39-win32.whl", hash = "sha256:01a73627448b1f2145bddb6e6c2259988bb8aee0fb361776ff8604b99616cd08"}, + {file = "frozenlist-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:772965f773757a6026dea111a15e6e2678fbd6216180f82a48a40b27de1ee2ab"}, + {file = "frozenlist-1.3.0.tar.gz", hash = "sha256:ce6f2ba0edb7b0c1d8976565298ad2deba6f8064d2bebb6ffce2ca896eb35b0b"}, +] ftrack-python-api = [ {file = "ftrack-python-api-2.0.0.tar.gz", hash = "sha256:dd6f02c31daf5a10078196dc9eac4671e4297c762fbbf4df98de668ac12281d9"}, {file = "ftrack_python_api-2.0.0-py2.py3-none-any.whl", hash = "sha256:d0df0f2df4b53947272f95e179ec98b477ee425bf4217b37bb59030ad989771e"}, @@ -1881,52 +2037,52 @@ gitdb = [ {file = "gitdb-4.0.9.tar.gz", hash = "sha256:bac2fd45c0a1c9cf619e63a90d62bdc63892ef92387424b855792a6cabe789aa"}, ] gitpython = [ - {file = "GitPython-3.1.24-py3-none-any.whl", hash = "sha256:dc0a7f2f697657acc8d7f89033e8b1ea94dd90356b2983bca89dc8d2ab3cc647"}, - {file = "GitPython-3.1.24.tar.gz", hash = "sha256:df83fdf5e684fef7c6ee2c02fc68a5ceb7e7e759d08b694088d0cacb4eba59e5"}, + {file = "GitPython-3.1.26-py3-none-any.whl", hash = "sha256:26ac35c212d1f7b16036361ca5cff3ec66e11753a0d677fb6c48fa4e1a9dd8d6"}, + {file = "GitPython-3.1.26.tar.gz", hash = "sha256:fc8868f63a2e6d268fb25f481995ba185a85a66fcad126f039323ff6635669ee"}, ] google-api-core = [ - {file = "google-api-core-1.31.3.tar.gz", hash = "sha256:4b7ad965865aef22afa4aded3318b8fa09b20bcc7e8dbb639a3753cf60af08ea"}, - {file = "google_api_core-1.31.3-py2.py3-none-any.whl", hash = "sha256:f52c708ab9fd958862dea9ac94d9db1a065608073fe583c3b9c18537b177f59a"}, + {file = "google-api-core-2.4.0.tar.gz", hash = "sha256:ba8787b7c61632cd0340f095e1c036bef9426b2594f10afb290ba311ae8cb2cb"}, + {file = "google_api_core-2.4.0-py2.py3-none-any.whl", hash = "sha256:58e2c1171a3d51778bf4e428fbb4bf79cbd05007b4b44deaa80cf73c80eebc0f"}, ] google-api-python-client = [ - {file = "google-api-python-client-1.12.8.tar.gz", hash = "sha256:f3b9684442eec2cfe9f9bb48e796ef919456b82142c7528c5fd527e5224f08bb"}, - {file = "google_api_python_client-1.12.8-py2.py3-none-any.whl", hash = "sha256:3c4c4ca46b5c21196bec7ee93453443e477d82cbfa79234d1ce0645f81170eaf"}, + {file = "google-api-python-client-1.12.10.tar.gz", hash = "sha256:1cb773647e7d97048d9d1c7fa746247fbad39fd1a3b5040f2cb2645dd7156b11"}, + {file = "google_api_python_client-1.12.10-py2.py3-none-any.whl", hash = "sha256:5a8742b9b604b34e13462cc3d6aedbbf11d3af1ef558eb95defe74a29ebc5c28"}, ] google-auth = [ - {file = "google-auth-1.35.0.tar.gz", hash = "sha256:b7033be9028c188ee30200b204ea00ed82ea1162e8ac1df4aa6ded19a191d88e"}, - {file = "google_auth-1.35.0-py2.py3-none-any.whl", hash = "sha256:997516b42ecb5b63e8d80f5632c1a61dddf41d2a4c2748057837e06e00014258"}, + {file = "google-auth-2.6.0.tar.gz", hash = "sha256:ad160fc1ea8f19e331a16a14a79f3d643d813a69534ba9611d2c80dc10439dad"}, + {file = "google_auth-2.6.0-py2.py3-none-any.whl", hash = "sha256:218ca03d7744ca0c8b6697b6083334be7df49b7bf76a69d555962fd1a7657b5f"}, ] google-auth-httplib2 = [ {file = "google-auth-httplib2-0.1.0.tar.gz", hash = "sha256:a07c39fd632becacd3f07718dfd6021bf396978f03ad3ce4321d060015cc30ac"}, {file = "google_auth_httplib2-0.1.0-py2.py3-none-any.whl", hash = "sha256:31e49c36c6b5643b57e82617cb3e021e3e1d2df9da63af67252c02fa9c1f4a10"}, ] googleapis-common-protos = [ - {file = "googleapis-common-protos-1.53.0.tar.gz", hash = "sha256:a88ee8903aa0a81f6c3cec2d5cf62d3c8aa67c06439b0496b49048fb1854ebf4"}, - {file = "googleapis_common_protos-1.53.0-py2.py3-none-any.whl", hash = "sha256:f6d561ab8fb16b30020b940e2dd01cd80082f4762fa9f3ee670f4419b4b8dbd0"}, + {file = "googleapis-common-protos-1.54.0.tar.gz", hash = "sha256:a4031d6ec6c2b1b6dc3e0be7e10a1bd72fb0b18b07ef9be7b51f2c1004ce2437"}, + {file = "googleapis_common_protos-1.54.0-py2.py3-none-any.whl", hash = "sha256:e54345a2add15dc5e1a7891c27731ff347b4c33765d79b5ed7026a6c0c7cbcae"}, ] httplib2 = [ - {file = "httplib2-0.20.1-py3-none-any.whl", hash = "sha256:8fa4dbf2fbf839b71f8c7837a831e00fcdc860feca99b8bda58ceae4bc53d185"}, - {file = "httplib2-0.20.1.tar.gz", hash = "sha256:0efbcb8bfbfbc11578130d87d8afcc65c2274c6eb446e59fc674e4d7c972d327"}, + {file = "httplib2-0.20.2-py3-none-any.whl", hash = "sha256:6b937120e7d786482881b44b8eec230c1ee1c5c1d06bce8cc865f25abbbf713b"}, + {file = "httplib2-0.20.2.tar.gz", hash = "sha256:e404681d2fbcec7506bcb52c503f2b021e95bee0ef7d01e5c221468a2406d8dc"}, ] idna = [ {file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"}, {file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"}, ] imagesize = [ - {file = "imagesize-1.2.0-py2.py3-none-any.whl", hash = "sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1"}, - {file = "imagesize-1.2.0.tar.gz", hash = "sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1"}, + {file = "imagesize-1.3.0-py2.py3-none-any.whl", hash = "sha256:1db2f82529e53c3e929e8926a1fa9235aa82d0bd0c580359c67ec31b2fddaa8c"}, + {file = "imagesize-1.3.0.tar.gz", hash = "sha256:cd1750d452385ca327479d45b64d9c7729ecf0b3969a58148298c77092261f9d"}, ] importlib-metadata = [ - {file = "importlib_metadata-4.8.1-py3-none-any.whl", hash = "sha256:b618b6d2d5ffa2f16add5697cf57a46c76a56229b0ed1c438322e4e95645bd15"}, - {file = "importlib_metadata-4.8.1.tar.gz", hash = "sha256:f284b3e11256ad1e5d03ab86bb2ccd6f5339688ff17a4d797a0fe7df326f23b1"}, + {file = "importlib_metadata-4.10.1-py3-none-any.whl", hash = "sha256:899e2a40a8c4a1aec681feef45733de8a6c58f3f6a0dbed2eb6574b4387a77b6"}, + {file = "importlib_metadata-4.10.1.tar.gz", hash = "sha256:951f0d8a5b7260e9db5e41d429285b5f451e928479f19d80818878527d36e95e"}, ] iniconfig = [ {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, ] isort = [ - {file = "isort-5.9.3-py3-none-any.whl", hash = "sha256:e17d6e2b81095c9db0a03a8025a957f334d6ea30b26f9ec70805411e5c7c81f2"}, - {file = "isort-5.9.3.tar.gz", hash = "sha256:9c2ea1e62d871267b78307fe511c0838ba0da28698c5732d54e2790bf3ba9899"}, + {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, + {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, ] jedi = [ {file = "jedi-0.13.3-py2.py3-none-any.whl", hash = "sha256:2c6bcd9545c7d6440951b12b44d373479bf18123a401a52025cf98563fbd826c"}, @@ -1953,55 +2109,54 @@ keyring = [ {file = "keyring-22.4.0.tar.gz", hash = "sha256:d981e02d134cc3d636a716fbc3ca967bc9609bae5dc21b0063e4409355993ddf"}, ] lazy-object-proxy = [ - {file = "lazy-object-proxy-1.6.0.tar.gz", hash = "sha256:489000d368377571c6f982fba6497f2aa13c6d1facc40660963da62f5c379726"}, - {file = "lazy_object_proxy-1.6.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:c6938967f8528b3668622a9ed3b31d145fab161a32f5891ea7b84f6b790be05b"}, - {file = "lazy_object_proxy-1.6.0-cp27-cp27m-win32.whl", hash = "sha256:ebfd274dcd5133e0afae738e6d9da4323c3eb021b3e13052d8cbd0e457b1256e"}, - {file = "lazy_object_proxy-1.6.0-cp27-cp27m-win_amd64.whl", hash = "sha256:ed361bb83436f117f9917d282a456f9e5009ea12fd6de8742d1a4752c3017e93"}, - {file = "lazy_object_proxy-1.6.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d900d949b707778696fdf01036f58c9876a0d8bfe116e8d220cfd4b15f14e741"}, - {file = "lazy_object_proxy-1.6.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:5743a5ab42ae40caa8421b320ebf3a998f89c85cdc8376d6b2e00bd12bd1b587"}, - {file = "lazy_object_proxy-1.6.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:bf34e368e8dd976423396555078def5cfc3039ebc6fc06d1ae2c5a65eebbcde4"}, - {file = "lazy_object_proxy-1.6.0-cp36-cp36m-win32.whl", hash = "sha256:b579f8acbf2bdd9ea200b1d5dea36abd93cabf56cf626ab9c744a432e15c815f"}, - {file = "lazy_object_proxy-1.6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:4f60460e9f1eb632584c9685bccea152f4ac2130e299784dbaf9fae9f49891b3"}, - {file = "lazy_object_proxy-1.6.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d7124f52f3bd259f510651450e18e0fd081ed82f3c08541dffc7b94b883aa981"}, - {file = "lazy_object_proxy-1.6.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:22ddd618cefe54305df49e4c069fa65715be4ad0e78e8d252a33debf00f6ede2"}, - {file = "lazy_object_proxy-1.6.0-cp37-cp37m-win32.whl", hash = "sha256:9d397bf41caad3f489e10774667310d73cb9c4258e9aed94b9ec734b34b495fd"}, - {file = "lazy_object_proxy-1.6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:24a5045889cc2729033b3e604d496c2b6f588c754f7a62027ad4437a7ecc4837"}, - {file = "lazy_object_proxy-1.6.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:17e0967ba374fc24141738c69736da90e94419338fd4c7c7bef01ee26b339653"}, - {file = "lazy_object_proxy-1.6.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:410283732af311b51b837894fa2f24f2c0039aa7f220135192b38fcc42bd43d3"}, - {file = "lazy_object_proxy-1.6.0-cp38-cp38-win32.whl", hash = "sha256:85fb7608121fd5621cc4377a8961d0b32ccf84a7285b4f1d21988b2eae2868e8"}, - {file = "lazy_object_proxy-1.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:d1c2676e3d840852a2de7c7d5d76407c772927addff8d742b9808fe0afccebdf"}, - {file = "lazy_object_proxy-1.6.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:b865b01a2e7f96db0c5d12cfea590f98d8c5ba64ad222300d93ce6ff9138bcad"}, - {file = "lazy_object_proxy-1.6.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:4732c765372bd78a2d6b2150a6e99d00a78ec963375f236979c0626b97ed8e43"}, - {file = "lazy_object_proxy-1.6.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:9698110e36e2df951c7c36b6729e96429c9c32b3331989ef19976592c5f3c77a"}, - {file = "lazy_object_proxy-1.6.0-cp39-cp39-win32.whl", hash = "sha256:1fee665d2638491f4d6e55bd483e15ef21f6c8c2095f235fef72601021e64f61"}, - {file = "lazy_object_proxy-1.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:f5144c75445ae3ca2057faac03fda5a902eff196702b0a24daf1d6ce0650514b"}, + {file = "lazy-object-proxy-1.7.1.tar.gz", hash = "sha256:d609c75b986def706743cdebe5e47553f4a5a1da9c5ff66d76013ef396b5a8a4"}, + {file = "lazy_object_proxy-1.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bb8c5fd1684d60a9902c60ebe276da1f2281a318ca16c1d0a96db28f62e9166b"}, + {file = "lazy_object_proxy-1.7.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a57d51ed2997e97f3b8e3500c984db50a554bb5db56c50b5dab1b41339b37e36"}, + {file = "lazy_object_proxy-1.7.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd45683c3caddf83abbb1249b653a266e7069a09f486daa8863fb0e7496a9fdb"}, + {file = "lazy_object_proxy-1.7.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8561da8b3dd22d696244d6d0d5330618c993a215070f473b699e00cf1f3f6443"}, + {file = "lazy_object_proxy-1.7.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fccdf7c2c5821a8cbd0a9440a456f5050492f2270bd54e94360cac663398739b"}, + {file = "lazy_object_proxy-1.7.1-cp310-cp310-win32.whl", hash = "sha256:898322f8d078f2654d275124a8dd19b079080ae977033b713f677afcfc88e2b9"}, + {file = "lazy_object_proxy-1.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:85b232e791f2229a4f55840ed54706110c80c0a210d076eee093f2b2e33e1bfd"}, + {file = "lazy_object_proxy-1.7.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:46ff647e76f106bb444b4533bb4153c7370cdf52efc62ccfc1a28bdb3cc95442"}, + {file = "lazy_object_proxy-1.7.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:12f3bb77efe1367b2515f8cb4790a11cffae889148ad33adad07b9b55e0ab22c"}, + {file = "lazy_object_proxy-1.7.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c19814163728941bb871240d45c4c30d33b8a2e85972c44d4e63dd7107faba44"}, + {file = "lazy_object_proxy-1.7.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:e40f2013d96d30217a51eeb1db28c9ac41e9d0ee915ef9d00da639c5b63f01a1"}, + {file = "lazy_object_proxy-1.7.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:2052837718516a94940867e16b1bb10edb069ab475c3ad84fd1e1a6dd2c0fcfc"}, + {file = "lazy_object_proxy-1.7.1-cp36-cp36m-win32.whl", hash = "sha256:6a24357267aa976abab660b1d47a34aaf07259a0c3859a34e536f1ee6e76b5bb"}, + {file = "lazy_object_proxy-1.7.1-cp36-cp36m-win_amd64.whl", hash = "sha256:6aff3fe5de0831867092e017cf67e2750c6a1c7d88d84d2481bd84a2e019ec35"}, + {file = "lazy_object_proxy-1.7.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6a6e94c7b02641d1311228a102607ecd576f70734dc3d5e22610111aeacba8a0"}, + {file = "lazy_object_proxy-1.7.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4ce15276a1a14549d7e81c243b887293904ad2d94ad767f42df91e75fd7b5b6"}, + {file = "lazy_object_proxy-1.7.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e368b7f7eac182a59ff1f81d5f3802161932a41dc1b1cc45c1f757dc876b5d2c"}, + {file = "lazy_object_proxy-1.7.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6ecbb350991d6434e1388bee761ece3260e5228952b1f0c46ffc800eb313ff42"}, + {file = "lazy_object_proxy-1.7.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:553b0f0d8dbf21890dd66edd771f9b1b5f51bd912fa5f26de4449bfc5af5e029"}, + {file = "lazy_object_proxy-1.7.1-cp37-cp37m-win32.whl", hash = "sha256:c7a683c37a8a24f6428c28c561c80d5f4fd316ddcf0c7cab999b15ab3f5c5c69"}, + {file = "lazy_object_proxy-1.7.1-cp37-cp37m-win_amd64.whl", hash = "sha256:df2631f9d67259dc9620d831384ed7732a198eb434eadf69aea95ad18c587a28"}, + {file = "lazy_object_proxy-1.7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:07fa44286cda977bd4803b656ffc1c9b7e3bc7dff7d34263446aec8f8c96f88a"}, + {file = "lazy_object_proxy-1.7.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4dca6244e4121c74cc20542c2ca39e5c4a5027c81d112bfb893cf0790f96f57e"}, + {file = "lazy_object_proxy-1.7.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91ba172fc5b03978764d1df5144b4ba4ab13290d7bab7a50f12d8117f8630c38"}, + {file = "lazy_object_proxy-1.7.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:043651b6cb706eee4f91854da4a089816a6606c1428fd391573ef8cb642ae4f7"}, + {file = "lazy_object_proxy-1.7.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b9e89b87c707dd769c4ea91f7a31538888aad05c116a59820f28d59b3ebfe25a"}, + {file = "lazy_object_proxy-1.7.1-cp38-cp38-win32.whl", hash = "sha256:9d166602b525bf54ac994cf833c385bfcc341b364e3ee71e3bf5a1336e677b55"}, + {file = "lazy_object_proxy-1.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:8f3953eb575b45480db6568306893f0bd9d8dfeeebd46812aa09ca9579595148"}, + {file = "lazy_object_proxy-1.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dd7ed7429dbb6c494aa9bc4e09d94b778a3579be699f9d67da7e6804c422d3de"}, + {file = "lazy_object_proxy-1.7.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70ed0c2b380eb6248abdef3cd425fc52f0abd92d2b07ce26359fcbc399f636ad"}, + {file = "lazy_object_proxy-1.7.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7096a5e0c1115ec82641afbdd70451a144558ea5cf564a896294e346eb611be1"}, + {file = "lazy_object_proxy-1.7.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f769457a639403073968d118bc70110e7dce294688009f5c24ab78800ae56dc8"}, + {file = "lazy_object_proxy-1.7.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:39b0e26725c5023757fc1ab2a89ef9d7ab23b84f9251e28f9cc114d5b59c1b09"}, + {file = "lazy_object_proxy-1.7.1-cp39-cp39-win32.whl", hash = "sha256:2130db8ed69a48a3440103d4a520b89d8a9405f1b06e2cc81640509e8bf6548f"}, + {file = "lazy_object_proxy-1.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:677ea950bef409b47e51e733283544ac3d660b709cfce7b187f5ace137960d61"}, + {file = "lazy_object_proxy-1.7.1-pp37.pp38-none-any.whl", hash = "sha256:d66906d5785da8e0be7360912e99c9188b70f52c422f9fc18223347235691a84"}, ] log4mongo = [ {file = "log4mongo-1.7.0.tar.gz", hash = "sha256:dc374617206162a0b14167fbb5feac01dbef587539a235dadba6200362984a68"}, ] markupsafe = [ - {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-win32.whl", hash = "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"}, @@ -2010,27 +2165,14 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9"}, {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee"}, {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"}, {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"}, {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"}, @@ -2040,12 +2182,6 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"}, {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"}, {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1"}, {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"}, {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"}, {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"}, @@ -2055,91 +2191,78 @@ mccabe = [ {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, ] multidict = [ - {file = "multidict-5.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3822c5894c72e3b35aae9909bef66ec83e44522faf767c0ad39e0e2de11d3b55"}, - {file = "multidict-5.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:28e6d883acd8674887d7edc896b91751dc2d8e87fbdca8359591a13872799e4e"}, - {file = "multidict-5.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b61f85101ef08cbbc37846ac0e43f027f7844f3fade9b7f6dd087178caedeee7"}, - {file = "multidict-5.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9b668c065968c5979fe6b6fa6760bb6ab9aeb94b75b73c0a9c1acf6393ac3bf"}, - {file = "multidict-5.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:517d75522b7b18a3385726b54a081afd425d4f41144a5399e5abd97ccafdf36b"}, - {file = "multidict-5.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1b4ac3ba7a97b35a5ccf34f41b5a8642a01d1e55454b699e5e8e7a99b5a3acf5"}, - {file = "multidict-5.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:df23c83398715b26ab09574217ca21e14694917a0c857e356fd39e1c64f8283f"}, - {file = "multidict-5.2.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e58a9b5cc96e014ddf93c2227cbdeca94b56a7eb77300205d6e4001805391747"}, - {file = "multidict-5.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f76440e480c3b2ca7f843ff8a48dc82446b86ed4930552d736c0bac507498a52"}, - {file = "multidict-5.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cfde464ca4af42a629648c0b0d79b8f295cf5b695412451716531d6916461628"}, - {file = "multidict-5.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:0fed465af2e0eb6357ba95795d003ac0bdb546305cc2366b1fc8f0ad67cc3fda"}, - {file = "multidict-5.2.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:b70913cbf2e14275013be98a06ef4b412329fe7b4f83d64eb70dce8269ed1e1a"}, - {file = "multidict-5.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a5635bcf1b75f0f6ef3c8a1ad07b500104a971e38d3683167b9454cb6465ac86"}, - {file = "multidict-5.2.0-cp310-cp310-win32.whl", hash = "sha256:77f0fb7200cc7dedda7a60912f2059086e29ff67cefbc58d2506638c1a9132d7"}, - {file = "multidict-5.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:9416cf11bcd73c861267e88aea71e9fcc35302b3943e45e1dbb4317f91a4b34f"}, - {file = "multidict-5.2.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:fd77c8f3cba815aa69cb97ee2b2ef385c7c12ada9c734b0f3b32e26bb88bbf1d"}, - {file = "multidict-5.2.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:98ec9aea6223adf46999f22e2c0ab6cf33f5914be604a404f658386a8f1fba37"}, - {file = "multidict-5.2.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e5283c0a00f48e8cafcecadebfa0ed1dac8b39e295c7248c44c665c16dc1138b"}, - {file = "multidict-5.2.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5f79c19c6420962eb17c7e48878a03053b7ccd7b69f389d5831c0a4a7f1ac0a1"}, - {file = "multidict-5.2.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e4a67f1080123de76e4e97a18d10350df6a7182e243312426d508712e99988d4"}, - {file = "multidict-5.2.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:94b117e27efd8e08b4046c57461d5a114d26b40824995a2eb58372b94f9fca02"}, - {file = "multidict-5.2.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:2e77282fd1d677c313ffcaddfec236bf23f273c4fba7cdf198108f5940ae10f5"}, - {file = "multidict-5.2.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:116347c63ba049c1ea56e157fa8aa6edaf5e92925c9b64f3da7769bdfa012858"}, - {file = "multidict-5.2.0-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:dc3a866cf6c13d59a01878cd806f219340f3e82eed514485e094321f24900677"}, - {file = "multidict-5.2.0-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:ac42181292099d91217a82e3fa3ce0e0ddf3a74fd891b7c2b347a7f5aa0edded"}, - {file = "multidict-5.2.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:f0bb0973f42ffcb5e3537548e0767079420aefd94ba990b61cf7bb8d47f4916d"}, - {file = "multidict-5.2.0-cp36-cp36m-win32.whl", hash = "sha256:ea21d4d5104b4f840b91d9dc8cbc832aba9612121eaba503e54eaab1ad140eb9"}, - {file = "multidict-5.2.0-cp36-cp36m-win_amd64.whl", hash = "sha256:e6453f3cbeb78440747096f239d282cc57a2997a16b5197c9bc839099e1633d0"}, - {file = "multidict-5.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d3def943bfd5f1c47d51fd324df1e806d8da1f8e105cc7f1c76a1daf0f7e17b0"}, - {file = "multidict-5.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35591729668a303a02b06e8dba0eb8140c4a1bfd4c4b3209a436a02a5ac1de11"}, - {file = "multidict-5.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8cacda0b679ebc25624d5de66c705bc53dcc7c6f02a7fb0f3ca5e227d80422"}, - {file = "multidict-5.2.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:baf1856fab8212bf35230c019cde7c641887e3fc08cadd39d32a421a30151ea3"}, - {file = "multidict-5.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a43616aec0f0d53c411582c451f5d3e1123a68cc7b3475d6f7d97a626f8ff90d"}, - {file = "multidict-5.2.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:25cbd39a9029b409167aa0a20d8a17f502d43f2efebfe9e3ac019fe6796c59ac"}, - {file = "multidict-5.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0a2cbcfbea6dc776782a444db819c8b78afe4db597211298dd8b2222f73e9cd0"}, - {file = "multidict-5.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:3d2d7d1fff8e09d99354c04c3fd5b560fb04639fd45926b34e27cfdec678a704"}, - {file = "multidict-5.2.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:a37e9a68349f6abe24130846e2f1d2e38f7ddab30b81b754e5a1fde32f782b23"}, - {file = "multidict-5.2.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:637c1896497ff19e1ee27c1c2c2ddaa9f2d134bbb5e0c52254361ea20486418d"}, - {file = "multidict-5.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:9815765f9dcda04921ba467957be543423e5ec6a1136135d84f2ae092c50d87b"}, - {file = "multidict-5.2.0-cp37-cp37m-win32.whl", hash = "sha256:8b911d74acdc1fe2941e59b4f1a278a330e9c34c6c8ca1ee21264c51ec9b67ef"}, - {file = "multidict-5.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:380b868f55f63d048a25931a1632818f90e4be71d2081c2338fcf656d299949a"}, - {file = "multidict-5.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e7d81ce5744757d2f05fc41896e3b2ae0458464b14b5a2c1e87a6a9d69aefaa8"}, - {file = "multidict-5.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d1d55cdf706ddc62822d394d1df53573d32a7a07d4f099470d3cb9323b721b6"}, - {file = "multidict-5.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a4771d0d0ac9d9fe9e24e33bed482a13dfc1256d008d101485fe460359476065"}, - {file = "multidict-5.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da7d57ea65744d249427793c042094c4016789eb2562576fb831870f9c878d9e"}, - {file = "multidict-5.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cdd68778f96216596218b4e8882944d24a634d984ee1a5a049b300377878fa7c"}, - {file = "multidict-5.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ecc99bce8ee42dcad15848c7885197d26841cb24fa2ee6e89d23b8993c871c64"}, - {file = "multidict-5.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:067150fad08e6f2dd91a650c7a49ba65085303fcc3decbd64a57dc13a2733031"}, - {file = "multidict-5.2.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:78c106b2b506b4d895ddc801ff509f941119394b89c9115580014127414e6c2d"}, - {file = "multidict-5.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e6c4fa1ec16e01e292315ba76eb1d012c025b99d22896bd14a66628b245e3e01"}, - {file = "multidict-5.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b227345e4186809d31f22087d0265655114af7cda442ecaf72246275865bebe4"}, - {file = "multidict-5.2.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:06560fbdcf22c9387100979e65b26fba0816c162b888cb65b845d3def7a54c9b"}, - {file = "multidict-5.2.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:7878b61c867fb2df7a95e44b316f88d5a3742390c99dfba6c557a21b30180cac"}, - {file = "multidict-5.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:246145bff76cc4b19310f0ad28bd0769b940c2a49fc601b86bfd150cbd72bb22"}, - {file = "multidict-5.2.0-cp38-cp38-win32.whl", hash = "sha256:c30ac9f562106cd9e8071c23949a067b10211917fdcb75b4718cf5775356a940"}, - {file = "multidict-5.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:f19001e790013ed580abfde2a4465388950728861b52f0da73e8e8a9418533c0"}, - {file = "multidict-5.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c1ff762e2ee126e6f1258650ac641e2b8e1f3d927a925aafcfde943b77a36d24"}, - {file = "multidict-5.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bd6c9c50bf2ad3f0448edaa1a3b55b2e6866ef8feca5d8dbec10ec7c94371d21"}, - {file = "multidict-5.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fc66d4016f6e50ed36fb39cd287a3878ffcebfa90008535c62e0e90a7ab713ae"}, - {file = "multidict-5.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9acb76d5f3dd9421874923da2ed1e76041cb51b9337fd7f507edde1d86535d6"}, - {file = "multidict-5.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dfc924a7e946dd3c6360e50e8f750d51e3ef5395c95dc054bc9eab0f70df4f9c"}, - {file = "multidict-5.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:32fdba7333eb2351fee2596b756d730d62b5827d5e1ab2f84e6cbb287cc67fe0"}, - {file = "multidict-5.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:b9aad49466b8d828b96b9e3630006234879c8d3e2b0a9d99219b3121bc5cdb17"}, - {file = "multidict-5.2.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:93de39267c4c676c9ebb2057e98a8138bade0d806aad4d864322eee0803140a0"}, - {file = "multidict-5.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f9bef5cff994ca3026fcc90680e326d1a19df9841c5e3d224076407cc21471a1"}, - {file = "multidict-5.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:5f841c4f14331fd1e36cbf3336ed7be2cb2a8f110ce40ea253e5573387db7621"}, - {file = "multidict-5.2.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:38ba256ee9b310da6a1a0f013ef4e422fca30a685bcbec86a969bd520504e341"}, - {file = "multidict-5.2.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:3bc3b1621b979621cee9f7b09f024ec76ec03cc365e638126a056317470bde1b"}, - {file = "multidict-5.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6ee908c070020d682e9b42c8f621e8bb10c767d04416e2ebe44e37d0f44d9ad5"}, - {file = "multidict-5.2.0-cp39-cp39-win32.whl", hash = "sha256:1c7976cd1c157fa7ba5456ae5d31ccdf1479680dc9b8d8aa28afabc370df42b8"}, - {file = "multidict-5.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:c9631c642e08b9fff1c6255487e62971d8b8e821808ddd013d8ac058087591ac"}, - {file = "multidict-5.2.0.tar.gz", hash = "sha256:0dd1c93edb444b33ba2274b66f63def8a327d607c6c790772f448a53b6ea59ce"}, + {file = "multidict-6.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b9e95a740109c6047602f4db4da9949e6c5945cefbad34a1299775ddc9a62e2"}, + {file = "multidict-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ac0e27844758d7177989ce406acc6a83c16ed4524ebc363c1f748cba184d89d3"}, + {file = "multidict-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:041b81a5f6b38244b34dc18c7b6aba91f9cdaf854d9a39e5ff0b58e2b5773b9c"}, + {file = "multidict-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fdda29a3c7e76a064f2477c9aab1ba96fd94e02e386f1e665bca1807fc5386f"}, + {file = "multidict-6.0.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3368bf2398b0e0fcbf46d85795adc4c259299fec50c1416d0f77c0a843a3eed9"}, + {file = "multidict-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4f052ee022928d34fe1f4d2bc743f32609fb79ed9c49a1710a5ad6b2198db20"}, + {file = "multidict-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:225383a6603c086e6cef0f2f05564acb4f4d5f019a4e3e983f572b8530f70c88"}, + {file = "multidict-6.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50bd442726e288e884f7be9071016c15a8742eb689a593a0cac49ea093eef0a7"}, + {file = "multidict-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:47e6a7e923e9cada7c139531feac59448f1f47727a79076c0b1ee80274cd8eee"}, + {file = "multidict-6.0.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:0556a1d4ea2d949efe5fd76a09b4a82e3a4a30700553a6725535098d8d9fb672"}, + {file = "multidict-6.0.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:626fe10ac87851f4cffecee161fc6f8f9853f0f6f1035b59337a51d29ff3b4f9"}, + {file = "multidict-6.0.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:8064b7c6f0af936a741ea1efd18690bacfbae4078c0c385d7c3f611d11f0cf87"}, + {file = "multidict-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2d36e929d7f6a16d4eb11b250719c39560dd70545356365b494249e2186bc389"}, + {file = "multidict-6.0.2-cp310-cp310-win32.whl", hash = "sha256:fcb91630817aa8b9bc4a74023e4198480587269c272c58b3279875ed7235c293"}, + {file = "multidict-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:8cbf0132f3de7cc6c6ce00147cc78e6439ea736cee6bca4f068bcf892b0fd658"}, + {file = "multidict-6.0.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:05f6949d6169878a03e607a21e3b862eaf8e356590e8bdae4227eedadacf6e51"}, + {file = "multidict-6.0.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2c2e459f7050aeb7c1b1276763364884595d47000c1cddb51764c0d8976e608"}, + {file = "multidict-6.0.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d0509e469d48940147e1235d994cd849a8f8195e0bca65f8f5439c56e17872a3"}, + {file = "multidict-6.0.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:514fe2b8d750d6cdb4712346a2c5084a80220821a3e91f3f71eec11cf8d28fd4"}, + {file = "multidict-6.0.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19adcfc2a7197cdc3987044e3f415168fc5dc1f720c932eb1ef4f71a2067e08b"}, + {file = "multidict-6.0.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b9d153e7f1f9ba0b23ad1568b3b9e17301e23b042c23870f9ee0522dc5cc79e8"}, + {file = "multidict-6.0.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:aef9cc3d9c7d63d924adac329c33835e0243b5052a6dfcbf7732a921c6e918ba"}, + {file = "multidict-6.0.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4571f1beddff25f3e925eea34268422622963cd8dc395bb8778eb28418248e43"}, + {file = "multidict-6.0.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:d48b8ee1d4068561ce8033d2c344cf5232cb29ee1a0206a7b828c79cbc5982b8"}, + {file = "multidict-6.0.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:45183c96ddf61bf96d2684d9fbaf6f3564d86b34cb125761f9a0ef9e36c1d55b"}, + {file = "multidict-6.0.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:75bdf08716edde767b09e76829db8c1e5ca9d8bb0a8d4bd94ae1eafe3dac5e15"}, + {file = "multidict-6.0.2-cp37-cp37m-win32.whl", hash = "sha256:a45e1135cb07086833ce969555df39149680e5471c04dfd6a915abd2fc3f6dbc"}, + {file = "multidict-6.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6f3cdef8a247d1eafa649085812f8a310e728bdf3900ff6c434eafb2d443b23a"}, + {file = "multidict-6.0.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0327292e745a880459ef71be14e709aaea2f783f3537588fb4ed09b6c01bca60"}, + {file = "multidict-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e875b6086e325bab7e680e4316d667fc0e5e174bb5611eb16b3ea121c8951b86"}, + {file = "multidict-6.0.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:feea820722e69451743a3d56ad74948b68bf456984d63c1a92e8347b7b88452d"}, + {file = "multidict-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cc57c68cb9139c7cd6fc39f211b02198e69fb90ce4bc4a094cf5fe0d20fd8b0"}, + {file = "multidict-6.0.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:497988d6b6ec6ed6f87030ec03280b696ca47dbf0648045e4e1d28b80346560d"}, + {file = "multidict-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:89171b2c769e03a953d5969b2f272efa931426355b6c0cb508022976a17fd376"}, + {file = "multidict-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:684133b1e1fe91eda8fa7447f137c9490a064c6b7f392aa857bba83a28cfb693"}, + {file = "multidict-6.0.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd9fc9c4849a07f3635ccffa895d57abce554b467d611a5009ba4f39b78a8849"}, + {file = "multidict-6.0.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e07c8e79d6e6fd37b42f3250dba122053fddb319e84b55dd3a8d6446e1a7ee49"}, + {file = "multidict-6.0.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4070613ea2227da2bfb2c35a6041e4371b0af6b0be57f424fe2318b42a748516"}, + {file = "multidict-6.0.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:47fbeedbf94bed6547d3aa632075d804867a352d86688c04e606971595460227"}, + {file = "multidict-6.0.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:5774d9218d77befa7b70d836004a768fb9aa4fdb53c97498f4d8d3f67bb9cfa9"}, + {file = "multidict-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2957489cba47c2539a8eb7ab32ff49101439ccf78eab724c828c1a54ff3ff98d"}, + {file = "multidict-6.0.2-cp38-cp38-win32.whl", hash = "sha256:e5b20e9599ba74391ca0cfbd7b328fcc20976823ba19bc573983a25b32e92b57"}, + {file = "multidict-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:8004dca28e15b86d1b1372515f32eb6f814bdf6f00952699bdeb541691091f96"}, + {file = "multidict-6.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2e4a0785b84fb59e43c18a015ffc575ba93f7d1dbd272b4cdad9f5134b8a006c"}, + {file = "multidict-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6701bf8a5d03a43375909ac91b6980aea74b0f5402fbe9428fc3f6edf5d9677e"}, + {file = "multidict-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a007b1638e148c3cfb6bf0bdc4f82776cef0ac487191d093cdc316905e504071"}, + {file = "multidict-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:07a017cfa00c9890011628eab2503bee5872f27144936a52eaab449be5eaf032"}, + {file = "multidict-6.0.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c207fff63adcdf5a485969131dc70e4b194327666b7e8a87a97fbc4fd80a53b2"}, + {file = "multidict-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:373ba9d1d061c76462d74e7de1c0c8e267e9791ee8cfefcf6b0b2495762c370c"}, + {file = "multidict-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfba7c6d5d7c9099ba21f84662b037a0ffd4a5e6b26ac07d19e423e6fdf965a9"}, + {file = "multidict-6.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:19d9bad105dfb34eb539c97b132057a4e709919ec4dd883ece5838bcbf262b80"}, + {file = "multidict-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:de989b195c3d636ba000ee4281cd03bb1234635b124bf4cd89eeee9ca8fcb09d"}, + {file = "multidict-6.0.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7c40b7bbece294ae3a87c1bc2abff0ff9beef41d14188cda94ada7bcea99b0fb"}, + {file = "multidict-6.0.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:d16cce709ebfadc91278a1c005e3c17dd5f71f5098bfae1035149785ea6e9c68"}, + {file = "multidict-6.0.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:a2c34a93e1d2aa35fbf1485e5010337c72c6791407d03aa5f4eed920343dd360"}, + {file = "multidict-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:feba80698173761cddd814fa22e88b0661e98cb810f9f986c54aa34d281e4937"}, + {file = "multidict-6.0.2-cp39-cp39-win32.whl", hash = "sha256:23b616fdc3c74c9fe01d76ce0d1ce872d2d396d8fa8e4899398ad64fb5aa214a"}, + {file = "multidict-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:4bae31803d708f6f15fd98be6a6ac0b6958fcf68fda3c77a048a4f9073704aae"}, + {file = "multidict-6.0.2.tar.gz", hash = "sha256:5ff3bd75f38e4c43f1f470f2df7a4d430b821c4ce22be384e1459cb57d6bb013"}, ] opentimelineio = [] packaging = [ - {file = "packaging-21.2-py3-none-any.whl", hash = "sha256:14317396d1e8cdb122989b916fa2c7e9ca8e2be9e8060a6eff75b6b7b4d8a7e0"}, - {file = "packaging-21.2.tar.gz", hash = "sha256:096d689d78ca690e4cd8a89568ba06d07ca097e3306a4381635073ca91479966"}, + {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, + {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, ] paramiko = [ - {file = "paramiko-2.8.0-py2.py3-none-any.whl", hash = "sha256:def3ec612399bab4e9f5eb66b0ae5983980db9dd9120d9e9c6ea3ff673865d1c"}, - {file = "paramiko-2.8.0.tar.gz", hash = "sha256:e673b10ee0f1c80d46182d3af7751d033d9b573dd7054d2d0aa46be186c3c1d2"}, + {file = "paramiko-2.9.2-py2.py3-none-any.whl", hash = "sha256:04097dbd96871691cdb34c13db1883066b8a13a0df2afd4cb0a92221f51c2603"}, + {file = "paramiko-2.9.2.tar.gz", hash = "sha256:944a9e5dbdd413ab6c7951ea46b0ab40713235a9c4c5ca81cfe45c6f14fa677b"}, ] parso = [ - {file = "parso-0.8.2-py2.py3-none-any.whl", hash = "sha256:a8c4922db71e4fdb90e0d0bc6e50f9b273d3397925e5e60a717e719201778d22"}, - {file = "parso-0.8.2.tar.gz", hash = "sha256:12b83492c6239ce32ff5eed6d3639d6a536170723c6f3f1506869f1ace413398"}, + {file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"}, + {file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"}, ] pathlib2 = [ {file = "pathlib2-2.3.6-py2.py3-none-any.whl", hash = "sha256:3a130b266b3a36134dcc79c17b3c7ac9634f083825ca6ea9d8f557ee6195c9c8"}, @@ -2180,8 +2303,8 @@ pillow = [ {file = "Pillow-9.0.0.tar.gz", hash = "sha256:ee6e2963e92762923956fe5d3479b1fdc3b76c83f290aad131a2f98c3df0593e"}, ] platformdirs = [ - {file = "platformdirs-2.4.0-py3-none-any.whl", hash = "sha256:8868bbe3c3c80d42f20156f22e7131d2fb321f5bc86a2a345375c6481a67021d"}, - {file = "platformdirs-2.4.0.tar.gz", hash = "sha256:367a5e80b3d04d2428ffa76d33f124cf11e8fff2acdaa9b43d545f5c7d661ef2"}, + {file = "platformdirs-2.4.1-py3-none-any.whl", hash = "sha256:1d7385c7db91728b83efd0ca99a5afb296cab9d0ed8313a45ed8ba17967ecfca"}, + {file = "platformdirs-2.4.1.tar.gz", hash = "sha256:440633ddfebcc36264232365d7840a970e75e1018d15b4327d11f91909045fda"}, ] pluggy = [ {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, @@ -2196,37 +2319,36 @@ prefixed = [ {file = "prefixed-0.3.2.tar.gz", hash = "sha256:ca48277ba5fa8346dd4b760847da930c7b84416387c39e93affef086add2c029"}, ] protobuf = [ - {file = "protobuf-3.17.3-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ab6bb0e270c6c58e7ff4345b3a803cc59dbee19ddf77a4719c5b635f1d547aa8"}, - {file = "protobuf-3.17.3-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:13ee7be3c2d9a5d2b42a1030976f760f28755fcf5863c55b1460fd205e6cd637"}, - {file = "protobuf-3.17.3-cp35-cp35m-macosx_10_9_intel.whl", hash = "sha256:1556a1049ccec58c7855a78d27e5c6e70e95103b32de9142bae0576e9200a1b0"}, - {file = "protobuf-3.17.3-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:f0e59430ee953184a703a324b8ec52f571c6c4259d496a19d1cabcdc19dabc62"}, - {file = "protobuf-3.17.3-cp35-cp35m-win32.whl", hash = "sha256:a981222367fb4210a10a929ad5983ae93bd5a050a0824fc35d6371c07b78caf6"}, - {file = "protobuf-3.17.3-cp35-cp35m-win_amd64.whl", hash = "sha256:6d847c59963c03fd7a0cd7c488cadfa10cda4fff34d8bc8cba92935a91b7a037"}, - {file = "protobuf-3.17.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:145ce0af55c4259ca74993ddab3479c78af064002ec8227beb3d944405123c71"}, - {file = "protobuf-3.17.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6ce4d8bf0321e7b2d4395e253f8002a1a5ffbcfd7bcc0a6ba46712c07d47d0b4"}, - {file = "protobuf-3.17.3-cp36-cp36m-win32.whl", hash = "sha256:7a4c97961e9e5b03a56f9a6c82742ed55375c4a25f2692b625d4087d02ed31b9"}, - {file = "protobuf-3.17.3-cp36-cp36m-win_amd64.whl", hash = "sha256:a22b3a0dbac6544dacbafd4c5f6a29e389a50e3b193e2c70dae6bbf7930f651d"}, - {file = "protobuf-3.17.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:ffea251f5cd3c0b9b43c7a7a912777e0bc86263436a87c2555242a348817221b"}, - {file = "protobuf-3.17.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:9b7a5c1022e0fa0dbde7fd03682d07d14624ad870ae52054849d8960f04bc764"}, - {file = "protobuf-3.17.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:8727ee027157516e2c311f218ebf2260a18088ffb2d29473e82add217d196b1c"}, - {file = "protobuf-3.17.3-cp37-cp37m-win32.whl", hash = "sha256:14c1c9377a7ffbeaccd4722ab0aa900091f52b516ad89c4b0c3bb0a4af903ba5"}, - {file = "protobuf-3.17.3-cp37-cp37m-win_amd64.whl", hash = "sha256:c56c050a947186ba51de4f94ab441d7f04fcd44c56df6e922369cc2e1a92d683"}, - {file = "protobuf-3.17.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2ae692bb6d1992afb6b74348e7bb648a75bb0d3565a3f5eea5bec8f62bd06d87"}, - {file = "protobuf-3.17.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:99938f2a2d7ca6563c0ade0c5ca8982264c484fdecf418bd68e880a7ab5730b1"}, - {file = "protobuf-3.17.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6902a1e4b7a319ec611a7345ff81b6b004b36b0d2196ce7a748b3493da3d226d"}, - {file = "protobuf-3.17.3-cp38-cp38-win32.whl", hash = "sha256:59e5cf6b737c3a376932fbfb869043415f7c16a0cf176ab30a5bbc419cd709c1"}, - {file = "protobuf-3.17.3-cp38-cp38-win_amd64.whl", hash = "sha256:ebcb546f10069b56dc2e3da35e003a02076aaa377caf8530fe9789570984a8d2"}, - {file = "protobuf-3.17.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4ffbd23640bb7403574f7aff8368e2aeb2ec9a5c6306580be48ac59a6bac8bde"}, - {file = "protobuf-3.17.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:26010f693b675ff5a1d0e1bdb17689b8b716a18709113288fead438703d45539"}, - {file = "protobuf-3.17.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:e76d9686e088fece2450dbc7ee905f9be904e427341d289acbe9ad00b78ebd47"}, - {file = "protobuf-3.17.3-cp39-cp39-win32.whl", hash = "sha256:a38bac25f51c93e4be4092c88b2568b9f407c27217d3dd23c7a57fa522a17554"}, - {file = "protobuf-3.17.3-cp39-cp39-win_amd64.whl", hash = "sha256:85d6303e4adade2827e43c2b54114d9a6ea547b671cb63fafd5011dc47d0e13d"}, - {file = "protobuf-3.17.3-py2.py3-none-any.whl", hash = "sha256:2bfb815216a9cd9faec52b16fd2bfa68437a44b67c56bee59bc3926522ecb04e"}, - {file = "protobuf-3.17.3.tar.gz", hash = "sha256:72804ea5eaa9c22a090d2803813e280fb273b62d5ae497aaf3553d141c4fdd7b"}, + {file = "protobuf-3.19.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f51d5a9f137f7a2cec2d326a74b6e3fc79d635d69ffe1b036d39fc7d75430d37"}, + {file = "protobuf-3.19.4-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:09297b7972da685ce269ec52af761743714996b4381c085205914c41fcab59fb"}, + {file = "protobuf-3.19.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:072fbc78d705d3edc7ccac58a62c4c8e0cec856987da7df8aca86e647be4e35c"}, + {file = "protobuf-3.19.4-cp310-cp310-win32.whl", hash = "sha256:7bb03bc2873a2842e5ebb4801f5c7ff1bfbdf426f85d0172f7644fcda0671ae0"}, + {file = "protobuf-3.19.4-cp310-cp310-win_amd64.whl", hash = "sha256:f358aa33e03b7a84e0d91270a4d4d8f5df6921abe99a377828839e8ed0c04e07"}, + {file = "protobuf-3.19.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:1c91ef4110fdd2c590effb5dca8fdbdcb3bf563eece99287019c4204f53d81a4"}, + {file = "protobuf-3.19.4-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c438268eebb8cf039552897d78f402d734a404f1360592fef55297285f7f953f"}, + {file = "protobuf-3.19.4-cp36-cp36m-win32.whl", hash = "sha256:835a9c949dc193953c319603b2961c5c8f4327957fe23d914ca80d982665e8ee"}, + {file = "protobuf-3.19.4-cp36-cp36m-win_amd64.whl", hash = "sha256:4276cdec4447bd5015453e41bdc0c0c1234eda08420b7c9a18b8d647add51e4b"}, + {file = "protobuf-3.19.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6cbc312be5e71869d9d5ea25147cdf652a6781cf4d906497ca7690b7b9b5df13"}, + {file = "protobuf-3.19.4-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:54a1473077f3b616779ce31f477351a45b4fef8c9fd7892d6d87e287a38df368"}, + {file = "protobuf-3.19.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:435bb78b37fc386f9275a7035fe4fb1364484e38980d0dd91bc834a02c5ec909"}, + {file = "protobuf-3.19.4-cp37-cp37m-win32.whl", hash = "sha256:16f519de1313f1b7139ad70772e7db515b1420d208cb16c6d7858ea989fc64a9"}, + {file = "protobuf-3.19.4-cp37-cp37m-win_amd64.whl", hash = "sha256:cdc076c03381f5c1d9bb1abdcc5503d9ca8b53cf0a9d31a9f6754ec9e6c8af0f"}, + {file = "protobuf-3.19.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:69da7d39e39942bd52848438462674c463e23963a1fdaa84d88df7fbd7e749b2"}, + {file = "protobuf-3.19.4-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:48ed3877fa43e22bcacc852ca76d4775741f9709dd9575881a373bd3e85e54b2"}, + {file = "protobuf-3.19.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd95d1dfb9c4f4563e6093a9aa19d9c186bf98fa54da5252531cc0d3a07977e7"}, + {file = "protobuf-3.19.4-cp38-cp38-win32.whl", hash = "sha256:b38057450a0c566cbd04890a40edf916db890f2818e8682221611d78dc32ae26"}, + {file = "protobuf-3.19.4-cp38-cp38-win_amd64.whl", hash = "sha256:7ca7da9c339ca8890d66958f5462beabd611eca6c958691a8fe6eccbd1eb0c6e"}, + {file = "protobuf-3.19.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:36cecbabbda242915529b8ff364f2263cd4de7c46bbe361418b5ed859677ba58"}, + {file = "protobuf-3.19.4-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:c1068287025f8ea025103e37d62ffd63fec8e9e636246b89c341aeda8a67c934"}, + {file = "protobuf-3.19.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96bd766831596d6014ca88d86dc8fe0fb2e428c0b02432fd9db3943202bf8c5e"}, + {file = "protobuf-3.19.4-cp39-cp39-win32.whl", hash = "sha256:84123274d982b9e248a143dadd1b9815049f4477dc783bf84efe6250eb4b836a"}, + {file = "protobuf-3.19.4-cp39-cp39-win_amd64.whl", hash = "sha256:3112b58aac3bac9c8be2b60a9daf6b558ca3f7681c130dcdd788ade7c9ffbdca"}, + {file = "protobuf-3.19.4-py2.py3-none-any.whl", hash = "sha256:8961c3a78ebfcd000920c9060a262f082f29838682b1f7201889300c1fbe0616"}, + {file = "protobuf-3.19.4.tar.gz", hash = "sha256:9df0c10adf3e83015ced42a9a7bd64e13d06c4cf45c340d2c63020ea04499d0a"}, ] py = [ - {file = "py-1.10.0-py2.py3-none-any.whl", hash = "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"}, - {file = "py-1.10.0.tar.gz", hash = "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3"}, + {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, + {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, ] pyaaf2 = [ {file = "pyaaf2-1.4.0.tar.gz", hash = "sha256:160d3c26c7cfef7176d0bdb0e55772156570435982c3abfa415e89639f76e71b"}, @@ -2270,8 +2392,8 @@ pycodestyle = [ {file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"}, ] pycparser = [ - {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"}, - {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"}, + {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, + {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, ] pydocstyle = [ {file = "pydocstyle-3.0.0-py2-none-any.whl", hash = "sha256:2258f9b0df68b97bf3a6c29003edc5238ff8879f1efb6f1999988d934e432bd8"}, @@ -2283,213 +2405,201 @@ pyflakes = [ {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"}, ] pygments = [ - {file = "Pygments-2.10.0-py3-none-any.whl", hash = "sha256:b8e67fe6af78f492b3c4b3e2970c0624cbf08beb1e493b2c99b9fa1b67a20380"}, - {file = "Pygments-2.10.0.tar.gz", hash = "sha256:f398865f7eb6874156579fdf36bc840a03cab64d1cde9e93d68f46a425ec52c6"}, + {file = "Pygments-2.11.2-py3-none-any.whl", hash = "sha256:44238f1b60a76d78fc8ca0528ee429702aae011c265fe6a8dd8b63049ae41c65"}, + {file = "Pygments-2.11.2.tar.gz", hash = "sha256:4e426f72023d88d03b2fa258de560726ce890ff3b630f88c21cbb8b2503b8c6a"}, ] pylint = [ - {file = "pylint-2.11.1-py3-none-any.whl", hash = "sha256:0f358e221c45cbd4dad2a1e4b883e75d28acdcccd29d40c76eb72b307269b126"}, - {file = "pylint-2.11.1.tar.gz", hash = "sha256:2c9843fff1a88ca0ad98a256806c82c5a8f86086e7ccbdb93297d86c3f90c436"}, + {file = "pylint-2.12.2-py3-none-any.whl", hash = "sha256:daabda3f7ed9d1c60f52d563b1b854632fd90035bcf01443e234d3dc794e3b74"}, + {file = "pylint-2.12.2.tar.gz", hash = "sha256:9d945a73640e1fec07ee34b42f5669b770c759acd536ec7b16d7e4b87a9c9ff9"}, ] pymongo = [ - {file = "pymongo-3.12.1-cp27-cp27m-macosx_10_14_intel.whl", hash = "sha256:c4653830375ab019b86d218c749ad38908b74182b2863d09936aa8d7f990d30e"}, - {file = "pymongo-3.12.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:2462a68f6675da548e333fa299d8e9807e00f95a4d198cfe9194d7be69f40c9b"}, - {file = "pymongo-3.12.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:4168b6c425d783e81723fc3dc382d374a228ff29530436a472a36d9f27593e73"}, - {file = "pymongo-3.12.1-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:36806ee53a85c3ba73939652f2ced2961e6a77cfbae385cd83f2e24cd97964b7"}, - {file = "pymongo-3.12.1-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:bf2d9d62178bb5c05e77d40becf89c309b1966fbcfb5c306238f81bf1ec2d6a2"}, - {file = "pymongo-3.12.1-cp27-cp27m-win32.whl", hash = "sha256:75c7ef67b4b8ec070e7a4740764f6c03ec9246b59d95e2ae45c029d41cb9efa1"}, - {file = "pymongo-3.12.1-cp27-cp27m-win_amd64.whl", hash = "sha256:49b0d92724d3fce1174fd30b0b428595072d5c6b14d6203e46a9ea347ae7b439"}, - {file = "pymongo-3.12.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:cef2675004d85d85a4ccc24730b73a99931547368d18ceeed1259a2d9fcddbc1"}, - {file = "pymongo-3.12.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:5e3833c001a04aa06a28c6fd9628256862a654c09b0f81c07734b5629bc014ab"}, - {file = "pymongo-3.12.1-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6a96c04ce39d66df60d9ce89f4c254c4967bc7d9e2e2c52adc58f47be826ee96"}, - {file = "pymongo-3.12.1-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:c2a17752f97a942bdb4ff4a0516a67c5ade1658ebe1ab2edacdec0b42e39fa75"}, - {file = "pymongo-3.12.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:02e0c088f189ca69fac094cb5f851b43bbbd7cec42114495777d4d8f297f7f8a"}, - {file = "pymongo-3.12.1-cp310-cp310-manylinux1_i686.whl", hash = "sha256:45d6b47d70ed44e3c40bef618ed61866c48176e7e5dff80d06d8b1a6192e8584"}, - {file = "pymongo-3.12.1-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:891f541c7ed29b95799da0cd249ae1db1842777b564e8205a197b038c5df6135"}, - {file = "pymongo-3.12.1-cp310-cp310-manylinux2014_i686.whl", hash = "sha256:dc4749c230a71b34db50ac2481d9008bb17b67c92671c443c3b40e192fbea78e"}, - {file = "pymongo-3.12.1-cp310-cp310-manylinux2014_ppc64le.whl", hash = "sha256:aa434534cc91f51a85e3099dc257ee8034b3d2be77f2ca58fb335a686e3a681f"}, - {file = "pymongo-3.12.1-cp310-cp310-manylinux2014_s390x.whl", hash = "sha256:180b405e17b90a877ea5dbc5efe7f4c171af4c89323148e100c0f12cedb86f12"}, - {file = "pymongo-3.12.1-cp310-cp310-manylinux2014_x86_64.whl", hash = "sha256:a472ca3d43d33e596ff5836c6cc71c3e61be33f44fe1cfdab4a1100f4af60333"}, - {file = "pymongo-3.12.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe16517b275031d61261a4e3941c411fb7c46a9cd012f02381b56e7907cc9e06"}, - {file = "pymongo-3.12.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c0947d7be30335cb4c3d5d0983d8ebc8294ae52503cf1d596c926f7e7183900b"}, - {file = "pymongo-3.12.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:adb37bf22d25a51b84d989a2a5c770d4514ac590201eea1cb50ce8c9c5257f1d"}, - {file = "pymongo-3.12.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f5fe59328838fa28958cc06ecf94be585726b97d637012f168bc3c7abe4fd81"}, - {file = "pymongo-3.12.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87114b995506e7584cf3daf891e419b5f6e7e383e7df6267494da3a76312aa22"}, - {file = "pymongo-3.12.1-cp310-cp310-win32.whl", hash = "sha256:4f4bc64fe9cbd70d46f519f1e88c9e4677f7af18ab9cd4942abce2bcfa7549c3"}, - {file = "pymongo-3.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:8f87f53c9cd89010ae45490ec2c963ff18b31f5f290dc08b04151709589fe8d9"}, - {file = "pymongo-3.12.1-cp34-cp34m-macosx_10_6_intel.whl", hash = "sha256:37a63da5ee623acdf98e6d511171c8a5827a6106b0712c18af4441ef4f11e6be"}, - {file = "pymongo-3.12.1-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:b1b06038c9940a49c73db0aeb0f6809b308e198da1326171768cf68d843af521"}, - {file = "pymongo-3.12.1-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:ab27d6d7d41a66d9e54269a290d27cd5c74f08e9add0054a754b4821026c4f42"}, - {file = "pymongo-3.12.1-cp34-cp34m-win32.whl", hash = "sha256:63be03f7ae1e15e72a234637ec7941ef229c7ab252c9ff6af48bba1e5418961c"}, - {file = "pymongo-3.12.1-cp34-cp34m-win_amd64.whl", hash = "sha256:56feb80ea1f5334ccab9bd16a5161571ab70392e51fcc752fb8a1dc67125f663"}, - {file = "pymongo-3.12.1-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:a81e52dbf95f236a0c89a5abcd2b6e1331da0c0312f471c73fae76c79d2acf6b"}, - {file = "pymongo-3.12.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:712de1876608fd5d76abc3fc8ec55077278dd5044073fbe9492631c9a2c58351"}, - {file = "pymongo-3.12.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:47ed77f62c8417a86f9ad158b803f3459a636386cb9d3d4e9e7d6a82d051f907"}, - {file = "pymongo-3.12.1-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1fa6f08ddb6975371777f97592d35c771e713ee2250e55618148a5e57e260aff"}, - {file = "pymongo-3.12.1-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:3a2fcbd04273a509fa85285d9eccf17ab65ce440bd4f5e5a58c978e563cd9e9a"}, - {file = "pymongo-3.12.1-cp35-cp35m-win32.whl", hash = "sha256:d1b98539b0de822b6f717498e59ae3e5ae2e7f564370ab513e6d0c060753e447"}, - {file = "pymongo-3.12.1-cp35-cp35m-win_amd64.whl", hash = "sha256:c660fd1e4a4b52f79f7d134a3d31d452948477b7f46ff5061074a534c5805ba6"}, - {file = "pymongo-3.12.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:460bdaa3f65ddb5b7474ae08589a1763b5da1a78b8348351b9ba1c63b459d67d"}, - {file = "pymongo-3.12.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:1d55982e5335925c55e2b87467043866ce72bd30ea7e7e3eeed6ec3d95a806d4"}, - {file = "pymongo-3.12.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:67e0b2ad3692f6d0335ae231a40de55ec395b6c2e971ad6f55b162244d1ec542"}, - {file = "pymongo-3.12.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:515e4708d6567901ffc06476a38abe2c9093733f52638235d9f149579c1d3de0"}, - {file = "pymongo-3.12.1-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:ed20ec5a01c43254f6047c5d8124b70d28e39f128c8ad960b437644fe94e1827"}, - {file = "pymongo-3.12.1-cp36-cp36m-manylinux2014_ppc64le.whl", hash = "sha256:e2bccadbe313b11704160aaba5eec95d2da1aa663f02f41d2d1520d02bbbdcd5"}, - {file = "pymongo-3.12.1-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:ef8b927813c27c3bdfc82c55682d7767403bcdadfd9f9c0fc49f4be4553a877b"}, - {file = "pymongo-3.12.1-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:2d3abe548a280b49269c7907d5b71199882510c484d680a5ea7860f30c4a695f"}, - {file = "pymongo-3.12.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e30cce3cc86d6082c8596b3fbee0d4f54bc4d337a4fa1bf536920e2e319e24f0"}, - {file = "pymongo-3.12.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fe3ae4294d593da54862f0140fdcc89d1aeeb94258ca97f094119ed7f0e5882d"}, - {file = "pymongo-3.12.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9641be893ccce7d192a0094efd0a0d9f1783a1ebf314b4128f8a27bfadb8a77c"}, - {file = "pymongo-3.12.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13a7c6d055af58a1e9c505e736da8b6a2e95ccc8cec10b008143f7a536e5de8a"}, - {file = "pymongo-3.12.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:25fd76deabe9ea37c8360c362b32f702cc095a208dd1c5328189938ca7685847"}, - {file = "pymongo-3.12.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e841695b5dbea38909ab2dbf17e91e9a823412d8d88d1ef77f1b94a7bc551c0f"}, - {file = "pymongo-3.12.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6ead0126fb4424c6c6a4fdc603d699a9db7c03cdb8eac374c352a75fec8a820a"}, - {file = "pymongo-3.12.1-cp36-cp36m-win32.whl", hash = "sha256:a5dbeeea6a375fbd79448b48a54c46fc9351611a03ef8398d2a40b684ce46194"}, - {file = "pymongo-3.12.1-cp36-cp36m-win_amd64.whl", hash = "sha256:87db421c9eb915b8d9a9a13c5b2ee338350e36ee83e26ff0adfc48abc5db3ac3"}, - {file = "pymongo-3.12.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:8851544168703fb519e95556e3b463fca4beeef7ed3f731d81a68c8268515d9d"}, - {file = "pymongo-3.12.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:7d8cdd2f070c71366e64990653522cce84b08dc26ab0d1fa19aa8d14ee0cf9ba"}, - {file = "pymongo-3.12.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:51437c77030bed72d57d8a61e22758e3c389b13fea7787c808030002bb05ca39"}, - {file = "pymongo-3.12.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:f43cacda46fc188f998e6d308afe1c61ff41dcb300949f4cbf731e9a0a5eb2d3"}, - {file = "pymongo-3.12.1-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:1a7b138a04fdd17849930dc8bf664002e17db38448850bfb96d200c9c5a8b3a1"}, - {file = "pymongo-3.12.1-cp37-cp37m-manylinux2014_ppc64le.whl", hash = "sha256:444c00ebc20f2f9dc62e34f7dc9453dc2f5f5a72419c8dccad6e26d546c35712"}, - {file = "pymongo-3.12.1-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:81ce5f871f5d8e82615c8bd0b34b68a9650204c8b1a04ce7890d58c98eb66e39"}, - {file = "pymongo-3.12.1-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:837cdef094f39c6f4a2967abc646a412999c2540fbf5d3cce1dd3b671f4b876c"}, - {file = "pymongo-3.12.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2174d3279b8e2b6d7613b338f684cd78ff7adf1e7ec5b7b7bde5609a129c9898"}, - {file = "pymongo-3.12.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:303531649fa45f96b694054c1aa02f79bda32ef57affe42c5c339336717eed74"}, - {file = "pymongo-3.12.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1821ce4e5a293313947fd017bbd2d2535aa6309680fa29b33d0442d15da296ec"}, - {file = "pymongo-3.12.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15dae01341571d0af51526b7a21648ca575e9375e16ba045c9860848dfa8952f"}, - {file = "pymongo-3.12.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fcc021530b7c71069132fe4846d95a3cdd74d143adc2f7e398d5fabf610f111c"}, - {file = "pymongo-3.12.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f44bea60fd2178d7153deef9621c4b526a93939da30010bba24d3408a98b0f79"}, - {file = "pymongo-3.12.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6f0f0a10f128ea0898e607d351ebfabf70941494fc94e87f12c76e2894d8e6c4"}, - {file = "pymongo-3.12.1-cp37-cp37m-win32.whl", hash = "sha256:afb16330ab6efbbf995375ad94e970fa2f89bb46bd10d854b7047620fdb0d67d"}, - {file = "pymongo-3.12.1-cp37-cp37m-win_amd64.whl", hash = "sha256:dcf906c1f7a33e4222e4bff18da1554d69323bc4dd95fe867a6fa80709ee5f93"}, - {file = "pymongo-3.12.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9b62d84478f471fdb0dcea3876acff38f146bd23cbdbed15074fb4622064ec2e"}, - {file = "pymongo-3.12.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:48722e91981bb22a16b0431ea01da3e1cc5b96805634d3b8d3c2a5315c1ce7f1"}, - {file = "pymongo-3.12.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:d6c6989c10008ac70c2bb2ad2b940fcfe883712746c89f7e3308c14c213a70d7"}, - {file = "pymongo-3.12.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:573e2387d0686976642142c50740dfc4d3494cc627e2a7d22782b99f70879055"}, - {file = "pymongo-3.12.1-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:7117bfd8827cfe550f65a3c399dcd6e02226197a91c6d11a3540c3e8efc686d6"}, - {file = "pymongo-3.12.1-cp38-cp38-manylinux2014_ppc64le.whl", hash = "sha256:6eb6789f26c398c383225e1313c8e75a7d290d323b8eaf65f3f3ddd0eb8a5a3c"}, - {file = "pymongo-3.12.1-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:138248c542051eb462f88b50b0267bd5286d6661064bab06faa0ef6ac30cdb4b"}, - {file = "pymongo-3.12.1-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:7abc87e45b572eb6d17a50422e69a9e5d6f13e691e821fe2312df512500faa50"}, - {file = "pymongo-3.12.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a7430f3987d232e782304c109be1d0e6fff46ca6405cb2479e4d8d08cd29541e"}, - {file = "pymongo-3.12.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cb48ff6cc6109190e1ccf8ea1fc71cc244c9185813ce7d1c415dce991cfb8709"}, - {file = "pymongo-3.12.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:68409171ab2aa7ccd6e8e839233e4b8ddeec246383c9a3698614e814739356f9"}, - {file = "pymongo-3.12.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13d74bf3435c1e58d8fafccc0d5e87f246ae2c6e9cbef4b35e32a1c3759e354f"}, - {file = "pymongo-3.12.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:849e641cfed05c75d772f9e9018f42c5fbd00655d43d52da1b9c56346fd3e4cc"}, - {file = "pymongo-3.12.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5183b698d6542219e4135de583b57bc6286bd37df7f645b688278eb919bfa785"}, - {file = "pymongo-3.12.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:65f159c445761cab04b665fc448b3fc008aebc98e54fdcbfd1aff195ef1b1408"}, - {file = "pymongo-3.12.1-cp38-cp38-win32.whl", hash = "sha256:3b40e36d3036bfe69ba63ec8e746a390721f75467085a0384b528e1dda532c69"}, - {file = "pymongo-3.12.1-cp38-cp38-win_amd64.whl", hash = "sha256:58a67b3800476232f9989e533d0244060309451b436d46670a53e6d189f1a7e7"}, - {file = "pymongo-3.12.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db3efec9dcecd96555d752215797816da40315d61878f90ca39c8e269791bf17"}, - {file = "pymongo-3.12.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:bfd073fea04061019a103a288847846b5ef40dfa2f73b940ed61e399ca95314f"}, - {file = "pymongo-3.12.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:5067c04d3b19c820faac6342854d887ade58e8d38c3db79b68c2a102bbb100e7"}, - {file = "pymongo-3.12.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:1c4e51a3b69789b6f468a8e881a13f2d1e8f5e99e41f80fd44845e6ec0f701e1"}, - {file = "pymongo-3.12.1-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:2fa101bb23619120673899694a65b094364269e597f551a87c4bdae3a474d726"}, - {file = "pymongo-3.12.1-cp39-cp39-manylinux2014_ppc64le.whl", hash = "sha256:eb65ec0255a0fccc47c87d44e505ef5180bfd71690bd5f84161b1f23949fb209"}, - {file = "pymongo-3.12.1-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:ed751a20840a31242e7bea566fcf93ba75bc11b33afe2777bbf46069c1af5094"}, - {file = "pymongo-3.12.1-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:17238115e6d37f5423b046cb829f1ca02c4ea7edb163f5b8b88e0c975dc3fec9"}, - {file = "pymongo-3.12.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2fda3b3fb5c0d159195ab834b322a23808f1b059bcc7e475765abeddee6a2529"}, - {file = "pymongo-3.12.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6235bf2157aa46e53568ed79b70603aa8874baa202d5d1de82fa0eb917696e73"}, - {file = "pymongo-3.12.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5d6428b8b422ba5205140e8be11722fa7292a0bedaa8bc80fb34c92eb19ba45"}, - {file = "pymongo-3.12.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e6d1cf4bd6552b5f519432cce1530c09e6b0aab98d44803b991f7e880bd332"}, - {file = "pymongo-3.12.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:287c2a0063267c1458c4ddf528b44063ce7f376a6436eea5bccd7f625bbc3b5e"}, - {file = "pymongo-3.12.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4a2d73a9281faefb273a5448f6d25f44ebd311ada9eb79b6801ae890508fe231"}, - {file = "pymongo-3.12.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6f07888e3b73c0dfa46f12d098760494f5f23fd66923a6615edfe486e6a7649c"}, - {file = "pymongo-3.12.1-cp39-cp39-win32.whl", hash = "sha256:77dddf596fb065de29fb39992fbc81301f7fd0003be649b7fa7448c77ca53bed"}, - {file = "pymongo-3.12.1-cp39-cp39-win_amd64.whl", hash = "sha256:979e34db4f3dc5710c18db437aaf282f691092b352e708cb2afd4df287698c76"}, - {file = "pymongo-3.12.1-py2.7-macosx-10.14-intel.egg", hash = "sha256:c04e84ccf590933a266180286d8b6a5fc844078a5d934432628301bd8b5f9ca7"}, - {file = "pymongo-3.12.1.tar.gz", hash = "sha256:704879b6a54c45ad76cea7c6789c1ae7185050acea7afd15b58318fa1932ed45"}, + {file = "pymongo-3.12.3-cp27-cp27m-macosx_10_14_intel.whl", hash = "sha256:c164eda0be9048f83c24b9b2656900041e069ddf72de81c17d874d0c32f6079f"}, + {file = "pymongo-3.12.3-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:a055d29f1302892a9389a382bed10a3f77708bcf3e49bfb76f7712fa5f391cc6"}, + {file = "pymongo-3.12.3-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:8c7ad5cab282f53b9d78d51504330d1c88c83fbe187e472c07e6908a0293142e"}, + {file = "pymongo-3.12.3-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a766157b195a897c64945d4ff87b050bb0e763bb78f3964e996378621c703b00"}, + {file = "pymongo-3.12.3-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:c8d6bf6fcd42cde2f02efb8126812a010c297eacefcd090a609639d2aeda6185"}, + {file = "pymongo-3.12.3-cp27-cp27m-win32.whl", hash = "sha256:5fdffb0cfeb4dc8646a5381d32ec981ae8472f29c695bf09e8f7a8edb2db12ca"}, + {file = "pymongo-3.12.3-cp27-cp27m-win_amd64.whl", hash = "sha256:648fcfd8e019b122b7be0e26830a3a2224d57c3e934f19c1e53a77b8380e6675"}, + {file = "pymongo-3.12.3-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:3f0ac6e0203bd88863649e6ed9c7cfe53afab304bc8225f2597c4c0a74e4d1f0"}, + {file = "pymongo-3.12.3-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:71c0db2c313ea8a80825fb61b7826b8015874aec29ee6364ade5cb774fe4511b"}, + {file = "pymongo-3.12.3-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5b779e87300635b8075e8d5cfd4fdf7f46078cd7610c381d956bca5556bb8f97"}, + {file = "pymongo-3.12.3-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:351a2efe1c9566c348ad0076f4bf541f4905a0ebe2d271f112f60852575f3c16"}, + {file = "pymongo-3.12.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0a02313e71b7c370c43056f6b16c45effbb2d29a44d24403a3d5ba6ed322fa3f"}, + {file = "pymongo-3.12.3-cp310-cp310-manylinux1_i686.whl", hash = "sha256:d3082e5c4d7b388792124f5e805b469109e58f1ab1eb1fbd8b998e8ab766ffb7"}, + {file = "pymongo-3.12.3-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:514e78d20d8382d5b97f32b20c83d1d0452c302c9a135f0a9022236eb9940fda"}, + {file = "pymongo-3.12.3-cp310-cp310-manylinux2014_i686.whl", hash = "sha256:b1b5be40ebf52c3c67ee547e2c4435ed5bc6352f38d23e394520b686641a6be4"}, + {file = "pymongo-3.12.3-cp310-cp310-manylinux2014_ppc64le.whl", hash = "sha256:58db209da08a502ce6948841d522dcec80921d714024354153d00b054571993c"}, + {file = "pymongo-3.12.3-cp310-cp310-manylinux2014_s390x.whl", hash = "sha256:5296e5e69243ffd76bd919854c4da6630ae52e46175c804bc4c0e050d937b705"}, + {file = "pymongo-3.12.3-cp310-cp310-manylinux2014_x86_64.whl", hash = "sha256:51d1d061df3995c2332ae78f036492cc188cb3da8ef122caeab3631a67bb477e"}, + {file = "pymongo-3.12.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:463b974b7f49d65a16ca1435bc1c25a681bb7d630509dd23b2e819ed36da0b7f"}, + {file = "pymongo-3.12.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e099b79ccf7c40f18b149a64d3d10639980035f9ceb223169dd806ff1bb0d9cc"}, + {file = "pymongo-3.12.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:27e5ea64332385385b75414888ce9d1a9806be8616d7cef4ef409f4f256c6d06"}, + {file = "pymongo-3.12.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed7d11330e443aeecab23866055e08a5a536c95d2c25333aeb441af2dbac38d2"}, + {file = "pymongo-3.12.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93111fd4e08fa889c126aa8baf5c009a941880a539c87672e04583286517450a"}, + {file = "pymongo-3.12.3-cp310-cp310-win32.whl", hash = "sha256:2301051701b27aff2cbdf83fae22b7ca883c9563dfd088033267291b46196643"}, + {file = "pymongo-3.12.3-cp310-cp310-win_amd64.whl", hash = "sha256:c7e8221278e5f9e2b6d3893cfc3a3e46c017161a57bb0e6f244826e4cee97916"}, + {file = "pymongo-3.12.3-cp34-cp34m-macosx_10_6_intel.whl", hash = "sha256:7b4a9fcd95e978cd3c96cdc2096aa54705266551422cf0883c12a4044def31c6"}, + {file = "pymongo-3.12.3-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:06b64cdf5121f86b78a84e61b8f899b6988732a8d304b503ea1f94a676221c06"}, + {file = "pymongo-3.12.3-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:c8f7dd025cb0bf19e2f60a64dfc24b513c8330e0cfe4a34ccf941eafd6194d9e"}, + {file = "pymongo-3.12.3-cp34-cp34m-win32.whl", hash = "sha256:ab23b0545ec71ea346bf50a5d376d674f56205b729980eaa62cdb7871805014b"}, + {file = "pymongo-3.12.3-cp34-cp34m-win_amd64.whl", hash = "sha256:1b5cb75d2642ff7db823f509641f143f752c0d1ab03166cafea1e42e50469834"}, + {file = "pymongo-3.12.3-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:fc2048d13ff427605fea328cbe5369dce549b8c7657b0e22051a5b8831170af6"}, + {file = "pymongo-3.12.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:c5f83bb59d0ff60c6fdb1f8a7b0288fbc4640b1f0fd56f5ae2387749c35d34e3"}, + {file = "pymongo-3.12.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:6632b1c63d58cddc72f43ab9f17267354ddce563dd5e11eadabd222dcc808808"}, + {file = "pymongo-3.12.3-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3fedad05147b40ff8a93fcd016c421e6c159f149a2a481cfa0b94bfa3e473bab"}, + {file = "pymongo-3.12.3-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:208a61db8b8b647fb5b1ff3b52b4ed6dbced01eac3b61009958adb203596ee99"}, + {file = "pymongo-3.12.3-cp35-cp35m-win32.whl", hash = "sha256:3100a2352bdded6232b385ceda0c0a4624598c517d52c2d8cf014b7abbebd84d"}, + {file = "pymongo-3.12.3-cp35-cp35m-win_amd64.whl", hash = "sha256:3492ae1f97209c66af70e863e6420e6301cecb0a51a5efa701058aa73a8ca29e"}, + {file = "pymongo-3.12.3-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:87e18f29bac4a6be76a30e74de9c9005475e27100acf0830679420ce1fd9a6fd"}, + {file = "pymongo-3.12.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:b3e08aef4ea05afbc0a70cd23c13684e7f5e074f02450964ec5cfa1c759d33d2"}, + {file = "pymongo-3.12.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:e66b3c9f8b89d4fd58a59c04fdbf10602a17c914fbaaa5e6ea593f1d54b06362"}, + {file = "pymongo-3.12.3-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:5d67dbc8da2dac1644d71c1839d12d12aa333e266a9964d5b1a49feed036bc94"}, + {file = "pymongo-3.12.3-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:a351986d6c9006308f163c359ced40f80b6cffb42069f3e569b979829951038d"}, + {file = "pymongo-3.12.3-cp36-cp36m-manylinux2014_ppc64le.whl", hash = "sha256:5296669bff390135528001b4e48d33a7acaffcd361d98659628ece7f282f11aa"}, + {file = "pymongo-3.12.3-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:9d5b66d457d2c5739c184a777455c8fde7ab3600a56d8bbebecf64f7c55169e1"}, + {file = "pymongo-3.12.3-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:1c771f1a8b3cd2d697baaf57e9cfa4ae42371cacfbea42ea01d9577c06d92f96"}, + {file = "pymongo-3.12.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81a3ebc33b1367f301d1c8eda57eec4868e951504986d5d3fe437479dcdac5b2"}, + {file = "pymongo-3.12.3-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cf113a46d81cff0559d57aa66ffa473d57d1a9496f97426318b6b5b14fdec1c"}, + {file = "pymongo-3.12.3-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:64b9122be1c404ce4eb367ad609b590394587a676d84bfed8e03c3ce76d70560"}, + {file = "pymongo-3.12.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c6c71e198b36f0f0dfe354f06d3655ecfa30d69493a1da125a9a54668aad652"}, + {file = "pymongo-3.12.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33ab8c031f788609924e329003088831045f683931932a52a361d4a955b7dce2"}, + {file = "pymongo-3.12.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e2b4c95c47fb81b19ea77dc1c50d23af3eba87c9628fcc2e03d44124a3d336ea"}, + {file = "pymongo-3.12.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:4e0a3ea7fd01cf0a36509f320226bd8491e0f448f00b8cb89f601c109f6874e1"}, + {file = "pymongo-3.12.3-cp36-cp36m-win32.whl", hash = "sha256:dfec57f15f53d677b8e4535695ff3f37df7f8fe431f2efa8c3c8c4025b53d1eb"}, + {file = "pymongo-3.12.3-cp36-cp36m-win_amd64.whl", hash = "sha256:c22591cff80188dd8543be0b559d0c807f7288bd353dc0bcfe539b4588b3a5cd"}, + {file = "pymongo-3.12.3-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:7738147cd9dbd6d18d5593b3491b4620e13b61de975fd737283e4ad6c255c273"}, + {file = "pymongo-3.12.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:be1f10145f7ea76e3e836fdc5c8429c605675bdcddb0bca9725ee6e26874c00c"}, + {file = "pymongo-3.12.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:295a5beaecb7bf054c1c6a28749ed72b19f4d4b61edcd8a0815d892424baf780"}, + {file = "pymongo-3.12.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:320f8734553c50cffe8a8e1ae36dfc7d7be1941c047489db20a814d2a170d7b5"}, + {file = "pymongo-3.12.3-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:5d20072d81cbfdd8e15e6a0c91fc7e3a4948c71e0adebfc67d3b4bcbe8602711"}, + {file = "pymongo-3.12.3-cp37-cp37m-manylinux2014_ppc64le.whl", hash = "sha256:2c46a0afef69d61938a6fe32c3afd75b91dec3ab3056085dc72abbeedcc94166"}, + {file = "pymongo-3.12.3-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:5f530f35e1a57d4360eddcbed6945aecdaee2a491cd3f17025e7b5f2eea88ee7"}, + {file = "pymongo-3.12.3-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:6526933760ee1e6090db808f1690a111ec409699c1990efc96f134d26925c37f"}, + {file = "pymongo-3.12.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95d15cf81cd2fb926f2a6151a9f94c7aacc102b415e72bc0e040e29332b6731c"}, + {file = "pymongo-3.12.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0d52a70350ec3dfc39b513df12b03b7f4c8f8ec6873bbf958299999db7b05eb1"}, + {file = "pymongo-3.12.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9252c991e8176b5a2fa574c5ab9a841679e315f6e576eb7cf0bd958f3e39b0ad"}, + {file = "pymongo-3.12.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:145d78c345a38011497e55aff22c0f8edd40ee676a6810f7e69563d68a125e83"}, + {file = "pymongo-3.12.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a8e0a086dbbee406cc6f603931dfe54d1cb2fba585758e06a2de01037784b737"}, + {file = "pymongo-3.12.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f6d5443104f89a840250087863c91484a72f254574848e951d1bdd7d8b2ce7c9"}, + {file = "pymongo-3.12.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6f93dbfa5a461107bc3f5026e0d5180499e13379e9404f07a9f79eb5e9e1303d"}, + {file = "pymongo-3.12.3-cp37-cp37m-win32.whl", hash = "sha256:c9d212e2af72d5c8d082775a43eb726520e95bf1c84826440f74225843975136"}, + {file = "pymongo-3.12.3-cp37-cp37m-win_amd64.whl", hash = "sha256:320a1fe403dd83a35709fcf01083d14bc1462e9789b711201349a9158db3a87e"}, + {file = "pymongo-3.12.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a1ba93be779a9b8e5e44f5c133dc1db4313661cead8a2fd27661e6cb8d942ee9"}, + {file = "pymongo-3.12.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:4294f2c1cd069b793e31c2e6d7ac44b121cf7cedccd03ebcc30f3fc3417b314a"}, + {file = "pymongo-3.12.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:845b178bd127bb074835d2eac635b980c58ec5e700ebadc8355062df708d5a71"}, + {file = "pymongo-3.12.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:176fdca18391e1206c32fb1d8265628a84d28333c20ad19468d91e3e98312cd1"}, + {file = "pymongo-3.12.3-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:28bfd5244d32faf3e49b5a8d1fab0631e922c26e8add089312e4be19fb05af50"}, + {file = "pymongo-3.12.3-cp38-cp38-manylinux2014_ppc64le.whl", hash = "sha256:f38b35ecd2628bf0267761ed659e48af7e620a7fcccfccf5774e7308fb18325c"}, + {file = "pymongo-3.12.3-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:cebb3d8bcac4a6b48be65ebbc5c9881ed4a738e27bb96c86d9d7580a1fb09e05"}, + {file = "pymongo-3.12.3-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:80710d7591d579442c67a3bc7ae9dcba9ff95ea8414ac98001198d894fc4ff46"}, + {file = "pymongo-3.12.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89d7baa847383b9814de640c6f1a8553d125ec65e2761ad146ea2e75a7ad197c"}, + {file = "pymongo-3.12.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:602284e652bb56ca8760f8e88a5280636c5b63d7946fca1c2fe0f83c37dffc64"}, + {file = "pymongo-3.12.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bfc2d763d05ec7211313a06e8571236017d3e61d5fef97fcf34ec4b36c0b6556"}, + {file = "pymongo-3.12.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a6e4dccae8ef5dd76052647d78f02d5d0ffaff1856277d951666c54aeba3ad2"}, + {file = "pymongo-3.12.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1fc4d3985868860b6585376e511bb32403c5ffb58b0ed913496c27fd791deea"}, + {file = "pymongo-3.12.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e4e5d163e6644c2bc84dd9f67bfa89288c23af26983d08fefcc2cbc22f6e57e6"}, + {file = "pymongo-3.12.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:8d92c6bb9174d47c2257528f64645a00bbc6324a9ff45a626192797aff01dc14"}, + {file = "pymongo-3.12.3-cp38-cp38-win32.whl", hash = "sha256:b0db9a4691074c347f5d7ee830ab3529bc5ad860939de21c1f9c403daf1eda9a"}, + {file = "pymongo-3.12.3-cp38-cp38-win_amd64.whl", hash = "sha256:d81047341ab56061aa4b6823c54d4632579c3b16e675089e8f520e9b918a133b"}, + {file = "pymongo-3.12.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:07398d8a03545b98282f459f2603a6bb271f4448d484ed7f411121a519a7ea48"}, + {file = "pymongo-3.12.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:b7df0d99e189b7027d417d4bfd9b8c53c9c7ed5a0a1495d26a6f547d820eca88"}, + {file = "pymongo-3.12.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:a283425e6a474facd73072d8968812d1d9058490a5781e022ccf8895500b83ce"}, + {file = "pymongo-3.12.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:2577b8161eeae4dd376d13100b2137d883c10bb457dd08935f60c9f9d4b5c5f6"}, + {file = "pymongo-3.12.3-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:517b09b1dd842390a965a896d1327c55dfe78199c9f5840595d40facbcd81854"}, + {file = "pymongo-3.12.3-cp39-cp39-manylinux2014_ppc64le.whl", hash = "sha256:2567885ff0c8c7c0887ba6cefe4ae4af96364a66a7069f924ce0cd12eb971d04"}, + {file = "pymongo-3.12.3-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:71c5c200fd37a5322706080b09c3ec8907cf01c377a7187f354fc9e9e13abc73"}, + {file = "pymongo-3.12.3-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:14dee106a10b77224bba5efeeb6aee025aabe88eb87a2b850c46d3ee55bdab4a"}, + {file = "pymongo-3.12.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f340a2a908644ea6cccd399be0fb308c66e05d2800107345f9f0f0d59e1731c4"}, + {file = "pymongo-3.12.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1b4c535f524c9d8c86c3afd71d199025daa070859a2bdaf94a298120b0de16db"}, + {file = "pymongo-3.12.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8455176fd1b86de97d859fed4ae0ef867bf998581f584c7a1a591246dfec330f"}, + {file = "pymongo-3.12.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf254a1a95e95fdf4eaa25faa1ea450a6533ed7a997f9f8e49ab971b61ea514d"}, + {file = "pymongo-3.12.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a8a3540e21213cb8ce232e68a7d0ee49cdd35194856c50b8bd87eeb572fadd42"}, + {file = "pymongo-3.12.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0e7a5d0b9077e8c3e57727f797ee8adf12e1d5e7534642230d98980d160d1320"}, + {file = "pymongo-3.12.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:0be605bfb8461384a4cb81e80f51eb5ca1b89851f2d0e69a75458c788a7263a4"}, + {file = "pymongo-3.12.3-cp39-cp39-win32.whl", hash = "sha256:2157d68f85c28688e8b723bbe70c8013e0aba5570e08c48b3562f74d33fc05c4"}, + {file = "pymongo-3.12.3-cp39-cp39-win_amd64.whl", hash = "sha256:dfa217bf8cf3ff6b30c8e6a89014e0c0e7b50941af787b970060ae5ba04a4ce5"}, + {file = "pymongo-3.12.3-py2.7-macosx-10.14-intel.egg", hash = "sha256:d81299f63dc33cc172c26faf59cc54dd795fc6dd5821a7676cca112a5ee8bbd6"}, + {file = "pymongo-3.12.3.tar.gz", hash = "sha256:0a89cadc0062a5e53664dde043f6c097172b8c1c5f0094490095282ff9995a5f"}, ] pynacl = [ - {file = "PyNaCl-1.4.0-cp27-cp27m-macosx_10_10_x86_64.whl", hash = "sha256:ea6841bc3a76fa4942ce00f3bda7d436fda21e2d91602b9e21b7ca9ecab8f3ff"}, - {file = "PyNaCl-1.4.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:d452a6746f0a7e11121e64625109bc4468fc3100452817001dbe018bb8b08514"}, - {file = "PyNaCl-1.4.0-cp27-cp27m-win32.whl", hash = "sha256:2fe0fc5a2480361dcaf4e6e7cea00e078fcda07ba45f811b167e3f99e8cff574"}, - {file = "PyNaCl-1.4.0-cp27-cp27m-win_amd64.whl", hash = "sha256:f8851ab9041756003119368c1e6cd0b9c631f46d686b3904b18c0139f4419f80"}, - {file = "PyNaCl-1.4.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:7757ae33dae81c300487591c68790dfb5145c7d03324000433d9a2c141f82af7"}, - {file = "PyNaCl-1.4.0-cp35-abi3-macosx_10_10_x86_64.whl", hash = "sha256:757250ddb3bff1eecd7e41e65f7f833a8405fede0194319f87899690624f2122"}, - {file = "PyNaCl-1.4.0-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:30f9b96db44e09b3304f9ea95079b1b7316b2b4f3744fe3aaecccd95d547063d"}, - {file = "PyNaCl-1.4.0-cp35-abi3-win32.whl", hash = "sha256:4e10569f8cbed81cb7526ae137049759d2a8d57726d52c1a000a3ce366779634"}, - {file = "PyNaCl-1.4.0-cp35-abi3-win_amd64.whl", hash = "sha256:c914f78da4953b33d4685e3cdc7ce63401247a21425c16a39760e282075ac4a6"}, - {file = "PyNaCl-1.4.0-cp35-cp35m-win32.whl", hash = "sha256:06cbb4d9b2c4bd3c8dc0d267416aaed79906e7b33f114ddbf0911969794b1cc4"}, - {file = "PyNaCl-1.4.0-cp35-cp35m-win_amd64.whl", hash = "sha256:511d269ee845037b95c9781aa702f90ccc36036f95d0f31373a6a79bd8242e25"}, - {file = "PyNaCl-1.4.0-cp36-cp36m-win32.whl", hash = "sha256:11335f09060af52c97137d4ac54285bcb7df0cef29014a1a4efe64ac065434c4"}, - {file = "PyNaCl-1.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:cd401ccbc2a249a47a3a1724c2918fcd04be1f7b54eb2a5a71ff915db0ac51c6"}, - {file = "PyNaCl-1.4.0-cp37-cp37m-win32.whl", hash = "sha256:8122ba5f2a2169ca5da936b2e5a511740ffb73979381b4229d9188f6dcb22f1f"}, - {file = "PyNaCl-1.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:537a7ccbea22905a0ab36ea58577b39d1fa9b1884869d173b5cf111f006f689f"}, - {file = "PyNaCl-1.4.0-cp38-cp38-win32.whl", hash = "sha256:9c4a7ea4fb81536c1b1f5cc44d54a296f96ae78c1ebd2311bd0b60be45a48d96"}, - {file = "PyNaCl-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:7c6092102219f59ff29788860ccb021e80fffd953920c4a8653889c029b2d420"}, - {file = "PyNaCl-1.4.0.tar.gz", hash = "sha256:54e9a2c849c742006516ad56a88f5c74bf2ce92c9f67435187c3c5953b346505"}, + {file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858"}, + {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b"}, + {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff"}, + {file = "PyNaCl-1.5.0-cp36-abi3-win32.whl", hash = "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543"}, + {file = "PyNaCl-1.5.0-cp36-abi3-win_amd64.whl", hash = "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93"}, + {file = "PyNaCl-1.5.0.tar.gz", hash = "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba"}, ] pynput = [ - {file = "pynput-1.7.4-py2.py3-none-any.whl", hash = "sha256:f78502cb2abd101721d867451bf315a4e1334666372f8682651393f16e1d2d9b"}, - {file = "pynput-1.7.4-py3.9.egg", hash = "sha256:225926bf5e98d36738911112c72e19e0cba830aafee3882ef8661c8d9cfb3b63"}, - {file = "pynput-1.7.4.tar.gz", hash = "sha256:16fecc4d1e53a28fb7c669c79e189c3f2cde14a08d6b457c3da07075c82f3b4c"}, + {file = "pynput-1.7.6-py2.py3-none-any.whl", hash = "sha256:19861b2a0c430d646489852f89500e0c9332e295f2c020e7c2775e7046aa2e2f"}, + {file = "pynput-1.7.6-py3.9.egg", hash = "sha256:264429fbe676e98e9050ad26a7017453bdd08768adb25cafb918347cf9f1eb4a"}, + {file = "pynput-1.7.6.tar.gz", hash = "sha256:3a5726546da54116b687785d38b1db56997ce1d28e53e8d22fc656d8b92e533c"}, ] pyobjc-core = [ - {file = "pyobjc-core-7.3.tar.gz", hash = "sha256:5081aedf8bb40aac1a8ad95adac9e44e148a882686ded614adf46bb67fd67574"}, - {file = "pyobjc_core-7.3-1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a1f1e6b457127cbf2b5bd2b94520a7c89fb590b739911eadb2b0499a3a5b0e6f"}, - {file = "pyobjc_core-7.3-1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:ed708cc47bae8b711f81f252af09898a5f986c7a38cec5ad5623d571d328bff8"}, - {file = "pyobjc_core-7.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4e93ad769a20b908778fe950f62a843a6d8f0fa71996e5f3cc9fab5ae7d17771"}, - {file = "pyobjc_core-7.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9f63fd37bbf3785af4ddb2f86cad5ca81c62cfc7d1c0099637ca18343c3656c1"}, - {file = "pyobjc_core-7.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e9b1311f72f2e170742a7ee3a8149f52c35158dc024a21e88d6f1e52ba5d718b"}, - {file = "pyobjc_core-7.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8d5e12a0729dfd1d998a861998b422d0a3e41923d75ea229bacf31372c831d7b"}, - {file = "pyobjc_core-7.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:efdee8c4884405e0c0186c57f87d7bfaa0abc1f50b18e865db3caea3a1f329b9"}, + {file = "pyobjc-core-8.2.tar.gz", hash = "sha256:6afb8ee1dd0647cbfaaf99906eca3b43ce045b27e3d4510462d04e7e5361c89b"}, + {file = "pyobjc_core-8.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:311e45556c3afa8831713b89017e0204562f51f35661d76c07ffe04985f44e1d"}, + {file = "pyobjc_core-8.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:711f361e83382e405e4273ff085178b0cf730901ccf6801f834e7037e50278f9"}, + {file = "pyobjc_core-8.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:bdd2e2960ec73214bcfe2d86bb4ca94f5f5119db86d129fa32d3c003b6532c50"}, + {file = "pyobjc_core-8.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b879f91fc614c399aafa1d08cf5e279c267510e904bad5c336c3a6064c0eb3aa"}, + {file = "pyobjc_core-8.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:b4ef4bdb99a330f5e15cc6273098964276fccbc432453cdba3c2963292bc066c"}, + {file = "pyobjc_core-8.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:fd8e5be0955790ff8f9d17a0f356b6eb7eb1ce4995e0c94355c462dd52d22d6d"}, ] pyobjc-framework-applicationservices = [ - {file = "pyobjc-framework-ApplicationServices-7.3.tar.gz", hash = "sha256:1925ac30a817e557d1c08450005103bbf76ebd3ff473631fe9875070377b0b4d"}, - {file = "pyobjc_framework_ApplicationServices-7.3-1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:484e5b5e9f1757ad7e28799bb5d5d59ce861a3e5449f06fc3a0d05b998e9e6bb"}, - {file = "pyobjc_framework_ApplicationServices-7.3-1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:ec0c07775ff7034751306fa382117d12ae8e383b696cda1b2815dfd334c36ff7"}, - {file = "pyobjc_framework_ApplicationServices-7.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:daa4a9c51a927630fdd3d3f627e03ebc370aee3c397305db85a0a8ba4c28ae93"}, - {file = "pyobjc_framework_ApplicationServices-7.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:167aa21ee47b0ee6e4e399915371d183ae84880dc3813c27519e759acb9d20c9"}, - {file = "pyobjc_framework_ApplicationServices-7.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7a98f0f1e21465868f9dd32588ae71e5e6a4cb5c434d4158c9e12273fd7b8f27"}, - {file = "pyobjc_framework_ApplicationServices-7.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2d55796610e6293e83cc40183347e7f75a7c0682775cc19e5986945efa9cac1b"}, - {file = "pyobjc_framework_ApplicationServices-7.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:afd1ef147447fe7b06a271458eabb37ece6436705abf86265d7fb57310eca45f"}, + {file = "pyobjc-framework-ApplicationServices-8.2.tar.gz", hash = "sha256:f901b2ebb278b7d00033b45cf9ee9d43f651e096ff4c4defa261509238138da8"}, + {file = "pyobjc_framework_ApplicationServices-8.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b5be1757a8df944a58449c628ed68fc76dd746fcd1e96ebb6db0f734e94cdfc8"}, + {file = "pyobjc_framework_ApplicationServices-8.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:32657c4b89983a98fbe831a14884954710719e763197968a20ac07e1daa21f1e"}, + {file = "pyobjc_framework_ApplicationServices-8.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6ce2c9701590f752a75151b2fe1e462e7a7ad67dec3119a796711ea93ea01031"}, + {file = "pyobjc_framework_ApplicationServices-8.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:28124bc892045222305cf8953b163495bf662c401e54f48905dafb1104d9c1d1"}, + {file = "pyobjc_framework_ApplicationServices-8.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:d5c60d66c6ed2569cb042a6c14dd5b9f4d01e182a464b893cd6002ce445b4ddf"}, + {file = "pyobjc_framework_ApplicationServices-8.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e1727fccc1d48922fa28a4cebf4a6d287d633f451cb03779968df60de8cb1bd0"}, ] pyobjc-framework-cocoa = [ - {file = "pyobjc-framework-Cocoa-7.3.tar.gz", hash = "sha256:b18d05e7a795a3455ad191c3e43d6bfa673c2a4fd480bb1ccf57191051b80b7e"}, - {file = "pyobjc_framework_Cocoa-7.3-1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1e31376806e5de883a1d7c7c87d9ff2a8b09fc05d267e0dfce6e42409fb70c67"}, - {file = "pyobjc_framework_Cocoa-7.3-1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:d999387927284346035cb63ebb51f86331abc41f9376f9a6970e7f18207db392"}, - {file = "pyobjc_framework_Cocoa-7.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:9edffdfa6dd1f71f21b531c3e61fdd3e4d5d3bf6c5a528c98e88828cd60bac11"}, - {file = "pyobjc_framework_Cocoa-7.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:35a6340437a4e0109a302150b7d1f6baf57004ccf74834f9e6062fcafe2fd8d7"}, - {file = "pyobjc_framework_Cocoa-7.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7c3886f2608ab3ed02482f8b2ebf9f782b324c559e84b52cfd92dba8a1109872"}, - {file = "pyobjc_framework_Cocoa-7.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2e8e7a1a82cca21d9bfac9115baf065305f3da577bf240085964dfb9c9fff337"}, - {file = "pyobjc_framework_Cocoa-7.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6c15f43077c9a2ba1853eb402ff7a9515df9e584315bc2fcb779d4c95ef46dc5"}, + {file = "pyobjc-framework-Cocoa-8.2.tar.gz", hash = "sha256:f0901998e2f18415ef6d1f8a12b083f69fc93bd56b3e88040002e3c09bd8c304"}, + {file = "pyobjc_framework_Cocoa-8.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5af73f150e242542735e0663bb5504f88aabaec2a54c60e856cfca3ff6dd9712"}, + {file = "pyobjc_framework_Cocoa-8.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d1de3763ee01850c311da74de5c82c85ec199120e85ab45acaf203accc37a470"}, + {file = "pyobjc_framework_Cocoa-8.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:86d69bf667f99f3c43184d8830567195fff94c675fe7f60f899dd90553d9b265"}, + {file = "pyobjc_framework_Cocoa-8.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9dbadb22826392c48b00087359f66579f8404a4f4f77498f31f9869c54bb0fa9"}, + {file = "pyobjc_framework_Cocoa-8.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:7adf8b57da1c1292c24375b8e74b6dd45f99a4d3c10ba925a9b38f63a97ba782"}, + {file = "pyobjc_framework_Cocoa-8.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bc8279c8c1544087d46a7e99324f093029df89b8c527c5da2a682bad4cb3197e"}, ] pyobjc-framework-quartz = [ - {file = "pyobjc-framework-Quartz-7.3.tar.gz", hash = "sha256:98812844c34262def980bdf60923a875cd43428a8375b6fd53bd2cd800eccf0b"}, - {file = "pyobjc_framework_Quartz-7.3-1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1139bc6874c0f8b58f0b8602015e0994198bc506a6bcec1071208de32b55ed26"}, - {file = "pyobjc_framework_Quartz-7.3-1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:d94a3ed7051266c52392ec07d3b5adbf28d4be83341a24df0d88639344dcd84f"}, - {file = "pyobjc_framework_Quartz-7.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1ef18f5a16511ded65980bf4f5983ea5d35c88224dbad1b3112abd29c60413ea"}, - {file = "pyobjc_framework_Quartz-7.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3b41eec8d4b10c7c7e011e2f9051367f5499ef315ba52dfbae573c3a2e05469c"}, - {file = "pyobjc_framework_Quartz-7.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c65456ed045dfe1711d0298734e5a3ad670f8c770f7eb3b19979256c388bdd2"}, - {file = "pyobjc_framework_Quartz-7.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8ddbca6b466584c3dc0e5b701b1c2a9b5d97ddc1d79a949927499ebb1be1f210"}, - {file = "pyobjc_framework_Quartz-7.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7aba3cd966a0768dd58a35680742820f0c5ac596a9cd11014e2057818e65b0af"}, + {file = "pyobjc-framework-Quartz-8.2.tar.gz", hash = "sha256:219d8797235bf071723f8b0f30a681de0b12875e2d04ae902a3a269f72de0b66"}, + {file = "pyobjc_framework_Quartz-8.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e5ab3117201a494b11bb1b80febf5dd288111a196b35731815b656ae30ee6ce3"}, + {file = "pyobjc_framework_Quartz-8.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:4941b3039ab7bcf89cb4255c381358de2383c1ab45c9e00c3b64655f271a3b32"}, + {file = "pyobjc_framework_Quartz-8.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:ab75a50dea84ec794641522d9f035fc6c19ec4eb37a56c9186b9943575fbc7ab"}, + {file = "pyobjc_framework_Quartz-8.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8cb687b20ebfc467034868b38945b573d1c50f237e379cf86c4f557c9766b759"}, + {file = "pyobjc_framework_Quartz-8.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:8b5c3ca1fef900fa66aafe82fff07bc352c60ea7dceed2bb9b5b1db0957b4fea"}, + {file = "pyobjc_framework_Quartz-8.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7bca7e649da77056348d71032def44e345043319d71b0c592197888d92e3eec1"}, ] pyparsing = [ {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, ] pyrsistent = [ - {file = "pyrsistent-0.18.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f4c8cabb46ff8e5d61f56a037974228e978f26bfefce4f61a4b1ac0ba7a2ab72"}, - {file = "pyrsistent-0.18.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:da6e5e818d18459fa46fac0a4a4e543507fe1110e808101277c5a2b5bab0cd2d"}, - {file = "pyrsistent-0.18.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:5e4395bbf841693eaebaa5bb5c8f5cdbb1d139e07c975c682ec4e4f8126e03d2"}, - {file = "pyrsistent-0.18.0-cp36-cp36m-win32.whl", hash = "sha256:527be2bfa8dc80f6f8ddd65242ba476a6c4fb4e3aedbf281dfbac1b1ed4165b1"}, - {file = "pyrsistent-0.18.0-cp36-cp36m-win_amd64.whl", hash = "sha256:2aaf19dc8ce517a8653746d98e962ef480ff34b6bc563fc067be6401ffb457c7"}, - {file = "pyrsistent-0.18.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58a70d93fb79dc585b21f9d72487b929a6fe58da0754fa4cb9f279bb92369396"}, - {file = "pyrsistent-0.18.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:4916c10896721e472ee12c95cdc2891ce5890898d2f9907b1b4ae0f53588b710"}, - {file = "pyrsistent-0.18.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:73ff61b1411e3fb0ba144b8f08d6749749775fe89688093e1efef9839d2dcc35"}, - {file = "pyrsistent-0.18.0-cp37-cp37m-win32.whl", hash = "sha256:b29b869cf58412ca5738d23691e96d8aff535e17390128a1a52717c9a109da4f"}, - {file = "pyrsistent-0.18.0-cp37-cp37m-win_amd64.whl", hash = "sha256:097b96f129dd36a8c9e33594e7ebb151b1515eb52cceb08474c10a5479e799f2"}, - {file = "pyrsistent-0.18.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:772e94c2c6864f2cd2ffbe58bb3bdefbe2a32afa0acb1a77e472aac831f83427"}, - {file = "pyrsistent-0.18.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:c1a9ff320fa699337e05edcaae79ef8c2880b52720bc031b219e5b5008ebbdef"}, - {file = "pyrsistent-0.18.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:cd3caef37a415fd0dae6148a1b6957a8c5f275a62cca02e18474608cb263640c"}, - {file = "pyrsistent-0.18.0-cp38-cp38-win32.whl", hash = "sha256:e79d94ca58fcafef6395f6352383fa1a76922268fa02caa2272fff501c2fdc78"}, - {file = "pyrsistent-0.18.0-cp38-cp38-win_amd64.whl", hash = "sha256:a0c772d791c38bbc77be659af29bb14c38ced151433592e326361610250c605b"}, - {file = "pyrsistent-0.18.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d5ec194c9c573aafaceebf05fc400656722793dac57f254cd4741f3c27ae57b4"}, - {file = "pyrsistent-0.18.0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:6b5eed00e597b5b5773b4ca30bd48a5774ef1e96f2a45d105db5b4ebb4bca680"}, - {file = "pyrsistent-0.18.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:48578680353f41dca1ca3dc48629fb77dfc745128b56fc01096b2530c13fd426"}, - {file = "pyrsistent-0.18.0-cp39-cp39-win32.whl", hash = "sha256:f3ef98d7b76da5eb19c37fda834d50262ff9167c65658d1d8f974d2e4d90676b"}, - {file = "pyrsistent-0.18.0-cp39-cp39-win_amd64.whl", hash = "sha256:404e1f1d254d314d55adb8d87f4f465c8693d6f902f67eb6ef5b4526dc58e6ea"}, - {file = "pyrsistent-0.18.0.tar.gz", hash = "sha256:773c781216f8c2900b42a7b638d5b517bb134ae1acbebe4d1e8f1f41ea60eb4b"}, + {file = "pyrsistent-0.18.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:df46c854f490f81210870e509818b729db4488e1f30f2a1ce1698b2295a878d1"}, + {file = "pyrsistent-0.18.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d45866ececf4a5fff8742c25722da6d4c9e180daa7b405dc0a2a2790d668c26"}, + {file = "pyrsistent-0.18.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4ed6784ceac462a7d6fcb7e9b663e93b9a6fb373b7f43594f9ff68875788e01e"}, + {file = "pyrsistent-0.18.1-cp310-cp310-win32.whl", hash = "sha256:e4f3149fd5eb9b285d6bfb54d2e5173f6a116fe19172686797c056672689daf6"}, + {file = "pyrsistent-0.18.1-cp310-cp310-win_amd64.whl", hash = "sha256:636ce2dc235046ccd3d8c56a7ad54e99d5c1cd0ef07d9ae847306c91d11b5fec"}, + {file = "pyrsistent-0.18.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e92a52c166426efbe0d1ec1332ee9119b6d32fc1f0bbfd55d5c1088070e7fc1b"}, + {file = "pyrsistent-0.18.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7a096646eab884bf8bed965bad63ea327e0d0c38989fc83c5ea7b8a87037bfc"}, + {file = "pyrsistent-0.18.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cdfd2c361b8a8e5d9499b9082b501c452ade8bbf42aef97ea04854f4a3f43b22"}, + {file = "pyrsistent-0.18.1-cp37-cp37m-win32.whl", hash = "sha256:7ec335fc998faa4febe75cc5268a9eac0478b3f681602c1f27befaf2a1abe1d8"}, + {file = "pyrsistent-0.18.1-cp37-cp37m-win_amd64.whl", hash = "sha256:6455fc599df93d1f60e1c5c4fe471499f08d190d57eca040c0ea182301321286"}, + {file = "pyrsistent-0.18.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fd8da6d0124efa2f67d86fa70c851022f87c98e205f0594e1fae044e7119a5a6"}, + {file = "pyrsistent-0.18.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bfe2388663fd18bd8ce7db2c91c7400bf3e1a9e8bd7d63bf7e77d39051b85ec"}, + {file = "pyrsistent-0.18.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e3e1fcc45199df76053026a51cc59ab2ea3fc7c094c6627e93b7b44cdae2c8c"}, + {file = "pyrsistent-0.18.1-cp38-cp38-win32.whl", hash = "sha256:b568f35ad53a7b07ed9b1b2bae09eb15cdd671a5ba5d2c66caee40dbf91c68ca"}, + {file = "pyrsistent-0.18.1-cp38-cp38-win_amd64.whl", hash = "sha256:d1b96547410f76078eaf66d282ddca2e4baae8964364abb4f4dcdde855cd123a"}, + {file = "pyrsistent-0.18.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f87cc2863ef33c709e237d4b5f4502a62a00fab450c9e020892e8e2ede5847f5"}, + {file = "pyrsistent-0.18.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bc66318fb7ee012071b2792024564973ecc80e9522842eb4e17743604b5e045"}, + {file = "pyrsistent-0.18.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:914474c9f1d93080338ace89cb2acee74f4f666fb0424896fcfb8d86058bf17c"}, + {file = "pyrsistent-0.18.1-cp39-cp39-win32.whl", hash = "sha256:1b34eedd6812bf4d33814fca1b66005805d3640ce53140ab8bbb1e2651b0d9bc"}, + {file = "pyrsistent-0.18.1-cp39-cp39-win_amd64.whl", hash = "sha256:e24a828f57e0c337c8d8bb9f6b12f09dfdf0273da25fda9e314f0b684b415a07"}, + {file = "pyrsistent-0.18.1.tar.gz", hash = "sha256:d4d61f8b993a7255ba714df3aca52700f8125289f84f704cf80916517c46eb96"}, ] pysftp = [ {file = "pysftp-0.2.9.tar.gz", hash = "sha256:fbf55a802e74d663673400acd92d5373c1c7ee94d765b428d9f977567ac4854a"}, @@ -2503,8 +2613,8 @@ pytest-cov = [ {file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"}, ] pytest-print = [ - {file = "pytest_print-0.3.0-py2.py3-none-any.whl", hash = "sha256:53fb0f71d371f137ac2e7171d92f204eb45055580e8c7920df619d9b2ee45359"}, - {file = "pytest_print-0.3.0.tar.gz", hash = "sha256:769f1b1b0943b2941dbeeaac6985766e76b341130ed538f88c23ebcd7087b90d"}, + {file = "pytest_print-0.3.1-py2.py3-none-any.whl", hash = "sha256:3be6c66e4b23e53b489edfdf16857da9adf2c309dcc7c6fea01ae2ce3c7542ed"}, + {file = "pytest_print-0.3.1.tar.gz", hash = "sha256:60457fbef7ce49936484a65ee6fd5f8dc95a1309f2c9ea707f98324d92e8527b"}, ] python-dateutil = [ {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, @@ -2550,8 +2660,8 @@ requests = [ {file = "requests-2.25.1.tar.gz", hash = "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804"}, ] rsa = [ - {file = "rsa-4.7.2-py3-none-any.whl", hash = "sha256:78f9a9bf4e7be0c5ded4583326e7461e3a3c5aae24073648b4bdfa797d78c9d2"}, - {file = "rsa-4.7.2.tar.gz", hash = "sha256:9d689e6ca1b3038bc82bf8d23e944b6b6037bc02301a574935b2dd946e0353b9"}, + {file = "rsa-4.8-py3-none-any.whl", hash = "sha256:95c5d300c4e879ee69708c428ba566c59478fd653cc3a22243eeb8ed846950bb"}, + {file = "rsa-4.8.tar.gz", hash = "sha256:5c6bd9dc7a543b7fe4304a631f8a8a3b674e2bbfc49c2ae96200cdbe55df6b17"}, ] secretstorage = [ {file = "SecretStorage-3.3.1-py3-none-any.whl", hash = "sha256:422d82c36172d88d6a0ed5afdec956514b189ddbfb72fefab0c8a1cee4eaf71f"}, @@ -2566,16 +2676,16 @@ six = [ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] slack-sdk = [ - {file = "slack_sdk-3.11.2-py2.py3-none-any.whl", hash = "sha256:35245ec34c8549fbb5c43ccc17101afd725b3508bb784da46530b214f496bf93"}, - {file = "slack_sdk-3.11.2.tar.gz", hash = "sha256:131bf605894525c2d66da064677eabc19f53f02ce0f82a3f2fa130d4ec3bc1b0"}, + {file = "slack_sdk-3.13.0-py2.py3-none-any.whl", hash = "sha256:54f2a5f7419f1ab932af9e3200f7f2f93db96e0f0eb8ad7d3b4214aa9f124641"}, + {file = "slack_sdk-3.13.0.tar.gz", hash = "sha256:aae6ce057e286a5e7fe7a9f256e85b886eee556def8e04b82b08f699e64d7f67"}, ] smmap = [ {file = "smmap-5.0.0-py3-none-any.whl", hash = "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94"}, {file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"}, ] snowballstemmer = [ - {file = "snowballstemmer-2.1.0-py2.py3-none-any.whl", hash = "sha256:b51b447bea85f9968c13b650126a888aabd4cb4463fca868ec596826325dedc2"}, - {file = "snowballstemmer-2.1.0.tar.gz", hash = "sha256:e997baa4f2e9139951b6f4c631bad912dfd3c792467e2f03d7239464af90e914"}, + {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, + {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, ] speedcopy = [ {file = "speedcopy-2.1.2-py3-none-any.whl", hash = "sha256:91e271b84c00952812dbf669d360b2610fd8fa198670373e02acf2a04db89a4c"}, @@ -2622,9 +2732,9 @@ sphinxcontrib-websupport = [ {file = "sphinxcontrib_websupport-1.2.4-py2.py3-none-any.whl", hash = "sha256:6fc9287dfc823fe9aa432463edd6cea47fa9ebbf488d7f289b322ffcfca075c7"}, ] stone = [ - {file = "stone-3.2.1-py2-none-any.whl", hash = "sha256:2a50866528f60cc7cedd010def733e8ae9d581d17f967278a08059bffaea3c57"}, - {file = "stone-3.2.1-py3-none-any.whl", hash = "sha256:76235137c09ee88aa53e8c1e666819f6c20ac8064c4ac6c4ee4194eac0e3b7af"}, - {file = "stone-3.2.1.tar.gz", hash = "sha256:9bc78b40143b4ef33bf569e515408c2996ffebefbb1a897616ebe8aa6f2d7e75"}, + {file = "stone-3.3.1-py2-none-any.whl", hash = "sha256:cd2f7f9056fc39b16c8fd46a26971dc5ccd30b5c2c246566cd2c0dd27ff96609"}, + {file = "stone-3.3.1-py3-none-any.whl", hash = "sha256:e15866fad249c11a963cce3bdbed37758f2e88c8ff4898616bc0caeb1e216047"}, + {file = "stone-3.3.1.tar.gz", hash = "sha256:4ef0397512f609757975f7ec09b35639d72ba7e3e17ce4ddf399578346b4cb50"}, ] termcolor = [ {file = "termcolor-1.1.0.tar.gz", hash = "sha256:1d6d69ce66211143803fbc56652b41d73b4a400a2891d7bf7a1cdf4c02de613b"}, @@ -2634,53 +2744,46 @@ toml = [ {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, ] tomli = [ - {file = "tomli-1.2.2-py3-none-any.whl", hash = "sha256:f04066f68f5554911363063a30b108d2b5a5b1a010aa8b6132af78489fe3aade"}, - {file = "tomli-1.2.2.tar.gz", hash = "sha256:c6ce0015eb38820eaf32b5db832dbc26deb3dd427bd5f6556cf0acac2c214fee"}, + {file = "tomli-2.0.0-py3-none-any.whl", hash = "sha256:b5bde28da1fed24b9bd1d4d2b8cba62300bfb4ec9a6187a957e8ddb9434c5224"}, + {file = "tomli-2.0.0.tar.gz", hash = "sha256:c292c34f58502a1eb2bbb9f5bbc9a5ebc37bee10ffb8c2d6bbdfa8eb13cc14e1"}, ] typed-ast = [ - {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:2068531575a125b87a41802130fa7e29f26c09a2833fea68d9a40cf33902eba6"}, - {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:c907f561b1e83e93fad565bac5ba9c22d96a54e7ea0267c708bffe863cbe4075"}, - {file = "typed_ast-1.4.3-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:1b3ead4a96c9101bef08f9f7d1217c096f31667617b58de957f690c92378b528"}, - {file = "typed_ast-1.4.3-cp35-cp35m-win32.whl", hash = "sha256:dde816ca9dac1d9c01dd504ea5967821606f02e510438120091b84e852367428"}, - {file = "typed_ast-1.4.3-cp35-cp35m-win_amd64.whl", hash = "sha256:777a26c84bea6cd934422ac2e3b78863a37017618b6e5c08f92ef69853e765d3"}, - {file = "typed_ast-1.4.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f8afcf15cc511ada719a88e013cec87c11aff7b91f019295eb4530f96fe5ef2f"}, - {file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:52b1eb8c83f178ab787f3a4283f68258525f8d70f778a2f6dd54d3b5e5fb4341"}, - {file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:01ae5f73431d21eead5015997ab41afa53aa1fbe252f9da060be5dad2c730ace"}, - {file = "typed_ast-1.4.3-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:c190f0899e9f9f8b6b7863debfb739abcb21a5c054f911ca3596d12b8a4c4c7f"}, - {file = "typed_ast-1.4.3-cp36-cp36m-win32.whl", hash = "sha256:398e44cd480f4d2b7ee8d98385ca104e35c81525dd98c519acff1b79bdaac363"}, - {file = "typed_ast-1.4.3-cp36-cp36m-win_amd64.whl", hash = "sha256:bff6ad71c81b3bba8fa35f0f1921fb24ff4476235a6e94a26ada2e54370e6da7"}, - {file = "typed_ast-1.4.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0fb71b8c643187d7492c1f8352f2c15b4c4af3f6338f21681d3681b3dc31a266"}, - {file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:760ad187b1041a154f0e4d0f6aae3e40fdb51d6de16e5c99aedadd9246450e9e"}, - {file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5feca99c17af94057417d744607b82dd0a664fd5e4ca98061480fd8b14b18d04"}, - {file = "typed_ast-1.4.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:95431a26309a21874005845c21118c83991c63ea800dd44843e42a916aec5899"}, - {file = "typed_ast-1.4.3-cp37-cp37m-win32.whl", hash = "sha256:aee0c1256be6c07bd3e1263ff920c325b59849dc95392a05f258bb9b259cf39c"}, - {file = "typed_ast-1.4.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9ad2c92ec681e02baf81fdfa056fe0d818645efa9af1f1cd5fd6f1bd2bdfd805"}, - {file = "typed_ast-1.4.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b36b4f3920103a25e1d5d024d155c504080959582b928e91cb608a65c3a49e1a"}, - {file = "typed_ast-1.4.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:067a74454df670dcaa4e59349a2e5c81e567d8d65458d480a5b3dfecec08c5ff"}, - {file = "typed_ast-1.4.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7538e495704e2ccda9b234b82423a4038f324f3a10c43bc088a1636180f11a41"}, - {file = "typed_ast-1.4.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:af3d4a73793725138d6b334d9d247ce7e5f084d96284ed23f22ee626a7b88e39"}, - {file = "typed_ast-1.4.3-cp38-cp38-win32.whl", hash = "sha256:f2362f3cb0f3172c42938946dbc5b7843c2a28aec307c49100c8b38764eb6927"}, - {file = "typed_ast-1.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:dd4a21253f42b8d2b48410cb31fe501d32f8b9fbeb1f55063ad102fe9c425e40"}, - {file = "typed_ast-1.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f328adcfebed9f11301eaedfa48e15bdece9b519fb27e6a8c01aa52a17ec31b3"}, - {file = "typed_ast-1.4.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:2c726c276d09fc5c414693a2de063f521052d9ea7c240ce553316f70656c84d4"}, - {file = "typed_ast-1.4.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:cae53c389825d3b46fb37538441f75d6aecc4174f615d048321b716df2757fb0"}, - {file = "typed_ast-1.4.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b9574c6f03f685070d859e75c7f9eeca02d6933273b5e69572e5ff9d5e3931c3"}, - {file = "typed_ast-1.4.3-cp39-cp39-win32.whl", hash = "sha256:209596a4ec71d990d71d5e0d312ac935d86930e6eecff6ccc7007fe54d703808"}, - {file = "typed_ast-1.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:9c6d1a54552b5330bc657b7ef0eae25d00ba7ffe85d9ea8ae6540d2197a3788c"}, - {file = "typed_ast-1.4.3.tar.gz", hash = "sha256:fb1bbeac803adea29cedd70781399c99138358c26d05fcbd23c13016b7f5ec65"}, + {file = "typed_ast-1.5.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:183b183b7771a508395d2cbffd6db67d6ad52958a5fdc99f450d954003900266"}, + {file = "typed_ast-1.5.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:676d051b1da67a852c0447621fdd11c4e104827417bf216092ec3e286f7da596"}, + {file = "typed_ast-1.5.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc2542e83ac8399752bc16e0b35e038bdb659ba237f4222616b4e83fb9654985"}, + {file = "typed_ast-1.5.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:74cac86cc586db8dfda0ce65d8bcd2bf17b58668dfcc3652762f3ef0e6677e76"}, + {file = "typed_ast-1.5.2-cp310-cp310-win_amd64.whl", hash = "sha256:18fe320f354d6f9ad3147859b6e16649a0781425268c4dde596093177660e71a"}, + {file = "typed_ast-1.5.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:31d8c6b2df19a777bc8826770b872a45a1f30cfefcfd729491baa5237faae837"}, + {file = "typed_ast-1.5.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:963a0ccc9a4188524e6e6d39b12c9ca24cc2d45a71cfdd04a26d883c922b4b78"}, + {file = "typed_ast-1.5.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0eb77764ea470f14fcbb89d51bc6bbf5e7623446ac4ed06cbd9ca9495b62e36e"}, + {file = "typed_ast-1.5.2-cp36-cp36m-win_amd64.whl", hash = "sha256:294a6903a4d087db805a7656989f613371915fc45c8cc0ddc5c5a0a8ad9bea4d"}, + {file = "typed_ast-1.5.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:26a432dc219c6b6f38be20a958cbe1abffcc5492821d7e27f08606ef99e0dffd"}, + {file = "typed_ast-1.5.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7407cfcad702f0b6c0e0f3e7ab876cd1d2c13b14ce770e412c0c4b9728a0f88"}, + {file = "typed_ast-1.5.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f30ddd110634c2d7534b2d4e0e22967e88366b0d356b24de87419cc4410c41b7"}, + {file = "typed_ast-1.5.2-cp37-cp37m-win_amd64.whl", hash = "sha256:8c08d6625bb258179b6e512f55ad20f9dfef019bbfbe3095247401e053a3ea30"}, + {file = "typed_ast-1.5.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:90904d889ab8e81a956f2c0935a523cc4e077c7847a836abee832f868d5c26a4"}, + {file = "typed_ast-1.5.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bbebc31bf11762b63bf61aaae232becb41c5bf6b3461b80a4df7e791fabb3aca"}, + {file = "typed_ast-1.5.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c29dd9a3a9d259c9fa19d19738d021632d673f6ed9b35a739f48e5f807f264fb"}, + {file = "typed_ast-1.5.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:58ae097a325e9bb7a684572d20eb3e1809802c5c9ec7108e85da1eb6c1a3331b"}, + {file = "typed_ast-1.5.2-cp38-cp38-win_amd64.whl", hash = "sha256:da0a98d458010bf4fe535f2d1e367a2e2060e105978873c04c04212fb20543f7"}, + {file = "typed_ast-1.5.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:33b4a19ddc9fc551ebabca9765d54d04600c4a50eda13893dadf67ed81d9a098"}, + {file = "typed_ast-1.5.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1098df9a0592dd4c8c0ccfc2e98931278a6c6c53cb3a3e2cf7e9ee3b06153344"}, + {file = "typed_ast-1.5.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42c47c3b43fe3a39ddf8de1d40dbbfca60ac8530a36c9b198ea5b9efac75c09e"}, + {file = "typed_ast-1.5.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f290617f74a610849bd8f5514e34ae3d09eafd521dceaa6cf68b3f4414266d4e"}, + {file = "typed_ast-1.5.2-cp39-cp39-win_amd64.whl", hash = "sha256:df05aa5b241e2e8045f5f4367a9f6187b09c4cdf8578bb219861c4e27c443db5"}, + {file = "typed_ast-1.5.2.tar.gz", hash = "sha256:525a2d4088e70a9f75b08b3f87a51acc9cde640e19cc523c7e41aa355564ae27"}, ] typing-extensions = [ - {file = "typing_extensions-3.10.0.2-py2-none-any.whl", hash = "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7"}, - {file = "typing_extensions-3.10.0.2-py3-none-any.whl", hash = "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34"}, - {file = "typing_extensions-3.10.0.2.tar.gz", hash = "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e"}, + {file = "typing_extensions-4.0.1-py3-none-any.whl", hash = "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"}, + {file = "typing_extensions-4.0.1.tar.gz", hash = "sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e"}, ] uritemplate = [ {file = "uritemplate-3.0.1-py2.py3-none-any.whl", hash = "sha256:07620c3f3f8eed1f12600845892b0e036a2420acf513c53f7de0abd911a5894f"}, {file = "uritemplate-3.0.1.tar.gz", hash = "sha256:5af8ad10cec94f215e3f48112de2022e1d5a37ed427fbd88652fa908f2ab7cae"}, ] urllib3 = [ - {file = "urllib3-1.26.7-py2.py3-none-any.whl", hash = "sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844"}, - {file = "urllib3-1.26.7.tar.gz", hash = "sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece"}, + {file = "urllib3-1.26.8-py2.py3-none-any.whl", hash = "sha256:000ca7f471a233c2251c6c7023ee85305721bfdf18621ebff4fd17a8653427ed"}, + {file = "urllib3-1.26.8.tar.gz", hash = "sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c"}, ] wcwidth = [ {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, @@ -2691,130 +2794,137 @@ websocket-client = [ {file = "websocket_client-0.59.0-py2.py3-none-any.whl", hash = "sha256:2e50d26ca593f70aba7b13a489435ef88b8fc3b5c5643c1ce8808ff9b40f0b32"}, ] wrapt = [ - {file = "wrapt-1.13.2-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3de7b4d3066cc610054e7aa2c005645e308df2f92be730aae3a47d42e910566a"}, - {file = "wrapt-1.13.2-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:8164069f775c698d15582bf6320a4f308c50d048c1c10cf7d7a341feaccf5df7"}, - {file = "wrapt-1.13.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9adee1891253670575028279de8365c3a02d3489a74a66d774c321472939a0b1"}, - {file = "wrapt-1.13.2-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:a70d876c9aba12d3bd7f8f1b05b419322c6789beb717044eea2c8690d35cb91b"}, - {file = "wrapt-1.13.2-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:3f87042623530bcffea038f824b63084180513c21e2e977291a9a7e65a66f13b"}, - {file = "wrapt-1.13.2-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:e634136f700a21e1fcead0c137f433dde928979538c14907640607d43537d468"}, - {file = "wrapt-1.13.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:3e33c138d1e3620b1e0cc6fd21e46c266393ed5dae0d595b7ed5a6b73ed57aa0"}, - {file = "wrapt-1.13.2-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:283e402e5357e104ac1e3fba5791220648e9af6fb14ad7d9cc059091af2b31d2"}, - {file = "wrapt-1.13.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:ccb34ce599cab7f36a4c90318697ead18312c67a9a76327b3f4f902af8f68ea1"}, - {file = "wrapt-1.13.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:fbad5ba74c46517e6488149514b2e2348d40df88cd6b52a83855b7a8bf04723f"}, - {file = "wrapt-1.13.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:724ed2bc9c91a2b9026e5adce310fa60c6e7c8760b03391445730b9789b9d108"}, - {file = "wrapt-1.13.2-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:83f2793ec6f3ef513ad8d5b9586f5ee6081cad132e6eae2ecb7eac1cc3decae0"}, - {file = "wrapt-1.13.2-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:0473d1558b93e314e84313cc611f6c86be779369f9d3734302bf185a4d2625b1"}, - {file = "wrapt-1.13.2-cp35-cp35m-win32.whl", hash = "sha256:15eee0e6fd07f48af2f66d0e6f2ff1916ffe9732d464d5e2390695296872cad9"}, - {file = "wrapt-1.13.2-cp35-cp35m-win_amd64.whl", hash = "sha256:bc85d17d90201afd88e3d25421da805e4e135012b5d1f149e4de2981394b2a52"}, - {file = "wrapt-1.13.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c6ee5f8734820c21b9b8bf705e99faba87f21566d20626568eeb0d62cbeaf23c"}, - {file = "wrapt-1.13.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:53c6706a1bcfb6436f1625511b95b812798a6d2ccc51359cd791e33722b5ea32"}, - {file = "wrapt-1.13.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:fbe6aebc9559fed7ea27de51c2bf5c25ba2a4156cf0017556f72883f2496ee9a"}, - {file = "wrapt-1.13.2-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:0582180566e7a13030f896c2f1ac6a56134ab5f3c3f4c5538086f758b1caf3f2"}, - {file = "wrapt-1.13.2-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:bff0a59387a0a2951cb869251257b6553663329a1b5525b5226cab8c88dcbe7e"}, - {file = "wrapt-1.13.2-cp36-cp36m-win32.whl", hash = "sha256:df3eae297a5f1594d1feb790338120f717dac1fa7d6feed7b411f87e0f2401c7"}, - {file = "wrapt-1.13.2-cp36-cp36m-win_amd64.whl", hash = "sha256:1eb657ed84f4d3e6ad648483c8a80a0cf0a78922ef94caa87d327e2e1ad49b48"}, - {file = "wrapt-1.13.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a0cdedf681db878416c05e1831ec69691b0e6577ac7dca9d4f815632e3549580"}, - {file = "wrapt-1.13.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:87ee3c73bdfb4367b26c57259995935501829f00c7b3eed373e2ad19ec21e4e4"}, - {file = "wrapt-1.13.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:3e0d16eedc242d01a6f8cf0623e9cdc3b869329da3f97a15961d8864111d8cf0"}, - {file = "wrapt-1.13.2-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:8318088860968c07e741537030b1abdd8908ee2c71fbe4facdaade624a09e006"}, - {file = "wrapt-1.13.2-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:d90520616fce71c05dedeac3a0fe9991605f0acacd276e5f821842e454485a70"}, - {file = "wrapt-1.13.2-cp37-cp37m-win32.whl", hash = "sha256:22142afab65daffc95863d78effcbd31c19a8003eca73de59f321ee77f73cadb"}, - {file = "wrapt-1.13.2-cp37-cp37m-win_amd64.whl", hash = "sha256:d0d717e10f952df7ea41200c507cc7e24458f4c45b56c36ad418d2e79dacd1d4"}, - {file = "wrapt-1.13.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:593cb049ce1c391e0288523b30426c4430b26e74c7e6f6e2844bd99ac7ecc831"}, - {file = "wrapt-1.13.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:8860c8011a6961a651b1b9f46fdbc589ab63b0a50d645f7d92659618a3655867"}, - {file = "wrapt-1.13.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:ada5e29e59e2feb710589ca1c79fd989b1dd94d27079dc1d199ec954a6ecc724"}, - {file = "wrapt-1.13.2-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:fdede980273aeca591ad354608778365a3a310e0ecdd7a3587b38bc5be9b1808"}, - {file = "wrapt-1.13.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:af9480de8e63c5f959a092047aaf3d7077422ded84695b3398f5d49254af3e90"}, - {file = "wrapt-1.13.2-cp38-cp38-win32.whl", hash = "sha256:c65e623ea7556e39c4f0818200a046cbba7575a6b570ff36122c276fdd30ab0a"}, - {file = "wrapt-1.13.2-cp38-cp38-win_amd64.whl", hash = "sha256:b20703356cae1799080d0ad15085dc3213c1ac3f45e95afb9f12769b98231528"}, - {file = "wrapt-1.13.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1c5c4cf188b5643a97e87e2110bbd4f5bc491d54a5b90633837b34d5df6a03fe"}, - {file = "wrapt-1.13.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:82223f72eba6f63eafca87a0f614495ae5aa0126fe54947e2b8c023969e9f2d7"}, - {file = "wrapt-1.13.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:81a4cf257263b299263472d669692785f9c647e7dca01c18286b8f116dbf6b38"}, - {file = "wrapt-1.13.2-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:728e2d9b7a99dd955d3426f237b940fc74017c4a39b125fec913f575619ddfe9"}, - {file = "wrapt-1.13.2-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:7574de567dcd4858a2ffdf403088d6df8738b0e1eabea220553abf7c9048f59e"}, - {file = "wrapt-1.13.2-cp39-cp39-win32.whl", hash = "sha256:c7ac2c7a8e34bd06710605b21dd1f3576764443d68e069d2afba9b116014d072"}, - {file = "wrapt-1.13.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e6d1a8eeef415d7fb29fe017de0e48f45e45efd2d1bfda28fc50b7b330859ef"}, - {file = "wrapt-1.13.2.tar.gz", hash = "sha256:dca56cc5963a5fd7c2aa8607017753f534ee514e09103a6c55d2db70b50e7447"}, + {file = "wrapt-1.13.3-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:e05e60ff3b2b0342153be4d1b597bbcfd8330890056b9619f4ad6b8d5c96a81a"}, + {file = "wrapt-1.13.3-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:85148f4225287b6a0665eef08a178c15097366d46b210574a658c1ff5b377489"}, + {file = "wrapt-1.13.3-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:2dded5496e8f1592ec27079b28b6ad2a1ef0b9296d270f77b8e4a3a796cf6909"}, + {file = "wrapt-1.13.3-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:e94b7d9deaa4cc7bac9198a58a7240aaf87fe56c6277ee25fa5b3aa1edebd229"}, + {file = "wrapt-1.13.3-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:498e6217523111d07cd67e87a791f5e9ee769f9241fcf8a379696e25806965af"}, + {file = "wrapt-1.13.3-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:ec7e20258ecc5174029a0f391e1b948bf2906cd64c198a9b8b281b811cbc04de"}, + {file = "wrapt-1.13.3-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:87883690cae293541e08ba2da22cacaae0a092e0ed56bbba8d018cc486fbafbb"}, + {file = "wrapt-1.13.3-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:f99c0489258086308aad4ae57da9e8ecf9e1f3f30fa35d5e170b4d4896554d80"}, + {file = "wrapt-1.13.3-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:6a03d9917aee887690aa3f1747ce634e610f6db6f6b332b35c2dd89412912bca"}, + {file = "wrapt-1.13.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:936503cb0a6ed28dbfa87e8fcd0a56458822144e9d11a49ccee6d9a8adb2ac44"}, + {file = "wrapt-1.13.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f9c51d9af9abb899bd34ace878fbec8bf357b3194a10c4e8e0a25512826ef056"}, + {file = "wrapt-1.13.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:220a869982ea9023e163ba915077816ca439489de6d2c09089b219f4e11b6785"}, + {file = "wrapt-1.13.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:0877fe981fd76b183711d767500e6b3111378ed2043c145e21816ee589d91096"}, + {file = "wrapt-1.13.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:43e69ffe47e3609a6aec0fe723001c60c65305784d964f5007d5b4fb1bc6bf33"}, + {file = "wrapt-1.13.3-cp310-cp310-win32.whl", hash = "sha256:78dea98c81915bbf510eb6a3c9c24915e4660302937b9ae05a0947164248020f"}, + {file = "wrapt-1.13.3-cp310-cp310-win_amd64.whl", hash = "sha256:ea3e746e29d4000cd98d572f3ee2a6050a4f784bb536f4ac1f035987fc1ed83e"}, + {file = "wrapt-1.13.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:8c73c1a2ec7c98d7eaded149f6d225a692caa1bd7b2401a14125446e9e90410d"}, + {file = "wrapt-1.13.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:086218a72ec7d986a3eddb7707c8c4526d677c7b35e355875a0fe2918b059179"}, + {file = "wrapt-1.13.3-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:e92d0d4fa68ea0c02d39f1e2f9cb5bc4b4a71e8c442207433d8db47ee79d7aa3"}, + {file = "wrapt-1.13.3-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:d4a5f6146cfa5c7ba0134249665acd322a70d1ea61732723c7d3e8cc0fa80755"}, + {file = "wrapt-1.13.3-cp35-cp35m-win32.whl", hash = "sha256:8aab36778fa9bba1a8f06a4919556f9f8c7b33102bd71b3ab307bb3fecb21851"}, + {file = "wrapt-1.13.3-cp35-cp35m-win_amd64.whl", hash = "sha256:944b180f61f5e36c0634d3202ba8509b986b5fbaf57db3e94df11abee244ba13"}, + {file = "wrapt-1.13.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:2ebdde19cd3c8cdf8df3fc165bc7827334bc4e353465048b36f7deeae8ee0918"}, + {file = "wrapt-1.13.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:610f5f83dd1e0ad40254c306f4764fcdc846641f120c3cf424ff57a19d5f7ade"}, + {file = "wrapt-1.13.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5601f44a0f38fed36cc07db004f0eedeaadbdcec90e4e90509480e7e6060a5bc"}, + {file = "wrapt-1.13.3-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:e6906d6f48437dfd80464f7d7af1740eadc572b9f7a4301e7dd3d65db285cacf"}, + {file = "wrapt-1.13.3-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:766b32c762e07e26f50d8a3468e3b4228b3736c805018e4b0ec8cc01ecd88125"}, + {file = "wrapt-1.13.3-cp36-cp36m-win32.whl", hash = "sha256:5f223101f21cfd41deec8ce3889dc59f88a59b409db028c469c9b20cfeefbe36"}, + {file = "wrapt-1.13.3-cp36-cp36m-win_amd64.whl", hash = "sha256:f122ccd12fdc69628786d0c947bdd9cb2733be8f800d88b5a37c57f1f1d73c10"}, + {file = "wrapt-1.13.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:46f7f3af321a573fc0c3586612db4decb7eb37172af1bc6173d81f5b66c2e068"}, + {file = "wrapt-1.13.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:778fd096ee96890c10ce96187c76b3e99b2da44e08c9e24d5652f356873f6709"}, + {file = "wrapt-1.13.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0cb23d36ed03bf46b894cfec777eec754146d68429c30431c99ef28482b5c1df"}, + {file = "wrapt-1.13.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:96b81ae75591a795d8c90edc0bfaab44d3d41ffc1aae4d994c5aa21d9b8e19a2"}, + {file = "wrapt-1.13.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:7dd215e4e8514004c8d810a73e342c536547038fb130205ec4bba9f5de35d45b"}, + {file = "wrapt-1.13.3-cp37-cp37m-win32.whl", hash = "sha256:47f0a183743e7f71f29e4e21574ad3fa95676136f45b91afcf83f6a050914829"}, + {file = "wrapt-1.13.3-cp37-cp37m-win_amd64.whl", hash = "sha256:fd76c47f20984b43d93de9a82011bb6e5f8325df6c9ed4d8310029a55fa361ea"}, + {file = "wrapt-1.13.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b73d4b78807bd299b38e4598b8e7bd34ed55d480160d2e7fdaabd9931afa65f9"}, + {file = "wrapt-1.13.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ec9465dd69d5657b5d2fa6133b3e1e989ae27d29471a672416fd729b429eb554"}, + {file = "wrapt-1.13.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:dd91006848eb55af2159375134d724032a2d1d13bcc6f81cd8d3ed9f2b8e846c"}, + {file = "wrapt-1.13.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ae9de71eb60940e58207f8e71fe113c639da42adb02fb2bcbcaccc1ccecd092b"}, + {file = "wrapt-1.13.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:51799ca950cfee9396a87f4a1240622ac38973b6df5ef7a41e7f0b98797099ce"}, + {file = "wrapt-1.13.3-cp38-cp38-win32.whl", hash = "sha256:4b9c458732450ec42578b5642ac53e312092acf8c0bfce140ada5ca1ac556f79"}, + {file = "wrapt-1.13.3-cp38-cp38-win_amd64.whl", hash = "sha256:7dde79d007cd6dfa65afe404766057c2409316135cb892be4b1c768e3f3a11cb"}, + {file = "wrapt-1.13.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:981da26722bebb9247a0601e2922cedf8bb7a600e89c852d063313102de6f2cb"}, + {file = "wrapt-1.13.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:705e2af1f7be4707e49ced9153f8d72131090e52be9278b5dbb1498c749a1e32"}, + {file = "wrapt-1.13.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:25b1b1d5df495d82be1c9d2fad408f7ce5ca8a38085e2da41bb63c914baadff7"}, + {file = "wrapt-1.13.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:77416e6b17926d953b5c666a3cb718d5945df63ecf922af0ee576206d7033b5e"}, + {file = "wrapt-1.13.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:865c0b50003616f05858b22174c40ffc27a38e67359fa1495605f96125f76640"}, + {file = "wrapt-1.13.3-cp39-cp39-win32.whl", hash = "sha256:0a017a667d1f7411816e4bf214646d0ad5b1da2c1ea13dec6c162736ff25a374"}, + {file = "wrapt-1.13.3-cp39-cp39-win_amd64.whl", hash = "sha256:81bd7c90d28a4b2e1df135bfbd7c23aee3050078ca6441bead44c42483f9ebfb"}, + {file = "wrapt-1.13.3.tar.gz", hash = "sha256:1fea9cd438686e6682271d36f3481a9f3636195578bab9ca3382e2f5f01fc185"}, ] wsrpc-aiohttp = [ {file = "wsrpc-aiohttp-3.2.0.tar.gz", hash = "sha256:f467abc51bcdc760fc5aeb7041abdeef46eeca3928dc43dd6e7fa7a533563818"}, {file = "wsrpc_aiohttp-3.2.0-py3-none-any.whl", hash = "sha256:fa9b0bf5cb056898cb5c9f64cbc5eacb8a5dd18ab1b7f0cd4a2208b4a7fde282"}, ] yarl = [ - {file = "yarl-1.7.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e35d8230e4b08d86ea65c32450533b906a8267a87b873f2954adeaecede85169"}, - {file = "yarl-1.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eb4b3f277880c314e47720b4b6bb2c85114ab3c04c5442c9bc7006b3787904d8"}, - {file = "yarl-1.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c7015dcedb91d90a138eebdc7e432aec8966e0147ab2a55f2df27b1904fa7291"}, - {file = "yarl-1.7.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb3e478175e15e00d659fb0354a6a8db71a7811a2a5052aed98048bc972e5d2b"}, - {file = "yarl-1.7.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8b8c409aa3a7966647e7c1c524846b362a6bcbbe120bf8a176431f940d2b9a2e"}, - {file = "yarl-1.7.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b22ea41c7e98170474a01e3eded1377d46b2dfaef45888a0005c683eaaa49285"}, - {file = "yarl-1.7.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a7dfc46add4cfe5578013dbc4127893edc69fe19132d2836ff2f6e49edc5ecd6"}, - {file = "yarl-1.7.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:82ff6f85f67500a4f74885d81659cd270eb24dfe692fe44e622b8a2fd57e7279"}, - {file = "yarl-1.7.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f3cd2158b2ed0fb25c6811adfdcc47224efe075f2d68a750071dacc03a7a66e4"}, - {file = "yarl-1.7.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:59c0f13f9592820c51280d1cf811294d753e4a18baf90f0139d1dc93d4b6fc5f"}, - {file = "yarl-1.7.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:7f7655ad83d1a8afa48435a449bf2f3009293da1604f5dd95b5ddcf5f673bd69"}, - {file = "yarl-1.7.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:aa9f0d9b62d15182341b3e9816582f46182cab91c1a57b2d308b9a3c4e2c4f78"}, - {file = "yarl-1.7.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fdd1b90c225a653b1bd1c0cae8edf1957892b9a09c8bf7ee6321eeb8208eac0f"}, - {file = "yarl-1.7.0-cp310-cp310-win32.whl", hash = "sha256:7c8d0bb76eabc5299db203e952ec55f8f4c53f08e0df4285aac8c92bd9e12675"}, - {file = "yarl-1.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:622a36fa779efb4ff9eff5fe52730ff17521431379851a31e040958fc251670c"}, - {file = "yarl-1.7.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:3d461b7a8e139b9e4b41f62eb417ffa0b98d1c46d4caf14c845e6a3b349c0bb1"}, - {file = "yarl-1.7.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81cfacdd1e40bc931b5519499342efa388d24d262c30a3d31187bfa04f4a7001"}, - {file = "yarl-1.7.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:821b978f2152be7695d4331ef0621d207aedf9bbd591ba23a63412a3efc29a01"}, - {file = "yarl-1.7.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b64bd24c8c9a487f4a12260dc26732bf41028816dbf0c458f17864fbebdb3131"}, - {file = "yarl-1.7.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:98c9ddb92b60a83c21be42c776d3d9d5ec632a762a094c41bda37b7dfbd2cd83"}, - {file = "yarl-1.7.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a532d75ca74431c053a88a802e161fb3d651b8bf5821a3440bc3616e38754583"}, - {file = "yarl-1.7.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:053e09817eafb892e94e172d05406c1b3a22a93bc68f6eff5198363a3d764459"}, - {file = "yarl-1.7.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:98c51f02d542945d306c8e934aa2c1e66ba5e9c1c86b5bf37f3a51c8a747067e"}, - {file = "yarl-1.7.0-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:15ec41a5a5fdb7bace6d7b16701f9440007a82734f69127c0fbf6d87e10f4a1e"}, - {file = "yarl-1.7.0-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:a7f08819dba1e1255d6991ed37448a1bf4b1352c004bcd899b9da0c47958513d"}, - {file = "yarl-1.7.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:8e3ffab21db0542ffd1887f3b9575ddd58961f2cf61429cb6458afc00c4581e0"}, - {file = "yarl-1.7.0-cp36-cp36m-win32.whl", hash = "sha256:50127634f519b2956005891507e3aa4ac345f66a7ea7bbc2d7dcba7401f41898"}, - {file = "yarl-1.7.0-cp36-cp36m-win_amd64.whl", hash = "sha256:36ec44f15193f6d5288d42ebb8e751b967ebdfb72d6830983838d45ab18edb4f"}, - {file = "yarl-1.7.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:ec1b5a25a25c880c976d0bb3d107def085bb08dbb3db7f4442e0a2b980359d24"}, - {file = "yarl-1.7.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b36f5a63c891f813c6f04ef19675b382efc190fd5ce7e10ab19386d2548bca06"}, - {file = "yarl-1.7.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38173b8c3a29945e7ecade9a3f6ff39581eee8201338ee6a2c8882db5df3e806"}, - {file = "yarl-1.7.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ba402f32184f0b405fb281b93bd0d8ab7e3257735b57b62a6ed2e94cdf4fe50"}, - {file = "yarl-1.7.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:be52bc5208d767cdd8308a9e93059b3b36d1e048fecbea0e0346d0d24a76adc0"}, - {file = "yarl-1.7.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:08c2044a956f4ef30405f2f433ce77f1f57c2c773bf81ae43201917831044d5a"}, - {file = "yarl-1.7.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:484d61c047c45670ef5967653a1d0783e232c54bf9dd786a7737036828fa8d54"}, - {file = "yarl-1.7.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b7de92a4af85cfcaf4081f8aa6165b1d63ee5de150af3ee85f954145f93105a7"}, - {file = "yarl-1.7.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:376e41775aab79c5575534924a386c8e0f1a5d91db69fc6133fd27a489bcaf10"}, - {file = "yarl-1.7.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:8a8b10d0e7bac154f959b709fcea593cda527b234119311eb950096653816a86"}, - {file = "yarl-1.7.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:f46cd4c43e6175030e2a56def8f1d83b64e6706eeb2bb9ab0ef4756f65eab23f"}, - {file = "yarl-1.7.0-cp37-cp37m-win32.whl", hash = "sha256:b28cfb46140efe1a6092b8c5c4994a1fe70dc83c38fbcea4992401e0c6fb9cce"}, - {file = "yarl-1.7.0-cp37-cp37m-win_amd64.whl", hash = "sha256:9624154ec9c02a776802da1086eed7f5034bd1971977f5146233869c2ac80297"}, - {file = "yarl-1.7.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:69945d13e1bbf81784a9bc48824feb9cd66491e6a503d4e83f6cd7c7cc861361"}, - {file = "yarl-1.7.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:46a742ed9e363bd01be64160ce7520e92e11989bd4cb224403cfd31c101cc83d"}, - {file = "yarl-1.7.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cb4ff1ac7cb4500f43581b3f4cbd627d702143aa6be1fdc1fa3ebffaf4dc1be5"}, - {file = "yarl-1.7.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ad51e17cd65ea3debb0e10f0120cf8dd987c741fe423ed2285087368090b33d"}, - {file = "yarl-1.7.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7e37786ea89a5d3ffbbf318ea9790926f8dfda83858544f128553c347ad143c6"}, - {file = "yarl-1.7.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c63c1e208f800daad71715786bfeb1cecdc595d87e2e9b1cd234fd6e597fd71d"}, - {file = "yarl-1.7.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:91cbe24300c11835ef186436363352b3257db7af165e0a767f4f17aa25761388"}, - {file = "yarl-1.7.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e510dbec7c59d32eaa61ffa48173d5e3d7170a67f4a03e8f5e2e9e3971aca622"}, - {file = "yarl-1.7.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3def6e681cc02397e5d8141ee97b41d02932b2bcf0fb34532ad62855eab7c60e"}, - {file = "yarl-1.7.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:263c81b94e6431942b27f6f671fa62f430a0a5c14bb255f2ab69eeb9b2b66ff7"}, - {file = "yarl-1.7.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:e78c91faefe88d601ddd16e3882918dbde20577a2438e2320f8239c8b7507b8f"}, - {file = "yarl-1.7.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:22b2430c49713bfb2f0a0dd4a8d7aab218b28476ba86fd1c78ad8899462cbcf2"}, - {file = "yarl-1.7.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2e7ad9db939082f5d0b9269cfd92c025cb8f2fbbb1f1b9dc5a393c639db5bd92"}, - {file = "yarl-1.7.0-cp38-cp38-win32.whl", hash = "sha256:3a31e4a8dcb1beaf167b7e7af61b88cb961b220db8d3ba1c839723630e57eef7"}, - {file = "yarl-1.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:d579957439933d752358c6a300c93110f84aae67b63dd0c19dde6ecbf4056f6b"}, - {file = "yarl-1.7.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:87721b549505a546eb003252185103b5ec8147de6d3ad3714d148a5a67b6fe53"}, - {file = "yarl-1.7.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1fa866fa24d9f4108f9e58ea8a2135655419885cdb443e36b39a346e1181532"}, - {file = "yarl-1.7.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1d3b8449dfedfe94eaff2b77954258b09b24949f6818dfa444b05dbb05ae1b7e"}, - {file = "yarl-1.7.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db2372e350794ce8b9f810feb094c606b7e0e4aa6807141ac4fadfe5ddd75bb0"}, - {file = "yarl-1.7.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a06d9d0b9a97fa99b84fee71d9dd11e69e21ac8a27229089f07b5e5e50e8d63c"}, - {file = "yarl-1.7.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a3455c2456d6307bcfa80bc1157b8603f7d93573291f5bdc7144489ca0df4628"}, - {file = "yarl-1.7.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:d30d67e3486aea61bb2cbf7cf81385364c2e4f7ce7469a76ed72af76a5cdfe6b"}, - {file = "yarl-1.7.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c18a4b286e8d780c3a40c31d7b79836aa93b720f71d5743f20c08b7e049ca073"}, - {file = "yarl-1.7.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d54c925396e7891666cabc0199366ca55b27d003393465acef63fd29b8b7aa92"}, - {file = "yarl-1.7.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:64773840952de17851a1c7346ad7f71688c77e74248d1f0bc230e96680f84028"}, - {file = "yarl-1.7.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:acbf1756d9dc7cd0ae943d883be72e84e04396f6c2ff93a6ddeca929d562039f"}, - {file = "yarl-1.7.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:2e48f27936aa838939c798f466c851ba4ae79e347e8dfce43b009c64b930df12"}, - {file = "yarl-1.7.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1beef4734ca1ad40a9d8c6b20a76ab46e3a2ed09f38561f01e4aa2ea82cafcef"}, - {file = "yarl-1.7.0-cp39-cp39-win32.whl", hash = "sha256:8ee78c9a5f3c642219d4607680a4693b59239c27a3aa608b64ef79ddc9698039"}, - {file = "yarl-1.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:d750503682605088a14d29a4701548c15c510da4f13c8b17409c4097d5b04c52"}, - {file = "yarl-1.7.0.tar.gz", hash = "sha256:8e7ebaf62e19c2feb097ffb7c94deb0f0c9fab52590784c8cd679d30ab009162"}, + {file = "yarl-1.7.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f2a8508f7350512434e41065684076f640ecce176d262a7d54f0da41d99c5a95"}, + {file = "yarl-1.7.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:da6df107b9ccfe52d3a48165e48d72db0eca3e3029b5b8cb4fe6ee3cb870ba8b"}, + {file = "yarl-1.7.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a1d0894f238763717bdcfea74558c94e3bc34aeacd3351d769460c1a586a8b05"}, + {file = "yarl-1.7.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dfe4b95b7e00c6635a72e2d00b478e8a28bfb122dc76349a06e20792eb53a523"}, + {file = "yarl-1.7.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c145ab54702334c42237a6c6c4cc08703b6aa9b94e2f227ceb3d477d20c36c63"}, + {file = "yarl-1.7.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1ca56f002eaf7998b5fcf73b2421790da9d2586331805f38acd9997743114e98"}, + {file = "yarl-1.7.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1d3d5ad8ea96bd6d643d80c7b8d5977b4e2fb1bab6c9da7322616fd26203d125"}, + {file = "yarl-1.7.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:167ab7f64e409e9bdd99333fe8c67b5574a1f0495dcfd905bc7454e766729b9e"}, + {file = "yarl-1.7.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:95a1873b6c0dd1c437fb3bb4a4aaa699a48c218ac7ca1e74b0bee0ab16c7d60d"}, + {file = "yarl-1.7.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6152224d0a1eb254f97df3997d79dadd8bb2c1a02ef283dbb34b97d4f8492d23"}, + {file = "yarl-1.7.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:5bb7d54b8f61ba6eee541fba4b83d22b8a046b4ef4d8eb7f15a7e35db2e1e245"}, + {file = "yarl-1.7.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:9c1f083e7e71b2dd01f7cd7434a5f88c15213194df38bc29b388ccdf1492b739"}, + {file = "yarl-1.7.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f44477ae29025d8ea87ec308539f95963ffdc31a82f42ca9deecf2d505242e72"}, + {file = "yarl-1.7.2-cp310-cp310-win32.whl", hash = "sha256:cff3ba513db55cc6a35076f32c4cdc27032bd075c9faef31fec749e64b45d26c"}, + {file = "yarl-1.7.2-cp310-cp310-win_amd64.whl", hash = "sha256:c9c6d927e098c2d360695f2e9d38870b2e92e0919be07dbe339aefa32a090265"}, + {file = "yarl-1.7.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:9b4c77d92d56a4c5027572752aa35082e40c561eec776048330d2907aead891d"}, + {file = "yarl-1.7.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c01a89a44bb672c38f42b49cdb0ad667b116d731b3f4c896f72302ff77d71656"}, + {file = "yarl-1.7.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c19324a1c5399b602f3b6e7db9478e5b1adf5cf58901996fc973fe4fccd73eed"}, + {file = "yarl-1.7.2-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3abddf0b8e41445426d29f955b24aeecc83fa1072be1be4e0d194134a7d9baee"}, + {file = "yarl-1.7.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6a1a9fe17621af43e9b9fcea8bd088ba682c8192d744b386ee3c47b56eaabb2c"}, + {file = "yarl-1.7.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8b0915ee85150963a9504c10de4e4729ae700af11df0dc5550e6587ed7891e92"}, + {file = "yarl-1.7.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:29e0656d5497733dcddc21797da5a2ab990c0cb9719f1f969e58a4abac66234d"}, + {file = "yarl-1.7.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:bf19725fec28452474d9887a128e98dd67eee7b7d52e932e6949c532d820dc3b"}, + {file = "yarl-1.7.2-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:d6f3d62e16c10e88d2168ba2d065aa374e3c538998ed04996cd373ff2036d64c"}, + {file = "yarl-1.7.2-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:ac10bbac36cd89eac19f4e51c032ba6b412b3892b685076f4acd2de18ca990aa"}, + {file = "yarl-1.7.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:aa32aaa97d8b2ed4e54dc65d241a0da1c627454950f7d7b1f95b13985afd6c5d"}, + {file = "yarl-1.7.2-cp36-cp36m-win32.whl", hash = "sha256:87f6e082bce21464857ba58b569370e7b547d239ca22248be68ea5d6b51464a1"}, + {file = "yarl-1.7.2-cp36-cp36m-win_amd64.whl", hash = "sha256:ac35ccde589ab6a1870a484ed136d49a26bcd06b6a1c6397b1967ca13ceb3913"}, + {file = "yarl-1.7.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a467a431a0817a292121c13cbe637348b546e6ef47ca14a790aa2fa8cc93df63"}, + {file = "yarl-1.7.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ab0c3274d0a846840bf6c27d2c60ba771a12e4d7586bf550eefc2df0b56b3b4"}, + {file = "yarl-1.7.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d260d4dc495c05d6600264a197d9d6f7fc9347f21d2594926202fd08cf89a8ba"}, + {file = "yarl-1.7.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fc4dd8b01a8112809e6b636b00f487846956402834a7fd59d46d4f4267181c41"}, + {file = "yarl-1.7.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c1164a2eac148d85bbdd23e07dfcc930f2e633220f3eb3c3e2a25f6148c2819e"}, + {file = "yarl-1.7.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:67e94028817defe5e705079b10a8438b8cb56e7115fa01640e9c0bb3edf67332"}, + {file = "yarl-1.7.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:89ccbf58e6a0ab89d487c92a490cb5660d06c3a47ca08872859672f9c511fc52"}, + {file = "yarl-1.7.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:8cce6f9fa3df25f55521fbb5c7e4a736683148bcc0c75b21863789e5185f9185"}, + {file = "yarl-1.7.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:211fcd65c58bf250fb994b53bc45a442ddc9f441f6fec53e65de8cba48ded986"}, + {file = "yarl-1.7.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c10ea1e80a697cf7d80d1ed414b5cb8f1eec07d618f54637067ae3c0334133c4"}, + {file = "yarl-1.7.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:52690eb521d690ab041c3919666bea13ab9fbff80d615ec16fa81a297131276b"}, + {file = "yarl-1.7.2-cp37-cp37m-win32.whl", hash = "sha256:695ba021a9e04418507fa930d5f0704edbce47076bdcfeeaba1c83683e5649d1"}, + {file = "yarl-1.7.2-cp37-cp37m-win_amd64.whl", hash = "sha256:c17965ff3706beedafd458c452bf15bac693ecd146a60a06a214614dc097a271"}, + {file = "yarl-1.7.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fce78593346c014d0d986b7ebc80d782b7f5e19843ca798ed62f8e3ba8728576"}, + {file = "yarl-1.7.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c2a1ac41a6aa980db03d098a5531f13985edcb451bcd9d00670b03129922cd0d"}, + {file = "yarl-1.7.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:39d5493c5ecd75c8093fa7700a2fb5c94fe28c839c8e40144b7ab7ccba6938c8"}, + {file = "yarl-1.7.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1eb6480ef366d75b54c68164094a6a560c247370a68c02dddb11f20c4c6d3c9d"}, + {file = "yarl-1.7.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ba63585a89c9885f18331a55d25fe81dc2d82b71311ff8bd378fc8004202ff6"}, + {file = "yarl-1.7.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e39378894ee6ae9f555ae2de332d513a5763276a9265f8e7cbaeb1b1ee74623a"}, + {file = "yarl-1.7.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c0910c6b6c31359d2f6184828888c983d54d09d581a4a23547a35f1d0b9484b1"}, + {file = "yarl-1.7.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6feca8b6bfb9eef6ee057628e71e1734caf520a907b6ec0d62839e8293e945c0"}, + {file = "yarl-1.7.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8300401dc88cad23f5b4e4c1226f44a5aa696436a4026e456fe0e5d2f7f486e6"}, + {file = "yarl-1.7.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:788713c2896f426a4e166b11f4ec538b5736294ebf7d5f654ae445fd44270832"}, + {file = "yarl-1.7.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:fd547ec596d90c8676e369dd8a581a21227fe9b4ad37d0dc7feb4ccf544c2d59"}, + {file = "yarl-1.7.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:737e401cd0c493f7e3dd4db72aca11cfe069531c9761b8ea474926936b3c57c8"}, + {file = "yarl-1.7.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:baf81561f2972fb895e7844882898bda1eef4b07b5b385bcd308d2098f1a767b"}, + {file = "yarl-1.7.2-cp38-cp38-win32.whl", hash = "sha256:ede3b46cdb719c794427dcce9d8beb4abe8b9aa1e97526cc20de9bd6583ad1ef"}, + {file = "yarl-1.7.2-cp38-cp38-win_amd64.whl", hash = "sha256:cc8b7a7254c0fc3187d43d6cb54b5032d2365efd1df0cd1749c0c4df5f0ad45f"}, + {file = "yarl-1.7.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:580c1f15500e137a8c37053e4cbf6058944d4c114701fa59944607505c2fe3a0"}, + {file = "yarl-1.7.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3ec1d9a0d7780416e657f1e405ba35ec1ba453a4f1511eb8b9fbab81cb8b3ce1"}, + {file = "yarl-1.7.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3bf8cfe8856708ede6a73907bf0501f2dc4e104085e070a41f5d88e7faf237f3"}, + {file = "yarl-1.7.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1be4bbb3d27a4e9aa5f3df2ab61e3701ce8fcbd3e9846dbce7c033a7e8136746"}, + {file = "yarl-1.7.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:534b047277a9a19d858cde163aba93f3e1677d5acd92f7d10ace419d478540de"}, + {file = "yarl-1.7.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6ddcd80d79c96eb19c354d9dca95291589c5954099836b7c8d29278a7ec0bda"}, + {file = "yarl-1.7.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9bfcd43c65fbb339dc7086b5315750efa42a34eefad0256ba114cd8ad3896f4b"}, + {file = "yarl-1.7.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f64394bd7ceef1237cc604b5a89bf748c95982a84bcd3c4bbeb40f685c810794"}, + {file = "yarl-1.7.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:044daf3012e43d4b3538562da94a88fb12a6490652dbc29fb19adfa02cf72eac"}, + {file = "yarl-1.7.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:368bcf400247318382cc150aaa632582d0780b28ee6053cd80268c7e72796dec"}, + {file = "yarl-1.7.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:bab827163113177aee910adb1f48ff7af31ee0289f434f7e22d10baf624a6dfe"}, + {file = "yarl-1.7.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0cba38120db72123db7c58322fa69e3c0efa933040ffb586c3a87c063ec7cae8"}, + {file = "yarl-1.7.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:59218fef177296451b23214c91ea3aba7858b4ae3306dde120224cfe0f7a6ee8"}, + {file = "yarl-1.7.2-cp39-cp39-win32.whl", hash = "sha256:1edc172dcca3f11b38a9d5c7505c83c1913c0addc99cd28e993efeaafdfaa18d"}, + {file = "yarl-1.7.2-cp39-cp39-win_amd64.whl", hash = "sha256:797c2c412b04403d2da075fb93c123df35239cd7b4cc4e0cd9e5839b73f52c58"}, + {file = "yarl-1.7.2.tar.gz", hash = "sha256:45399b46d60c253327a460e99856752009fcee5f5d3c80b2f7c0cae1c38d56dd"}, ] zipp = [ - {file = "zipp-3.6.0-py3-none-any.whl", hash = "sha256:9fe5ea21568a0a70e50f273397638d39b03353731e6cbbb3fd8502a33fec40bc"}, - {file = "zipp-3.6.0.tar.gz", hash = "sha256:71c644c5369f4a6e07636f0aa966270449561fcea2e3d6747b8d23efaa9d7832"}, + {file = "zipp-3.7.0-py3-none-any.whl", hash = "sha256:b47250dd24f92b7dd6a0a8fc5244da14608f3ca90a5efcd37a3b1642fac9a375"}, + {file = "zipp-3.7.0.tar.gz", hash = "sha256:9f50f446828eb9d45b267433fd3e9da8d801f614129124863f9c51ebceafb87d"}, ] diff --git a/pyproject.toml b/pyproject.toml index a3d2ecabd9..7d16b2e62e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -71,7 +71,7 @@ dropbox = "^11.20.0" flake8 = "^3.7" autopep8 = "^1.4" coverage = "*" -cx_freeze = { version = "6.7", source = "openpype" } +cx_freeze = "~6.9" GitPython = "^3.1.17" jedi = "^0.13" Jinja2 = "^2.11" diff --git a/tools/create_env.sh b/tools/create_env.sh index 917ddc36ba..94b11d6776 100755 --- a/tools/create_env.sh +++ b/tools/create_env.sh @@ -194,7 +194,6 @@ main () { "$POETRY_HOME/bin/poetry" run pip install setuptools==49.6.0 "$POETRY_HOME/bin/poetry" run pip install --disable-pip-version-check --force-reinstall wheel "$POETRY_HOME/bin/poetry" run python -m pip install --disable-pip-version-check --force-reinstall pip - "$POETRY_HOME/bin/poetry" run pip install --disable-pip-version-check --force-reinstall cx_freeze -i $openpype_index --extra-index-url https://pypi.org/simple } return_code=0 From c6b109bcdb9fb6e5b0d3cb52d7121bfde5d7cdf7 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 2 Feb 2022 15:39:32 +0100 Subject: [PATCH 47/74] created project_backpack in openpype lib --- openpype/lib/project_backpack.py | 232 +++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100644 openpype/lib/project_backpack.py diff --git a/openpype/lib/project_backpack.py b/openpype/lib/project_backpack.py new file mode 100644 index 0000000000..045e8b4ea1 --- /dev/null +++ b/openpype/lib/project_backpack.py @@ -0,0 +1,232 @@ +"""These lib functions are primarily for development purposes. + +WARNING: This is not meant for production data. + +Goal is to be able create package of current state of project with related +documents from mongo and files from disk to zip file and then be able recreate +the project based on the zip. + +This gives ability to create project where a changes and tests can be done. + +Keep in mind that to be able create a package of project has few requirements. +Possible requirement should be listed in 'pack_project' function. +""" +import os +import json +import platform +import tempfile +import shutil +import datetime + +import zipfile +from bson.json_util import ( + loads, + dumps, + CANONICAL_JSON_OPTIONS +) + +from avalon.api import AvalonMongoDB + +DOCUMENTS_FILE_NAME = "database" +METADATA_FILE_NAME = "metadata" +PROJECT_FILES_DIR = "project_files" + + +def add_timestamp(filepath): + """Add timestamp string to a file.""" + base, ext = os.path.splitext(filepath) + timestamp = datetime.datetime.now().strftime("%y%m%d_%H%M%S") + new_base = "{}_{}".format(base, timestamp) + return new_base + ext + + +def pack_project(project_name, destination_dir=None): + """Make a package of a project with mongo documents and files. + + This function has few restrictions: + - project must have only one root + - project must have all templates starting with + "{root[...]}/{project[name]}" + + Args: + project_name(str): Project that should be packaged. + destination_dir(str): Optinal path where zip will be stored. Project's + root is used if not passed. + """ + # Validate existence of project + dbcon = AvalonMongoDB() + dbcon.Session["AVALON_PROJECT"] = project_name + project_doc = dbcon.find_one({"type": "project"}) + if not project_doc: + raise ValueError("Project \"{}\" was not found in database".format( + project_name + )) + + roots = project_doc["config"]["roots"] + # Determine root directory of project + source_root = None + for root_name, root_value in roots.items(): + if source_root is not None: + raise ValueError( + "Packaging is supported only for single root projects" + ) + source_root = root_value + + root_path = source_root[platform.system().lower()] + print("Using root \"{}\" with path \"{}\"".format( + root_name, root_value + )) + + project_source_path = os.path.join(root_path, project_name) + if not os.path.exists(project_source_path): + raise ValueError("Didn't find source of project files") + + # Determine zip filepath where data will be stored + if not destination_dir: + destination_dir = root_path + + if not os.path.exists(destination_dir): + os.makedirs(destination_dir) + + zip_path = os.path.join(destination_dir, project_name + ".zip") + + print("Project will be packaged into {}".format(zip_path)) + # Rename already existing zip + if os.path.exists(zip_path): + dst_filepath = add_timestamp(zip_path) + os.rename(zip_path, dst_filepath) + + # We can add more data + metadata = { + "project_name": project_name, + "root": source_root, + "version": 1 + } + # Create temp json file where metadata are stored + with tempfile.NamedTemporaryFile("w", suffix=".json", delete=False) as s: + temp_metadata_json = s.name + + with open(temp_metadata_json, "w") as stream: + json.dump(metadata, stream) + + # Create temp json file where database documents are stored + with tempfile.NamedTemporaryFile("w", suffix=".json", delete=False) as s: + temp_docs_json = s.name + + # Query all project documents and store them to temp json + docs = list(dbcon.find({})) + data = dumps( + docs, json_options=CANONICAL_JSON_OPTIONS + ) + with open(temp_docs_json, "w") as stream: + stream.write(data) + + # Write all to zip file + with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zip_stream: + # Add metadata file + zip_stream.write(temp_metadata_json, METADATA_FILE_NAME + ".json") + # Add database documents + zip_stream.write(temp_docs_json, DOCUMENTS_FILE_NAME + ".json") + # Add project files to zip + for root, _, filenames in os.walk(project_source_path): + for filename in filenames: + filepath = os.path.join(root, filename) + # TODO add one more folder + archive_name = os.path.join( + PROJECT_FILES_DIR, + os.path.relpath(filepath, root_path) + ) + zip_stream.write(filepath, archive_name) + + # Cleanup + os.remove(temp_docs_json) + os.remove(temp_metadata_json) + dbcon.uninstall() + + +def unpack_project(path_to_zip, new_root=None): + """Unpack project zip file to recreate project. + + Args: + path_to_zip(str): Path to zip which was created using 'pack_project' + function. + new_root(str): Optional way how to set different root path for unpacked + project. + """ + if not os.path.exists(path_to_zip): + print("Zip file does not exists: {}".format(path_to_zip)) + return + + tmp_dir = tempfile.mkdtemp(prefix="unpack_") + print("Zip is extracted to: {}".format(tmp_dir)) + with zipfile.ZipFile(path_to_zip, "r") as zip_stream: + zip_stream.extractall(tmp_dir) + + metadata_json_path = os.path.join(tmp_dir, METADATA_FILE_NAME + ".json") + with open(metadata_json_path, "r") as stream: + metadata = json.load(stream) + + docs_json_path = os.path.join(tmp_dir, DOCUMENTS_FILE_NAME + ".json") + with open(docs_json_path, "r") as stream: + content = stream.readlines() + docs = loads("".join(content)) + + low_platform = platform.system().lower() + project_name = metadata["project_name"] + source_root = metadata["root"] + root_path = source_root[low_platform] + + # Drop existing collection + dbcon = AvalonMongoDB() + database = dbcon.database + if project_name in database.list_collection_names(): + database.drop_collection(project_name) + print("Removed existing project collection") + + collection = database[project_name] + # Create new collection with loaded docs + print("Creating project documents ({})".format(len(docs))) + collection.insert_many(docs) + + # Skip change of root if is the same as the one stored in metadata + if ( + new_root + and (os.path.normpath(new_root) == os.path.normpath(root_path)) + ): + new_root = None + + if new_root: + print("Using different root path {}".format(new_root)) + root_path = new_root + + project_doc = collection.find_one({"type": "project"}) + roots = project_doc["config"]["roots"] + key = tuple(roots.keys())[0] + update_key = "config.roots.{}.{}".format(key, low_platform) + collection.update_one( + {"_id": project_doc["_id"]}, + {"$set": { + update_key: new_root + }} + ) + + # Make sure root path exists + if not os.path.exists(root_path): + os.makedirs(root_path) + + src_project_files_dir = os.path.join( + tmp_dir, PROJECT_FILES_DIR, project_name + ) + dst_project_files_dir = os.path.join(root_path, project_name) + if os.path.exists(dst_project_files_dir): + new_path = add_timestamp(dst_project_files_dir) + os.rename(dst_project_files_dir, new_path) + + print("Moving {} -> {}".format( + src_project_files_dir, dst_project_files_dir + )) + shutil.move(src_project_files_dir, dst_project_files_dir) + + # CLeanup + shutil.rmtree(tmp_dir) + dbcon.uninstall() From 7d19db96c4c3cc9625ab8303d7d0777cb72fea90 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 2 Feb 2022 15:39:53 +0100 Subject: [PATCH 48/74] create cli commands for project backpack functions --- openpype/cli.py | 20 ++++++++++++++++++++ openpype/pype_commands.py | 10 ++++++++++ 2 files changed, 30 insertions(+) diff --git a/openpype/cli.py b/openpype/cli.py index 6e9c237b0e..f15306e3d3 100644 --- a/openpype/cli.py +++ b/openpype/cli.py @@ -412,3 +412,23 @@ def repack_version(directory): directory name. """ PypeCommands().repack_version(directory) + + +@main.command() +@click.option("--project", help="Project name") +@click.option( + "--dirpath", help="Directory where package is stored", default=None +) +def pack_project(project_name, dirpath): + """Create a package of project with all files and database dump.""" + PypeCommands().pack_project(project_name, dirpath) + + +@main.command() +@click.option("--zipfile", help="Path to zip file") +@click.option( + "--root", help="Replace root which was stored in project", default=None +) +def uppack_project(zipfile, root): + """Create a package of project with all files and database dump.""" + PypeCommands().unpack_project(zipfile, root) diff --git a/openpype/pype_commands.py b/openpype/pype_commands.py index de0336be2b..e5db036c04 100644 --- a/openpype/pype_commands.py +++ b/openpype/pype_commands.py @@ -433,3 +433,13 @@ class PypeCommands: version_packer = VersionRepacker(directory) version_packer.process() + + def pack_project(project_name, dirpath): + from openpype.lib.project_backpack import pack_project + + pack_project(project_name, dirpath) + + def unpack_project(zip_filepath, new_root): + from openpype.lib.project_backpack import unpack_project + + unpack_project(zip_filepath, new_root) From ea4e5b040776ac560904752325b7505886a04bc9 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 2 Feb 2022 16:21:13 +0100 Subject: [PATCH 49/74] few fixes and smaller modifications --- openpype/cli.py | 6 +++--- openpype/lib/project_backpack.py | 27 ++++++++++++++++++++------- openpype/pype_commands.py | 4 ++-- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/openpype/cli.py b/openpype/cli.py index f15306e3d3..0597c387d0 100644 --- a/openpype/cli.py +++ b/openpype/cli.py @@ -419,9 +419,9 @@ def repack_version(directory): @click.option( "--dirpath", help="Directory where package is stored", default=None ) -def pack_project(project_name, dirpath): +def pack_project(project, dirpath): """Create a package of project with all files and database dump.""" - PypeCommands().pack_project(project_name, dirpath) + PypeCommands().pack_project(project, dirpath) @main.command() @@ -429,6 +429,6 @@ def pack_project(project_name, dirpath): @click.option( "--root", help="Replace root which was stored in project", default=None ) -def uppack_project(zipfile, root): +def unpack_project(zipfile, root): """Create a package of project with all files and database dump.""" PypeCommands().unpack_project(zipfile, root) diff --git a/openpype/lib/project_backpack.py b/openpype/lib/project_backpack.py index 045e8b4ea1..42dc8a4f63 100644 --- a/openpype/lib/project_backpack.py +++ b/openpype/lib/project_backpack.py @@ -53,6 +53,7 @@ def pack_project(project_name, destination_dir=None): destination_dir(str): Optinal path where zip will be stored. Project's root is used if not passed. """ + print("Creating package of project \"{}\"".format(project_name)) # Validate existence of project dbcon = AvalonMongoDB() dbcon.Session["AVALON_PROJECT"] = project_name @@ -74,7 +75,7 @@ def pack_project(project_name, destination_dir=None): root_path = source_root[platform.system().lower()] print("Using root \"{}\" with path \"{}\"".format( - root_name, root_value + root_name, root_path )) project_source_path = os.path.join(root_path, project_name) @@ -85,12 +86,13 @@ def pack_project(project_name, destination_dir=None): if not destination_dir: destination_dir = root_path + destination_dir = os.path.normpath(destination_dir) if not os.path.exists(destination_dir): os.makedirs(destination_dir) zip_path = os.path.join(destination_dir, project_name + ".zip") - print("Project will be packaged into {}".format(zip_path)) + print("Project will be packaged into \"{}\"".format(zip_path)) # Rename already existing zip if os.path.exists(zip_path): dst_filepath = add_timestamp(zip_path) @@ -121,6 +123,7 @@ def pack_project(project_name, destination_dir=None): with open(temp_docs_json, "w") as stream: stream.write(data) + print("Packing files into zip") # Write all to zip file with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zip_stream: # Add metadata file @@ -138,10 +141,12 @@ def pack_project(project_name, destination_dir=None): ) zip_stream.write(filepath, archive_name) + print("Cleaning up") # Cleanup os.remove(temp_docs_json) os.remove(temp_metadata_json) dbcon.uninstall() + print("*** Packing finished ***") def unpack_project(path_to_zip, new_root=None): @@ -153,12 +158,13 @@ def unpack_project(path_to_zip, new_root=None): new_root(str): Optional way how to set different root path for unpacked project. """ + print("Unpacking project from zip {}".format(path_to_zip)) if not os.path.exists(path_to_zip): print("Zip file does not exists: {}".format(path_to_zip)) return tmp_dir = tempfile.mkdtemp(prefix="unpack_") - print("Zip is extracted to: {}".format(tmp_dir)) + print("Zip is extracted to temp: {}".format(tmp_dir)) with zipfile.ZipFile(path_to_zip, "r") as zip_stream: zip_stream.extractall(tmp_dir) @@ -183,9 +189,9 @@ def unpack_project(path_to_zip, new_root=None): database.drop_collection(project_name) print("Removed existing project collection") - collection = database[project_name] - # Create new collection with loaded docs print("Creating project documents ({})".format(len(docs))) + # Create new collection with loaded docs + collection = database[project_name] collection.insert_many(docs) # Skip change of root if is the same as the one stored in metadata @@ -217,16 +223,23 @@ def unpack_project(path_to_zip, new_root=None): src_project_files_dir = os.path.join( tmp_dir, PROJECT_FILES_DIR, project_name ) - dst_project_files_dir = os.path.join(root_path, project_name) + dst_project_files_dir = os.path.normpath( + os.path.join(root_path, project_name) + ) if os.path.exists(dst_project_files_dir): new_path = add_timestamp(dst_project_files_dir) + print("Project folder already exists. Renamed \"{}\" -> \"{}\"".format( + dst_project_files_dir, new_path + )) os.rename(dst_project_files_dir, new_path) - print("Moving {} -> {}".format( + print("Moving project files from temp \"{}\" -> \"{}\"".format( src_project_files_dir, dst_project_files_dir )) shutil.move(src_project_files_dir, dst_project_files_dir) # CLeanup + print("Cleaning up") shutil.rmtree(tmp_dir) dbcon.uninstall() + print("*** Unpack finished ***") diff --git a/openpype/pype_commands.py b/openpype/pype_commands.py index e5db036c04..1ed6cc9344 100644 --- a/openpype/pype_commands.py +++ b/openpype/pype_commands.py @@ -434,12 +434,12 @@ class PypeCommands: version_packer = VersionRepacker(directory) version_packer.process() - def pack_project(project_name, dirpath): + def pack_project(self, project_name, dirpath): from openpype.lib.project_backpack import pack_project pack_project(project_name, dirpath) - def unpack_project(zip_filepath, new_root): + def unpack_project(self, zip_filepath, new_root): from openpype.lib.project_backpack import unpack_project unpack_project(zip_filepath, new_root) From 9a3f74735eda5f17e1f4b6239a33ee29ac22dbaa Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 2 Feb 2022 16:41:07 +0100 Subject: [PATCH 50/74] fix unset variable name --- openpype/lib/project_backpack.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openpype/lib/project_backpack.py b/openpype/lib/project_backpack.py index 42dc8a4f63..11fd0c0c3e 100644 --- a/openpype/lib/project_backpack.py +++ b/openpype/lib/project_backpack.py @@ -66,16 +66,18 @@ def pack_project(project_name, destination_dir=None): roots = project_doc["config"]["roots"] # Determine root directory of project source_root = None + source_root_name = None for root_name, root_value in roots.items(): if source_root is not None: raise ValueError( "Packaging is supported only for single root projects" ) source_root = root_value + source_root_name = root_name root_path = source_root[platform.system().lower()] print("Using root \"{}\" with path \"{}\"".format( - root_name, root_path + source_root_name, root_path )) project_source_path = os.path.join(root_path, project_name) From 5e050b6d5d3777076277638c805a35049d3a3246 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Wed, 2 Feb 2022 18:52:02 +0100 Subject: [PATCH 51/74] OP-2505 - fix skip already created subset --- .../publish/collect_remote_instances.py | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/openpype/hosts/photoshop/plugins/publish/collect_remote_instances.py b/openpype/hosts/photoshop/plugins/publish/collect_remote_instances.py index 2a07c684da..97634678df 100644 --- a/openpype/hosts/photoshop/plugins/publish/collect_remote_instances.py +++ b/openpype/hosts/photoshop/plugins/publish/collect_remote_instances.py @@ -9,7 +9,7 @@ from openpype.hosts.photoshop import api as photoshop class CollectRemoteInstances(pyblish.api.ContextPlugin): - """Gather instances configured color code of a layer. + """Creates instances for configured color code of a layer. Used in remote publishing when artists marks publishable layers by color- coding. @@ -46,6 +46,11 @@ class CollectRemoteInstances(pyblish.api.ContextPlugin): stub = photoshop.stub() layers = stub.get_layers() + existing_subset_names = [] + for instance in context: + if instance.data.get('publish'): + existing_subset_names.append(instance.data.get('subset')) + asset, task_name, task_type = get_batch_asset_task_info( task_data["context"]) @@ -70,21 +75,27 @@ class CollectRemoteInstances(pyblish.api.ContextPlugin): self.log.debug("!!! Not a top layer, skip") continue + fill_pairs = { + "variant": variant, + "family": resolved_family, + "task": task_name, + "layer": layer.name + } + + subset = resolved_subset_template.format( + **prepare_template_data(fill_pairs)) + + if subset in existing_subset_names: + self.log.info( + "Subset {} already created, skipping.".format(subset)) + continue + instance = context.create_instance(layer.name) instance.append(layer) instance.data["family"] = resolved_family instance.data["publish"] = layer.visible instance.data["asset"] = asset instance.data["task"] = task_name - - fill_pairs = { - "variant": variant, - "family": instance.data["family"], - "task": instance.data["task"], - "layer": layer.name - } - subset = resolved_subset_template.format( - **prepare_template_data(fill_pairs)) instance.data["subset"] = subset instance_names.append(layer.name) From fe46093ada0494b745b1e8e7263bd9489dd665bd Mon Sep 17 00:00:00 2001 From: "clement.hector" Date: Wed, 2 Feb 2022 19:36:49 +0100 Subject: [PATCH 52/74] fix test on string to boolean --- openpype/hosts/photoshop/api/lib.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/photoshop/api/lib.py b/openpype/hosts/photoshop/api/lib.py index 707cd476c5..10d9e33543 100644 --- a/openpype/hosts/photoshop/api/lib.py +++ b/openpype/hosts/photoshop/api/lib.py @@ -2,7 +2,7 @@ import os import sys import contextlib import traceback - +import ast from Qt import QtWidgets import avalon.api @@ -41,7 +41,8 @@ def main(*subprocess_args): "ClosePS", os.environ.get("IS_TEST") ) - elif os.environ.get("AVALON_PHOTOSHOP_WORKFILES_ON_LAUNCH", True): + elif ast.literal_eval( + os.getenv("AVALON_PHOTOSHOP_WORKFILES_ON_LAUNCH", True)): save = False if os.getenv("WORKFILES_SAVE_AS"): save = True From de2d6dd83d9b89574bdfb28d0f9a61fffa8956cc Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 3 Feb 2022 10:45:59 +0100 Subject: [PATCH 53/74] image loaders also work on review family --- openpype/hosts/tvpaint/plugins/load/load_image.py | 2 +- openpype/hosts/tvpaint/plugins/load/load_reference_image.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/tvpaint/plugins/load/load_image.py b/openpype/hosts/tvpaint/plugins/load/load_image.py index 1246fe8248..7dba1e3619 100644 --- a/openpype/hosts/tvpaint/plugins/load/load_image.py +++ b/openpype/hosts/tvpaint/plugins/load/load_image.py @@ -5,7 +5,7 @@ from openpype.hosts.tvpaint.api import lib, plugin class ImportImage(plugin.Loader): """Load image or image sequence to TVPaint as new layer.""" - families = ["render", "image", "background", "plate"] + families = ["render", "image", "background", "plate", "review"] representations = ["*"] label = "Import Image" diff --git a/openpype/hosts/tvpaint/plugins/load/load_reference_image.py b/openpype/hosts/tvpaint/plugins/load/load_reference_image.py index b5e0a86686..0a85e5dc76 100644 --- a/openpype/hosts/tvpaint/plugins/load/load_reference_image.py +++ b/openpype/hosts/tvpaint/plugins/load/load_reference_image.py @@ -7,7 +7,7 @@ from openpype.hosts.tvpaint.api import lib, pipeline, plugin class LoadImage(plugin.Loader): """Load image or image sequence to TVPaint as new layer.""" - families = ["render", "image", "background", "plate"] + families = ["render", "image", "background", "plate", "review"] representations = ["*"] label = "Load Image" From a623dbd0a4e5968f550c5fb11ee7ced453d2bbb3 Mon Sep 17 00:00:00 2001 From: OpenPype Date: Thu, 3 Feb 2022 10:30:37 +0000 Subject: [PATCH 54/74] [Automated] Bump version --- CHANGELOG.md | 19 +++++++++++++------ openpype/version.py | 2 +- pyproject.toml | 2 +- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 70089e4868..0224ea957c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,21 @@ # Changelog -## [3.8.2-nightly.1](https://github.com/pypeclub/OpenPype/tree/HEAD) +## [3.8.2-nightly.2](https://github.com/pypeclub/OpenPype/tree/HEAD) [Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.8.1...HEAD) +### 📖 Documentation + +- Cosmetics: Fix common typos in openpype/website [\#2617](https://github.com/pypeclub/OpenPype/pull/2617) + +**🚀 Enhancements** + +- nuke: adding clear button to write nodes [\#2627](https://github.com/pypeclub/OpenPype/pull/2627) +- Ftrack: Family to Asset type mapping is in settings [\#2602](https://github.com/pypeclub/OpenPype/pull/2602) + **🐛 Bug fixes** +- Fix pulling of cx\_freeze 6.10 [\#2628](https://github.com/pypeclub/OpenPype/pull/2628) - Global: fix broken otio review extractor [\#2590](https://github.com/pypeclub/OpenPype/pull/2590) **Merged pull requests:** @@ -20,7 +30,6 @@ - Webpublisher: Thumbnail extractor [\#2600](https://github.com/pypeclub/OpenPype/pull/2600) - Loader: Allow to toggle default family filters between "include" or "exclude" filtering [\#2541](https://github.com/pypeclub/OpenPype/pull/2541) -- Launcher: Added context menu to to skip opening last workfile [\#2536](https://github.com/pypeclub/OpenPype/pull/2536) **🐛 Bug fixes** @@ -64,10 +73,12 @@ - Settings: PathInput strip passed string [\#2550](https://github.com/pypeclub/OpenPype/pull/2550) - Global: Exctract Review anatomy fill data with output name [\#2548](https://github.com/pypeclub/OpenPype/pull/2548) - Cosmetics: Clean up some cosmetics / typos [\#2542](https://github.com/pypeclub/OpenPype/pull/2542) +- Launcher: Added context menu to to skip opening last workfile [\#2536](https://github.com/pypeclub/OpenPype/pull/2536) - General: Validate if current process OpenPype version is requested version [\#2529](https://github.com/pypeclub/OpenPype/pull/2529) - General: Be able to use anatomy data in ffmpeg output arguments [\#2525](https://github.com/pypeclub/OpenPype/pull/2525) - Expose toggle publish plug-in settings for Maya Look Shading Engine Naming [\#2521](https://github.com/pypeclub/OpenPype/pull/2521) - Photoshop: Move implementation to OpenPype [\#2510](https://github.com/pypeclub/OpenPype/pull/2510) +- TimersManager: Move module one hierarchy higher [\#2501](https://github.com/pypeclub/OpenPype/pull/2501) - Slack: notifications are sent with Openpype logo and bot name [\#2499](https://github.com/pypeclub/OpenPype/pull/2499) - Slack: Add review to notification message [\#2498](https://github.com/pypeclub/OpenPype/pull/2498) - Maya: Collect 'fps' animation data only for "review" instances [\#2486](https://github.com/pypeclub/OpenPype/pull/2486) @@ -104,10 +115,6 @@ [Full Changelog](https://github.com/pypeclub/OpenPype/compare/CI/3.7.0-nightly.14...3.7.0) -**🚀 Enhancements** - -- General: Workdir extra folders [\#2462](https://github.com/pypeclub/OpenPype/pull/2462) - **🐛 Bug fixes** - TVPaint: Create render layer dialog is in front [\#2471](https://github.com/pypeclub/OpenPype/pull/2471) diff --git a/openpype/version.py b/openpype/version.py index 4fa91e280b..5ebc6d00c8 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.8.2-nightly.1" +__version__ = "3.8.2-nightly.2" diff --git a/pyproject.toml b/pyproject.toml index 7d16b2e62e..68713802cf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "OpenPype" -version = "3.8.2-nightly.1" # OpenPype +version = "3.8.2-nightly.2" # OpenPype description = "Open VFX and Animation pipeline with support." authors = ["OpenPype Team "] license = "MIT License" From b39b5e58c173d52a4d3a7473a1e53f01582fc3e2 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 3 Feb 2022 11:44:09 +0100 Subject: [PATCH 55/74] OP-2505 - better validation message --- .../plugins/publish/validate_unique_subsets.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/photoshop/plugins/publish/validate_unique_subsets.py b/openpype/hosts/photoshop/plugins/publish/validate_unique_subsets.py index 15ae5fbcea..e000352601 100644 --- a/openpype/hosts/photoshop/plugins/publish/validate_unique_subsets.py +++ b/openpype/hosts/photoshop/plugins/publish/validate_unique_subsets.py @@ -1,3 +1,4 @@ +import collections import pyblish.api import openpype.api @@ -16,11 +17,16 @@ class ValidateSubsetUniqueness(pyblish.api.ContextPlugin): subset_names = [] for instance in context: + self.log.info("instance:: {}".format(instance.data)) if instance.data.get('publish'): subset_names.append(instance.data.get('subset')) + non_unique = \ + [item + for item, count in collections.Counter(subset_names).items() + if count > 1] msg = ( - "Instance subset names are not unique. " + - "Remove duplicates via SubsetManager." + "Instance subset names {} are not unique. " + + "Remove duplicates via SubsetManager.".format(non_unique) ) - assert len(subset_names) == len(set(subset_names)), msg + assert not non_unique, msg From 3089438234b64347c3a7b1a33bf42167eb7b761a Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 3 Feb 2022 11:45:34 +0100 Subject: [PATCH 56/74] OP-2505 - better order --- .../photoshop/plugins/publish/collect_remote_instances.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/photoshop/plugins/publish/collect_remote_instances.py b/openpype/hosts/photoshop/plugins/publish/collect_remote_instances.py index 97634678df..48c6f583a4 100644 --- a/openpype/hosts/photoshop/plugins/publish/collect_remote_instances.py +++ b/openpype/hosts/photoshop/plugins/publish/collect_remote_instances.py @@ -60,6 +60,10 @@ class CollectRemoteInstances(pyblish.api.ContextPlugin): instance_names = [] for layer in layers: self.log.debug("Layer:: {}".format(layer)) + if layer.parents: + self.log.debug("!!! Not a top layer, skip") + continue + resolved_family, resolved_subset_template = self._resolve_mapping( layer ) @@ -71,10 +75,6 @@ class CollectRemoteInstances(pyblish.api.ContextPlugin): self.log.debug("!!! Not found family or template, skip") continue - if layer.parents: - self.log.debug("!!! Not a top layer, skip") - continue - fill_pairs = { "variant": variant, "family": resolved_family, From 1c700faacfc6ee23e6bcd0b7fc33841f100c6368 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 3 Feb 2022 11:46:27 +0100 Subject: [PATCH 57/74] OP-2505 - safer initialization --- openpype/pype_commands.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openpype/pype_commands.py b/openpype/pype_commands.py index de0336be2b..2b19075341 100644 --- a/openpype/pype_commands.py +++ b/openpype/pype_commands.py @@ -251,7 +251,10 @@ class PypeCommands: data = { "last_workfile_path": workfile_path, - "start_last_workfile": True + "start_last_workfile": True, + "project_name": project, + "asset_name": asset, + "task_name": task_name } launched_app = application_manager.launch(app_name, **data) From 78b3e9dad86b58bd3eda378c18037f4726f2c934 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 3 Feb 2022 12:14:13 +0100 Subject: [PATCH 58/74] OP-2505 - fixed message --- .../photoshop/plugins/publish/validate_unique_subsets.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/photoshop/plugins/publish/validate_unique_subsets.py b/openpype/hosts/photoshop/plugins/publish/validate_unique_subsets.py index e000352601..40abfb1bbd 100644 --- a/openpype/hosts/photoshop/plugins/publish/validate_unique_subsets.py +++ b/openpype/hosts/photoshop/plugins/publish/validate_unique_subsets.py @@ -25,8 +25,6 @@ class ValidateSubsetUniqueness(pyblish.api.ContextPlugin): [item for item, count in collections.Counter(subset_names).items() if count > 1] - msg = ( - "Instance subset names {} are not unique. " + - "Remove duplicates via SubsetManager.".format(non_unique) - ) + msg = ("Instance subset names {} are not unique. ".format(non_unique) + + "Remove duplicates via SubsetManager.") assert not non_unique, msg From 4103654c4ca2fc4775f226454797cb09c47daa2a Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 3 Feb 2022 14:20:52 +0100 Subject: [PATCH 59/74] OP-2505 - removed explicit exit, breaks closing of console --- openpype/lib/remote_publish.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/openpype/lib/remote_publish.py b/openpype/lib/remote_publish.py index 9632e63ea0..ced03ea613 100644 --- a/openpype/lib/remote_publish.py +++ b/openpype/lib/remote_publish.py @@ -88,7 +88,6 @@ def publish(log, close_plugin_name=None): if close_plugin: # close host app explicitly after error context = pyblish.api.Context() close_plugin().process(context) - sys.exit(1) def publish_and_log(dbcon, _id, log, close_plugin_name=None, batch_id=None): @@ -137,7 +136,6 @@ def publish_and_log(dbcon, _id, log, close_plugin_name=None, batch_id=None): if close_plugin: # close host app explicitly after error context = pyblish.api.Context() close_plugin().process(context) - sys.exit(1) elif processed % log_every == 0: # pyblish returns progress in 0.0 - 2.0 progress = min(round(result["progress"] / 2 * 100), 99) From 13519cfcda8cf71ee772328f8aaa689d9168523b Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 3 Feb 2022 14:54:19 +0100 Subject: [PATCH 60/74] OP-2505 - added return --- openpype/lib/remote_publish.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/lib/remote_publish.py b/openpype/lib/remote_publish.py index ced03ea613..871eb82f11 100644 --- a/openpype/lib/remote_publish.py +++ b/openpype/lib/remote_publish.py @@ -136,6 +136,7 @@ def publish_and_log(dbcon, _id, log, close_plugin_name=None, batch_id=None): if close_plugin: # close host app explicitly after error context = pyblish.api.Context() close_plugin().process(context) + return elif processed % log_every == 0: # pyblish returns progress in 0.0 - 2.0 progress = min(round(result["progress"] / 2 * 100), 99) From 99eb61abaf727cf3aada1c971f872bb484da52b7 Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Thu, 3 Feb 2022 18:28:54 +0100 Subject: [PATCH 61/74] fix pyenv, enhance dockerfile metadata --- Dockerfile | 35 ++++++++++++++++++++++++----------- Dockerfile.centos7 | 6 +++++- tools/docker_build.sh | 2 +- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/Dockerfile b/Dockerfile index cef83b5811..7232223c3c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,18 @@ # Build Pype docker image -FROM debian:bookworm-slim AS builder +FROM ubuntu:focal AS builder ARG OPENPYPE_PYTHON_VERSION=3.7.12 +ARG BUILD_DATE +ARG VERSION LABEL maintainer="info@openpype.io" -LABEL description="Docker Image to build and run OpenPype" +LABEL description="Docker Image to build and run OpenPype under Ubuntu 20.04" LABEL org.opencontainers.image.name="pypeclub/openpype" LABEL org.opencontainers.image.title="OpenPype Docker Image" LABEL org.opencontainers.image.url="https://openpype.io/" -LABEL org.opencontainers.image.source="https://github.com/pypeclub/pype" +LABEL org.opencontainers.image.source="https://github.com/pypeclub/OpenPype" +LABEL org.opencontainers.image.documentation="https://openpype.io/docs/system_introduction" +LABEL org.opencontainers.image.created=$BUILD_DATE +LABEL org.opencontainers.image.version=$VERSION USER root @@ -42,14 +47,19 @@ RUN apt-get update \ SHELL ["/bin/bash", "-c"] + RUN mkdir /opt/openpype +# download and install pyenv RUN curl https://pyenv.run | bash \ - && echo 'export PATH="$HOME/.pyenv/bin:$PATH"'>> $HOME/.bashrc \ - && echo 'eval "$(pyenv init -)"' >> $HOME/.bashrc \ - && echo 'eval "$(pyenv virtualenv-init -)"' >> $HOME/.bashrc \ - && echo 'eval "$(pyenv init --path)"' >> $HOME/.bashrc \ - && source $HOME/.bashrc && pyenv install ${OPENPYPE_PYTHON_VERSION} + && echo 'export PATH="$HOME/.pyenv/bin:$PATH"'>> $HOME/init_pyenv.sh \ + && echo 'eval "$(pyenv init -)"' >> $HOME/init_pyenv.sh \ + && echo 'eval "$(pyenv virtualenv-init -)"' >> $HOME/init_pyenv.sh \ + && echo 'eval "$(pyenv init --path)"' >> $HOME/init_pyenv.sh + +# install python with pyenv +RUN source $HOME/init_pyenv.sh \ + && pyenv install ${OPENPYPE_PYTHON_VERSION} COPY . /opt/openpype/ @@ -57,13 +67,16 @@ RUN chmod +x /opt/openpype/tools/create_env.sh && chmod +x /opt/openpype/tools/b WORKDIR /opt/openpype +# set local python version RUN cd /opt/openpype \ - && source $HOME/.bashrc \ + && source $HOME/init_pyenv.sh \ && pyenv local ${OPENPYPE_PYTHON_VERSION} -RUN source $HOME/.bashrc \ +# fetch third party tools/libraries +RUN source $HOME/init_pyenv.sh \ && ./tools/create_env.sh \ && ./tools/fetch_thirdparty_libs.sh -RUN source $HOME/.bashrc \ +# build openpype +RUN source $HOME/init_pyenv.sh \ && bash ./tools/build.sh diff --git a/Dockerfile.centos7 b/Dockerfile.centos7 index 736a42663c..16cb02cd20 100644 --- a/Dockerfile.centos7 +++ b/Dockerfile.centos7 @@ -1,11 +1,15 @@ # Build Pype docker image FROM centos:7 AS builder -ARG OPENPYPE_PYTHON_VERSION=3.7.10 +ARG OPENPYPE_PYTHON_VERSION=3.7.12 LABEL org.opencontainers.image.name="pypeclub/openpype" LABEL org.opencontainers.image.title="OpenPype Docker Image" LABEL org.opencontainers.image.url="https://openpype.io/" LABEL org.opencontainers.image.source="https://github.com/pypeclub/pype" +LABEL org.opencontainers.image.documentation="https://openpype.io/docs/system_introduction" +LABEL org.opencontainers.image.created=$BUILD_DATE +LABEL org.opencontainers.image.version=$VERSION + USER root diff --git a/tools/docker_build.sh b/tools/docker_build.sh index 04c26424eb..7d61986883 100755 --- a/tools/docker_build.sh +++ b/tools/docker_build.sh @@ -68,7 +68,7 @@ main () { echo -e "${BIGreen}>>>${RST} Running docker build ..." # docker build --pull --no-cache -t pypeclub/openpype:$openpype_version . - docker build --pull --iidfile $openpype_root/build/docker-image.id -t pypeclub/openpype:$openpype_version -f $dockerfile . + docker build --pull --iidfile $openpype_root/build/docker-image.id --build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') --build-arg VERSION=$openpype_version -t pypeclub/openpype:$openpype_version -f $dockerfile . if [ $? -ne 0 ] ; then echo $? echo -e "${BIRed}!!!${RST} Docker build failed." From f94f636ff20f438cd470dc2ef0258a69b29b27e1 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Thu, 3 Feb 2022 18:44:27 +0100 Subject: [PATCH 62/74] moved maya implementation to openpype --- openpype/hosts/maya/__init__.py | 4 +- openpype/hosts/maya/api/__init__.py | 293 +++------ openpype/hosts/maya/api/action.py | 5 +- openpype/hosts/maya/api/commands.py | 134 ++++ openpype/hosts/maya/api/customize.py | 10 +- openpype/hosts/maya/api/lib.py | 486 +++++++++++++- openpype/hosts/maya/api/menu.py | 268 ++++---- openpype/hosts/maya/api/pipeline.py | 594 ++++++++++++++++++ openpype/hosts/maya/api/plugin.py | 39 +- openpype/hosts/maya/api/setdress.py | 8 +- openpype/hosts/maya/api/workio.py | 67 ++ .../plugins/inventory/import_modelrender.py | 15 +- .../maya/plugins/load/_load_animation.py | 10 +- openpype/hosts/maya/plugins/load/actions.py | 11 +- openpype/hosts/maya/plugins/load/load_ass.py | 21 +- .../hosts/maya/plugins/load/load_assembly.py | 14 +- .../hosts/maya/plugins/load/load_audio.py | 8 +- .../hosts/maya/plugins/load/load_gpucache.py | 6 +- .../maya/plugins/load/load_image_plane.py | 9 +- openpype/hosts/maya/plugins/load/load_look.py | 21 +- .../maya/plugins/load/load_redshift_proxy.py | 23 +- .../hosts/maya/plugins/load/load_reference.py | 12 +- .../maya/plugins/load/load_rendersetup.py | 7 +- .../maya/plugins/load/load_vdb_to_redshift.py | 9 +- .../maya/plugins/load/load_vdb_to_vray.py | 8 +- .../hosts/maya/plugins/load/load_vrayproxy.py | 13 +- .../hosts/maya/plugins/load/load_vrayscene.py | 21 +- .../maya/plugins/load/load_yeti_cache.py | 26 +- .../hosts/maya/plugins/load/load_yeti_rig.py | 3 +- .../maya/plugins/publish/collect_assembly.py | 4 +- .../maya/plugins/publish/collect_render.py | 4 +- .../maya/plugins/publish/extract_animation.py | 11 +- .../hosts/maya/plugins/publish/extract_ass.py | 4 +- .../maya/plugins/publish/extract_assproxy.py | 8 +- .../plugins/publish/extract_camera_alembic.py | 6 +- .../publish/extract_camera_mayaScene.py | 5 +- .../hosts/maya/plugins/publish/extract_fbx.py | 12 +- .../maya/plugins/publish/extract_look.py | 5 +- .../plugins/publish/extract_maya_scene_raw.py | 4 +- .../maya/plugins/publish/extract_model.py | 3 +- .../plugins/publish/extract_pointcache.py | 11 +- .../plugins/publish/extract_redshift_proxy.py | 8 +- .../hosts/maya/plugins/publish/extract_rig.py | 4 +- .../maya/plugins/publish/extract_vrayproxy.py | 8 +- .../maya/plugins/publish/extract_vrayscene.py | 4 +- .../plugins/publish/extract_xgen_cache.py | 9 +- .../maya/plugins/publish/extract_yeti_rig.py | 3 +- .../plugins/publish/validate_cycle_error.py | 5 +- .../validate_mesh_arnold_attributes.py | 4 +- .../plugins/publish/validate_mesh_ngons.py | 1 - .../plugins/publish/validate_shape_zero.py | 4 +- openpype/hosts/maya/startup/userSetup.py | 4 + 52 files changed, 1707 insertions(+), 569 deletions(-) create mode 100644 openpype/hosts/maya/api/pipeline.py create mode 100644 openpype/hosts/maya/api/workio.py diff --git a/openpype/hosts/maya/__init__.py b/openpype/hosts/maya/__init__.py index 549f100007..b7d26a7818 100644 --- a/openpype/hosts/maya/__init__.py +++ b/openpype/hosts/maya/__init__.py @@ -5,9 +5,7 @@ def add_implementation_envs(env, _app): # Add requirements to PYTHONPATH pype_root = os.environ["OPENPYPE_REPOS_ROOT"] new_python_paths = [ - os.path.join(pype_root, "openpype", "hosts", "maya", "startup"), - os.path.join(pype_root, "repos", "avalon-core", "setup", "maya"), - os.path.join(pype_root, "tools", "mayalookassigner") + os.path.join(pype_root, "openpype", "hosts", "maya", "startup") ] old_python_path = env.get("PYTHONPATH") or "" for path in old_python_path.split(os.pathsep): diff --git a/openpype/hosts/maya/api/__init__.py b/openpype/hosts/maya/api/__init__.py index 0ad1c8ba29..1b75076028 100644 --- a/openpype/hosts/maya/api/__init__.py +++ b/openpype/hosts/maya/api/__init__.py @@ -1,233 +1,90 @@ -import os -import logging -import weakref +"""Public API -from maya import utils, cmds +Anything that isn't defined here is INTERNAL and unreliable for external use. -from avalon import api as avalon -from avalon import pipeline -from avalon.maya import suspended_refresh -from avalon.maya.pipeline import IS_HEADLESS -from openpype.tools.utils import host_tools -from pyblish import api as pyblish -from openpype.lib import any_outdated -import openpype.hosts.maya -from openpype.hosts.maya.lib import copy_workspace_mel -from openpype.lib.path_tools import HostDirmap -from . import menu, lib +""" -log = logging.getLogger("openpype.hosts.maya") +from .pipeline import ( + install, + uninstall, -HOST_DIR = os.path.dirname(os.path.abspath(openpype.hosts.maya.__file__)) -PLUGINS_DIR = os.path.join(HOST_DIR, "plugins") -PUBLISH_PATH = os.path.join(PLUGINS_DIR, "publish") -LOAD_PATH = os.path.join(PLUGINS_DIR, "load") -CREATE_PATH = os.path.join(PLUGINS_DIR, "create") -INVENTORY_PATH = os.path.join(PLUGINS_DIR, "inventory") + ls, + containerise, + + lock, + unlock, + is_locked, + lock_ignored, + +) +from .plugin import ( + Creator, + Loader +) + +from .workio import ( + open_file, + save_file, + current_file, + has_unsaved_changes, + file_extensions, + work_root +) + +from .lib import ( + export_alembic, + lsattr, + lsattrs, + read, + + apply_shaders, + without_extension, + maintained_selection, + suspended_refresh, + + unique_name, + unique_namespace, +) -def install(): - from openpype.settings import get_project_settings +__all__ = [ + "install", + "uninstall", - project_settings = get_project_settings(os.getenv("AVALON_PROJECT")) - # process path mapping - dirmap_processor = MayaDirmap("maya", project_settings) - dirmap_processor.process_dirmap() + "Creator", + "Loader", - pyblish.register_plugin_path(PUBLISH_PATH) - avalon.register_plugin_path(avalon.Loader, LOAD_PATH) - avalon.register_plugin_path(avalon.Creator, CREATE_PATH) - avalon.register_plugin_path(avalon.InventoryAction, INVENTORY_PATH) - log.info(PUBLISH_PATH) - menu.install() + "ls", - log.info("Installing callbacks ... ") - avalon.on("init", on_init) + "lock", + "unlock", + "is_locked", + "lock_ignored", - # Callbacks below are not required for headless mode, the `init` however - # is important to load referenced Alembics correctly at rendertime. - if IS_HEADLESS: - log.info("Running in headless mode, skipping Maya " - "save/open/new callback installation..") - return + # Workfiles API + "open_file", + "save_file", + "current_file", + "has_unsaved_changes", + "file_extensions", + "work_root", - avalon.on("save", on_save) - avalon.on("open", on_open) - avalon.on("new", on_new) - avalon.before("save", on_before_save) - avalon.on("taskChanged", on_task_changed) - avalon.on("before.workfile.save", before_workfile_save) + # Utility functions + "export_alembic", + "lsattr", + "lsattrs", + "read", - log.info("Setting default family states for loader..") - avalon.data["familiesStateToggled"] = ["imagesequence"] + "unique_name", + "unique_namespace", + "apply_shaders", + "without_extension", + "maintained_selection", + "suspended_refresh", -def uninstall(): - pyblish.deregister_plugin_path(PUBLISH_PATH) - avalon.deregister_plugin_path(avalon.Loader, LOAD_PATH) - avalon.deregister_plugin_path(avalon.Creator, CREATE_PATH) - avalon.deregister_plugin_path(avalon.InventoryAction, INVENTORY_PATH) +] - menu.uninstall() - - -def on_init(_): - avalon.logger.info("Running callback on init..") - - def safe_deferred(fn): - """Execute deferred the function in a try-except""" - - def _fn(): - """safely call in deferred callback""" - try: - fn() - except Exception as exc: - print(exc) - - try: - utils.executeDeferred(_fn) - except Exception as exc: - print(exc) - - # Force load Alembic so referenced alembics - # work correctly on scene open - cmds.loadPlugin("AbcImport", quiet=True) - cmds.loadPlugin("AbcExport", quiet=True) - - # Force load objExport plug-in (requested by artists) - cmds.loadPlugin("objExport", quiet=True) - - from .customize import ( - override_component_mask_commands, - override_toolbox_ui - ) - safe_deferred(override_component_mask_commands) - - launch_workfiles = os.environ.get("WORKFILES_STARTUP") - - if launch_workfiles: - safe_deferred(host_tools.show_workfiles) - - if not IS_HEADLESS: - safe_deferred(override_toolbox_ui) - - -def on_before_save(return_code, _): - """Run validation for scene's FPS prior to saving""" - return lib.validate_fps() - - -def on_save(_): - """Automatically add IDs to new nodes - - Any transform of a mesh, without an existing ID, is given one - automatically on file save. - """ - - avalon.logger.info("Running callback on save..") - - # # Update current task for the current scene - # update_task_from_path(cmds.file(query=True, sceneName=True)) - - # Generate ids of the current context on nodes in the scene - nodes = lib.get_id_required_nodes(referenced_nodes=False) - for node, new_id in lib.generate_ids(nodes): - lib.set_id(node, new_id, overwrite=False) - - -def on_open(_): - """On scene open let's assume the containers have changed.""" - - from Qt import QtWidgets - from openpype.widgets import popup - - cmds.evalDeferred( - "from openpype.hosts.maya.api import lib;" - "lib.remove_render_layer_observer()") - cmds.evalDeferred( - "from openpype.hosts.maya.api import lib;" - "lib.add_render_layer_observer()") - cmds.evalDeferred( - "from openpype.hosts.maya.api import lib;" - "lib.add_render_layer_change_observer()") - # # Update current task for the current scene - # update_task_from_path(cmds.file(query=True, sceneName=True)) - - # Validate FPS after update_task_from_path to - # ensure it is using correct FPS for the asset - lib.validate_fps() - lib.fix_incompatible_containers() - - if any_outdated(): - log.warning("Scene has outdated content.") - - # Find maya main window - top_level_widgets = {w.objectName(): w for w in - QtWidgets.QApplication.topLevelWidgets()} - parent = top_level_widgets.get("MayaWindow", None) - - if parent is None: - log.info("Skipping outdated content pop-up " - "because Maya window can't be found.") - else: - - # Show outdated pop-up - def _on_show_inventory(): - host_tools.show_scene_inventory(parent=parent) - - dialog = popup.Popup(parent=parent) - dialog.setWindowTitle("Maya scene has outdated content") - dialog.setMessage("There are outdated containers in " - "your Maya scene.") - dialog.on_show.connect(_on_show_inventory) - dialog.show() - - -def on_new(_): - """Set project resolution and fps when create a new file""" - avalon.logger.info("Running callback on new..") - with suspended_refresh(): - cmds.evalDeferred( - "from openpype.hosts.maya.api import lib;" - "lib.remove_render_layer_observer()") - cmds.evalDeferred( - "from openpype.hosts.maya.api import lib;" - "lib.add_render_layer_observer()") - cmds.evalDeferred( - "from openpype.hosts.maya.api import lib;" - "lib.add_render_layer_change_observer()") - lib.set_context_settings() - - -def on_task_changed(*args): - """Wrapped function of app initialize and maya's on task changed""" - # Run - with suspended_refresh(): - lib.set_context_settings() - lib.update_content_on_context_change() - - msg = " project: {}\n asset: {}\n task:{}".format( - avalon.Session["AVALON_PROJECT"], - avalon.Session["AVALON_ASSET"], - avalon.Session["AVALON_TASK"] - ) - - lib.show_message( - "Context was changed", - ("Context was changed to:\n{}".format(msg)), - ) - - -def before_workfile_save(event): - workdir_path = event.workdir_path - if workdir_path: - copy_workspace_mel(workdir_path) - - -class MayaDirmap(HostDirmap): - def on_enable_dirmap(self): - cmds.dirmap(en=True) - - def dirmap_routine(self, source_path, destination_path): - cmds.dirmap(m=(source_path, destination_path)) - cmds.dirmap(m=(destination_path, source_path)) +# Backwards API compatibility +open = open_file +save = save_file diff --git a/openpype/hosts/maya/api/action.py b/openpype/hosts/maya/api/action.py index a98b906d8c..ab26748c8a 100644 --- a/openpype/hosts/maya/api/action.py +++ b/openpype/hosts/maya/api/action.py @@ -2,7 +2,7 @@ from __future__ import absolute_import import pyblish.api - +from avalon import io from openpype.api import get_errored_instances_from_context @@ -72,8 +72,7 @@ class GenerateUUIDsOnInvalidAction(pyblish.api.Action): nodes (list): all nodes to regenerate ids on """ - from openpype.hosts.maya.api import lib - import avalon.io as io + from . import lib asset = instance.data['asset'] asset_id = io.find_one({"name": asset, "type": "asset"}, diff --git a/openpype/hosts/maya/api/commands.py b/openpype/hosts/maya/api/commands.py index d4c2b6a225..ebae3b1399 100644 --- a/openpype/hosts/maya/api/commands.py +++ b/openpype/hosts/maya/api/commands.py @@ -1,5 +1,7 @@ # -*- coding: utf-8 -*- """OpenPype script commands to be used directly in Maya.""" +from maya import cmds +from avalon import api, io class ToolWindows: @@ -51,3 +53,135 @@ def edit_shader_definitions(): window = ShaderDefinitionsEditor(parent=main_window) ToolWindows.set_window("shader_definition_editor", window) window.show() + + + +def reset_frame_range(): + """Set frame range to current asset""" + # Set FPS first + fps = {15: 'game', + 24: 'film', + 25: 'pal', + 30: 'ntsc', + 48: 'show', + 50: 'palf', + 60: 'ntscf', + 23.98: '23.976fps', + 23.976: '23.976fps', + 29.97: '29.97fps', + 47.952: '47.952fps', + 47.95: '47.952fps', + 59.94: '59.94fps', + 44100: '44100fps', + 48000: '48000fps' + }.get(float(api.Session.get("AVALON_FPS", 25)), "pal") + + cmds.currentUnit(time=fps) + + # Set frame start/end + asset_name = api.Session["AVALON_ASSET"] + asset = io.find_one({"name": asset_name, "type": "asset"}) + + frame_start = asset["data"].get("frameStart") + frame_end = asset["data"].get("frameEnd") + # Backwards compatibility + if frame_start is None or frame_end is None: + frame_start = asset["data"].get("edit_in") + frame_end = asset["data"].get("edit_out") + + if frame_start is None or frame_end is None: + cmds.warning("No edit information found for %s" % asset_name) + return + + handles = asset["data"].get("handles") or 0 + handle_start = asset["data"].get("handleStart") + if handle_start is None: + handle_start = handles + + handle_end = asset["data"].get("handleEnd") + if handle_end is None: + handle_end = handles + + frame_start -= int(handle_start) + frame_end += int(handle_end) + + cmds.playbackOptions(minTime=frame_start) + cmds.playbackOptions(maxTime=frame_end) + cmds.playbackOptions(animationStartTime=frame_start) + cmds.playbackOptions(animationEndTime=frame_end) + cmds.playbackOptions(minTime=frame_start) + cmds.playbackOptions(maxTime=frame_end) + cmds.currentTime(frame_start) + + cmds.setAttr("defaultRenderGlobals.startFrame", frame_start) + cmds.setAttr("defaultRenderGlobals.endFrame", frame_end) + + +def _resolution_from_document(doc): + if not doc or "data" not in doc: + print("Entered document is not valid. \"{}\"".format(str(doc))) + return None + + resolution_width = doc["data"].get("resolutionWidth") + resolution_height = doc["data"].get("resolutionHeight") + # Backwards compatibility + if resolution_width is None or resolution_height is None: + resolution_width = doc["data"].get("resolution_width") + resolution_height = doc["data"].get("resolution_height") + + # Make sure both width and heigh are set + if resolution_width is None or resolution_height is None: + cmds.warning( + "No resolution information found for \"{}\"".format(doc["name"]) + ) + return None + + return int(resolution_width), int(resolution_height) + + +def reset_resolution(): + # Default values + resolution_width = 1920 + resolution_height = 1080 + + # Get resolution from asset + asset_name = api.Session["AVALON_ASSET"] + asset_doc = io.find_one({"name": asset_name, "type": "asset"}) + resolution = _resolution_from_document(asset_doc) + # Try get resolution from project + if resolution is None: + # TODO go through visualParents + print(( + "Asset \"{}\" does not have set resolution." + " Trying to get resolution from project" + ).format(asset_name)) + project_doc = io.find_one({"type": "project"}) + resolution = _resolution_from_document(project_doc) + + if resolution is None: + msg = "Using default resolution {}x{}" + else: + resolution_width, resolution_height = resolution + msg = "Setting resolution to {}x{}" + + print(msg.format(resolution_width, resolution_height)) + + # set for different renderers + # arnold, vray, redshift, renderman + + renderer = cmds.getAttr("defaultRenderGlobals.currentRenderer").lower() + # handle various renderman names + if renderer.startswith("renderman"): + renderer = "renderman" + + # default attributes are usable for Arnold, Renderman and Redshift + width_attr_name = "defaultResolution.width" + height_attr_name = "defaultResolution.height" + + # Vray has its own way + if renderer == "vray": + width_attr_name = "vraySettings.width" + height_attr_name = "vraySettings.height" + + cmds.setAttr(width_attr_name, resolution_width) + cmds.setAttr(height_attr_name, resolution_height) diff --git a/openpype/hosts/maya/api/customize.py b/openpype/hosts/maya/api/customize.py index c7fb042ead..37fd543315 100644 --- a/openpype/hosts/maya/api/customize.py +++ b/openpype/hosts/maya/api/customize.py @@ -8,10 +8,9 @@ from functools import partial import maya.cmds as mc import maya.mel as mel -from avalon.maya import pipeline from openpype.api import resources from openpype.tools.utils import host_tools - +from .lib import get_main_window log = logging.getLogger(__name__) @@ -76,6 +75,7 @@ def override_component_mask_commands(): def override_toolbox_ui(): """Add custom buttons in Toolbox as replacement for Maya web help icon.""" icons = resources.get_resource("icons") + parent_widget = get_main_window() # Ensure the maya web icon on toolbox exists web_button = "ToolBox|MainToolboxLayout|mayaWebButton" @@ -115,7 +115,7 @@ def override_toolbox_ui(): label="Work Files", image=os.path.join(icons, "workfiles.png"), command=lambda: host_tools.show_workfiles( - parent=pipeline._parent + parent=parent_widget ), width=icon_size, height=icon_size, @@ -130,7 +130,7 @@ def override_toolbox_ui(): label="Loader", image=os.path.join(icons, "loader.png"), command=lambda: host_tools.show_loader( - parent=pipeline._parent, use_context=True + parent=parent_widget, use_context=True ), width=icon_size, height=icon_size, @@ -145,7 +145,7 @@ def override_toolbox_ui(): label="Inventory", image=os.path.join(icons, "inventory.png"), command=lambda: host_tools.show_scene_inventory( - parent=pipeline._parent + parent=parent_widget ), width=icon_size, height=icon_size, diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index b236fa7cdb..ff19f72097 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -1,7 +1,8 @@ """Standalone helper functions""" -import re import os +import sys +import re import platform import uuid import math @@ -18,16 +19,19 @@ import bson from maya import cmds, mel import maya.api.OpenMaya as om -from avalon import api, maya, io, pipeline -import avalon.maya.lib -import avalon.maya.interactive +from avalon import api, io, pipeline from openpype import lib from openpype.api import get_anatomy_settings +from .commands import reset_frame_range +self = sys.modules[__name__] +self._parent = None + log = logging.getLogger(__name__) +IS_HEADLESS = not hasattr(cmds, "about") or cmds.about(batch=True) ATTRIBUTE_DICT = {"int": {"attributeType": "long"}, "str": {"dataType": "string"}, "unicode": {"dataType": "string"}, @@ -100,6 +104,155 @@ FLOAT_FPS = {23.98, 23.976, 29.97, 47.952, 59.94} RENDERLIKE_INSTANCE_FAMILIES = ["rendering", "vrayscene"] +def get_main_window(): + """Acquire Maya's main window""" + from Qt import QtWidgets + + if self._parent is None: + self._parent = { + widget.objectName(): widget + for widget in QtWidgets.QApplication.topLevelWidgets() + }["MayaWindow"] + return self._parent + + +@contextlib.contextmanager +def suspended_refresh(): + """Suspend viewport refreshes""" + + try: + cmds.refresh(suspend=True) + yield + finally: + cmds.refresh(suspend=False) + + +@contextlib.contextmanager +def maintained_selection(): + """Maintain selection during context + + Example: + >>> scene = cmds.file(new=True, force=True) + >>> node = cmds.createNode("transform", name="Test") + >>> cmds.select("persp") + >>> with maintained_selection(): + ... cmds.select("Test", replace=True) + >>> "Test" in cmds.ls(selection=True) + False + + """ + + previous_selection = cmds.ls(selection=True) + try: + yield + finally: + if previous_selection: + cmds.select(previous_selection, + replace=True, + noExpand=True) + else: + cmds.select(clear=True) + + +def unique_name(name, format="%02d", namespace="", prefix="", suffix=""): + """Return unique `name` + + The function takes into consideration an optional `namespace` + and `suffix`. The suffix is included in evaluating whether a + name exists - such as `name` + "_GRP" - but isn't included + in the returned value. + + If a namespace is provided, only names within that namespace + are considered when evaluating whether the name is unique. + + Arguments: + format (str, optional): The `name` is given a number, this determines + how this number is formatted. Defaults to a padding of 2. + E.g. my_name01, my_name02. + namespace (str, optional): Only consider names within this namespace. + suffix (str, optional): Only consider names with this suffix. + + Example: + >>> name = cmds.createNode("transform", name="MyName") + >>> cmds.objExists(name) + True + >>> unique = unique_name(name) + >>> cmds.objExists(unique) + False + + """ + + iteration = 1 + unique = prefix + (name + format % iteration) + suffix + + while cmds.objExists(namespace + ":" + unique): + iteration += 1 + unique = prefix + (name + format % iteration) + suffix + + if suffix: + return unique[:-len(suffix)] + + return unique + + +def unique_namespace(namespace, format="%02d", prefix="", suffix=""): + """Return unique namespace + + Similar to :func:`unique_name` but evaluating namespaces + as opposed to object names. + + Arguments: + namespace (str): Name of namespace to consider + format (str, optional): Formatting of the given iteration number + suffix (str, optional): Only consider namespaces with this suffix. + + """ + + iteration = 1 + unique = prefix + (namespace + format % iteration) + suffix + + # The `existing` set does not just contain the namespaces but *all* nodes + # within "current namespace". We need all because the namespace could + # also clash with a node name. To be truly unique and valid one needs to + # check against all. + existing = set(cmds.namespaceInfo(listNamespace=True)) + while unique in existing: + iteration += 1 + unique = prefix + (namespace + format % iteration) + suffix + + return unique + + +def read(node): + """Return user-defined attributes from `node`""" + + data = dict() + + for attr in cmds.listAttr(node, userDefined=True) or list(): + try: + value = cmds.getAttr(node + "." + attr, asString=True) + + except RuntimeError: + # For Message type attribute or others that have connections, + # take source node name as value. + source = cmds.listConnections(node + "." + attr, + source=True, + destination=False) + source = cmds.ls(source, long=True) or [None] + value = source[0] + + except ValueError: + # Some attributes cannot be read directly, + # such as mesh and color attributes. These + # are considered non-essential to this + # particular publishing pipeline. + value = None + + data[attr] = value + + return data + + def _get_mel_global(name): """Return the value of a mel global variable""" return mel.eval("$%s = $%s;" % (name, name)) @@ -280,6 +433,73 @@ def shape_from_element(element): return node +def export_alembic(nodes, + file, + frame_range=None, + write_uv=True, + write_visibility=True, + attribute_prefix=None): + """Wrap native MEL command with limited set of arguments + + Arguments: + nodes (list): Long names of nodes to cache + + file (str): Absolute path to output destination + + frame_range (tuple, optional): Start- and end-frame of cache, + default to current animation range. + + write_uv (bool, optional): Whether or not to include UVs, + default to True + + write_visibility (bool, optional): Turn on to store the visibility + state of objects in the Alembic file. Otherwise, all objects are + considered visible, default to True + + attribute_prefix (str, optional): Include all user-defined + attributes with this prefix. + + """ + + if frame_range is None: + frame_range = ( + cmds.playbackOptions(query=True, ast=True), + cmds.playbackOptions(query=True, aet=True) + ) + + options = [ + ("file", file), + ("frameRange", "%s %s" % frame_range), + ] + [("root", mesh) for mesh in nodes] + + if isinstance(attribute_prefix, string_types): + # Include all attributes prefixed with "mb" + # TODO(marcus): This would be a good candidate for + # external registration, so that the developer + # doesn't have to edit this function to modify + # the behavior of Alembic export. + options.append(("attrPrefix", str(attribute_prefix))) + + if write_uv: + options.append(("uvWrite", "")) + + if write_visibility: + options.append(("writeVisibility", "")) + + # Generate MEL command + mel_args = list() + for key, value in options: + mel_args.append("-{0} {1}".format(key, value)) + + mel_args_string = " ".join(mel_args) + mel_cmd = "AbcExport -j \"{0}\"".format(mel_args_string) + + # For debuggability, put the string passed to MEL in the Script editor. + print("mel.eval('%s')" % mel_cmd) + + return mel.eval(mel_cmd) + + def collect_animation_data(fps=False): """Get the basic animation data @@ -305,6 +525,256 @@ def collect_animation_data(fps=False): return data +def imprint(node, data): + """Write `data` to `node` as userDefined attributes + + Arguments: + node (str): Long name of node + data (dict): Dictionary of key/value pairs + + Example: + >>> from maya import cmds + >>> def compute(): + ... return 6 + ... + >>> cube, generator = cmds.polyCube() + >>> imprint(cube, { + ... "regularString": "myFamily", + ... "computedValue": lambda: compute() + ... }) + ... + >>> cmds.getAttr(cube + ".computedValue") + 6 + + """ + + for key, value in data.items(): + + if callable(value): + # Support values evaluated at imprint + value = value() + + if isinstance(value, bool): + add_type = {"attributeType": "bool"} + set_type = {"keyable": False, "channelBox": True} + elif isinstance(value, string_types): + add_type = {"dataType": "string"} + set_type = {"type": "string"} + elif isinstance(value, int): + add_type = {"attributeType": "long"} + set_type = {"keyable": False, "channelBox": True} + elif isinstance(value, float): + add_type = {"attributeType": "double"} + set_type = {"keyable": False, "channelBox": True} + elif isinstance(value, (list, tuple)): + add_type = {"attributeType": "enum", "enumName": ":".join(value)} + set_type = {"keyable": False, "channelBox": True} + value = 0 # enum default + else: + raise TypeError("Unsupported type: %r" % type(value)) + + cmds.addAttr(node, longName=key, **add_type) + cmds.setAttr(node + "." + key, value, **set_type) + + +def serialise_shaders(nodes): + """Generate a shader set dictionary + + Arguments: + nodes (list): Absolute paths to nodes + + Returns: + dictionary of (shader: id) pairs + + Schema: + { + "shader1": ["id1", "id2"], + "shader2": ["id3", "id1"] + } + + Example: + { + "Bazooka_Brothers01_:blinn4SG": [ + "f9520572-ac1d-11e6-b39e-3085a99791c9.f[4922:5001]", + "f9520572-ac1d-11e6-b39e-3085a99791c9.f[4587:4634]", + "f9520572-ac1d-11e6-b39e-3085a99791c9.f[1120:1567]", + "f9520572-ac1d-11e6-b39e-3085a99791c9.f[4251:4362]" + ], + "lambert2SG": [ + "f9520571-ac1d-11e6-9dbb-3085a99791c9" + ] + } + + """ + + valid_nodes = cmds.ls( + nodes, + long=True, + recursive=True, + showType=True, + objectsOnly=True, + type="transform" + ) + + meshes_by_id = {} + for mesh in valid_nodes: + shapes = cmds.listRelatives(valid_nodes[0], + shapes=True, + fullPath=True) or list() + + if shapes: + shape = shapes[0] + if not cmds.nodeType(shape): + continue + + try: + id_ = cmds.getAttr(mesh + ".mbID") + + if id_ not in meshes_by_id: + meshes_by_id[id_] = list() + + meshes_by_id[id_].append(mesh) + + except ValueError: + continue + + meshes_by_shader = dict() + for id_, mesh in meshes_by_id.items(): + shape = cmds.listRelatives(mesh, + shapes=True, + fullPath=True) or list() + + for shader in cmds.listConnections(shape, + type="shadingEngine") or list(): + + # Objects in this group are those that haven't got + # any shaders. These are expected to be managed + # elsewhere, such as by the default model loader. + if shader == "initialShadingGroup": + continue + + if shader not in meshes_by_shader: + meshes_by_shader[shader] = list() + + shaded = cmds.sets(shader, query=True) or list() + meshes_by_shader[shader].extend(shaded) + + shader_by_id = {} + for shader, shaded in meshes_by_shader.items(): + + if shader not in shader_by_id: + shader_by_id[shader] = list() + + for mesh in shaded: + + # Enable shader assignment to faces. + name = mesh.split(".f[")[0] + + transform = name + if cmds.objectType(transform) == "mesh": + transform = cmds.listRelatives(name, parent=True)[0] + + try: + id_ = cmds.getAttr(transform + ".mbID") + shader_by_id[shader].append(mesh.replace(name, id_)) + except KeyError: + continue + + # Remove duplicates + shader_by_id[shader] = list(set(shader_by_id[shader])) + + return shader_by_id + + +def lsattr(attr, value=None): + """Return nodes matching `key` and `value` + + Arguments: + attr (str): Name of Maya attribute + value (object, optional): Value of attribute. If none + is provided, return all nodes with this attribute. + + Example: + >> lsattr("id", "myId") + ["myNode"] + >> lsattr("id") + ["myNode", "myOtherNode"] + + """ + + if value is None: + return cmds.ls("*.%s" % attr, + recursive=True, + objectsOnly=True, + long=True) + return lsattrs({attr: value}) + + +def lsattrs(attrs): + """Return nodes with the given attribute(s). + + Arguments: + attrs (dict): Name and value pairs of expected matches + + Example: + >> # Return nodes with an `age` of five. + >> lsattr({"age": "five"}) + >> # Return nodes with both `age` and `color` of five and blue. + >> lsattr({"age": "five", "color": "blue"}) + + Return: + list: matching nodes. + + """ + + dep_fn = om.MFnDependencyNode() + dag_fn = om.MFnDagNode() + selection_list = om.MSelectionList() + + first_attr = next(iter(attrs)) + + try: + selection_list.add("*.{0}".format(first_attr), + searchChildNamespaces=True) + except RuntimeError as exc: + if str(exc).endswith("Object does not exist"): + return [] + + matches = set() + for i in range(selection_list.length()): + node = selection_list.getDependNode(i) + if node.hasFn(om.MFn.kDagNode): + fn_node = dag_fn.setObject(node) + full_path_names = [path.fullPathName() + for path in fn_node.getAllPaths()] + else: + fn_node = dep_fn.setObject(node) + full_path_names = [fn_node.name()] + + for attr in attrs: + try: + plug = fn_node.findPlug(attr, True) + if plug.asString() != attrs[attr]: + break + except RuntimeError: + break + else: + matches.update(full_path_names) + + return list(matches) + + +@contextlib.contextmanager +def without_extension(): + """Use cmds.file with defaultExtensions=False""" + previous_setting = cmds.file(defaultExtensions=True, query=True) + try: + cmds.file(defaultExtensions=False) + yield + finally: + cmds.file(defaultExtensions=previous_setting) + + @contextlib.contextmanager def attribute_values(attr_values): """Remaps node attributes to values during context. @@ -736,7 +1206,7 @@ def namespaced(namespace, new=True): """ original = cmds.namespaceInfo(cur=True, absoluteName=True) if new: - namespace = avalon.maya.lib.unique_namespace(namespace) + namespace = unique_namespace(namespace) cmds.namespace(add=namespace) try: @@ -1408,7 +1878,7 @@ def assign_look_by_version(nodes, version_id): raise RuntimeError("Could not find LookLoader, this is a bug") # Reference the look file - with maya.maintained_selection(): + with maintained_selection(): container_node = pipeline.load(Loader, look_representation) # Get container members @@ -1947,7 +2417,7 @@ def set_context_settings(): reset_scene_resolution() # Set frame range. - avalon.maya.interactive.reset_frame_range() + reset_frame_range() # Set colorspace set_colorspace() @@ -2386,7 +2856,7 @@ def get_attr_in_layer(attr, layer): def fix_incompatible_containers(): """Return whether the current scene has any outdated content""" - host = avalon.api.registered_host() + host = api.registered_host() for container in host.ls(): loader = container['loader'] diff --git a/openpype/hosts/maya/api/menu.py b/openpype/hosts/maya/api/menu.py index df5058dfd5..5554fce583 100644 --- a/openpype/hosts/maya/api/menu.py +++ b/openpype/hosts/maya/api/menu.py @@ -1,58 +1,144 @@ -import sys import os import logging from Qt import QtWidgets, QtGui +import maya.utils import maya.cmds as cmds -from avalon.maya import pipeline +import avalon.api from openpype.api import BuildWorkfile from openpype.settings import get_project_settings from openpype.tools.utils import host_tools from openpype.hosts.maya.api import lib +from .lib import get_main_window, IS_HEADLESS +from .commands import reset_frame_range log = logging.getLogger(__name__) +MENU_NAME = "op_maya_menu" + def _get_menu(menu_name=None): """Return the menu instance if it currently exists in Maya""" if menu_name is None: - menu_name = pipeline._menu + menu_name = MENU_NAME widgets = {w.objectName(): w for w in QtWidgets.QApplication.allWidgets()} return widgets.get(menu_name) -def deferred(): - def add_build_workfiles_item(): - # Add build first workfile - cmds.menuItem(divider=True, parent=pipeline._menu) +def install(): + if cmds.about(batch=True): + log.info("Skipping openpype.menu initialization in batch mode..") + return + + def deferred(): + from avalon.tools import publish + parent_widget = get_main_window() + cmds.menu( + MENU_NAME, + label=avalon.api.Session["AVALON_LABEL"], + tearOff=True, + parent="MayaWindow" + ) + + # Create context menu + context_label = "{}, {}".format( + avalon.api.Session["AVALON_ASSET"], + avalon.api.Session["AVALON_TASK"] + ) + cmds.menuItem( + "currentContext", + label=context_label, + parent=MENU_NAME, + enable=False + ) + + cmds.setParent("..", menu=True) + + cmds.menuItem(divider=True) + + # Create default items + cmds.menuItem( + "Create...", + command=lambda *args: host_tools.show_creator(parent=parent_widget) + ) + + cmds.menuItem( + "Load...", + command=lambda *args: host_tools.show_loader( + parent=parent_widget, + use_context=True + ) + ) + + cmds.menuItem( + "Publish...", + command=lambda *args: host_tools.show_publish(parent=parent_widget), + image=publish.ICON + ) + + cmds.menuItem( + "Manage...", + command=lambda *args: host_tools.show_scene_inventory( + parent=parent_widget + ) + ) + + cmds.menuItem( + "Library...", + command=lambda *args: host_tools.show_library_loader( + parent=parent_widget + ) + ) + + cmds.menuItem(divider=True) + + cmds.menuItem( + "Work Files...", + command=lambda *args: host_tools.show_workfiles( + parent=parent_widget + ), + ) + + cmds.menuItem( + "Reset Frame Range", + command=reset_frame_range + ) + + cmds.menuItem( + "Reset Resolution", + command=lib.reset_scene_resolution + ) + + cmds.menuItem( + "Set Colorspace", + command=lib.set_colorspace, + ) + cmds.menuItem(divider=True, parent=MENU_NAME) cmds.menuItem( "Build First Workfile", - parent=pipeline._menu, + parent=MENU_NAME, command=lambda *args: BuildWorkfile().process() ) - def add_look_assigner_item(): cmds.menuItem( - "Look assigner", - parent=pipeline._menu, + "Look assigner...", command=lambda *args: host_tools.show_look_assigner( - pipeline._parent + parent_widget ) ) - def add_experimental_item(): cmds.menuItem( "Experimental tools...", - parent=pipeline._menu, command=lambda *args: host_tools.show_experimental_tools_dialog( - pipeline._parent + parent_widget ) ) + cmds.setParent(MENU_NAME, menu=True) def add_scripts_menu(): try: @@ -82,124 +168,13 @@ def deferred(): # apply configuration studio_menu.build_from_configuration(studio_menu, config) - def modify_workfiles(): - # Find the pipeline menu - top_menu = _get_menu() - - # Try to find workfile tool action in the menu - workfile_action = None - for action in top_menu.actions(): - if action.text() == "Work Files": - workfile_action = action - break - - # Add at the top of menu if "Work Files" action was not found - after_action = "" - if workfile_action: - # Use action's object name for `insertAfter` argument - after_action = workfile_action.objectName() - - # Insert action to menu - cmds.menuItem( - "Work Files", - parent=pipeline._menu, - command=lambda *args: host_tools.show_workfiles(pipeline._parent), - insertAfter=after_action - ) - - # Remove replaced action - if workfile_action: - top_menu.removeAction(workfile_action) - - def modify_resolution(): - # Find the pipeline menu - top_menu = _get_menu() - - # Try to find resolution tool action in the menu - resolution_action = None - for action in top_menu.actions(): - if action.text() == "Reset Resolution": - resolution_action = action - break - - # Add at the top of menu if "Work Files" action was not found - after_action = "" - if resolution_action: - # Use action's object name for `insertAfter` argument - after_action = resolution_action.objectName() - - # Insert action to menu - cmds.menuItem( - "Reset Resolution", - parent=pipeline._menu, - command=lambda *args: lib.reset_scene_resolution(), - insertAfter=after_action - ) - - # Remove replaced action - if resolution_action: - top_menu.removeAction(resolution_action) - - def remove_project_manager(): - top_menu = _get_menu() - - # Try to find "System" menu action in the menu - system_menu = None - for action in top_menu.actions(): - if action.text() == "System": - system_menu = action - break - - if system_menu is None: - return - - # Try to find "Project manager" action in "System" menu - project_manager_action = None - for action in system_menu.menu().children(): - if hasattr(action, "text") and action.text() == "Project Manager": - project_manager_action = action - break - - # Remove "Project manager" action if was found - if project_manager_action is not None: - system_menu.menu().removeAction(project_manager_action) - - def add_colorspace(): - # Find the pipeline menu - top_menu = _get_menu() - - # Try to find workfile tool action in the menu - workfile_action = None - for action in top_menu.actions(): - if action.text() == "Reset Resolution": - workfile_action = action - break - - # Add at the top of menu if "Work Files" action was not found - after_action = "" - if workfile_action: - # Use action's object name for `insertAfter` argument - after_action = workfile_action.objectName() - - # Insert action to menu - cmds.menuItem( - "Set Colorspace", - parent=pipeline._menu, - command=lambda *args: lib.set_colorspace(), - insertAfter=after_action - ) - - log.info("Attempting to install scripts menu ...") - - # add_scripts_menu() - add_build_workfiles_item() - add_look_assigner_item() - add_experimental_item() - modify_workfiles() - modify_resolution() - remove_project_manager() - add_colorspace() - add_scripts_menu() + # Allow time for uninstallation to finish. + # We use Maya's executeDeferred instead of QTimer.singleShot + # so that it only gets called after Maya UI has initialized too. + # This is crucial with Maya 2020+ which initializes without UI + # first as a QCoreApplication + maya.utils.executeDeferred(deferred) + cmds.evalDeferred(add_scripts_menu, lowestPriority=True) def uninstall(): @@ -214,18 +189,27 @@ def uninstall(): log.error(e) -def install(): - if cmds.about(batch=True): - log.info("Skipping openpype.menu initialization in batch mode..") - return - - # Allow time for uninstallation to finish. - cmds.evalDeferred(deferred, lowestPriority=True) - - def popup(): """Pop-up the existing menu near the mouse cursor.""" menu = _get_menu() cursor = QtGui.QCursor() point = cursor.pos() menu.exec_(point) + + +def update_menu_task_label(): + """Update the task label in Avalon menu to current session""" + + if IS_HEADLESS: + return + + object_name = "{}|currentContext".format(MENU_NAME) + if not cmds.menuItem(object_name, query=True, exists=True): + log.warning("Can't find menuItem: {}".format(object_name)) + return + + label = "{}, {}".format( + avalon.api.Session["AVALON_ASSET"], + avalon.api.Session["AVALON_TASK"] + ) + cmds.menuItem(object_name, edit=True, label=label) diff --git a/openpype/hosts/maya/api/pipeline.py b/openpype/hosts/maya/api/pipeline.py new file mode 100644 index 0000000000..a5455d0083 --- /dev/null +++ b/openpype/hosts/maya/api/pipeline.py @@ -0,0 +1,594 @@ +import os +import sys +import errno +import logging +import contextlib + +from maya import utils, cmds, OpenMaya +import maya.api.OpenMaya as om + +import pyblish.api +import avalon.api + +from avalon.lib import find_submodule +from avalon.pipeline import AVALON_CONTAINER_ID + +import openpype.hosts.maya +from openpype.tools.utils import host_tools +from openpype.lib import any_outdated +from openpype.lib.path_tools import HostDirmap +from openpype.hosts.maya.lib import copy_workspace_mel +from . import menu, lib + +log = logging.getLogger("openpype.hosts.maya") + +HOST_DIR = os.path.dirname(os.path.abspath(openpype.hosts.maya.__file__)) +PLUGINS_DIR = os.path.join(HOST_DIR, "plugins") +PUBLISH_PATH = os.path.join(PLUGINS_DIR, "publish") +LOAD_PATH = os.path.join(PLUGINS_DIR, "load") +CREATE_PATH = os.path.join(PLUGINS_DIR, "create") +INVENTORY_PATH = os.path.join(PLUGINS_DIR, "inventory") + +AVALON_CONTAINERS = ":AVALON_CONTAINERS" + +self = sys.modules[__name__] +self._ignore_lock = False +self._events = {} + + +def install(): + from openpype.settings import get_project_settings + + project_settings = get_project_settings(os.getenv("AVALON_PROJECT")) + # process path mapping + dirmap_processor = MayaDirmap("maya", project_settings) + dirmap_processor.process_dirmap() + + pyblish.api.register_plugin_path(PUBLISH_PATH) + pyblish.api.register_host("mayabatch") + pyblish.api.register_host("mayapy") + pyblish.api.register_host("maya") + + avalon.api.register_plugin_path(avalon.api.Loader, LOAD_PATH) + avalon.api.register_plugin_path(avalon.api.Creator, CREATE_PATH) + avalon.api.register_plugin_path(avalon.api.InventoryAction, INVENTORY_PATH) + log.info(PUBLISH_PATH) + + log.info("Installing callbacks ... ") + avalon.api.on("init", on_init) + + # Callbacks below are not required for headless mode, the `init` however + # is important to load referenced Alembics correctly at rendertime. + if lib.IS_HEADLESS: + log.info(("Running in headless mode, skipping Maya " + "save/open/new callback installation..")) + return + + _set_project() + _register_callbacks() + + menu.install() + + avalon.api.on("save", on_save) + avalon.api.on("open", on_open) + avalon.api.on("new", on_new) + avalon.api.before("save", on_before_save) + avalon.api.on("taskChanged", on_task_changed) + avalon.api.on("before.workfile.save", before_workfile_save) + + log.info("Setting default family states for loader..") + avalon.api.data["familiesStateToggled"] = ["imagesequence"] + + +def _set_project(): + """Sets the maya project to the current Session's work directory. + + Returns: + None + + """ + workdir = avalon.api.Session["AVALON_WORKDIR"] + + try: + os.makedirs(workdir) + except OSError as e: + # An already existing working directory is fine. + if e.errno == errno.EEXIST: + pass + else: + raise + + cmds.workspace(workdir, openWorkspace=True) + + +def _register_callbacks(): + for handler, event in self._events.copy().items(): + if event is None: + continue + + try: + OpenMaya.MMessage.removeCallback(event) + self._events[handler] = None + except RuntimeError as e: + log.info(e) + + self._events[_on_scene_save] = OpenMaya.MSceneMessage.addCallback( + OpenMaya.MSceneMessage.kBeforeSave, _on_scene_save + ) + + self._events[_before_scene_save] = OpenMaya.MSceneMessage.addCheckCallback( + OpenMaya.MSceneMessage.kBeforeSaveCheck, _before_scene_save + ) + + self._events[_on_scene_new] = OpenMaya.MSceneMessage.addCallback( + OpenMaya.MSceneMessage.kAfterNew, _on_scene_new + ) + + self._events[_on_maya_initialized] = OpenMaya.MSceneMessage.addCallback( + OpenMaya.MSceneMessage.kMayaInitialized, _on_maya_initialized + ) + + self._events[_on_scene_open] = OpenMaya.MSceneMessage.addCallback( + OpenMaya.MSceneMessage.kAfterOpen, _on_scene_open + ) + + log.info("Installed event handler _on_scene_save..") + log.info("Installed event handler _before_scene_save..") + log.info("Installed event handler _on_scene_new..") + log.info("Installed event handler _on_maya_initialized..") + log.info("Installed event handler _on_scene_open..") + + +def _on_maya_initialized(*args): + avalon.api.emit("init", args) + + if cmds.about(batch=True): + log.warning("Running batch mode ...") + return + + # Keep reference to the main Window, once a main window exists. + lib.get_main_window() + + +def _on_scene_new(*args): + avalon.api.emit("new", args) + + +def _on_scene_save(*args): + avalon.api.emit("save", args) + + +def _on_scene_open(*args): + avalon.api.emit("open", args) + + +def _before_scene_save(return_code, client_data): + + # Default to allowing the action. Registered + # callbacks can optionally set this to False + # in order to block the operation. + OpenMaya.MScriptUtil.setBool(return_code, True) + + avalon.api.emit("before_save", [return_code, client_data]) + + +def uninstall(): + pyblish.api.deregister_plugin_path(PUBLISH_PATH) + pyblish.api.deregister_host("mayabatch") + pyblish.api.deregister_host("mayapy") + pyblish.api.deregister_host("maya") + + avalon.api.deregister_plugin_path(avalon.api.Loader, LOAD_PATH) + avalon.api.deregister_plugin_path(avalon.api.Creator, CREATE_PATH) + avalon.api.deregister_plugin_path(avalon.api.InventoryAction, INVENTORY_PATH) + + menu.uninstall() + + +def lock(): + """Lock scene + + Add an invisible node to your Maya scene with the name of the + current file, indicating that this file is "locked" and cannot + be modified any further. + + """ + + if not cmds.objExists("lock"): + with lib.maintained_selection(): + cmds.createNode("objectSet", name="lock") + cmds.addAttr("lock", ln="basename", dataType="string") + + # Permanently hide from outliner + cmds.setAttr("lock.verticesOnlySet", True) + + fname = cmds.file(query=True, sceneName=True) + basename = os.path.basename(fname) + cmds.setAttr("lock.basename", basename, type="string") + + +def unlock(): + """Permanently unlock a locked scene + + Doesn't throw an error if scene is already unlocked. + + """ + + try: + cmds.delete("lock") + except ValueError: + pass + + +def is_locked(): + """Query whether current scene is locked""" + fname = cmds.file(query=True, sceneName=True) + basename = os.path.basename(fname) + + if self._ignore_lock: + return False + + try: + return cmds.getAttr("lock.basename") == basename + except ValueError: + return False + + +@contextlib.contextmanager +def lock_ignored(): + """Context manager for temporarily ignoring the lock of a scene + + The purpose of this function is to enable locking a scene and + saving it with the lock still in place. + + Example: + >>> with lock_ignored(): + ... pass # Do things without lock + + """ + + self._ignore_lock = True + + try: + yield + finally: + self._ignore_lock = False + + +def parse_container(container): + """Return the container node's full container data. + + Args: + container (str): A container node name. + + Returns: + dict: The container schema data for this container node. + + """ + data = lib.read(container) + + # Backwards compatibility pre-schemas for containers + data["schema"] = data.get("schema", "openpype:container-1.0") + + # Append transient data + data["objectName"] = container + + return data + + +def _ls(): + """Yields Avalon container node names. + + Used by `ls()` to retrieve the nodes and then query the full container's + data. + + Yields: + str: Avalon container node name (objectSet) + + """ + + def _maya_iterate(iterator): + """Helper to iterate a maya iterator""" + while not iterator.isDone(): + yield iterator.thisNode() + iterator.next() + + ids = {AVALON_CONTAINER_ID, + # Backwards compatibility + "pyblish.mindbender.container"} + + # Iterate over all 'set' nodes in the scene to detect whether + # they have the avalon container ".id" attribute. + fn_dep = om.MFnDependencyNode() + iterator = om.MItDependencyNodes(om.MFn.kSet) + for mobject in _maya_iterate(iterator): + if mobject.apiTypeStr != "kSet": + # Only match by exact type + continue + + fn_dep.setObject(mobject) + if not fn_dep.hasAttribute("id"): + continue + + plug = fn_dep.findPlug("id", True) + value = plug.asString() + if value in ids: + yield fn_dep.name() + + +def ls(): + """Yields containers from active Maya scene + + This is the host-equivalent of api.ls(), but instead of listing + assets on disk, it lists assets already loaded in Maya; once loaded + they are called 'containers' + + Yields: + dict: container + + """ + container_names = _ls() + + has_metadata_collector = False + config_host = find_submodule(avalon.api.registered_config(), "maya") + if hasattr(config_host, "collect_container_metadata"): + has_metadata_collector = True + + for container in sorted(container_names): + data = parse_container(container) + + # Collect custom data if attribute is present + if has_metadata_collector: + metadata = config_host.collect_container_metadata(container) + data.update(metadata) + + yield data + + +def containerise(name, + namespace, + nodes, + context, + loader=None, + suffix="CON"): + """Bundle `nodes` into an assembly and imprint it with metadata + + Containerisation enables a tracking of version, author and origin + for loaded assets. + + Arguments: + name (str): Name of resulting assembly + namespace (str): Namespace under which to host container + nodes (list): Long names of nodes to containerise + context (dict): Asset information + loader (str, optional): Name of loader used to produce this container. + suffix (str, optional): Suffix of container, defaults to `_CON`. + + Returns: + container (str): Name of container assembly + + """ + container = cmds.sets(nodes, name="%s_%s_%s" % (namespace, name, suffix)) + + data = [ + ("schema", "openpype:container-2.0"), + ("id", AVALON_CONTAINER_ID), + ("name", name), + ("namespace", namespace), + ("loader", str(loader)), + ("representation", context["representation"]["_id"]), + ] + + for key, value in data: + if not value: + continue + + if isinstance(value, (int, float)): + cmds.addAttr(container, longName=key, attributeType="short") + cmds.setAttr(container + "." + key, value) + + else: + cmds.addAttr(container, longName=key, dataType="string") + cmds.setAttr(container + "." + key, value, type="string") + + main_container = cmds.ls(AVALON_CONTAINERS, type="objectSet") + if not main_container: + main_container = cmds.sets(empty=True, name=AVALON_CONTAINERS) + + # Implement #399: Maya 2019+ hide AVALON_CONTAINERS on creation.. + if cmds.attributeQuery("hiddenInOutliner", + node=main_container, + exists=True): + cmds.setAttr(main_container + ".hiddenInOutliner", True) + else: + main_container = main_container[0] + + cmds.sets(container, addElement=main_container) + + # Implement #399: Maya 2019+ hide containers in outliner + if cmds.attributeQuery("hiddenInOutliner", + node=container, + exists=True): + cmds.setAttr(container + ".hiddenInOutliner", True) + + return container + + +def on_init(_): + log.info("Running callback on init..") + + def safe_deferred(fn): + """Execute deferred the function in a try-except""" + + def _fn(): + """safely call in deferred callback""" + try: + fn() + except Exception as exc: + print(exc) + + try: + utils.executeDeferred(_fn) + except Exception as exc: + print(exc) + + # Force load Alembic so referenced alembics + # work correctly on scene open + cmds.loadPlugin("AbcImport", quiet=True) + cmds.loadPlugin("AbcExport", quiet=True) + + # Force load objExport plug-in (requested by artists) + cmds.loadPlugin("objExport", quiet=True) + + from .customize import ( + override_component_mask_commands, + override_toolbox_ui + ) + safe_deferred(override_component_mask_commands) + + launch_workfiles = os.environ.get("WORKFILES_STARTUP") + + if launch_workfiles: + safe_deferred(host_tools.show_workfiles) + + if not lib.IS_HEADLESS: + safe_deferred(override_toolbox_ui) + + +def on_before_save(return_code, _): + """Run validation for scene's FPS prior to saving""" + return lib.validate_fps() + + +def on_save(_): + """Automatically add IDs to new nodes + + Any transform of a mesh, without an existing ID, is given one + automatically on file save. + """ + + log.info("Running callback on save..") + + # # Update current task for the current scene + # update_task_from_path(cmds.file(query=True, sceneName=True)) + + # Generate ids of the current context on nodes in the scene + nodes = lib.get_id_required_nodes(referenced_nodes=False) + for node, new_id in lib.generate_ids(nodes): + lib.set_id(node, new_id, overwrite=False) + + +def on_open(_): + """On scene open let's assume the containers have changed.""" + + from Qt import QtWidgets + from openpype.widgets import popup + + cmds.evalDeferred( + "from openpype.hosts.maya.api import lib;" + "lib.remove_render_layer_observer()") + cmds.evalDeferred( + "from openpype.hosts.maya.api import lib;" + "lib.add_render_layer_observer()") + cmds.evalDeferred( + "from openpype.hosts.maya.api import lib;" + "lib.add_render_layer_change_observer()") + # # Update current task for the current scene + # update_task_from_path(cmds.file(query=True, sceneName=True)) + + # Validate FPS after update_task_from_path to + # ensure it is using correct FPS for the asset + lib.validate_fps() + lib.fix_incompatible_containers() + + if any_outdated(): + log.warning("Scene has outdated content.") + + # Find maya main window + top_level_widgets = {w.objectName(): w for w in + QtWidgets.QApplication.topLevelWidgets()} + parent = top_level_widgets.get("MayaWindow", None) + + if parent is None: + log.info("Skipping outdated content pop-up " + "because Maya window can't be found.") + else: + + # Show outdated pop-up + def _on_show_inventory(): + host_tools.show_scene_inventory(parent=parent) + + dialog = popup.Popup(parent=parent) + dialog.setWindowTitle("Maya scene has outdated content") + dialog.setMessage("There are outdated containers in " + "your Maya scene.") + dialog.on_show.connect(_on_show_inventory) + dialog.show() + + +def on_new(_): + """Set project resolution and fps when create a new file""" + log.info("Running callback on new..") + with lib.suspended_refresh(): + cmds.evalDeferred( + "from openpype.hosts.maya.api import lib;" + "lib.remove_render_layer_observer()") + cmds.evalDeferred( + "from openpype.hosts.maya.api import lib;" + "lib.add_render_layer_observer()") + cmds.evalDeferred( + "from openpype.hosts.maya.api import lib;" + "lib.add_render_layer_change_observer()") + lib.set_context_settings() + + +def on_task_changed(*args): + """Wrapped function of app initialize and maya's on task changed""" + # Run + menu.update_menu_task_label() + + workdir = avalon.api.Session["AVALON_WORKDIR"] + if os.path.exists(workdir): + log.info("Updating Maya workspace for task change to %s", workdir) + + _set_project() + + # Set Maya fileDialog's start-dir to /scenes + frule_scene = cmds.workspace(fileRuleEntry="scene") + cmds.optionVar(stringValue=("browserLocationmayaBinaryscene", + workdir + "/" + frule_scene)) + + else: + log.warning(( + "Can't set project for new context because path does not exist: {}" + ).format(workdir)) + + with lib.suspended_refresh(): + lib.set_context_settings() + lib.update_content_on_context_change() + + msg = " project: {}\n asset: {}\n task:{}".format( + avalon.api.Session["AVALON_PROJECT"], + avalon.api.Session["AVALON_ASSET"], + avalon.api.Session["AVALON_TASK"] + ) + + lib.show_message( + "Context was changed", + ("Context was changed to:\n{}".format(msg)), + ) + + +def before_workfile_save(event): + workdir_path = event.workdir_path + if workdir_path: + copy_workspace_mel(workdir_path) + + +class MayaDirmap(HostDirmap): + def on_enable_dirmap(self): + cmds.dirmap(en=True) + + def dirmap_routine(self, source_path, destination_path): + cmds.dirmap(m=(source_path, destination_path)) + cmds.dirmap(m=(destination_path, source_path)) diff --git a/openpype/hosts/maya/api/plugin.py b/openpype/hosts/maya/api/plugin.py index a5f03cd576..64e910627d 100644 --- a/openpype/hosts/maya/api/plugin.py +++ b/openpype/hosts/maya/api/plugin.py @@ -1,8 +1,14 @@ +import os + +from maya import cmds + from avalon import api from avalon.vendor import qargparse -import avalon.maya from openpype.api import PypeCreatorMixin +from .pipeline import containerise +from . import lib + def get_reference_node(members, log=None): """Get the reference node from the container members @@ -14,8 +20,6 @@ def get_reference_node(members, log=None): """ - from maya import cmds - # Collect the references without .placeHolderList[] attributes as # unique entries (objects only) and skipping the sharedReferenceNode. references = set() @@ -61,8 +65,6 @@ def get_reference_node_parents(ref): list: The upstream parent reference nodes. """ - from maya import cmds - parent = cmds.referenceQuery(ref, referenceNode=True, parent=True) @@ -75,11 +77,25 @@ def get_reference_node_parents(ref): return parents -class Creator(PypeCreatorMixin, avalon.maya.Creator): - pass +class Creator(PypeCreatorMixin, api.Creator): + def process(self): + nodes = list() + + with lib.undo_chunk(): + if (self.options or {}).get("useSelection"): + nodes = cmds.ls(selection=True) + + instance = cmds.sets(nodes, name=self.name) + lib.imprint(instance, self.data) + + return instance -class ReferenceLoader(api.Loader): +class Loader(api.Loader): + hosts = ["maya"] + + +class ReferenceLoader(Loader): """A basic ReferenceLoader for Maya This will implement the basic behavior for a loader to inherit from that @@ -117,11 +133,6 @@ class ReferenceLoader(api.Loader): namespace=None, options=None ): - - import os - from avalon.maya import lib - from avalon.maya.pipeline import containerise - assert os.path.exists(self.fname), "%s does not exist." % self.fname asset = context['asset'] @@ -182,8 +193,6 @@ class ReferenceLoader(api.Loader): def update(self, container, representation): - - import os from maya import cmds node = container["objectName"] diff --git a/openpype/hosts/maya/api/setdress.py b/openpype/hosts/maya/api/setdress.py index 4f826b8fde..1a7c3933a1 100644 --- a/openpype/hosts/maya/api/setdress.py +++ b/openpype/hosts/maya/api/setdress.py @@ -9,8 +9,10 @@ import six from maya import cmds from avalon import api, io -from avalon.maya.lib import unique_namespace -from openpype.hosts.maya.api.lib import matrix_equals +from openpype.hosts.maya.api.lib import ( + matrix_equals, + unique_namespace +) log = logging.getLogger("PackageLoader") @@ -239,7 +241,7 @@ def get_contained_containers(container): """ import avalon.schema - from avalon.maya.pipeline import parse_container + from .pipeline import parse_container # Get avalon containers in this package setdress container containers = [] diff --git a/openpype/hosts/maya/api/workio.py b/openpype/hosts/maya/api/workio.py new file mode 100644 index 0000000000..698c48e81e --- /dev/null +++ b/openpype/hosts/maya/api/workio.py @@ -0,0 +1,67 @@ +"""Host API required Work Files tool""" +import os +from maya import cmds +from avalon import api + + +def file_extensions(): + return api.HOST_WORKFILE_EXTENSIONS["maya"] + + +def has_unsaved_changes(): + return cmds.file(query=True, modified=True) + + +def save_file(filepath): + cmds.file(rename=filepath) + ext = os.path.splitext(filepath)[1] + if ext == ".mb": + file_type = "mayaBinary" + else: + file_type = "mayaAscii" + cmds.file(save=True, type=file_type) + + +def open_file(filepath): + return cmds.file(filepath, open=True, force=True) + + +def current_file(): + + current_filepath = cmds.file(query=True, sceneName=True) + if not current_filepath: + return None + + return current_filepath + + +def work_root(session): + work_dir = session["AVALON_WORKDIR"] + scene_dir = None + + # Query scene file rule from workspace.mel if it exists in WORKDIR + # We are parsing the workspace.mel manually as opposed to temporarily + # setting the Workspace in Maya in a context manager since Maya had a + # tendency to crash on frequently changing the workspace when this + # function was called many times as one scrolled through Work Files assets. + workspace_mel = os.path.join(work_dir, "workspace.mel") + if os.path.exists(workspace_mel): + scene_rule = 'workspace -fr "scene" ' + # We need to use builtins as `open` is overridden by the workio API + open_file = __builtins__["open"] + with open_file(workspace_mel, "r") as f: + for line in f: + if line.strip().startswith(scene_rule): + # remainder == "rule"; + remainder = line[len(scene_rule):] + # scene_dir == rule + scene_dir = remainder.split('"')[1] + else: + # We can't query a workspace that does not exist + # so we return similar to what we do in other hosts. + scene_dir = session.get("AVALON_SCENEDIR") + + if scene_dir: + return os.path.join(work_dir, scene_dir) + else: + return work_dir diff --git a/openpype/hosts/maya/plugins/inventory/import_modelrender.py b/openpype/hosts/maya/plugins/inventory/import_modelrender.py index e3cad4cf2e..119edccb7a 100644 --- a/openpype/hosts/maya/plugins/inventory/import_modelrender.py +++ b/openpype/hosts/maya/plugins/inventory/import_modelrender.py @@ -1,4 +1,9 @@ -from avalon import api, io +import json +from avalon import api, io, pipeline +from openpype.hosts.maya.api.lib import ( + maintained_selection, + apply_shaders +) class ImportModelRender(api.InventoryAction): @@ -49,10 +54,8 @@ class ImportModelRender(api.InventoryAction): Returns: None """ - import json + from maya import cmds - from avalon import maya, io, pipeline - from openpype.hosts.maya.api import lib # Get representations of shader file and relationships look_repr = io.find_one({ @@ -77,7 +80,7 @@ class ImportModelRender(api.InventoryAction): json_file = pipeline.get_representation_path_from_context(context) # Import the look file - with maya.maintained_selection(): + with maintained_selection(): shader_nodes = cmds.file(maya_file, i=True, # import returnNewNodes=True) @@ -89,4 +92,4 @@ class ImportModelRender(api.InventoryAction): relationships = json.load(f) # Assign relationships - lib.apply_shaders(relationships, shader_nodes, nodes) + apply_shaders(relationships, shader_nodes, nodes) diff --git a/openpype/hosts/maya/plugins/load/_load_animation.py b/openpype/hosts/maya/plugins/load/_load_animation.py index b1784f1590..bce1f0fc67 100644 --- a/openpype/hosts/maya/plugins/load/_load_animation.py +++ b/openpype/hosts/maya/plugins/load/_load_animation.py @@ -17,7 +17,7 @@ class AbcLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): def process_reference(self, context, name, namespace, data): import maya.cmds as cmds - from avalon import maya + from openpype.hosts.maya.api.lib import unique_namespace cmds.loadPlugin("AbcImport.mll", quiet=True) # Prevent identical alembic nodes from being shared @@ -27,9 +27,11 @@ class AbcLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): # Assuming name is subset name from the animation, we split the number # suffix from the name to ensure the namespace is unique name = name.split("_")[0] - namespace = maya.unique_namespace("{}_".format(name), - format="%03d", - suffix="_abc") + namespace = unique_namespace( + "{}_".format(name), + format="%03d", + suffix="_abc" + ) # hero_001 (abc) # asset_counter{optional} diff --git a/openpype/hosts/maya/plugins/load/actions.py b/openpype/hosts/maya/plugins/load/actions.py index 1a9adf6142..1cc7ee0c03 100644 --- a/openpype/hosts/maya/plugins/load/actions.py +++ b/openpype/hosts/maya/plugins/load/actions.py @@ -3,6 +3,10 @@ """ from avalon import api +from openpype.hosts.maya.api.lib import ( + maintained_selection, + unique_namespace +) class SetFrameRangeLoader(api.Loader): @@ -98,22 +102,19 @@ class ImportMayaLoader(api.Loader): def load(self, context, name=None, namespace=None, data=None): import maya.cmds as cmds - from avalon import maya - from avalon.maya import lib - choice = self.display_warning() if choice is False: return asset = context['asset'] - namespace = namespace or lib.unique_namespace( + namespace = namespace or unique_namespace( asset["name"] + "_", prefix="_" if asset["name"][0].isdigit() else "", suffix="_", ) - with maya.maintained_selection(): + with maintained_selection(): cmds.file(self.fname, i=True, preserveReferences=True, diff --git a/openpype/hosts/maya/plugins/load/load_ass.py b/openpype/hosts/maya/plugins/load/load_ass.py index 891f21916c..18b34d2233 100644 --- a/openpype/hosts/maya/plugins/load/load_ass.py +++ b/openpype/hosts/maya/plugins/load/load_ass.py @@ -1,9 +1,15 @@ +import os +import clique + from avalon import api +from openpype.api import get_project_settings import openpype.hosts.maya.api.plugin from openpype.hosts.maya.api.plugin import get_reference_node -import os -from openpype.api import get_project_settings -import clique +from openpype.hosts.maya.api.lib import ( + maintained_selection, + unique_namespace +) +from openpype.hosts.maya.api.pipeline import containerise class AssProxyLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): @@ -20,7 +26,6 @@ class AssProxyLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): def process_reference(self, context, name, namespace, options): import maya.cmds as cmds - from avalon import maya import pymel.core as pm version = context['version'] @@ -35,7 +40,7 @@ class AssProxyLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): except ValueError: family = "ass" - with maya.maintained_selection(): + with maintained_selection(): groupName = "{}:{}".format(namespace, name) path = self.fname @@ -95,8 +100,6 @@ class AssProxyLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): self.update(container, representation) def update(self, container, representation): - - import os from maya import cmds import pymel.core as pm @@ -175,8 +178,6 @@ class AssStandinLoader(api.Loader): def load(self, context, name, namespace, options): import maya.cmds as cmds - import avalon.maya.lib as lib - from avalon.maya.pipeline import containerise import mtoa.ui.arnoldmenu import pymel.core as pm @@ -188,7 +189,7 @@ class AssStandinLoader(api.Loader): frameStart = version_data.get("frameStart", None) asset = context['asset']['name'] - namespace = namespace or lib.unique_namespace( + namespace = namespace or unique_namespace( asset + "_", prefix="_" if asset[0].isdigit() else "", suffix="_", diff --git a/openpype/hosts/maya/plugins/load/load_assembly.py b/openpype/hosts/maya/plugins/load/load_assembly.py index 2f0ca3922e..0151da7253 100644 --- a/openpype/hosts/maya/plugins/load/load_assembly.py +++ b/openpype/hosts/maya/plugins/load/load_assembly.py @@ -13,11 +13,11 @@ class AssemblyLoader(api.Loader): def load(self, context, name, namespace, data): - from avalon.maya.pipeline import containerise - from avalon.maya import lib + from openpype.hosts.maya.api.pipeline import containerise + from openpype.hosts.maya.api.lib import unique_namespace asset = context['asset']['name'] - namespace = namespace or lib.unique_namespace( + namespace = namespace or unique_namespace( asset + "_", prefix="_" if asset[0].isdigit() else "", suffix="_", @@ -25,9 +25,11 @@ class AssemblyLoader(api.Loader): from openpype.hosts.maya.api import setdress - containers = setdress.load_package(filepath=self.fname, - name=name, - namespace=namespace) + containers = setdress.load_package( + filepath=self.fname, + name=name, + namespace=namespace + ) self[:] = containers diff --git a/openpype/hosts/maya/plugins/load/load_audio.py b/openpype/hosts/maya/plugins/load/load_audio.py index 0611dcc189..99f1f7c172 100644 --- a/openpype/hosts/maya/plugins/load/load_audio.py +++ b/openpype/hosts/maya/plugins/load/load_audio.py @@ -1,7 +1,7 @@ -from avalon import api, io -from avalon.maya.pipeline import containerise -from avalon.maya import lib from maya import cmds, mel +from avalon import api, io +from openpype.hosts.maya.api.pipeline import containerise +from openpype.hosts.maya.api.lib import unique_namespace class AudioLoader(api.Loader): @@ -27,7 +27,7 @@ class AudioLoader(api.Loader): ) asset = context["asset"]["name"] - namespace = namespace or lib.unique_namespace( + namespace = namespace or unique_namespace( asset + "_", prefix="_" if asset[0].isdigit() else "", suffix="_", diff --git a/openpype/hosts/maya/plugins/load/load_gpucache.py b/openpype/hosts/maya/plugins/load/load_gpucache.py index 444f98f22e..2e0b7bb810 100644 --- a/openpype/hosts/maya/plugins/load/load_gpucache.py +++ b/openpype/hosts/maya/plugins/load/load_gpucache.py @@ -17,11 +17,11 @@ class GpuCacheLoader(api.Loader): def load(self, context, name, namespace, data): import maya.cmds as cmds - import avalon.maya.lib as lib - from avalon.maya.pipeline import containerise + from openpype.hosts.maya.api.pipeline import containerise + from openpype.hosts.maya.api.lib import unique_namespace asset = context['asset']['name'] - namespace = namespace or lib.unique_namespace( + namespace = namespace or unique_namespace( asset + "_", prefix="_" if asset[0].isdigit() else "", suffix="_", diff --git a/openpype/hosts/maya/plugins/load/load_image_plane.py b/openpype/hosts/maya/plugins/load/load_image_plane.py index 0652147324..8e33f51389 100644 --- a/openpype/hosts/maya/plugins/load/load_image_plane.py +++ b/openpype/hosts/maya/plugins/load/load_image_plane.py @@ -1,8 +1,9 @@ -from avalon import api, io -from avalon.maya.pipeline import containerise -from avalon.maya import lib from Qt import QtWidgets, QtCore +from avalon import api, io +from openpype.hosts.maya.api.pipeline import containerise +from openpype.hosts.maya.api.lib import unique_namespace + from maya import cmds @@ -88,7 +89,7 @@ class ImagePlaneLoader(api.Loader): new_nodes = [] image_plane_depth = 1000 asset = context['asset']['name'] - namespace = namespace or lib.unique_namespace( + namespace = namespace or unique_namespace( asset + "_", prefix="_" if asset[0].isdigit() else "", suffix="_", diff --git a/openpype/hosts/maya/plugins/load/load_look.py b/openpype/hosts/maya/plugins/load/load_look.py index 8e14778fd2..ef1076f2cb 100644 --- a/openpype/hosts/maya/plugins/load/load_look.py +++ b/openpype/hosts/maya/plugins/load/load_look.py @@ -1,13 +1,15 @@ # -*- coding: utf-8 -*- """Look loader.""" -import openpype.hosts.maya.api.plugin -from avalon import api, io import json -import openpype.hosts.maya.api.lib from collections import defaultdict -from openpype.widgets.message_window import ScrollMessageBox + from Qt import QtWidgets +from avalon import api, io +import openpype.hosts.maya.api.plugin +from openpype.hosts.maya.api import lib +from openpype.widgets.message_window import ScrollMessageBox + from openpype.hosts.maya.api.plugin import get_reference_node @@ -36,9 +38,8 @@ class LookLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): """ import maya.cmds as cmds - from avalon import maya - with maya.maintained_selection(): + with lib.maintained_selection(): nodes = cmds.file(self.fname, namespace=namespace, reference=True, @@ -140,9 +141,7 @@ class LookLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): cmds.file(cr=reference_node) # cleanReference # reapply shading groups from json representation on orig nodes - openpype.hosts.maya.api.lib.apply_shaders(json_data, - shader_nodes, - orig_nodes) + lib.apply_shaders(json_data, shader_nodes, orig_nodes) msg = ["During reference update some edits failed.", "All successful edits were kept intact.\n", @@ -159,8 +158,8 @@ class LookLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): # region compute lookup nodes_by_id = defaultdict(list) for n in nodes: - nodes_by_id[openpype.hosts.maya.api.lib.get_id(n)].append(n) - openpype.hosts.maya.api.lib.apply_attributes(attributes, nodes_by_id) + nodes_by_id[lib.get_id(n)].append(n) + lib.apply_attributes(attributes, nodes_by_id) # Update metadata cmds.setAttr("{}.representation".format(node), diff --git a/openpype/hosts/maya/plugins/load/load_redshift_proxy.py b/openpype/hosts/maya/plugins/load/load_redshift_proxy.py index 4c6a187bc3..fd2ae0f1d3 100644 --- a/openpype/hosts/maya/plugins/load/load_redshift_proxy.py +++ b/openpype/hosts/maya/plugins/load/load_redshift_proxy.py @@ -1,11 +1,18 @@ # -*- coding: utf-8 -*- """Loader for Redshift proxy.""" -from avalon.maya import lib +import os +import clique + +import maya.cmds as cmds + from avalon import api from openpype.api import get_project_settings -import os -import maya.cmds as cmds -import clique +from openpype.hosts.maya.api.lib import ( + namespaced, + maintained_selection, + unique_namespace +) +from openpype.hosts.maya.api.pipeline import containerise class RedshiftProxyLoader(api.Loader): @@ -21,17 +28,13 @@ class RedshiftProxyLoader(api.Loader): def load(self, context, name=None, namespace=None, options=None): """Plugin entry point.""" - - from avalon.maya.pipeline import containerise - from openpype.hosts.maya.api.lib import namespaced - try: family = context["representation"]["context"]["family"] except ValueError: family = "redshiftproxy" asset_name = context['asset']["name"] - namespace = namespace or lib.unique_namespace( + namespace = namespace or unique_namespace( asset_name + "_", prefix="_" if asset_name[0].isdigit() else "", suffix="_", @@ -40,7 +43,7 @@ class RedshiftProxyLoader(api.Loader): # Ensure Redshift for Maya is loaded. cmds.loadPlugin("redshift4maya", quiet=True) - with lib.maintained_selection(): + with maintained_selection(): cmds.namespace(addNamespace=namespace) with namespaced(namespace, new=False): nodes, group_node = self.create_rs_proxy( diff --git a/openpype/hosts/maya/plugins/load/load_reference.py b/openpype/hosts/maya/plugins/load/load_reference.py index 2cc24f1360..0565b0b95c 100644 --- a/openpype/hosts/maya/plugins/load/load_reference.py +++ b/openpype/hosts/maya/plugins/load/load_reference.py @@ -1,9 +1,10 @@ -import openpype.hosts.maya.api.plugin -from avalon import api, maya -from maya import cmds import os +from maya import cmds +from avalon import api from openpype.api import get_project_settings from openpype.lib import get_creator_by_name +import openpype.hosts.maya.api.plugin +from openpype.hosts.maya.api.lib import maintained_selection class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): @@ -32,7 +33,6 @@ class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): def process_reference(self, context, name, namespace, options): import maya.cmds as cmds - from avalon import maya import pymel.core as pm try: @@ -44,7 +44,7 @@ class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): # True by default to keep legacy behaviours attach_to_root = options.get("attach_to_root", True) - with maya.maintained_selection(): + with maintained_selection(): cmds.loadPlugin("AbcImport.mll", quiet=True) nodes = cmds.file(self.fname, namespace=namespace, @@ -149,7 +149,7 @@ class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): # Create the animation instance creator_plugin = get_creator_by_name(self.animation_creator_name) - with maya.maintained_selection(): + with maintained_selection(): cmds.select([output, controls] + roots, noExpand=True) api.create( creator_plugin, diff --git a/openpype/hosts/maya/plugins/load/load_rendersetup.py b/openpype/hosts/maya/plugins/load/load_rendersetup.py index 574ae9bd3d..efeff2f193 100644 --- a/openpype/hosts/maya/plugins/load/load_rendersetup.py +++ b/openpype/hosts/maya/plugins/load/load_rendersetup.py @@ -11,8 +11,8 @@ import six import sys from avalon import api -from avalon.maya import lib -from openpype.hosts.maya.api import lib as pypelib +from openpype.hosts.maya.api import lib +from openpype.hosts.maya.api.pipeline import containerise from maya import cmds import maya.app.renderSetup.model.renderSetup as renderSetup @@ -31,7 +31,6 @@ class RenderSetupLoader(api.Loader): def load(self, context, name, namespace, data): """Load RenderSetup settings.""" - from avalon.maya.pipeline import containerise # from openpype.hosts.maya.api.lib import namespaced @@ -83,7 +82,7 @@ class RenderSetupLoader(api.Loader): def update(self, container, representation): """Update RenderSetup setting by overwriting existing settings.""" - pypelib.show_message( + lib.show_message( "Render setup update", "Render setup setting will be overwritten by new version. All " "setting specified by user not included in loaded version " diff --git a/openpype/hosts/maya/plugins/load/load_vdb_to_redshift.py b/openpype/hosts/maya/plugins/load/load_vdb_to_redshift.py index f5662ba462..3e1d67ae9a 100644 --- a/openpype/hosts/maya/plugins/load/load_vdb_to_redshift.py +++ b/openpype/hosts/maya/plugins/load/load_vdb_to_redshift.py @@ -1,7 +1,8 @@ -from avalon import api import os +from avalon import api from openpype.api import get_project_settings + class LoadVDBtoRedShift(api.Loader): """Load OpenVDB in a Redshift Volume Shape""" @@ -15,8 +16,8 @@ class LoadVDBtoRedShift(api.Loader): def load(self, context, name=None, namespace=None, data=None): from maya import cmds - import avalon.maya.lib as lib - from avalon.maya.pipeline import containerise + from openpype.hosts.maya.api.pipeline import containerise + from openpype.hosts.maya.api.lib import unique_namespace try: family = context["representation"]["context"]["family"] @@ -45,7 +46,7 @@ class LoadVDBtoRedShift(api.Loader): asset = context['asset'] asset_name = asset["name"] - namespace = namespace or lib.unique_namespace( + namespace = namespace or unique_namespace( asset_name + "_", prefix="_" if asset_name[0].isdigit() else "", suffix="_", diff --git a/openpype/hosts/maya/plugins/load/load_vdb_to_vray.py b/openpype/hosts/maya/plugins/load/load_vdb_to_vray.py index ed561e1131..099c020093 100644 --- a/openpype/hosts/maya/plugins/load/load_vdb_to_vray.py +++ b/openpype/hosts/maya/plugins/load/load_vdb_to_vray.py @@ -1,6 +1,6 @@ +import os from avalon import api from openpype.api import get_project_settings -import os from maya import cmds @@ -80,8 +80,8 @@ class LoadVDBtoVRay(api.Loader): def load(self, context, name, namespace, data): - import avalon.maya.lib as lib - from avalon.maya.pipeline import containerise + from openpype.hosts.maya.api.lib import unique_namespace + from openpype.hosts.maya.api.pipeline import containerise assert os.path.exists(self.fname), ( "Path does not exist: %s" % self.fname @@ -111,7 +111,7 @@ class LoadVDBtoVRay(api.Loader): asset = context['asset'] asset_name = asset["name"] - namespace = namespace or lib.unique_namespace( + namespace = namespace or unique_namespace( asset_name + "_", prefix="_" if asset_name[0].isdigit() else "", suffix="_", diff --git a/openpype/hosts/maya/plugins/load/load_vrayproxy.py b/openpype/hosts/maya/plugins/load/load_vrayproxy.py index 806cf1fd18..ac2fe635b3 100644 --- a/openpype/hosts/maya/plugins/load/load_vrayproxy.py +++ b/openpype/hosts/maya/plugins/load/load_vrayproxy.py @@ -9,9 +9,14 @@ import os import maya.cmds as cmds -from avalon.maya import lib from avalon import api, io from openpype.api import get_project_settings +from openpype.hosts.maya.api.lib import ( + maintained_selection, + namespaced, + unique_namespace +) +from openpype.hosts.maya.api.pipeline import containerise class VRayProxyLoader(api.Loader): @@ -36,8 +41,6 @@ class VRayProxyLoader(api.Loader): options (dict): Optional loader options. """ - from avalon.maya.pipeline import containerise - from openpype.hosts.maya.api.lib import namespaced try: family = context["representation"]["context"]["family"] @@ -48,7 +51,7 @@ class VRayProxyLoader(api.Loader): self.fname = self._get_abc(context["version"]["_id"]) or self.fname asset_name = context['asset']["name"] - namespace = namespace or lib.unique_namespace( + namespace = namespace or unique_namespace( asset_name + "_", prefix="_" if asset_name[0].isdigit() else "", suffix="_", @@ -57,7 +60,7 @@ class VRayProxyLoader(api.Loader): # Ensure V-Ray for Maya is loaded. cmds.loadPlugin("vrayformaya", quiet=True) - with lib.maintained_selection(): + with maintained_selection(): cmds.namespace(addNamespace=namespace) with namespaced(namespace, new=False): nodes, group_node = self.create_vray_proxy( diff --git a/openpype/hosts/maya/plugins/load/load_vrayscene.py b/openpype/hosts/maya/plugins/load/load_vrayscene.py index 465dab2a76..2e85514938 100644 --- a/openpype/hosts/maya/plugins/load/load_vrayscene.py +++ b/openpype/hosts/maya/plugins/load/load_vrayscene.py @@ -1,8 +1,13 @@ -from avalon.maya import lib -from avalon import api -from openpype.api import config import os import maya.cmds as cmds +from avalon import api +from openpype.api import get_project_settings +from openpype.hosts.maya.api.lib import ( + maintained_selection, + namespaced, + unique_namespace +) +from openpype.hosts.maya.api.pipeline import containerise class VRaySceneLoader(api.Loader): @@ -18,8 +23,6 @@ class VRaySceneLoader(api.Loader): def load(self, context, name, namespace, data): - from avalon.maya.pipeline import containerise - from openpype.hosts.maya.lib import namespaced try: family = context["representation"]["context"]["family"] @@ -27,7 +30,7 @@ class VRaySceneLoader(api.Loader): family = "vrayscene_layer" asset_name = context['asset']["name"] - namespace = namespace or lib.unique_namespace( + namespace = namespace or unique_namespace( asset_name + "_", prefix="_" if asset_name[0].isdigit() else "", suffix="_", @@ -36,7 +39,7 @@ class VRaySceneLoader(api.Loader): # Ensure V-Ray for Maya is loaded. cmds.loadPlugin("vrayformaya", quiet=True) - with lib.maintained_selection(): + with maintained_selection(): cmds.namespace(addNamespace=namespace) with namespaced(namespace, new=False): nodes, group_node = self.create_vray_scene(name, @@ -47,8 +50,8 @@ class VRaySceneLoader(api.Loader): return # colour the group node - presets = config.get_presets(project=os.environ['AVALON_PROJECT']) - colors = presets['plugins']['maya']['load']['colors'] + presets = get_project_settings(os.environ['AVALON_PROJECT']) + colors = presets['maya']['load']['colors'] c = colors.get(family) if c is not None: cmds.setAttr("{0}.useOutlinerColor".format(group_node), 1) diff --git a/openpype/hosts/maya/plugins/load/load_yeti_cache.py b/openpype/hosts/maya/plugins/load/load_yeti_cache.py index de0ea6823c..dfe75173ac 100644 --- a/openpype/hosts/maya/plugins/load/load_yeti_cache.py +++ b/openpype/hosts/maya/plugins/load/load_yeti_cache.py @@ -3,14 +3,14 @@ import json import re import glob from collections import defaultdict +from pprint import pprint from maya import cmds from avalon import api, io -from avalon.maya import lib as avalon_lib, pipeline -from openpype.hosts.maya.api import lib from openpype.api import get_project_settings -from pprint import pprint +from openpype.hosts.maya.api import lib +from openpype.hosts.maya.api.pipeline import containerise class YetiCacheLoader(api.Loader): @@ -75,11 +75,13 @@ class YetiCacheLoader(api.Loader): self[:] = nodes - return pipeline.containerise(name=name, - namespace=namespace, - nodes=nodes, - context=context, - loader=self.__class__.__name__) + return containerise( + name=name, + namespace=namespace, + nodes=nodes, + context=context, + loader=self.__class__.__name__ + ) def remove(self, container): @@ -239,9 +241,11 @@ class YetiCacheLoader(api.Loader): asset_name = "{}_".format(asset) prefix = "_" if asset_name[0].isdigit()else "" - namespace = avalon_lib.unique_namespace(asset_name, - prefix=prefix, - suffix="_") + namespace = lib.unique_namespace( + asset_name, + prefix=prefix, + suffix="_" + ) return namespace diff --git a/openpype/hosts/maya/plugins/load/load_yeti_rig.py b/openpype/hosts/maya/plugins/load/load_yeti_rig.py index 3f67f98f51..b4d31b473f 100644 --- a/openpype/hosts/maya/plugins/load/load_yeti_rig.py +++ b/openpype/hosts/maya/plugins/load/load_yeti_rig.py @@ -25,7 +25,6 @@ class YetiRigLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): self, context, name=None, namespace=None, options=None): import maya.cmds as cmds - from avalon import maya # get roots of selected hierarchies selected_roots = [] @@ -53,7 +52,7 @@ class YetiRigLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): scene_lookup[cb_id] = node # load rig - with maya.maintained_selection(): + with lib.maintained_selection(): nodes = cmds.file(self.fname, namespace=namespace, reference=True, diff --git a/openpype/hosts/maya/plugins/publish/collect_assembly.py b/openpype/hosts/maya/plugins/publish/collect_assembly.py index 313636793b..1a65bf1fde 100644 --- a/openpype/hosts/maya/plugins/publish/collect_assembly.py +++ b/openpype/hosts/maya/plugins/publish/collect_assembly.py @@ -2,7 +2,7 @@ from collections import defaultdict import pyblish.api from maya import cmds, mel -from avalon import maya as avalon +from openpype.hosts.maya import api from openpype.hosts.maya.api import lib # TODO : Publish of assembly: -unique namespace for all assets, VALIDATOR! @@ -30,7 +30,7 @@ class CollectAssembly(pyblish.api.InstancePlugin): def process(self, instance): # Find containers - containers = avalon.ls() + containers = api.ls() # Get all content from the instance instance_lookup = set(cmds.ls(instance, type="transform", long=True)) diff --git a/openpype/hosts/maya/plugins/publish/collect_render.py b/openpype/hosts/maya/plugins/publish/collect_render.py index cbddb86e53..13ae1924b9 100644 --- a/openpype/hosts/maya/plugins/publish/collect_render.py +++ b/openpype/hosts/maya/plugins/publish/collect_render.py @@ -49,7 +49,7 @@ import maya.app.renderSetup.model.renderSetup as renderSetup import pyblish.api -from avalon import maya, api +from avalon import api from openpype.hosts.maya.api.lib_renderproducts import get as get_layer_render_products # noqa: E501 from openpype.hosts.maya.api import lib @@ -409,7 +409,7 @@ class CollectMayaRender(pyblish.api.ContextPlugin): dict: only overrides with values """ - attributes = maya.read(render_globals) + attributes = lib.read(render_globals) options = {"renderGlobals": {}} options["renderGlobals"]["Priority"] = attributes["priority"] diff --git a/openpype/hosts/maya/plugins/publish/extract_animation.py b/openpype/hosts/maya/plugins/publish/extract_animation.py index 7ecc40a68d..269972d996 100644 --- a/openpype/hosts/maya/plugins/publish/extract_animation.py +++ b/openpype/hosts/maya/plugins/publish/extract_animation.py @@ -2,9 +2,12 @@ import os from maya import cmds -import avalon.maya import openpype.api -from openpype.hosts.maya.api.lib import extract_alembic +from openpype.hosts.maya.api.lib import ( + extract_alembic, + suspended_refresh, + maintained_selection +) class ExtractAnimation(openpype.api.Extractor): @@ -71,8 +74,8 @@ class ExtractAnimation(openpype.api.Extractor): # Since Maya 2017 alembic supports multiple uv sets - write them. options["writeUVSets"] = True - with avalon.maya.suspended_refresh(): - with avalon.maya.maintained_selection(): + with suspended_refresh(): + with maintained_selection(): cmds.select(nodes, noExpand=True) extract_alembic(file=path, startFrame=float(start), diff --git a/openpype/hosts/maya/plugins/publish/extract_ass.py b/openpype/hosts/maya/plugins/publish/extract_ass.py index 7461ccdf78..ab149de700 100644 --- a/openpype/hosts/maya/plugins/publish/extract_ass.py +++ b/openpype/hosts/maya/plugins/publish/extract_ass.py @@ -1,9 +1,9 @@ import os -import avalon.maya import openpype.api from maya import cmds +from openpype.hosts.maya.api.lib import maintained_selection class ExtractAssStandin(openpype.api.Extractor): @@ -30,7 +30,7 @@ class ExtractAssStandin(openpype.api.Extractor): # Write out .ass file self.log.info("Writing: '%s'" % file_path) - with avalon.maya.maintained_selection(): + with maintained_selection(): self.log.info("Writing: {}".format(instance.data["setMembers"])) cmds.select(instance.data["setMembers"], noExpand=True) diff --git a/openpype/hosts/maya/plugins/publish/extract_assproxy.py b/openpype/hosts/maya/plugins/publish/extract_assproxy.py index f53f385b8b..93720dbb82 100644 --- a/openpype/hosts/maya/plugins/publish/extract_assproxy.py +++ b/openpype/hosts/maya/plugins/publish/extract_assproxy.py @@ -1,10 +1,10 @@ import os - -from maya import cmds import contextlib -import avalon.maya +from maya import cmds + import openpype.api +from openpype.hosts.maya.api.lib import maintained_selection class ExtractAssProxy(openpype.api.Extractor): @@ -54,7 +54,7 @@ class ExtractAssProxy(openpype.api.Extractor): noIntermediate=True) self.log.info(members) - with avalon.maya.maintained_selection(): + with maintained_selection(): with unparent(members[0]): cmds.select(members, noExpand=True) cmds.file(path, diff --git a/openpype/hosts/maya/plugins/publish/extract_camera_alembic.py b/openpype/hosts/maya/plugins/publish/extract_camera_alembic.py index 8950ed6254..806a079940 100644 --- a/openpype/hosts/maya/plugins/publish/extract_camera_alembic.py +++ b/openpype/hosts/maya/plugins/publish/extract_camera_alembic.py @@ -2,9 +2,7 @@ import os from maya import cmds -import avalon.maya import openpype.api - from openpype.hosts.maya.api import lib @@ -54,7 +52,7 @@ class ExtractCameraAlembic(openpype.api.Extractor): path = os.path.join(dir_path, filename) # Perform alembic extraction - with avalon.maya.maintained_selection(): + with lib.maintained_selection(): cmds.select(camera, replace=True, noExpand=True) # Enforce forward slashes for AbcExport because we're @@ -86,7 +84,7 @@ class ExtractCameraAlembic(openpype.api.Extractor): job_str += " -attr {0}".format(attr) with lib.evaluation("off"): - with avalon.maya.suspended_refresh(): + with lib.suspended_refresh(): cmds.AbcExport(j=job_str, verbose=False) if "representations" not in instance.data: diff --git a/openpype/hosts/maya/plugins/publish/extract_camera_mayaScene.py b/openpype/hosts/maya/plugins/publish/extract_camera_mayaScene.py index 888dc636b2..9d25b147de 100644 --- a/openpype/hosts/maya/plugins/publish/extract_camera_mayaScene.py +++ b/openpype/hosts/maya/plugins/publish/extract_camera_mayaScene.py @@ -5,7 +5,6 @@ import itertools from maya import cmds -import avalon.maya import openpype.api from openpype.hosts.maya.api import lib @@ -157,9 +156,9 @@ class ExtractCameraMayaScene(openpype.api.Extractor): path = os.path.join(dir_path, filename) # Perform extraction - with avalon.maya.maintained_selection(): + with lib.maintained_selection(): with lib.evaluation("off"): - with avalon.maya.suspended_refresh(): + with lib.suspended_refresh(): if bake_to_worldspace: self.log.info( "Performing camera bakes: {}".format(transform)) diff --git a/openpype/hosts/maya/plugins/publish/extract_fbx.py b/openpype/hosts/maya/plugins/publish/extract_fbx.py index e4894f28cd..844084b9ab 100644 --- a/openpype/hosts/maya/plugins/publish/extract_fbx.py +++ b/openpype/hosts/maya/plugins/publish/extract_fbx.py @@ -3,12 +3,12 @@ import os from maya import cmds # noqa import maya.mel as mel # noqa -from openpype.hosts.maya.api.lib import root_parent - import pyblish.api -import avalon.maya - import openpype.api +from openpype.hosts.maya.api.lib import ( + root_parent, + maintained_selection +) class ExtractFBX(openpype.api.Extractor): @@ -205,13 +205,13 @@ class ExtractFBX(openpype.api.Extractor): # Export if "unrealStaticMesh" in instance.data["families"]: - with avalon.maya.maintained_selection(): + with maintained_selection(): with root_parent(members): self.log.info("Un-parenting: {}".format(members)) cmds.select(members, r=1, noExpand=True) mel.eval('FBXExport -f "{}" -s'.format(path)) else: - with avalon.maya.maintained_selection(): + with maintained_selection(): cmds.select(members, r=1, noExpand=True) mel.eval('FBXExport -f "{}" -s'.format(path)) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index bf79ddbf44..fe89038a24 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -11,8 +11,7 @@ from collections import OrderedDict from maya import cmds # noqa import pyblish.api -import avalon.maya -from avalon import io, api +from avalon import io import openpype.api from openpype.hosts.maya.api import lib @@ -239,7 +238,7 @@ class ExtractLook(openpype.api.Extractor): # getting incorrectly remapped. (LKD-17, PLN-101) with no_workspace_dir(): with lib.attribute_values(remap): - with avalon.maya.maintained_selection(): + with lib.maintained_selection(): cmds.select(sets, noExpand=True) cmds.file( maya_path, diff --git a/openpype/hosts/maya/plugins/publish/extract_maya_scene_raw.py b/openpype/hosts/maya/plugins/publish/extract_maya_scene_raw.py index e7fb5bc8cb..9c432cbc67 100644 --- a/openpype/hosts/maya/plugins/publish/extract_maya_scene_raw.py +++ b/openpype/hosts/maya/plugins/publish/extract_maya_scene_raw.py @@ -4,8 +4,8 @@ import os from maya import cmds -import avalon.maya import openpype.api +from openpype.hosts.maya.api.lib import maintained_selection class ExtractMayaSceneRaw(openpype.api.Extractor): @@ -59,7 +59,7 @@ class ExtractMayaSceneRaw(openpype.api.Extractor): # Perform extraction self.log.info("Performing extraction ...") - with avalon.maya.maintained_selection(): + with maintained_selection(): cmds.select(members, noExpand=True) cmds.file(path, force=True, diff --git a/openpype/hosts/maya/plugins/publish/extract_model.py b/openpype/hosts/maya/plugins/publish/extract_model.py index 40cc9427f3..0282d1e9c8 100644 --- a/openpype/hosts/maya/plugins/publish/extract_model.py +++ b/openpype/hosts/maya/plugins/publish/extract_model.py @@ -4,7 +4,6 @@ import os from maya import cmds -import avalon.maya import openpype.api from openpype.hosts.maya.api import lib @@ -74,7 +73,7 @@ class ExtractModel(openpype.api.Extractor): polygonObject=1): with lib.shader(members, shadingEngine="initialShadingGroup"): - with avalon.maya.maintained_selection(): + with lib.maintained_selection(): cmds.select(members, noExpand=True) cmds.file(path, force=True, diff --git a/openpype/hosts/maya/plugins/publish/extract_pointcache.py b/openpype/hosts/maya/plugins/publish/extract_pointcache.py index 630cc39398..60502fdde1 100644 --- a/openpype/hosts/maya/plugins/publish/extract_pointcache.py +++ b/openpype/hosts/maya/plugins/publish/extract_pointcache.py @@ -2,9 +2,12 @@ import os from maya import cmds -import avalon.maya import openpype.api -from openpype.hosts.maya.api.lib import extract_alembic +from openpype.hosts.maya.api.lib import ( + extract_alembic, + suspended_refresh, + maintained_selection +) class ExtractAlembic(openpype.api.Extractor): @@ -70,8 +73,8 @@ class ExtractAlembic(openpype.api.Extractor): # Since Maya 2017 alembic supports multiple uv sets - write them. options["writeUVSets"] = True - with avalon.maya.suspended_refresh(): - with avalon.maya.maintained_selection(): + with suspended_refresh(): + with maintained_selection(): cmds.select(nodes, noExpand=True) extract_alembic(file=path, startFrame=start, diff --git a/openpype/hosts/maya/plugins/publish/extract_redshift_proxy.py b/openpype/hosts/maya/plugins/publish/extract_redshift_proxy.py index 7c9e201986..23cac9190d 100644 --- a/openpype/hosts/maya/plugins/publish/extract_redshift_proxy.py +++ b/openpype/hosts/maya/plugins/publish/extract_redshift_proxy.py @@ -2,11 +2,11 @@ """Redshift Proxy extractor.""" import os -import avalon.maya -import openpype.api - from maya import cmds +import openpype.api +from openpype.hosts.maya.api.lib import maintained_selection + class ExtractRedshiftProxy(openpype.api.Extractor): """Extract the content of the instance to a redshift proxy file.""" @@ -54,7 +54,7 @@ class ExtractRedshiftProxy(openpype.api.Extractor): # Write out rs file self.log.info("Writing: '%s'" % file_path) - with avalon.maya.maintained_selection(): + with maintained_selection(): cmds.select(instance.data["setMembers"], noExpand=True) cmds.file(file_path, pr=False, diff --git a/openpype/hosts/maya/plugins/publish/extract_rig.py b/openpype/hosts/maya/plugins/publish/extract_rig.py index b28b60114e..53c1eeb671 100644 --- a/openpype/hosts/maya/plugins/publish/extract_rig.py +++ b/openpype/hosts/maya/plugins/publish/extract_rig.py @@ -4,8 +4,8 @@ import os from maya import cmds -import avalon.maya import openpype.api +from openpype.hosts.maya.api.lib import maintained_selection class ExtractRig(openpype.api.Extractor): @@ -40,7 +40,7 @@ class ExtractRig(openpype.api.Extractor): # Perform extraction self.log.info("Performing extraction ...") - with avalon.maya.maintained_selection(): + with maintained_selection(): cmds.select(instance, noExpand=True) cmds.file(path, force=True, diff --git a/openpype/hosts/maya/plugins/publish/extract_vrayproxy.py b/openpype/hosts/maya/plugins/publish/extract_vrayproxy.py index 7103601b85..615bc27878 100644 --- a/openpype/hosts/maya/plugins/publish/extract_vrayproxy.py +++ b/openpype/hosts/maya/plugins/publish/extract_vrayproxy.py @@ -1,10 +1,10 @@ import os -import avalon.maya -import openpype.api - from maya import cmds +import openpype.api +from openpype.hosts.maya.api.lib import maintained_selection + class ExtractVRayProxy(openpype.api.Extractor): """Extract the content of the instance to a vrmesh file @@ -41,7 +41,7 @@ class ExtractVRayProxy(openpype.api.Extractor): # Write out vrmesh file self.log.info("Writing: '%s'" % file_path) - with avalon.maya.maintained_selection(): + with maintained_selection(): cmds.select(instance.data["setMembers"], noExpand=True) cmds.vrayCreateProxy(exportType=1, dir=staging_dir, diff --git a/openpype/hosts/maya/plugins/publish/extract_vrayscene.py b/openpype/hosts/maya/plugins/publish/extract_vrayscene.py index 1d7c0fa717..5d41697e5f 100644 --- a/openpype/hosts/maya/plugins/publish/extract_vrayscene.py +++ b/openpype/hosts/maya/plugins/publish/extract_vrayscene.py @@ -3,9 +3,9 @@ import os import re -import avalon.maya import openpype.api from openpype.hosts.maya.api.render_setup_tools import export_in_rs_layer +from openpype.hosts.maya.api.lib import maintained_selection from maya import cmds @@ -57,7 +57,7 @@ class ExtractVrayscene(openpype.api.Extractor): # Write out vrscene file self.log.info("Writing: '%s'" % file_path) - with avalon.maya.maintained_selection(): + with maintained_selection(): if "*" not in instance.data["setMembers"]: self.log.info( "Exporting: {}".format(instance.data["setMembers"])) diff --git a/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py b/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py index d69911c404..5728682abe 100644 --- a/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py +++ b/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py @@ -2,8 +2,11 @@ import os from maya import cmds -import avalon.maya import openpype.api +from openpype.hosts.maya.api.lib import ( + suspended_refresh, + maintained_selection +) class ExtractXgenCache(openpype.api.Extractor): @@ -32,8 +35,8 @@ class ExtractXgenCache(openpype.api.Extractor): filename = "{name}.abc".format(**instance.data) path = os.path.join(parent_dir, filename) - with avalon.maya.suspended_refresh(): - with avalon.maya.maintained_selection(): + with suspended_refresh(): + with maintained_selection(): command = ( '-file ' + path diff --git a/openpype/hosts/maya/plugins/publish/extract_yeti_rig.py b/openpype/hosts/maya/plugins/publish/extract_yeti_rig.py index 56d5dfe901..d12567a55a 100644 --- a/openpype/hosts/maya/plugins/publish/extract_yeti_rig.py +++ b/openpype/hosts/maya/plugins/publish/extract_yeti_rig.py @@ -7,9 +7,8 @@ import contextlib from maya import cmds -import avalon.maya.lib as lib import openpype.api -import openpype.hosts.maya.api.lib as maya +from openpype.hosts.maya.api import lib @contextlib.contextmanager diff --git a/openpype/hosts/maya/plugins/publish/validate_cycle_error.py b/openpype/hosts/maya/plugins/publish/validate_cycle_error.py index d4faf2e562..4dfe0b8add 100644 --- a/openpype/hosts/maya/plugins/publish/validate_cycle_error.py +++ b/openpype/hosts/maya/plugins/publish/validate_cycle_error.py @@ -2,10 +2,9 @@ from maya import cmds import pyblish.api -from avalon import maya - import openpype.api import openpype.hosts.maya.api.action +from openpype.hosts.maya.api.lib import maintained_selection class ValidateCycleError(pyblish.api.InstancePlugin): @@ -26,7 +25,7 @@ class ValidateCycleError(pyblish.api.InstancePlugin): @classmethod def get_invalid(cls, instance): - with maya.maintained_selection(): + with maintained_selection(): cmds.select(instance[:], noExpand=True) plugs = cmds.cycleCheck(all=False, # check selection only list=True) diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py b/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py index 6b3f508561..90eb01aa12 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py @@ -3,7 +3,7 @@ from maya import cmds import pyblish.api import openpype.api import openpype.hosts.maya.api.action -from avalon import maya +from openpype.hosts.maya.api.lib import maintained_selection class ValidateMeshArnoldAttributes(pyblish.api.InstancePlugin): @@ -67,7 +67,7 @@ class ValidateMeshArnoldAttributes(pyblish.api.InstancePlugin): @classmethod def repair(cls, instance): - with maya.maintained_selection(): + with maintained_selection(): with pc.UndoChunk(): temp_transform = pc.polyCube()[0] diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_ngons.py b/openpype/hosts/maya/plugins/publish/validate_mesh_ngons.py index 839aab0d0b..ab0beb2a9c 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mesh_ngons.py +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_ngons.py @@ -3,7 +3,6 @@ from maya import cmds import pyblish.api import openpype.api import openpype.hosts.maya.api.action -from avalon import maya from openpype.hosts.maya.api import lib diff --git a/openpype/hosts/maya/plugins/publish/validate_shape_zero.py b/openpype/hosts/maya/plugins/publish/validate_shape_zero.py index 6b5c5d1398..343eaccb7d 100644 --- a/openpype/hosts/maya/plugins/publish/validate_shape_zero.py +++ b/openpype/hosts/maya/plugins/publish/validate_shape_zero.py @@ -5,8 +5,6 @@ import openpype.api import openpype.hosts.maya.api.action from openpype.hosts.maya.api import lib -from avalon.maya import maintained_selection - class ValidateShapeZero(pyblish.api.Validator): """Shape components may not have any "tweak" values @@ -51,7 +49,7 @@ class ValidateShapeZero(pyblish.api.Validator): if not invalid_shapes: return - with maintained_selection(): + with lib.maintained_selection(): with lib.tool("selectSuperContext"): for shape in invalid_shapes: cmds.polyCollapseTweaks(shape) diff --git a/openpype/hosts/maya/startup/userSetup.py b/openpype/hosts/maya/startup/userSetup.py index 6d27c66882..b89244817a 100644 --- a/openpype/hosts/maya/startup/userSetup.py +++ b/openpype/hosts/maya/startup/userSetup.py @@ -1,8 +1,12 @@ import os +import avalon.api from openpype.api import get_project_settings +from openpype.hosts.maya import api import openpype.hosts.maya.api.lib as mlib from maya import cmds +avalon.api.install(api) + print("starting OpenPype usersetup") From fb7a616f9ee7f4e67123ffd1af1d4b18816cf7d1 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Thu, 3 Feb 2022 19:14:08 +0100 Subject: [PATCH 63/74] hound fixes --- openpype/hosts/maya/api/__init__.py | 7 ++++--- openpype/hosts/maya/api/commands.py | 1 - openpype/hosts/maya/api/lib.py | 2 +- openpype/hosts/maya/api/menu.py | 4 +++- openpype/hosts/maya/api/pipeline.py | 4 +++- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/openpype/hosts/maya/api/__init__.py b/openpype/hosts/maya/api/__init__.py index 1b75076028..9ea798e927 100644 --- a/openpype/hosts/maya/api/__init__.py +++ b/openpype/hosts/maya/api/__init__.py @@ -51,16 +51,17 @@ __all__ = [ "install", "uninstall", - "Creator", - "Loader", - "ls", + "containerise", "lock", "unlock", "is_locked", "lock_ignored", + "Creator", + "Loader", + # Workfiles API "open_file", "save_file", diff --git a/openpype/hosts/maya/api/commands.py b/openpype/hosts/maya/api/commands.py index ebae3b1399..c774afcc12 100644 --- a/openpype/hosts/maya/api/commands.py +++ b/openpype/hosts/maya/api/commands.py @@ -55,7 +55,6 @@ def edit_shader_definitions(): window.show() - def reset_frame_range(): """Set frame range to current asset""" # Set FPS first diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index ff19f72097..27a7061f74 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -639,7 +639,7 @@ def serialise_shaders(nodes): continue meshes_by_shader = dict() - for id_, mesh in meshes_by_id.items(): + for mesh in meshes_by_id.values(): shape = cmds.listRelatives(mesh, shapes=True, fullPath=True) or list() diff --git a/openpype/hosts/maya/api/menu.py b/openpype/hosts/maya/api/menu.py index 5554fce583..40ffd825f3 100644 --- a/openpype/hosts/maya/api/menu.py +++ b/openpype/hosts/maya/api/menu.py @@ -77,7 +77,9 @@ def install(): cmds.menuItem( "Publish...", - command=lambda *args: host_tools.show_publish(parent=parent_widget), + command=lambda *args: host_tools.show_publish( + parent=parent_widget + ), image=publish.ICON ) diff --git a/openpype/hosts/maya/api/pipeline.py b/openpype/hosts/maya/api/pipeline.py index a5455d0083..476ceb840b 100644 --- a/openpype/hosts/maya/api/pipeline.py +++ b/openpype/hosts/maya/api/pipeline.py @@ -180,7 +180,9 @@ def uninstall(): avalon.api.deregister_plugin_path(avalon.api.Loader, LOAD_PATH) avalon.api.deregister_plugin_path(avalon.api.Creator, CREATE_PATH) - avalon.api.deregister_plugin_path(avalon.api.InventoryAction, INVENTORY_PATH) + avalon.api.deregister_plugin_path( + avalon.api.InventoryAction, INVENTORY_PATH + ) menu.uninstall() From 6468751179d2fa1002efa5927acaf04549bb8d6e Mon Sep 17 00:00:00 2001 From: "clement.hector" Date: Fri, 4 Feb 2022 12:11:05 +0100 Subject: [PATCH 64/74] use env_value_to_bool instead of ast.literal_eval + os.getenv --- openpype/hosts/photoshop/api/lib.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/openpype/hosts/photoshop/api/lib.py b/openpype/hosts/photoshop/api/lib.py index 10d9e33543..cb0a11789b 100644 --- a/openpype/hosts/photoshop/api/lib.py +++ b/openpype/hosts/photoshop/api/lib.py @@ -2,7 +2,7 @@ import os import sys import contextlib import traceback -import ast + from Qt import QtWidgets import avalon.api @@ -10,6 +10,7 @@ import avalon.api from openpype.api import Logger from openpype.tools.utils import host_tools from openpype.lib.remote_publish import headless_publish +from openpype.lib import env_value_to_bool from .launch_logic import ProcessLauncher, stub @@ -34,21 +35,19 @@ def main(*subprocess_args): launcher = ProcessLauncher(subprocess_args) launcher.start() - if os.environ.get("HEADLESS_PUBLISH"): + if env_value_to_bool("HEADLESS_PUBLISH"): launcher.execute_in_main_thread( headless_publish, log, "ClosePS", os.environ.get("IS_TEST") ) - elif ast.literal_eval( - os.getenv("AVALON_PHOTOSHOP_WORKFILES_ON_LAUNCH", True)): - save = False - if os.getenv("WORKFILES_SAVE_AS"): - save = True + elif env_value_to_bool("AVALON_PHOTOSHOP_WORKFILES_ON_LAUNCH", + default=True): launcher.execute_in_main_thread( - host_tools.show_workfiles, save=save + host_tools.show_workfiles, + save=env_value_to_bool("WORKFILES_SAVE_AS") ) sys.exit(app.exec_()) From 78d0b8c654a01e600130f523ef6774052773fc22 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 4 Feb 2022 15:22:39 +0100 Subject: [PATCH 65/74] remove environments that are not passed in data --- app_launcher.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/app_launcher.py b/app_launcher.py index 6dc1518370..2cb313742b 100644 --- a/app_launcher.py +++ b/app_launcher.py @@ -29,9 +29,16 @@ def main(input_json_path): data = json.load(stream) # Change environment variables - env = data.get("env") or {} - for key, value in env.items(): - os.environ[key] = value + # - environments that are in current environments and are not data are + # removed + if "env" in data: + env = data["env"] + # Pop environment variable keys that are not in source + for key in set(os.environ.keys()) - set(env.keys()): + os.environ.pop(key) + + for key, value in env.items(): + os.environ[key] = value # Prepare launch arguments args = data["args"] From ecf0da7721bf084c2145672d1d9f7ba5f2386a15 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 4 Feb 2022 15:28:14 +0100 Subject: [PATCH 66/74] temporary fix for nuke --- openpype/hosts/nuke/__init__.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/nuke/__init__.py b/openpype/hosts/nuke/__init__.py index 60b37ce1dd..4402d0b48e 100644 --- a/openpype/hosts/nuke/__init__.py +++ b/openpype/hosts/nuke/__init__.py @@ -18,7 +18,13 @@ def add_implementation_envs(env, _app): new_nuke_paths.append(norm_path) env["NUKE_PATH"] = os.pathsep.join(new_nuke_paths) - env.pop("QT_AUTO_SCREEN_SCALE_FACTOR", None) + # NOTE: Poping of the key is right way. But is commented because there is + # a bug in `app_launcher.py` which only change values and not remove + # existing. + # Fixed with https://github.com/pypeclub/OpenPype/pull/2655 + # but this fix requires new build + # env.pop("QT_AUTO_SCREEN_SCALE_FACTOR", None) + env["QT_AUTO_SCREEN_SCALE_FACTOR"] = "" # Try to add QuickTime to PATH quick_time_path = "C:/Program Files (x86)/QuickTime/QTSystem" From b81a7f2a97bf790a1c23158422d2a201e2054dcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Je=C5=BEek?= Date: Fri, 4 Feb 2022 15:36:19 +0100 Subject: [PATCH 67/74] Update openpype/hosts/nuke/plugins/load/load_clip.py Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- openpype/hosts/nuke/plugins/load/load_clip.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openpype/hosts/nuke/plugins/load/load_clip.py b/openpype/hosts/nuke/plugins/load/load_clip.py index 16df3e27d5..21b7a6a816 100644 --- a/openpype/hosts/nuke/plugins/load/load_clip.py +++ b/openpype/hosts/nuke/plugins/load/load_clip.py @@ -397,8 +397,7 @@ class LoadClip(plugin.NukeLoader): # Set colorspace defined in version data if ( colorspace is not None - and colorspace_exists_on_node( - node, str(colorspace)) is not False + and colorspace_exists_on_node(node, str(colorspace)) ): node["colorspace"].setValue(str(colorspace)) output_color = str(colorspace) From 391500b2a03275ebd43d88138d89bdb102b08b2e Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 4 Feb 2022 16:17:04 +0100 Subject: [PATCH 68/74] filter environments before launch --- app_launcher.py | 13 +++---------- openpype/hosts/nuke/__init__.py | 8 +------- openpype/lib/applications.py | 11 ++++++++++- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/app_launcher.py b/app_launcher.py index 2cb313742b..6dc1518370 100644 --- a/app_launcher.py +++ b/app_launcher.py @@ -29,16 +29,9 @@ def main(input_json_path): data = json.load(stream) # Change environment variables - # - environments that are in current environments and are not data are - # removed - if "env" in data: - env = data["env"] - # Pop environment variable keys that are not in source - for key in set(os.environ.keys()) - set(env.keys()): - os.environ.pop(key) - - for key, value in env.items(): - os.environ[key] = value + env = data.get("env") or {} + for key, value in env.items(): + os.environ[key] = value # Prepare launch arguments args = data["args"] diff --git a/openpype/hosts/nuke/__init__.py b/openpype/hosts/nuke/__init__.py index 4402d0b48e..60b37ce1dd 100644 --- a/openpype/hosts/nuke/__init__.py +++ b/openpype/hosts/nuke/__init__.py @@ -18,13 +18,7 @@ def add_implementation_envs(env, _app): new_nuke_paths.append(norm_path) env["NUKE_PATH"] = os.pathsep.join(new_nuke_paths) - # NOTE: Poping of the key is right way. But is commented because there is - # a bug in `app_launcher.py` which only change values and not remove - # existing. - # Fixed with https://github.com/pypeclub/OpenPype/pull/2655 - # but this fix requires new build - # env.pop("QT_AUTO_SCREEN_SCALE_FACTOR", None) - env["QT_AUTO_SCREEN_SCALE_FACTOR"] = "" + env.pop("QT_AUTO_SCREEN_SCALE_FACTOR", None) # Try to add QuickTime to PATH quick_time_path = "C:/Program Files (x86)/QuickTime/QTSystem" diff --git a/openpype/lib/applications.py b/openpype/lib/applications.py index a704c3ae68..4227195235 100644 --- a/openpype/lib/applications.py +++ b/openpype/lib/applications.py @@ -1040,10 +1040,19 @@ class ApplicationLaunchContext: # Prepare data that will be passed to midprocess # - store arguments to a json and pass path to json as last argument # - pass environments to set + app_env = self.kwargs.pop("env", {}) json_data = { "args": self.launch_args, - "env": self.kwargs.pop("env", {}) + "env": app_env } + if app_env: + # Filter environments of subprocess + self.kwargs["env"] = { + key: value + for key, value in os.environ.items() + if key in app_env + } + # Create temp file json_temp = tempfile.NamedTemporaryFile( mode="w", prefix="op_app_args", suffix=".json", delete=False From cda9beb2fd98be211016378072fbaea7b31d44b4 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 4 Feb 2022 16:22:40 +0100 Subject: [PATCH 69/74] pop 'QT_AUTO_SCREEN_SCALE_FACTOR' in hiero implementation --- openpype/hosts/hiero/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/hosts/hiero/__init__.py b/openpype/hosts/hiero/__init__.py index 15bd10fdb0..2d674b3fa7 100644 --- a/openpype/hosts/hiero/__init__.py +++ b/openpype/hosts/hiero/__init__.py @@ -18,6 +18,7 @@ def add_implementation_envs(env, _app): new_hiero_paths.append(norm_path) env["HIERO_PLUGIN_PATH"] = os.pathsep.join(new_hiero_paths) + env.pop("QT_AUTO_SCREEN_SCALE_FACTOR", None) # Try to add QuickTime to PATH quick_time_path = "C:/Program Files (x86)/QuickTime/QTSystem" From 7c22eee4d9afe90149017d6ee1a02c355256c19d Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 4 Feb 2022 18:24:31 +0100 Subject: [PATCH 70/74] moved houdini into openpype --- openpype/hosts/houdini/api/__init__.py | 208 +++-------- openpype/hosts/houdini/api/lib.py | 190 +++++++++- openpype/hosts/houdini/api/pipeline.py | 347 ++++++++++++++++++ openpype/hosts/houdini/api/plugin.py | 69 +++- openpype/hosts/houdini/api/workio.py | 58 +++ .../hosts/houdini/startup/MainMenuCommon.xml | 12 - openpype/hosts/houdini/startup/scripts/123.py | 5 +- .../houdini/startup/scripts/houdinicore.py | 5 +- 8 files changed, 707 insertions(+), 187 deletions(-) create mode 100644 openpype/hosts/houdini/api/pipeline.py create mode 100644 openpype/hosts/houdini/api/workio.py diff --git a/openpype/hosts/houdini/api/__init__.py b/openpype/hosts/houdini/api/__init__.py index 7328236b97..e1500aa5f5 100644 --- a/openpype/hosts/houdini/api/__init__.py +++ b/openpype/hosts/houdini/api/__init__.py @@ -1,174 +1,60 @@ -import os -import sys -import logging -import contextlib +from .pipeline import ( + install, + uninstall, -import hou - -from pyblish import api as pyblish -from avalon import api as avalon - -import openpype.hosts.houdini -from openpype.hosts.houdini.api import lib - -from openpype.lib import ( - any_outdated + ls, + containerise, ) -from .lib import get_asset_fps +from .plugin import ( + Creator, +) -log = logging.getLogger("openpype.hosts.houdini") +from .workio import ( + open_file, + save_file, + current_file, + has_unsaved_changes, + file_extensions, + work_root +) -HOST_DIR = os.path.dirname(os.path.abspath(openpype.hosts.houdini.__file__)) -PLUGINS_DIR = os.path.join(HOST_DIR, "plugins") -PUBLISH_PATH = os.path.join(PLUGINS_DIR, "publish") -LOAD_PATH = os.path.join(PLUGINS_DIR, "load") -CREATE_PATH = os.path.join(PLUGINS_DIR, "create") -INVENTORY_PATH = os.path.join(PLUGINS_DIR, "inventory") +from .lib import ( + lsattr, + lsattrs, + read, + + maintained_selection, + unique_name +) -def install(): +__all__ = [ + "install", + "uninstall", - pyblish.register_plugin_path(PUBLISH_PATH) - avalon.register_plugin_path(avalon.Loader, LOAD_PATH) - avalon.register_plugin_path(avalon.Creator, CREATE_PATH) + "ls", + "containerise", - log.info("Installing callbacks ... ") - # avalon.on("init", on_init) - avalon.before("save", before_save) - avalon.on("save", on_save) - avalon.on("open", on_open) - avalon.on("new", on_new) + "Creator", - pyblish.register_callback("instanceToggled", on_pyblish_instance_toggled) + # Workfiles API + "open_file", + "save_file", + "current_file", + "has_unsaved_changes", + "file_extensions", + "work_root", - log.info("Setting default family states for loader..") - avalon.data["familiesStateToggled"] = [ - "imagesequence", - "review" - ] + # Utility functions + "lsattr", + "lsattrs", + "read", - # add houdini vendor packages - hou_pythonpath = os.path.join(os.path.dirname(HOST_DIR), "vendor") + "maintained_selection", + "unique_name" +] - sys.path.append(hou_pythonpath) - - # Set asset FPS for the empty scene directly after launch of Houdini - # so it initializes into the correct scene FPS - _set_asset_fps() - - -def before_save(*args): - return lib.validate_fps() - - -def on_save(*args): - - avalon.logger.info("Running callback on save..") - - nodes = lib.get_id_required_nodes() - for node, new_id in lib.generate_ids(nodes): - lib.set_id(node, new_id, overwrite=False) - - -def on_open(*args): - - if not hou.isUIAvailable(): - log.debug("Batch mode detected, ignoring `on_open` callbacks..") - return - - avalon.logger.info("Running callback on open..") - - # Validate FPS after update_task_from_path to - # ensure it is using correct FPS for the asset - lib.validate_fps() - - if any_outdated(): - from openpype.widgets import popup - - log.warning("Scene has outdated content.") - - # Get main window - parent = hou.ui.mainQtWindow() - if parent is None: - log.info("Skipping outdated content pop-up " - "because Houdini window can't be found.") - else: - - # Show outdated pop-up - def _on_show_inventory(): - import avalon.tools.sceneinventory as tool - tool.show(parent=parent) - - dialog = popup.Popup(parent=parent) - dialog.setWindowTitle("Houdini scene has outdated content") - dialog.setMessage("There are outdated containers in " - "your Houdini scene.") - dialog.on_clicked.connect(_on_show_inventory) - dialog.show() - - -def on_new(_): - """Set project resolution and fps when create a new file""" - avalon.logger.info("Running callback on new..") - _set_asset_fps() - - -def _set_asset_fps(): - """Set Houdini scene FPS to the default required for current asset""" - - # Set new scene fps - fps = get_asset_fps() - print("Setting scene FPS to %i" % fps) - lib.set_scene_fps(fps) - - -def on_pyblish_instance_toggled(instance, new_value, old_value): - """Toggle saver tool passthrough states on instance toggles.""" - @contextlib.contextmanager - def main_take(no_update=True): - """Enter root take during context""" - original_take = hou.takes.currentTake() - original_update_mode = hou.updateModeSetting() - root = hou.takes.rootTake() - has_changed = False - try: - if original_take != root: - has_changed = True - if no_update: - hou.setUpdateMode(hou.updateMode.Manual) - hou.takes.setCurrentTake(root) - yield - finally: - if has_changed: - if no_update: - hou.setUpdateMode(original_update_mode) - hou.takes.setCurrentTake(original_take) - - if not instance.data.get("_allowToggleBypass", True): - return - - nodes = instance[:] - if not nodes: - return - - # Assume instance node is first node - instance_node = nodes[0] - - if not hasattr(instance_node, "isBypassed"): - # Likely not a node that can actually be bypassed - log.debug("Can't bypass node: %s", instance_node.path()) - return - - if instance_node.isBypassed() != (not old_value): - print("%s old bypass state didn't match old instance state, " - "updating anyway.." % instance_node.path()) - - try: - # Go into the main take, because when in another take changing - # the bypass state of a note cannot be done due to it being locked - # by default. - with main_take(no_update=True): - instance_node.bypass(not new_value) - except hou.PermissionError as exc: - log.warning("%s - %s", instance_node.path(), exc) +# Backwards API compatibility +open = open_file +save = save_file diff --git a/openpype/hosts/houdini/api/lib.py b/openpype/hosts/houdini/api/lib.py index 53f0e59ea9..eaaba94ed5 100644 --- a/openpype/hosts/houdini/api/lib.py +++ b/openpype/hosts/houdini/api/lib.py @@ -2,9 +2,11 @@ import uuid import logging from contextlib import contextmanager -from openpype.api import get_asset +import six + from avalon import api, io -from avalon.houdini import lib as houdini +from openpype.api import get_asset + import hou @@ -15,11 +17,11 @@ def get_asset_fps(): """Return current asset fps.""" return get_asset()["data"].get("fps") -def set_id(node, unique_id, overwrite=False): +def set_id(node, unique_id, overwrite=False): exists = node.parm("id") if not exists: - houdini.imprint(node, {"id": unique_id}) + imprint(node, {"id": unique_id}) if not exists and overwrite: node.setParm("id", unique_id) @@ -342,3 +344,183 @@ def render_rop(ropnode): import traceback traceback.print_exc() raise RuntimeError("Render failed: {0}".format(exc)) + + +def children_as_string(node): + return [c.name() for c in node.children()] + + +def imprint(node, data): + """Store attributes with value on a node + + Depending on the type of attribute it creates the correct parameter + template. Houdini uses a template per type, see the docs for more + information. + + http://www.sidefx.com/docs/houdini/hom/hou/ParmTemplate.html + + Args: + node(hou.Node): node object from Houdini + data(dict): collection of attributes and their value + + Returns: + None + + """ + + parm_group = node.parmTemplateGroup() + + parm_folder = hou.FolderParmTemplate("folder", "Extra") + for key, value in data.items(): + if value is None: + continue + + if isinstance(value, float): + parm = hou.FloatParmTemplate(name=key, + label=key, + num_components=1, + default_value=(value,)) + elif isinstance(value, bool): + parm = hou.ToggleParmTemplate(name=key, + label=key, + default_value=value) + elif isinstance(value, int): + parm = hou.IntParmTemplate(name=key, + label=key, + num_components=1, + default_value=(value,)) + elif isinstance(value, six.string_types): + parm = hou.StringParmTemplate(name=key, + label=key, + num_components=1, + default_value=(value,)) + else: + raise TypeError("Unsupported type: %r" % type(value)) + + parm_folder.addParmTemplate(parm) + + parm_group.append(parm_folder) + node.setParmTemplateGroup(parm_group) + + +def lsattr(attr, value=None): + if value is None: + nodes = list(hou.node("/obj").allNodes()) + return [n for n in nodes if n.parm(attr)] + return lsattrs({attr: value}) + + +def lsattrs(attrs): + """Return nodes matching `key` and `value` + + Arguments: + attrs (dict): collection of attribute: value + + Example: + >> lsattrs({"id": "myId"}) + ["myNode"] + >> lsattr("id") + ["myNode", "myOtherNode"] + + Returns: + list + """ + + matches = set() + nodes = list(hou.node("/obj").allNodes()) # returns generator object + for node in nodes: + for attr in attrs: + if not node.parm(attr): + continue + elif node.evalParm(attr) != attrs[attr]: + continue + else: + matches.add(node) + + return list(matches) + + +def read(node): + """Read the container data in to a dict + + Args: + node(hou.Node): Houdini node + + Returns: + dict + + """ + # `spareParms` returns a tuple of hou.Parm objects + return {parameter.name(): parameter.eval() for + parameter in node.spareParms()} + + +def unique_name(name, format="%03d", namespace="", prefix="", suffix="", + separator="_"): + """Return unique `name` + + The function takes into consideration an optional `namespace` + and `suffix`. The suffix is included in evaluating whether a + name exists - such as `name` + "_GRP" - but isn't included + in the returned value. + + If a namespace is provided, only names within that namespace + are considered when evaluating whether the name is unique. + + Arguments: + format (str, optional): The `name` is given a number, this determines + how this number is formatted. Defaults to a padding of 2. + E.g. my_name01, my_name02. + namespace (str, optional): Only consider names within this namespace. + suffix (str, optional): Only consider names with this suffix. + + Example: + >>> name = hou.node("/obj").createNode("geo", name="MyName") + >>> assert hou.node("/obj/MyName") + True + >>> unique = unique_name(name) + >>> assert hou.node("/obj/{}".format(unique)) + False + + """ + + iteration = 1 + + parts = [prefix, name, format % iteration, suffix] + if namespace: + parts.insert(0, namespace) + + unique = separator.join(parts) + children = children_as_string(hou.node("/obj")) + while unique in children: + iteration += 1 + unique = separator.join(parts) + + if suffix: + return unique[:-len(suffix)] + + return unique + + +@contextmanager +def maintained_selection(): + """Maintain selection during context + Example: + >>> with maintained_selection(): + ... # Modify selection + ... node.setSelected(on=False, clear_all_selected=True) + >>> # Selection restored + """ + + previous_selection = hou.selectedNodes() + try: + yield + finally: + # Clear the selection + # todo: does hou.clearAllSelected() do the same? + for node in hou.selectedNodes(): + node.setSelected(on=False) + + if previous_selection: + for node in previous_selection: + node.setSelected(on=True) diff --git a/openpype/hosts/houdini/api/pipeline.py b/openpype/hosts/houdini/api/pipeline.py new file mode 100644 index 0000000000..fdd09d8067 --- /dev/null +++ b/openpype/hosts/houdini/api/pipeline.py @@ -0,0 +1,347 @@ +import os +import sys +import logging +import contextlib + +import hou + +import pyblish.api +import avalon.api +from avalon.pipeline import AVALON_CONTAINER_ID +from avalon.lib import find_submodule + +import openpype.hosts.houdini +from openpype.hosts.houdini.api import lib + +from openpype.lib import ( + any_outdated +) + +from .lib import get_asset_fps + +log = logging.getLogger("openpype.hosts.houdini") + +AVALON_CONTAINERS = "/obj/AVALON_CONTAINERS" +IS_HEADLESS = not hasattr(hou, "ui") + +HOST_DIR = os.path.dirname(os.path.abspath(openpype.hosts.houdini.__file__)) +PLUGINS_DIR = os.path.join(HOST_DIR, "plugins") +PUBLISH_PATH = os.path.join(PLUGINS_DIR, "publish") +LOAD_PATH = os.path.join(PLUGINS_DIR, "load") +CREATE_PATH = os.path.join(PLUGINS_DIR, "create") +INVENTORY_PATH = os.path.join(PLUGINS_DIR, "inventory") + + +self = sys.modules[__name__] +self._has_been_setup = False +self._parent = None +self._events = dict() + + +def install(): + _register_callbacks() + + pyblish.api.register_host("houdini") + pyblish.api.register_host("hython") + pyblish.api.register_host("hpython") + + pyblish.api.register_plugin_path(PUBLISH_PATH) + avalon.api.register_plugin_path(avalon.api.Loader, LOAD_PATH) + avalon.api.register_plugin_path(avalon.api.Creator, CREATE_PATH) + + log.info("Installing callbacks ... ") + # avalon.on("init", on_init) + avalon.api.before("save", before_save) + avalon.api.on("save", on_save) + avalon.api.on("open", on_open) + avalon.api.on("new", on_new) + + pyblish.api.register_callback("instanceToggled", on_pyblish_instance_toggled) + + log.info("Setting default family states for loader..") + avalon.api.data["familiesStateToggled"] = [ + "imagesequence", + "review" + ] + + self._has_been_setup = True + # add houdini vendor packages + hou_pythonpath = os.path.join(os.path.dirname(HOST_DIR), "vendor") + + sys.path.append(hou_pythonpath) + + # Set asset FPS for the empty scene directly after launch of Houdini + # so it initializes into the correct scene FPS + _set_asset_fps() + + +def uninstall(): + """Uninstall Houdini-specific functionality of avalon-core. + + This function is called automatically on calling `api.uninstall()`. + """ + + pyblish.api.deregister_host("hython") + pyblish.api.deregister_host("hpython") + pyblish.api.deregister_host("houdini") + + +def _register_callbacks(): + for handler, event in self._events.copy().items(): + if event is None: + continue + + try: + hou.hipFile.removeEventCallback(event) + except RuntimeError as e: + log.info(e) + + self._events[on_file_event_callback] = hou.hipFile.addEventCallback( + on_file_event_callback + ) + + +def on_file_event_callback(event): + if event == hou.hipFileEventType.AfterLoad: + avalon.api.emit("open", [event]) + elif event == hou.hipFileEventType.AfterSave: + avalon.api.emit("save", [event]) + elif event == hou.hipFileEventType.BeforeSave: + avalon.api.emit("before_save", [event]) + elif event == hou.hipFileEventType.AfterClear: + avalon.api.emit("new", [event]) + + +def get_main_window(): + """Acquire Houdini's main window""" + if self._parent is None: + self._parent = hou.ui.mainQtWindow() + return self._parent + + +def teardown(): + """Remove integration""" + if not self._has_been_setup: + return + + self._has_been_setup = False + print("pyblish: Integration torn down successfully") + + +def containerise(name, + namespace, + nodes, + context, + loader=None, + suffix=""): + """Bundle `nodes` into a subnet and imprint it with metadata + + Containerisation enables a tracking of version, author and origin + for loaded assets. + + Arguments: + name (str): Name of resulting assembly + namespace (str): Namespace under which to host container + nodes (list): Long names of nodes to containerise + context (dict): Asset information + loader (str, optional): Name of loader used to produce this container. + suffix (str, optional): Suffix of container, defaults to `_CON`. + + Returns: + container (str): Name of container assembly + + """ + + # Ensure AVALON_CONTAINERS subnet exists + subnet = hou.node(AVALON_CONTAINERS) + if subnet is None: + obj_network = hou.node("/obj") + subnet = obj_network.createNode("subnet", + node_name="AVALON_CONTAINERS") + + # Create proper container name + container_name = "{}_{}".format(name, suffix or "CON") + container = hou.node("/obj/{}".format(name)) + container.setName(container_name, unique_name=True) + + data = { + "schema": "openpype:container-2.0", + "id": AVALON_CONTAINER_ID, + "name": name, + "namespace": namespace, + "loader": str(loader), + "representation": str(context["representation"]["_id"]), + } + + lib.imprint(container, data) + + # "Parent" the container under the container network + hou.moveNodesTo([container], subnet) + + subnet.node(container_name).moveToGoodPosition() + + return container + + +def parse_container(container): + """Return the container node's full container data. + + Args: + container (hou.Node): A container node name. + + Returns: + dict: The container schema data for this container node. + + """ + data = lib.read(container) + + # Backwards compatibility pre-schemas for containers + data["schema"] = data.get("schema", "openpype:container-1.0") + + # Append transient data + data["objectName"] = container.path() + data["node"] = container + + return data + + +def ls(): + containers = [] + for identifier in (AVALON_CONTAINER_ID, + "pyblish.mindbender.container"): + containers += lib.lsattr("id", identifier) + + has_metadata_collector = False + config_host = find_submodule(avalon.api.registered_config(), "houdini") + if hasattr(config_host, "collect_container_metadata"): + has_metadata_collector = True + + for container in sorted(containers, + # Hou 19+ Python 3 hou.ObjNode are not + # sortable due to not supporting greater + # than comparisons + key=lambda node: node.path()): + data = parse_container(container) + + # Collect custom data if attribute is present + if has_metadata_collector: + metadata = config_host.collect_container_metadata(container) + data.update(metadata) + + yield data + + +def before_save(*args): + return lib.validate_fps() + + +def on_save(*args): + + log.info("Running callback on save..") + + nodes = lib.get_id_required_nodes() + for node, new_id in lib.generate_ids(nodes): + lib.set_id(node, new_id, overwrite=False) + + +def on_open(*args): + + if not hou.isUIAvailable(): + log.debug("Batch mode detected, ignoring `on_open` callbacks..") + return + + log.info("Running callback on open..") + + # Validate FPS after update_task_from_path to + # ensure it is using correct FPS for the asset + lib.validate_fps() + + if any_outdated(): + from openpype.widgets import popup + + log.warning("Scene has outdated content.") + + # Get main window + parent = get_main_window() + if parent is None: + log.info("Skipping outdated content pop-up " + "because Houdini window can't be found.") + else: + + # Show outdated pop-up + def _on_show_inventory(): + from openpype.tools.utils import host_tools + host_tools.show_scene_inventory(parent=parent) + + dialog = popup.Popup(parent=parent) + dialog.setWindowTitle("Houdini scene has outdated content") + dialog.setMessage("There are outdated containers in " + "your Houdini scene.") + dialog.on_clicked.connect(_on_show_inventory) + dialog.show() + + +def on_new(_): + """Set project resolution and fps when create a new file""" + log.info("Running callback on new..") + _set_asset_fps() + + +def _set_asset_fps(): + """Set Houdini scene FPS to the default required for current asset""" + + # Set new scene fps + fps = get_asset_fps() + print("Setting scene FPS to %i" % fps) + lib.set_scene_fps(fps) + + +def on_pyblish_instance_toggled(instance, new_value, old_value): + """Toggle saver tool passthrough states on instance toggles.""" + @contextlib.contextmanager + def main_take(no_update=True): + """Enter root take during context""" + original_take = hou.takes.currentTake() + original_update_mode = hou.updateModeSetting() + root = hou.takes.rootTake() + has_changed = False + try: + if original_take != root: + has_changed = True + if no_update: + hou.setUpdateMode(hou.updateMode.Manual) + hou.takes.setCurrentTake(root) + yield + finally: + if has_changed: + if no_update: + hou.setUpdateMode(original_update_mode) + hou.takes.setCurrentTake(original_take) + + if not instance.data.get("_allowToggleBypass", True): + return + + nodes = instance[:] + if not nodes: + return + + # Assume instance node is first node + instance_node = nodes[0] + + if not hasattr(instance_node, "isBypassed"): + # Likely not a node that can actually be bypassed + log.debug("Can't bypass node: %s", instance_node.path()) + return + + if instance_node.isBypassed() != (not old_value): + print("%s old bypass state didn't match old instance state, " + "updating anyway.." % instance_node.path()) + + try: + # Go into the main take, because when in another take changing + # the bypass state of a note cannot be done due to it being locked + # by default. + with main_take(no_update=True): + instance_node.bypass(not new_value) + except hou.PermissionError as exc: + log.warning("%s - %s", instance_node.path(), exc) diff --git a/openpype/hosts/houdini/api/plugin.py b/openpype/hosts/houdini/api/plugin.py index 63d9bba470..e64b505d2c 100644 --- a/openpype/hosts/houdini/api/plugin.py +++ b/openpype/hosts/houdini/api/plugin.py @@ -1,25 +1,82 @@ # -*- coding: utf-8 -*- """Houdini specific Avalon/Pyblish plugin definitions.""" import sys -from avalon.api import CreatorError -from avalon import houdini import six +import avalon.api +from avalon.api import CreatorError import hou from openpype.api import PypeCreatorMixin +from .lib import imprint class OpenPypeCreatorError(CreatorError): pass -class Creator(PypeCreatorMixin, houdini.Creator): +class Creator(PypeCreatorMixin, avalon.api.Creator): + """Creator plugin to create instances in Houdini + + To support the wide range of node types for render output (Alembic, VDB, + Mantra) the Creator needs a node type to create the correct instance + + By default, if none is given, is `geometry`. An example of accepted node + types: geometry, alembic, ifd (mantra) + + Please check the Houdini documentation for more node types. + + Tip: to find the exact node type to create press the `i` left of the node + when hovering over a node. The information is visible under the name of + the node. + + """ + + def __init__(self, *args, **kwargs): + super(Creator, self).__init__(*args, **kwargs) + self.nodes = list() + def process(self): + """This is the base functionality to create instances in Houdini + + The selected nodes are stored in self to be used in an override method. + This is currently necessary in order to support the multiple output + types in Houdini which can only be rendered through their own node. + + Default node type if none is given is `geometry` + + It also makes it easier to apply custom settings per instance type + + Example of override method for Alembic: + + def process(self): + instance = super(CreateEpicNode, self, process() + # Set paramaters for Alembic node + instance.setParms( + {"sop_path": "$HIP/%s.abc" % self.nodes[0]} + ) + + Returns: + hou.Node + + """ try: - # re-raise as standard Python exception so - # Avalon can catch it - instance = super(Creator, self).process() + if (self.options or {}).get("useSelection"): + self.nodes = hou.selectedNodes() + + # Get the node type and remove it from the data, not needed + node_type = self.data.pop("node_type", None) + if node_type is None: + node_type = "geometry" + + # Get out node + out = hou.node("/out") + instance = out.createNode(node_type, node_name=self.name) + instance.moveToGoodPosition() + + imprint(instance, self.data) + self._process(instance) + except hou.Error as er: six.reraise( OpenPypeCreatorError, diff --git a/openpype/hosts/houdini/api/workio.py b/openpype/hosts/houdini/api/workio.py new file mode 100644 index 0000000000..e7310163ea --- /dev/null +++ b/openpype/hosts/houdini/api/workio.py @@ -0,0 +1,58 @@ +"""Host API required Work Files tool""" +import os + +import hou +from avalon import api + + +def file_extensions(): + return api.HOST_WORKFILE_EXTENSIONS["houdini"] + + +def has_unsaved_changes(): + return hou.hipFile.hasUnsavedChanges() + + +def save_file(filepath): + + # Force forwards slashes to avoid segfault + filepath = filepath.replace("\\", "/") + + hou.hipFile.save(file_name=filepath, + save_to_recent_files=True) + + return filepath + + +def open_file(filepath): + + # Force forwards slashes to avoid segfault + filepath = filepath.replace("\\", "/") + + hou.hipFile.load(filepath, + suppress_save_prompt=True, + ignore_load_warnings=False) + + return filepath + + +def current_file(): + + current_filepath = hou.hipFile.path() + if (os.path.basename(current_filepath) == "untitled.hip" and + not os.path.exists(current_filepath)): + # By default a new scene in houdini is saved in the current + # working directory as "untitled.hip" so we need to capture + # that and consider it 'not saved' when it's in that state. + return None + + return current_filepath + + +def work_root(session): + work_dir = session["AVALON_WORKDIR"] + scene_dir = session.get("AVALON_SCENEDIR") + if scene_dir: + return os.path.join(work_dir, scene_dir) + else: + return work_dir diff --git a/openpype/hosts/houdini/startup/MainMenuCommon.xml b/openpype/hosts/houdini/startup/MainMenuCommon.xml index c34310cf72..bc4a2e809a 100644 --- a/openpype/hosts/houdini/startup/MainMenuCommon.xml +++ b/openpype/hosts/houdini/startup/MainMenuCommon.xml @@ -56,18 +56,6 @@ host_tools.show_workfiles(parent) ]]> - - - - - - - - - - diff --git a/openpype/hosts/houdini/startup/scripts/123.py b/openpype/hosts/houdini/startup/scripts/123.py index 4233d68c15..eb33b49759 100644 --- a/openpype/hosts/houdini/startup/scripts/123.py +++ b/openpype/hosts/houdini/startup/scripts/123.py @@ -1,9 +1,10 @@ -from avalon import api, houdini +import avalon.api +from openpype.hosts.houdini import api def main(): print("Installing OpenPype ...") - api.install(houdini) + avalon.api.install(api) main() diff --git a/openpype/hosts/houdini/startup/scripts/houdinicore.py b/openpype/hosts/houdini/startup/scripts/houdinicore.py index 4233d68c15..eb33b49759 100644 --- a/openpype/hosts/houdini/startup/scripts/houdinicore.py +++ b/openpype/hosts/houdini/startup/scripts/houdinicore.py @@ -1,9 +1,10 @@ -from avalon import api, houdini +import avalon.api +from openpype.hosts.houdini import api def main(): print("Installing OpenPype ...") - api.install(houdini) + avalon.api.install(api) main() From 4c280328b85b8cccbe1f76bf8ffcfc26ae34df94 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 4 Feb 2022 18:32:43 +0100 Subject: [PATCH 71/74] fix imports in plugins --- openpype/hosts/houdini/plugins/create/create_hda.py | 6 +++--- openpype/hosts/houdini/plugins/load/load_alembic.py | 5 ++--- openpype/hosts/houdini/plugins/load/load_camera.py | 2 +- openpype/hosts/houdini/plugins/load/load_hda.py | 2 +- openpype/hosts/houdini/plugins/load/load_image.py | 2 +- openpype/hosts/houdini/plugins/load/load_usd_layer.py | 2 +- openpype/hosts/houdini/plugins/load/load_usd_reference.py | 2 +- openpype/hosts/houdini/plugins/load/load_vdb.py | 2 +- openpype/hosts/houdini/plugins/publish/collect_instances.py | 2 +- .../plugins/publish/collect_instances_usd_layered.py | 2 +- .../hosts/houdini/plugins/publish/collect_remote_publish.py | 2 +- 11 files changed, 14 insertions(+), 15 deletions(-) diff --git a/openpype/hosts/houdini/plugins/create/create_hda.py b/openpype/hosts/houdini/plugins/create/create_hda.py index 459da8bfdf..0a9c1bad1e 100644 --- a/openpype/hosts/houdini/plugins/create/create_hda.py +++ b/openpype/hosts/houdini/plugins/create/create_hda.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- -from openpype.hosts.houdini.api import plugin -from avalon.houdini import lib -from avalon import io import hou +from avalon import io +from openpype.hosts.houdini.api import lib +from openpype.hosts.houdini.api import plugin class CreateHDA(plugin.Creator): diff --git a/openpype/hosts/houdini/plugins/load/load_alembic.py b/openpype/hosts/houdini/plugins/load/load_alembic.py index df66d56008..eaab81f396 100644 --- a/openpype/hosts/houdini/plugins/load/load_alembic.py +++ b/openpype/hosts/houdini/plugins/load/load_alembic.py @@ -1,6 +1,7 @@ +import os from avalon import api -from avalon.houdini import pipeline +from openpype.hosts.houdini.api import pipeline class AbcLoader(api.Loader): @@ -14,8 +15,6 @@ class AbcLoader(api.Loader): color = "orange" def load(self, context, name=None, namespace=None, data=None): - - import os import hou # Format file name, Houdini only wants forward slashes diff --git a/openpype/hosts/houdini/plugins/load/load_camera.py b/openpype/hosts/houdini/plugins/load/load_camera.py index 8b98b7c05e..8916d3b9b7 100644 --- a/openpype/hosts/houdini/plugins/load/load_camera.py +++ b/openpype/hosts/houdini/plugins/load/load_camera.py @@ -1,5 +1,5 @@ from avalon import api -from avalon.houdini import pipeline +from openpype.hosts.houdini.api import pipeline ARCHIVE_EXPRESSION = ('__import__("_alembic_hom_extensions")' diff --git a/openpype/hosts/houdini/plugins/load/load_hda.py b/openpype/hosts/houdini/plugins/load/load_hda.py index 6610d5e513..f5f2fb7481 100644 --- a/openpype/hosts/houdini/plugins/load/load_hda.py +++ b/openpype/hosts/houdini/plugins/load/load_hda.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from avalon import api -from avalon.houdini import pipeline +from openpype.hosts.houdini.api import pipeline class HdaLoader(api.Loader): diff --git a/openpype/hosts/houdini/plugins/load/load_image.py b/openpype/hosts/houdini/plugins/load/load_image.py index 4ff2777d77..39f583677b 100644 --- a/openpype/hosts/houdini/plugins/load/load_image.py +++ b/openpype/hosts/houdini/plugins/load/load_image.py @@ -1,7 +1,7 @@ import os from avalon import api -from avalon.houdini import pipeline, lib +from openpype.hosts.houdini.api import lib, pipeline import hou diff --git a/openpype/hosts/houdini/plugins/load/load_usd_layer.py b/openpype/hosts/houdini/plugins/load/load_usd_layer.py index 7483101409..232ce59479 100644 --- a/openpype/hosts/houdini/plugins/load/load_usd_layer.py +++ b/openpype/hosts/houdini/plugins/load/load_usd_layer.py @@ -1,5 +1,5 @@ from avalon import api -from avalon.houdini import pipeline, lib +from openpype.hosts.houdini.api import lib, pipeline class USDSublayerLoader(api.Loader): diff --git a/openpype/hosts/houdini/plugins/load/load_usd_reference.py b/openpype/hosts/houdini/plugins/load/load_usd_reference.py index cab3cb5269..224bfc2d61 100644 --- a/openpype/hosts/houdini/plugins/load/load_usd_reference.py +++ b/openpype/hosts/houdini/plugins/load/load_usd_reference.py @@ -1,5 +1,5 @@ from avalon import api -from avalon.houdini import pipeline, lib +from openpype.hosts.houdini.api import lib, pipeline class USDReferenceLoader(api.Loader): diff --git a/openpype/hosts/houdini/plugins/load/load_vdb.py b/openpype/hosts/houdini/plugins/load/load_vdb.py index 5f7e400b39..40aa7a1d18 100644 --- a/openpype/hosts/houdini/plugins/load/load_vdb.py +++ b/openpype/hosts/houdini/plugins/load/load_vdb.py @@ -2,7 +2,7 @@ import os import re from avalon import api -from avalon.houdini import pipeline +from openpype.hosts.houdini.api import pipeline class VdbLoader(api.Loader): diff --git a/openpype/hosts/houdini/plugins/publish/collect_instances.py b/openpype/hosts/houdini/plugins/publish/collect_instances.py index 12d118f0cc..d38927984a 100644 --- a/openpype/hosts/houdini/plugins/publish/collect_instances.py +++ b/openpype/hosts/houdini/plugins/publish/collect_instances.py @@ -2,7 +2,7 @@ import hou import pyblish.api -from avalon.houdini import lib +from openpype.hosts.houdini.api import lib class CollectInstances(pyblish.api.ContextPlugin): diff --git a/openpype/hosts/houdini/plugins/publish/collect_instances_usd_layered.py b/openpype/hosts/houdini/plugins/publish/collect_instances_usd_layered.py index 7df5e8b6f2..0600730d00 100644 --- a/openpype/hosts/houdini/plugins/publish/collect_instances_usd_layered.py +++ b/openpype/hosts/houdini/plugins/publish/collect_instances_usd_layered.py @@ -1,6 +1,6 @@ import hou import pyblish.api -from avalon.houdini import lib +from openpype.hosts.houdini.api import lib import openpype.hosts.houdini.api.usd as hou_usdlib import openpype.lib.usdlib as usdlib diff --git a/openpype/hosts/houdini/plugins/publish/collect_remote_publish.py b/openpype/hosts/houdini/plugins/publish/collect_remote_publish.py index 3ae16efe56..c635a53074 100644 --- a/openpype/hosts/houdini/plugins/publish/collect_remote_publish.py +++ b/openpype/hosts/houdini/plugins/publish/collect_remote_publish.py @@ -2,7 +2,7 @@ import pyblish.api import openpype.api import hou -from avalon.houdini import lib +from openpype.hosts.houdini.api import lib class CollectRemotePublishSettings(pyblish.api.ContextPlugin): From c54c493fe0e59151322809d2260bacec672c21bb Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 4 Feb 2022 18:36:20 +0100 Subject: [PATCH 72/74] hound fixes --- openpype/hosts/houdini/api/pipeline.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/houdini/api/pipeline.py b/openpype/hosts/houdini/api/pipeline.py index fdd09d8067..4054d5991f 100644 --- a/openpype/hosts/houdini/api/pipeline.py +++ b/openpype/hosts/houdini/api/pipeline.py @@ -56,7 +56,9 @@ def install(): avalon.api.on("open", on_open) avalon.api.on("new", on_new) - pyblish.api.register_callback("instanceToggled", on_pyblish_instance_toggled) + pyblish.api.register_callback( + "instanceToggled", on_pyblish_instance_toggled + ) log.info("Setting default family states for loader..") avalon.api.data["familiesStateToggled"] = [ @@ -87,7 +89,7 @@ def uninstall(): def _register_callbacks(): - for handler, event in self._events.copy().items(): + for event in self._events.copy().values(): if event is None: continue From a11700e1e9e17570a063c0115ec90404e9f31eb8 Mon Sep 17 00:00:00 2001 From: OpenPype Date: Sat, 5 Feb 2022 03:34:41 +0000 Subject: [PATCH 73/74] [Automated] Bump version --- CHANGELOG.md | 14 +++++++------- openpype/version.py | 2 +- pyproject.toml | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0224ea957c..f45aefcbfa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## [3.8.2-nightly.2](https://github.com/pypeclub/OpenPype/tree/HEAD) +## [3.8.2-nightly.3](https://github.com/pypeclub/OpenPype/tree/HEAD) [Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.8.1...HEAD) @@ -10,8 +10,11 @@ **🚀 Enhancements** +- TVPaint: Image loaders also work on review family [\#2638](https://github.com/pypeclub/OpenPype/pull/2638) +- General: Project backup tools [\#2629](https://github.com/pypeclub/OpenPype/pull/2629) - nuke: adding clear button to write nodes [\#2627](https://github.com/pypeclub/OpenPype/pull/2627) - Ftrack: Family to Asset type mapping is in settings [\#2602](https://github.com/pypeclub/OpenPype/pull/2602) +- Nuke: load color space from representation data [\#2576](https://github.com/pypeclub/OpenPype/pull/2576) **🐛 Bug fixes** @@ -20,6 +23,8 @@ **Merged pull requests:** +- Docker: enhance dockerfiles with metadata, fix pyenv initialization [\#2647](https://github.com/pypeclub/OpenPype/pull/2647) +- WebPublisher: fix instance duplicates [\#2641](https://github.com/pypeclub/OpenPype/pull/2641) - Fix - safer pulling of task name for webpublishing from PS [\#2613](https://github.com/pypeclub/OpenPype/pull/2613) ## [3.8.1](https://github.com/pypeclub/OpenPype/tree/3.8.1) (2022-02-01) @@ -30,6 +35,7 @@ - Webpublisher: Thumbnail extractor [\#2600](https://github.com/pypeclub/OpenPype/pull/2600) - Loader: Allow to toggle default family filters between "include" or "exclude" filtering [\#2541](https://github.com/pypeclub/OpenPype/pull/2541) +- Launcher: Added context menu to to skip opening last workfile [\#2536](https://github.com/pypeclub/OpenPype/pull/2536) **🐛 Bug fixes** @@ -73,12 +79,10 @@ - Settings: PathInput strip passed string [\#2550](https://github.com/pypeclub/OpenPype/pull/2550) - Global: Exctract Review anatomy fill data with output name [\#2548](https://github.com/pypeclub/OpenPype/pull/2548) - Cosmetics: Clean up some cosmetics / typos [\#2542](https://github.com/pypeclub/OpenPype/pull/2542) -- Launcher: Added context menu to to skip opening last workfile [\#2536](https://github.com/pypeclub/OpenPype/pull/2536) - General: Validate if current process OpenPype version is requested version [\#2529](https://github.com/pypeclub/OpenPype/pull/2529) - General: Be able to use anatomy data in ffmpeg output arguments [\#2525](https://github.com/pypeclub/OpenPype/pull/2525) - Expose toggle publish plug-in settings for Maya Look Shading Engine Naming [\#2521](https://github.com/pypeclub/OpenPype/pull/2521) - Photoshop: Move implementation to OpenPype [\#2510](https://github.com/pypeclub/OpenPype/pull/2510) -- TimersManager: Move module one hierarchy higher [\#2501](https://github.com/pypeclub/OpenPype/pull/2501) - Slack: notifications are sent with Openpype logo and bot name [\#2499](https://github.com/pypeclub/OpenPype/pull/2499) - Slack: Add review to notification message [\#2498](https://github.com/pypeclub/OpenPype/pull/2498) - Maya: Collect 'fps' animation data only for "review" instances [\#2486](https://github.com/pypeclub/OpenPype/pull/2486) @@ -115,10 +119,6 @@ [Full Changelog](https://github.com/pypeclub/OpenPype/compare/CI/3.7.0-nightly.14...3.7.0) -**🐛 Bug fixes** - -- TVPaint: Create render layer dialog is in front [\#2471](https://github.com/pypeclub/OpenPype/pull/2471) - ## [3.6.4](https://github.com/pypeclub/OpenPype/tree/3.6.4) (2021-11-23) [Full Changelog](https://github.com/pypeclub/OpenPype/compare/CI/3.7.0-nightly.1...3.6.4) diff --git a/openpype/version.py b/openpype/version.py index 5ebc6d00c8..06bf8386a6 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.8.2-nightly.2" +__version__ = "3.8.2-nightly.3" diff --git a/pyproject.toml b/pyproject.toml index 68713802cf..df680f2212 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "OpenPype" -version = "3.8.2-nightly.2" # OpenPype +version = "3.8.2-nightly.3" # OpenPype description = "Open VFX and Animation pipeline with support." authors = ["OpenPype Team "] license = "MIT License" From 604a590fe50c313cbe7660405106fbab9bd4073a Mon Sep 17 00:00:00 2001 From: OpenPype Date: Mon, 7 Feb 2022 08:33:23 +0000 Subject: [PATCH 74/74] [Automated] Release --- CHANGELOG.md | 26 +++++++++++++------------- openpype/version.py | 2 +- pyproject.toml | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f45aefcbfa..f0593f9837 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,8 @@ # Changelog -## [3.8.2-nightly.3](https://github.com/pypeclub/OpenPype/tree/HEAD) +## [3.8.2](https://github.com/pypeclub/OpenPype/tree/3.8.2) (2022-02-07) -[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.8.1...HEAD) - -### 📖 Documentation - -- Cosmetics: Fix common typos in openpype/website [\#2617](https://github.com/pypeclub/OpenPype/pull/2617) +[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.8.1...3.8.2) **🚀 Enhancements** @@ -19,13 +15,17 @@ **🐛 Bug fixes** - Fix pulling of cx\_freeze 6.10 [\#2628](https://github.com/pypeclub/OpenPype/pull/2628) -- Global: fix broken otio review extractor [\#2590](https://github.com/pypeclub/OpenPype/pull/2590) + +### 📖 Documentation + +- Cosmetics: Fix common typos in openpype/website [\#2617](https://github.com/pypeclub/OpenPype/pull/2617) **Merged pull requests:** - Docker: enhance dockerfiles with metadata, fix pyenv initialization [\#2647](https://github.com/pypeclub/OpenPype/pull/2647) - WebPublisher: fix instance duplicates [\#2641](https://github.com/pypeclub/OpenPype/pull/2641) - Fix - safer pulling of task name for webpublishing from PS [\#2613](https://github.com/pypeclub/OpenPype/pull/2613) +- Webpublisher: Skip version collect [\#2591](https://github.com/pypeclub/OpenPype/pull/2591) ## [3.8.1](https://github.com/pypeclub/OpenPype/tree/3.8.1) (2022-02-01) @@ -34,6 +34,7 @@ **🚀 Enhancements** - Webpublisher: Thumbnail extractor [\#2600](https://github.com/pypeclub/OpenPype/pull/2600) +- Webpublisher: Added endpoint to reprocess batch through UI [\#2555](https://github.com/pypeclub/OpenPype/pull/2555) - Loader: Allow to toggle default family filters between "include" or "exclude" filtering [\#2541](https://github.com/pypeclub/OpenPype/pull/2541) - Launcher: Added context menu to to skip opening last workfile [\#2536](https://github.com/pypeclub/OpenPype/pull/2536) @@ -43,6 +44,7 @@ - hotfix: OIIO tool path - add extension on windows [\#2618](https://github.com/pypeclub/OpenPype/pull/2618) - Settings: Enum does not store empty string if has single item to select [\#2615](https://github.com/pypeclub/OpenPype/pull/2615) - switch distutils to sysconfig for `get\_platform\(\)` [\#2594](https://github.com/pypeclub/OpenPype/pull/2594) +- Global: fix broken otio review extractor [\#2590](https://github.com/pypeclub/OpenPype/pull/2590) - Fix poetry index and speedcopy update [\#2589](https://github.com/pypeclub/OpenPype/pull/2589) - Webpublisher: Fix - subset names from processed .psd used wrong value for task [\#2586](https://github.com/pypeclub/OpenPype/pull/2586) - `vrscene` creator Deadline webservice URL handling [\#2580](https://github.com/pypeclub/OpenPype/pull/2580) @@ -52,17 +54,12 @@ **Merged pull requests:** - Bump pillow from 8.4.0 to 9.0.0 [\#2595](https://github.com/pypeclub/OpenPype/pull/2595) -- Webpublisher: Skip version collect [\#2591](https://github.com/pypeclub/OpenPype/pull/2591) - build\(deps\): bump pillow from 8.4.0 to 9.0.0 [\#2523](https://github.com/pypeclub/OpenPype/pull/2523) ## [3.8.0](https://github.com/pypeclub/OpenPype/tree/3.8.0) (2022-01-24) [Full Changelog](https://github.com/pypeclub/OpenPype/compare/CI/3.8.0-nightly.7...3.8.0) -### 📖 Documentation - -- Variable in docs renamed to proper name [\#2546](https://github.com/pypeclub/OpenPype/pull/2546) - **🆕 New features** - Flame: extracting segments with trans-coding [\#2547](https://github.com/pypeclub/OpenPype/pull/2547) @@ -75,7 +72,6 @@ - Webpublisher: Moved error at the beginning of the log [\#2559](https://github.com/pypeclub/OpenPype/pull/2559) - Ftrack: Use ApplicationManager to get DJV path [\#2558](https://github.com/pypeclub/OpenPype/pull/2558) -- Webpublisher: Added endpoint to reprocess batch through UI [\#2555](https://github.com/pypeclub/OpenPype/pull/2555) - Settings: PathInput strip passed string [\#2550](https://github.com/pypeclub/OpenPype/pull/2550) - Global: Exctract Review anatomy fill data with output name [\#2548](https://github.com/pypeclub/OpenPype/pull/2548) - Cosmetics: Clean up some cosmetics / typos [\#2542](https://github.com/pypeclub/OpenPype/pull/2542) @@ -107,6 +103,10 @@ - Maya: reset empty string attributes correctly to "" instead of "None" [\#2506](https://github.com/pypeclub/OpenPype/pull/2506) - Improve FusionPreLaunch hook errors [\#2505](https://github.com/pypeclub/OpenPype/pull/2505) +### 📖 Documentation + +- Variable in docs renamed to proper name [\#2546](https://github.com/pypeclub/OpenPype/pull/2546) + **Merged pull requests:** - AfterEffects: Move implementation to OpenPype [\#2543](https://github.com/pypeclub/OpenPype/pull/2543) diff --git a/openpype/version.py b/openpype/version.py index 06bf8386a6..12f9b5d13e 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.8.2-nightly.3" +__version__ = "3.8.2" diff --git a/pyproject.toml b/pyproject.toml index df680f2212..1dafc7d279 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "OpenPype" -version = "3.8.2-nightly.3" # OpenPype +version = "3.8.2" # OpenPype description = "Open VFX and Animation pipeline with support." authors = ["OpenPype Team "] license = "MIT License"