From fd4e86fdae650498ef4bb2e7c03fb3521ec3cb17 Mon Sep 17 00:00:00 2001 From: NickPapONS Date: Thu, 11 Jan 2024 16:42:14 +0000 Subject: [PATCH 1/8] string and integer classes --- dpytools/config/properties/base.py | 11 ++++++++ dpytools/config/properties/integer.py | 38 +++++++++++++++++++++++++++ dpytools/config/properties/string.py | 5 +++- 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 dpytools/config/properties/integer.py diff --git a/dpytools/config/properties/base.py b/dpytools/config/properties/base.py index 02dd34c..c058ce8 100644 --- a/dpytools/config/properties/base.py +++ b/dpytools/config/properties/base.py @@ -9,6 +9,11 @@ class BaseProperty(metaclass=ABCMeta): # TODO: getter # allow someone to get the property + def _get_name(self): + return self.name + + def _get_value(self): + return self.value # TODO: setter # categorically disallow anyone from @@ -16,6 +21,12 @@ class BaseProperty(metaclass=ABCMeta): # has been instantiated. # Refuse to do it, and log an error. + def _set_name(self, value): + self.name = value + + def _set_value(self, new_value): + self.value = new_value + @abstractmethod def type_is_valid(self): """ diff --git a/dpytools/config/properties/integer.py b/dpytools/config/properties/integer.py new file mode 100644 index 0000000..ee7fd1c --- /dev/null +++ b/dpytools/config/properties/integer.py @@ -0,0 +1,38 @@ +from typing import Optional + +from .base import BaseProperty + + +class IntegerProperty(BaseProperty): + # TODO: Is there any scenario where IntegerProperty should have regex? + regex: Optional[str] + min_val: Optional[int] + max_val: Optional[int] + + def type_is_valid(self): + """ + Validate that the property looks like + its of the correct type + """ + try: + int(self.value) + except Exception as err: + raise Exception(f"Cannot cast {self.name} value {self.value} to integer.") from err + + def secondary_validation_passed(self): + """ + Non type based validation you might want to + run against a configuration value of this kind. + """ + if not self.value: + raise ValueError(f"Integer value for {self.name} does not exist") + + if self.regex: + # TODO - confirm the value matches the regex + ... + + if self.min_val: + assert self.value >= self.min_val + + if self.max_val: + assert self.value <= self.max_val \ No newline at end of file diff --git a/dpytools/config/properties/string.py b/dpytools/config/properties/string.py index 74aa102..5ea0931 100644 --- a/dpytools/config/properties/string.py +++ b/dpytools/config/properties/string.py @@ -29,11 +29,14 @@ def secondary_validation_passed(self): if self.regex: # TODO - confirm the value matches the regex ... + assert self.value == self.regex if self.min_len: # TODO - confirm the string matches of exceeds the minimum length ... + assert len(self.value) >= self.min_len if self.max_len: # TODO - confirm the value matches or is less than the max length - ... \ No newline at end of file + ... + assert len(self.value) <= self.max_len \ No newline at end of file From 90848d8cc5ac3a1322def9a493a2ab00a34f86e7 Mon Sep 17 00:00:00 2001 From: NickPapONS Date: Mon, 29 Jan 2024 10:15:24 +0000 Subject: [PATCH 2/8] Adding tests and more config work --- .vscode/settings.json | 7 ++ .../config/__pycache__/config.cpython-311.pyc | Bin 0 -> 3114 bytes .../test_config.cpython-311-pytest-7.4.4.pyc | Bin 0 -> 952 bytes dpytools/config/config.py | 74 +++++++++++-- dpytools/config/properties/__init__.py | 3 +- .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 329 bytes .../__pycache__/base.cpython-311.pyc | Bin 0 -> 2021 bytes .../__pycache__/intproperty.cpython-311.pyc | Bin 0 -> 2207 bytes .../__pycache__/string.cpython-311.pyc | Bin 0 -> 2445 bytes ...t_intproperty.cpython-311-pytest-7.4.4.pyc | Bin 0 -> 8242 bytes ...tringproperty.cpython-311-pytest-7.4.4.pyc | Bin 0 -> 7036 bytes .../properties/{integer.py => intproperty.py} | 20 ++-- dpytools/config/properties/string.py | 16 +-- .../config/properties/test_intproperty.py | 99 ++++++++++++++++++ .../config/properties/test_stringproperty.py | 83 +++++++++++++++ dpytools/config/test_config.py | 65 ++++++++++++ .../test_nothing.cpython-311-pytest-7.4.4.pyc | Bin 0 -> 503 bytes 17 files changed, 337 insertions(+), 30 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 dpytools/config/__pycache__/config.cpython-311.pyc create mode 100644 dpytools/config/__pycache__/test_config.cpython-311-pytest-7.4.4.pyc create mode 100644 dpytools/config/properties/__pycache__/__init__.cpython-311.pyc create mode 100644 dpytools/config/properties/__pycache__/base.cpython-311.pyc create mode 100644 dpytools/config/properties/__pycache__/intproperty.cpython-311.pyc create mode 100644 dpytools/config/properties/__pycache__/string.cpython-311.pyc create mode 100644 dpytools/config/properties/__pycache__/test_intproperty.cpython-311-pytest-7.4.4.pyc create mode 100644 dpytools/config/properties/__pycache__/test_stringproperty.cpython-311-pytest-7.4.4.pyc rename dpytools/config/properties/{integer.py => intproperty.py} (66%) create mode 100644 dpytools/config/properties/test_intproperty.py create mode 100644 dpytools/config/properties/test_stringproperty.py create mode 100644 dpytools/config/test_config.py create mode 100644 tests/__pycache__/test_nothing.cpython-311-pytest-7.4.4.pyc diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..f8322ec --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "python.testing.pytestArgs": [ + "dpytools" + ], + "python.testing.unittestEnabled": false, + "python.testing.pytestEnabled": true +} \ No newline at end of file diff --git a/dpytools/config/__pycache__/config.cpython-311.pyc b/dpytools/config/__pycache__/config.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..97ce87d06099c63ad945acec025bf876e7f3c3c1 GIT binary patch literal 3114 zcmb7G&2JM&6rZ*C%Z@{!arg)!**FPcDY2nZfI}2$NtLE*qqY=iEnr!^n`DW-c4s#f zN47v!j!1PSBz&|~NP~hZuDwHI3!)OnxQNxxG9P^=CvxW(b%~G%rm5*7$u{aNAb#(LMx0_ z*m=*1mX4d3J*)H@^lh~IW1Q?&KtrZi=@>6FU^#2DS5w-&x?pz1ty+}9gE-aFL5T2P zC_4cl5I$-Z<-ib7_RPgwk$^rPN;etE!tiG(OBJE<@8q^=8s(|m_iw>GIZw`;1>bi4 zF&wimSv-CTBOD&%uifpULt}Sk*}Dc#Y_y!p(Ff9^+q9SiX)$eDtj5YHM?+ztum%Zb zBf)&^uD4llmd-L+_7%6rfVEKUl;hmva(osQ9kVpYA(Z9ZYg5SZIeJl+hY_H;(bA^S zlRsc~XUwg8WNS5I{>1G!zUXf66La2eOU`#7Enl0KUn7z8LGc?M4qw_M=gazE`Pbm4 zZ!~W^%5}hsj`;pZ+&bK=?h&_+_PFJ#C$|kinr4#Q=J?URB7r%Ri6{Gl*O#$Rjw?`>&$c!5%%Tsqv+>luj)hy0oO~(dkrt znK+?GXH?_U<$F;%J(kWGiz#i)NTm`wv@u`6-leuJ`m;ap&0pW@ zK3+KXbn3;OO80oFd%Sk6ukh{DM|H&YoT&*T#l`1co5FZS7=Jxe7AC90WPz!L&aCs# zqnn|LN@(J>S`J;QhOQL2eZ&QBOBg0fr^yf??|2kCR~r~E#;OD7UNovkPMd9mearwD4CE~#`I-8mU4yrR#~bF}EC(m5 z!HH6EqG|4~1iId_=;TOgMpS|EC6Yfp%5SfT3C)xF0l4S@IH{SPyy_XbuS6eR`Xt$F4 zU4{P_iagOPvcGw8KC98pvr(7#1Fs% z7!YZ7&cVM=C&3p{)oqY4gSrBjOO|lP7D$Gg(jd%zU@$%n#2IExp23ygMuhhOo0~)- z0tAA682LIk`Q8fOTju+!d|!$0tMP$Nez3w1mieJ7KU8XFEA(?=AGzHGTtw0Ii()b* zFDD2e5XJA8r9`7ApaYz#@uUKHA!D*LrWYUzlb0Be5JIfP!-SA6wGId-$G{>41$7edh5RFA)LI{DNY9m2FP20gjvRt1@tooPkF0|>? z0Y)S?mhOm+KP4N{O_i9kS?bn_J3FZe5_jk4?|tvyckjLLrIG>o`f~Bp`>X))TR5|& zO~K_S4!!{d5Db6?v%eI|t^`52U@0(AYUydo;0B~(Vsc@$O7Wvhg$))InU(5y{FNu4HS>dQF#;P*IM z>Qd}Sy>~cHJWPk2DYql)^*lVIm=Zam_wcmbZiEhX`wgc-`#fbLT5n2B!Tk0K(?UP8 z121aIOmPE;5T++nQKlXpJGe)3rA@5!#8abBX+oZuX6t^=Kbr6fg2`&GS`cy{onYXx zLg<|2kZaevZ{KX$-M!s*XWQQD9M}ghcG+@9?(e?-hiP~AX3Rtux@D#x4*Y=n5n;vW z$UJ`u9-%E>IUj@{M=k6fW1sT(uPLU@ID;pP>$ZcLnnR|#*-)`~iB+b}`yOeL zY{Ym$@HhYB{fN#+ghlVHk}KHAcSQvb9x{0H16=YLxH>TRd1b_meD^4El6XLgbL12A zRqPHzFQUZU_UX>x&_u}wuc#kK8#Ims!u??ma&Af7XLy}I1NldO zag)jr!Z846|J$XrY+r!-X#R}BgVFpMgU!+WNp~QqHpVwrFILvax9X`P*NhYhqiJ{5 z6bMtD-YC|-zE5RI#MC;E39}5UYa+XTXIx*M%N92@Zq{zENGafE1S;ucpr~h1Y;XCTS&D^5SOIJKx)KQA*myCAV3zqF({F*~zZ-z7h}G&eP`q*&iQ zv&5q`Nk64Px1h2lBR@~KBtJi=7|5@LFp~50(lXQap{8f17VF2yXXa&=#K-FuRQ}?y q$<0qG%}KQ@0tEud1I7A4;sY}yBjXJQr3s0RQE4qzhy literal 0 HcmV?d00001 diff --git a/dpytools/config/properties/__pycache__/base.cpython-311.pyc b/dpytools/config/properties/__pycache__/base.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1209990446e8ed1957f0d67156cf87fd7a117bbd GIT binary patch literal 2021 zcmbVN&5zqe6rZu<#Lh>zv?=W_qIJ2HNObcLR7fpIWmh5~Een+oShMzQV%A^GI8=#x zNTnS1P;q3raVuJtzl2kcD~m%VPTW#0r=ECkoMe;kA}Yqo&+lvO-+O+~{ zS`ZAlZ0`Zz&2*4kZkJ~+@*TdroWthAj)Ww3%!r(2C=4k-)g|ez`69lL&eL~#14;pueC>jDQ z-_pbtI4MFB_t|zq#&YGqRAX+x0nri@foe3@4@=LiLpc67o9l3;8JpaS`D0h*yTYle zI9*sEB&8hhEwQ?G6IfLb;V4*L*nc?ZFy0iJR~tU6+OzdF3j>%lZf8A~0dRZPG6OqI zk^^an!2w@H2br{!eHG>I9F-YQq6ZX4rt9vqhPuPQ`Z%0A5m)Vb548)Vg9?_3&)@4B~Gn?7P==4Rg zOI3Sw5!w;AfZw^EZb}Z@d?p4(mTK?t_DZT3g|wD3uAXJwX*F`wRYU5!FfeYE`2CQB zTzB2?`z*xq1x<%nX1?aSERK^*-BY@*z(*}`CIt4b*g$w60p9&Y*a#mWs7!FG)F_A= zN(cu0<&OZPrQ>C_G1?k!J>5E~T^enVwx4cKO=_%9$pXsM*g$m#R~C}8f%g`AXHX{P z=2SC``jh~?(m@@6TNs*it8$%z>IFp*KMwGjC_WCIRxQ`ro+t2Cpi<0hi!TS40<+1> z&}Tv1ElN|tKobFbt;l<|7O%~FMa4fBA3+EXl>7-`s#8i&$eqbWzY}tMvidtAo0I?g hy`pcf8lQF;K00|zes2OE?_v{IxRa05V zfK;G^rUqdR1euQMKt z1Gf`PkUjM_d5d_E`|h|z#M}3%r*&lrkAjEpMaj>Q`(BSAD-X4Pzjx_c!c_0kZ|MqM zA*;$4WQFFn_U9?q8FPkhL6$l5mJJUGXN^vFneDnY$!x2}VfJQb)HWI zs^s=!pl~5%0`AY)OQSd|xsXN2s@57t!)^he{*R>_ct%#|*&Z4zc?A*`dvIsGBZ(C@zf)TunZb|&8mf4;<@#PDBYAhGYf!rrY zDP`zOdXUa+sz0WFnAw>5K73vrWX6vO1ywIS$WHpX*~jlaxe70se|`3MIpTosX6N>@ zbN;;Ur}Y;wjubQpMvlQrYh&Z&LF!sk`Ss#8MR}@d!1jR;p%Q{m1z>Fv00%5YLymhf za5_N3#D)Wb^ib&s&RQST#5=vddO=tVJ&5zYD`$F-p?=DHtf_^Zm^e3f^|W`a-Kc)s z%@~^{*NM=22YQH!$VB8ruVF2>$?De9vd2~o2O#anHlpb;W67`_K(oOj1T{ru6+t^J z2TQV=<(P%ouAS|Gr&9onu3+s^X1ZK5EDyeFNw3g;lYyn}u5f|%2S?c`m=KI()tmJ~ zo8g9K2<_AkV>R4S%4=c-zCneQ^Dkj~|ac$^DbN;^(e}M)Q%;yg!9=H(S}uR{V4&Hqy^BszgQ=e+uVr zc405O;HMX`eDtvTbPE1q9z&?4lurgpUB_0V>p@D_>#o_fkx%RT*G34k>IBSPbz=X7e558d z>=iw9EUjVuXVd6lJhPM^39Qn)Sbd-bl z1p@^lMScea5=iMjne_YTKDp@k&wcWS-#-s&>L@WmG5oXXru{tB{1?*a3P}vFUpQ?N G2Khfe$S(l^ literal 0 HcmV?d00001 diff --git a/dpytools/config/properties/__pycache__/string.cpython-311.pyc b/dpytools/config/properties/__pycache__/string.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f011bcff324ebe1ead9fe614e79b49acaecb96f1 GIT binary patch literal 2445 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 A7XSbN literal 0 HcmV?d00001 diff --git a/dpytools/config/properties/__pycache__/test_stringproperty.cpython-311-pytest-7.4.4.pyc b/dpytools/config/properties/__pycache__/test_stringproperty.cpython-311-pytest-7.4.4.pyc new file mode 100644 index 0000000000000000000000000000000000000000..404df9793127ac31d4ddfd197e1630ecb1fc9981 GIT binary patch literal 7036 zcmeGhU2ojRarchAFMV2)kvMS!!ma^d68R)6P8`5#lfX_})Kv^PHWDQO!8@)bDtF{z z$+IQ(4ls%Wc}O4HhaxY12>ReaP*CJgq|dhDA_C!u0DaQi39zd8BwJ2`KVZ z@s4w|v$Hd^!{yA*-Zvv7B?8w!_r7CZfsp@VBfK&JvU?qnuZT%ZS|2T85H_ zvY=AglUv9^Po|!46c!3V%l?@x6io$S$y5OjnK^*NCcR0@`E3+EU#9-(O^;jl(hcr3 z8TZy|flBd{2bhI>_cnm9h(`rg0F#;-GixfQ`fcvMO2{VM^6HQ_`8viK(h0c_=w{Re z3-e$}VO=k2aDBvF&(*9&&Cpz7k=6`M(k$Ec47P_`!Lsf82WJ0YlnE|Ab-dnG~QY>BOI;|#XX1K3b~#Wotu zR|S)=ihe)eux!1~Y(R`vMCQvGj?VI5c3I7_O@puLfnkrKOTnF$Ub@xU5AoSch# zv^}eG%VpfH*jDZHrqOg-o@;z=xs|I0*qYcaPX^vL;z+AcKL{HYi{GJ{Wo84BF)djRf{XT#*=*{!j2TjOW9#!qie zOm0m~b%$~%b2|jUQv~<^&>bi0#1G2!BW3!bQhBUY9)#ar5JD15sR#tIlqLWkeJOc3 zCb(9@*MWGskOqqi9Jq;26xSuvp|JdLCaEjE{5qL7UFj{{tT)md)XpX)ca(Oft=u6U zwXOb@x~ezU<6VIlS6*hJtu9ith`fuL`(VdrWJ_WM`a@jpOj3_o@=k_*gscpOc+&bi z#66XeHyrYL5w_nqJUJq=VDJc=nk94Si1tkNx2H{$^W#ar$cp`ZpnE7GvB$aZ$qe99 zl6uYIf2ixQZaO)0#2jtsEGk-g@8!^Qgd`-5hV*tmDJj|d6E(+HX(t1>3U{`nm}B_4 z536-ETCou9#%_|cWR|$f-OOtC6LObQ@(H2v!JhK?`WJ_VK@r;^0h)P}BqQgbZ-XB*r%hmQ7xk3GmWpB{+-=90*T$?RJn71`VFPGiY9|J^tN08>q z?s=rV8Fm2@biGk_FUWaz%B7BIU~u=ryBW*EwtQn$u_+ zocTrFH5M6C{9)kKt1YYULE7?jbqAPT|3%$hc3O2)jMA6tPSvREBCCwPCu{`w3&sAV z4xVioo(@m1ZrBDswv7Tmfu`V6^@mV_oY+jfaVg$-E8e&$8&dAu(n8sooptdEWB$d9 zPoRQV`XvZmtU63+{4HR@5apI3ILA}P#Nbr%Y@C$F|MH8!uRkoFd0afxC8~Oxer^0% zIQc_i_EBN>VPWoZVeUa;uB*`EZQ3P0_~gc|ZWf!*V#FPRKaEl1L(;h9mlB>_4Fsmy z(v-NOVEFZ5c)Uvv3>ZGVwId8pn-?&=bL*L47%1WTK!&)5M^`5uc!0V=42gO5oA{wV zkrJfpxbbN`&LhPJ!r$-X@bp~L0uP}SaSh6qDB+G+l}`nX(+|d>16krXg(S?B)H$1z?n7cQZx=31_k|s(y`*=V*P~u-n0p@-Dk)3hoINmLygS(^$ zcLe@4Mv3QZpoCrBS6=%Y_uID+c3|A4``ieR3lZc<>O}8&?zz|2P;P?~=>`!>0z8n*GcR z7=CA9sad51C44-PA#U^0)ky~)pl%RDVqX0weyC64Zj2kB#-(|2je+p_J`PXMB`xp} z3Y40-V0sWsO?+xSO1yUv9+a9%QE6t8yvrkgAv}iSxV!UD>GBNgf;>FJ13%90a?6AB ztBB<10~*KwKKMBtSnB<$AP&yNp9SI=NNgR&Te?B`6b`^Dcdu}z;h3#D`xXBHns_+x zehC1cJf&N>#T@V%xhFnb= self.min_val + if self.min_val and self.value < self.min_val: + raise ValueError(f"Integer value for {self.name} is lower than allowed minimum.") - if self.max_val: - assert self.value <= self.max_val \ No newline at end of file + if self.max_val and self.value > self.max_val: + raise ValueError(f"Integer value for {self.name} is higher than allowed maximum.") \ No newline at end of file diff --git a/dpytools/config/properties/string.py b/dpytools/config/properties/string.py index 5ea0931..e4d72df 100644 --- a/dpytools/config/properties/string.py +++ b/dpytools/config/properties/string.py @@ -1,8 +1,8 @@ from typing import Optional - +from dataclasses import dataclass from .base import BaseProperty - +@dataclass class StringProperty(BaseProperty): regex: Optional[str] min_len: Optional[int] @@ -23,20 +23,20 @@ def secondary_validation_passed(self): Non type based validation you might want to run against a configuration value of this kind. """ + if len(self.value) == 0: raise ValueError(f"Str value for {self.name} is an empty string") if self.regex: # TODO - confirm the value matches the regex - ... - assert self.value == self.regex + pass if self.min_len: # TODO - confirm the string matches of exceeds the minimum length - ... - assert len(self.value) >= self.min_len + if len(self.value) < self.min_len: + raise ValueError(f"Str value for {self.name} is shorter than minimum length {self.min_len}") if self.max_len: # TODO - confirm the value matches or is less than the max length - ... - assert len(self.value) <= self.max_len \ No newline at end of file + if len(self.value) > self.max_len: + raise ValueError(f"Str value for {self.name} is longer than maximum length {self.max_len}") \ No newline at end of file diff --git a/dpytools/config/properties/test_intproperty.py b/dpytools/config/properties/test_intproperty.py new file mode 100644 index 0000000..f32495b --- /dev/null +++ b/dpytools/config/properties/test_intproperty.py @@ -0,0 +1,99 @@ +import pytest +from properties import IntegerProperty + +def test_int_property(): + """ + Tests if an integer property instance can be created + and validated with no errors. + """ + + test_property = IntegerProperty( + name = "Test Integer property", + value = 24, + min_val = 0, + max_val = 101 + ) + + test_property.type_is_valid() + test_property.secondary_validation_passed() + + +def test_int_property_type_invalid(): + """ + Tests if an integer property with a type of value that + cannot be cast to string raises an exception. + """ + + test_property = IntegerProperty( + name = "Test Integer Property", + value = "Not an integer", + min_val = 0, + max_val = 101 + ) + + with pytest.raises(Exception) as e: + + test_property.type_is_valid() + + assert "Cannot cast Test Integer Property value Not an integer to integer." in str(e.value) + + +def test_int_property_empty_val(): + """ + Tests if an integer property with nothing as the value + raises the expected exception from the secondary validation. + """ + + test_property = IntegerProperty( + name = "Test Integer Property", + value = None, + min_val = 0, + max_val = 101 + ) + + with pytest.raises(ValueError) as e: + + test_property.secondary_validation_passed() + + assert "Integer value for Test Integer property does not exist." in str(e.value) + + +def test_int_property_min_val(): + """ + Tests if an integer property with a value lower than the allowed minimum + raises the expected exception from the secondary validation. + """ + + test_property = IntegerProperty( + name = "Test Integer Property", + value = 9, + min_val = 10, + max_val = 101 + ) + + with pytest.raises(ValueError) as e: + + test_property.secondary_validation_passed() + + assert "Integer value for Test Integer property is lower than allowed minimum." in str(e.value) + + + +def test_int_property_max_val(): + """ + Tests if an integer property with a value higher than the allowed maximum + raises the expected exception from the secondary validation. + """ + + test_property = IntegerProperty( + name = "Test Integer Property", + value = 102, + min_val = 0, + max_val = 101 + ) + + with pytest.raises(ValueError) as e: + + test_property.secondary_validation_passed() + + assert "Integer value for Test Integer property is higher than allowed maximum." in str(e.value) \ No newline at end of file diff --git a/dpytools/config/properties/test_stringproperty.py b/dpytools/config/properties/test_stringproperty.py new file mode 100644 index 0000000..1e96981 --- /dev/null +++ b/dpytools/config/properties/test_stringproperty.py @@ -0,0 +1,83 @@ +import pytest +from properties import StringProperty + +def test_string_property(): + """ + Tests if a string property instance can be created + and validated with no errors. + """ + + test_property = StringProperty( + name = "Test String Property", + value = "Test string value", + regex = "Test regex", + min_len = 1, + max_len = 40 + ) + + test_property.secondary_validation_passed() + + +def test_string_property_empty_val(): + """ + Tests if a string property with an empty string as the value + raises the expected exception from the secondary validation. + """ + + test_property = StringProperty( + name = "Test String Property", + value = "", + regex = "Test regex", + min_len = 1, + max_len = 40 + ) + + with pytest.raises(ValueError) as e: + + test_property.secondary_validation_passed() + + assert ( + f"Str value for Test String Property is an empty string") in str(e.value) + + +def test_string_property_min_len(): + """ + Tests if a string property instance with a non-matching minimum + length string raises the expected error from secondary validation. + """ + + test_property = StringProperty( + name = "Test String Property", + value = "Test string value", + regex = "Test regex", + min_len = 50, + max_len = 51 + ) + + with pytest.raises(ValueError) as e: + + test_property.secondary_validation_passed() + + assert "Str value for Test String Property is shorter than minimum length 50" in str(e.value) + + +def test_string_property_max_len(): + """ + Tests if a string property instance with a non-matching maximum + length string raises the expected error from secondary validation. + """ + + test_property = StringProperty( + name = "Test String Property", + value = "Test string value", + regex = "Test regex", + min_len = 1, + max_len = 2 + ) + + with pytest.raises(ValueError) as e: + + test_property.secondary_validation_passed() + + assert ( + "Str value for Test String Property is longer than maximum length 2") in str(e.value) \ No newline at end of file diff --git a/dpytools/config/test_config.py b/dpytools/config/test_config.py new file mode 100644 index 0000000..71c63a9 --- /dev/null +++ b/dpytools/config/test_config.py @@ -0,0 +1,65 @@ +import pytest + +from config import Config +from properties.string import StringProperty +from properties.intproperty import IntegerProperty + +# def test_config_loader(): + +# config_dictionary = { +# "SOME_STRING_ENV_VAR": { +# "class": StringProperty, +# "property": "name1", +# "kwargs": { +# "regex": "I match a thing", +# "min_len": 10 +# }, +# }, +# "SOME_URL_ENV_VAR": { +# "class": StringProperty, +# "property": "name2", +# "kwargs": { +# "regex": "https://.*" +# }, +# }, +# "SOME_INT_ENV_VAR": { +# "class": IntegerProperty, +# "property": "name3", +# "kwargs": { +# "min_value": 5, +# "max_value": 27 +# } +# }, +# } + +# config = Config.from_env(config_dictionary) +# pass + + +config_dictionary = { + "SOME_STRING_ENV_VAR": { + "class": StringProperty, + "property": "name1", + "kwargs": { + "regex": "I match a thing", + "min_len": 10 + }, + }, + "SOME_URL_ENV_VAR": { + "class": StringProperty, + "property": "name2", + "kwargs": { + "regex": "https://.*" + }, + }, + "SOME_INT_ENV_VAR": { + "class": IntegerProperty, + "property": "name3", + "kwargs": { + "min_value": 5, + "max_value": 27 + } + }, +} + +x = 3 \ No newline at end of file diff --git a/tests/__pycache__/test_nothing.cpython-311-pytest-7.4.4.pyc b/tests/__pycache__/test_nothing.cpython-311-pytest-7.4.4.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c075661570d54b955a54a22d6f51f9cab258e4a8 GIT binary patch literal 503 zcmZutJ5R$f5Vn&((yC==^Mur)4FekpApwGgE{LT|l_qX$HL)$*0fngpD>GYH#Q)$| zWMyKD)U6X|({}1v_uWHx_nq&v+ifF|)%S|NgZ;6=PQ0zNJ^|+gB`Cou8ewO>%#S^c zvf8MQQR2O!Q6s^RsOSIMreVBobp`|apz8(z%&~Re>sgzC+-A}g#87RB5kwmy$uweV zuBawcp~xwT#WPjWjJopS7g9Al3KVS~!Y56Y4mpb#GLj-UI$AIt-iSEQC^tI1W9B}e zgo*6S!psHl8zE91TE2fAb7AI;&jzw6J2t&bs3tJjt#u1viK+nAgXOiVL)2@Q!6av? zVO*D;D_M;9(eW6FV9X%Wu$p0l4-|b-%+Rv6PnFGGt_{tOHByeyea>+xd#p`xk%=Tv g>7_b?&>m8s15`f7xN0Dbm$2HQSD_jX4uKo~2aEZIBLDyZ literal 0 HcmV?d00001 From 0a099404edf627a5642d2c93a25b6214aded28f9 Mon Sep 17 00:00:00 2001 From: NickPapONS Date: Fri, 2 Feb 2024 16:51:57 +0000 Subject: [PATCH 3/8] Config and tests completed --- .vscode/settings.json | 3 +- .../config/__pycache__/config.cpython-311.pyc | Bin 3114 -> 3570 bytes .../test_config.cpython-311-pytest-7.4.4.pyc | Bin 952 -> 0 bytes dpytools/config/config.py | 153 ++++++++---------- .../__pycache__/__init__.cpython-311.pyc | Bin 329 -> 329 bytes .../__pycache__/string.cpython-311.pyc | Bin 2445 -> 2445 bytes ...t_intproperty.cpython-311-pytest-7.4.4.pyc | Bin 8242 -> 0 bytes ...tringproperty.cpython-311-pytest-7.4.4.pyc | Bin 7036 -> 0 bytes dpytools/config/test_config.py | 65 -------- .../test_nothing.cpython-311-pytest-7.4.4.pyc | Bin 503 -> 503 bytes tests/test_config.py | 116 +++++++++++++ .../properties => tests}/test_intproperty.py | 3 +- .../test_stringproperty.py | 2 +- 13 files changed, 190 insertions(+), 152 deletions(-) delete mode 100644 dpytools/config/__pycache__/test_config.cpython-311-pytest-7.4.4.pyc delete mode 100644 dpytools/config/properties/__pycache__/test_intproperty.cpython-311-pytest-7.4.4.pyc delete mode 100644 dpytools/config/properties/__pycache__/test_stringproperty.cpython-311-pytest-7.4.4.pyc delete mode 100644 dpytools/config/test_config.py create mode 100644 tests/test_config.py rename {dpytools/config/properties => tests}/test_intproperty.py (96%) rename {dpytools/config/properties => tests}/test_stringproperty.py (97%) diff --git a/.vscode/settings.json b/.vscode/settings.json index 9b38853..aa5d433 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,7 @@ { "python.testing.pytestArgs": [ - "tests" + "tests", + "dpytools" ], "python.testing.unittestEnabled": false, "python.testing.pytestEnabled": true diff --git a/dpytools/config/__pycache__/config.cpython-311.pyc b/dpytools/config/__pycache__/config.cpython-311.pyc index 97ce87d06099c63ad945acec025bf876e7f3c3c1..ed7fc3e5f2565273595b04d2142a9bc67965be23 100644 GIT binary patch literal 3570 zcmbVP-ESMm5#J;4j$bF~BssDy)67}2(b69zY}seW@Pi)wzyL;NpeaBUiPAzrpvS)Se>e&RL>y2+K#_;M(U9}vmv-h>qT1# z>(r^jypaz~M_~FTr%E8f?UiBe)$O+YUXW?6+W_Zr}Dqsyh{G2BH!L1%6ci1ayr! z0}%^GxX#r`b3lqKvl1M4jWoF1Uw#77u7~PjXYbVF$a{PHN=S2nyQc(RH8{V)^H=9< z{L1jp;iT6>e}*&umvC^cKXSFO7CzEf;rO?Qb?^J9n0^Z*`27*|X0ZQiOEh5}Jl*Jf zTNmDFmUv*6_(roL2WCY~Q6qH$9(+ffMBhCE`l9>3)cBfE6Kj!gV(S7}3lA&xXmDIT z<_z^@5M{0wt3}sgFE;x7!2$PPq&KFCXX2#-a{@8p$m1Viox$jj?N8c^{^!96&`ZJo zYoZ?yu2he|(X7OQSqYPe_{HH#IOF@4fv#W-MZ<{t090BK>16&%uv7EfAe_Ao9t|_|t0N|G*#wdVI6Vf<>ub=vnAg%erEh^@6czfD4Nj zReDP*V4<;OqC1&%f+Es+g5l^T+Y4E?7eRNaWqRQy-Jy8By@;*DC&;067<*#AT-HsE z#;_CnH7xW#r4~&OQQUJ+WYFkIpa-Cws_33?uQ%rVsDd#)#IGK7I1VrhA1Soeiy>vx z`<{9c!*q~u;{{U&3q`p0qKnijsjzk*(tC^%5ZnKO8?{1y5Xso&=aWw+SH+!~%=XNM zt(gn0nYs4NT$f~HA9K%q+LGR0{pjh*?~c!WIrVkwuc=MxA6o19)%NkLu9WJGpLEC1 zVV$kGH-C@RudVTOZJ)n0a;Wj!$A9=LwKbA;N3xyq$)}S~-s_Uc=u9Vhy!qoVezBd* zZY8sukyi4ZcJiIZ`<>KG^ZFOocIw<#>fC0!mAc$cU2ZJAhTT}$Nh&yL8ixS+?%3(h zQKdQ6K6<8;%)lC*)Jdq_gqRw8Mu0p=(uj9ua%{SJs+~OBi2X}G{8Vhl{`QlWJlB@z zTzRe|PqgLCwtR6*zPNd>C0}XFS6sjDj7~H@dy@Lftc{X72QcIq1%k!>04-MGn!-}i?t~HTsPvl%V zwN(c7pxE~J;4X!<26wm_$ zGJPRrk?bB1Ax5Z%&GIepkgdbb)$+93OTYm1(jki1h9-g7=$fLiYc>ub0-D)Sm0kJe zDQ0En6|(E7;6orQq#GwkjKF(g{~O;d9bkQo1Fb zZcC?KzwZ1fJ&=m|8+ii|5pjoNj!6;OeMCz~Fu6nMQB^OlswGRS6tOL->Zg@_kxA$% zjQ1oP6YN4shn!KP8B~F3@ZX8QfbXxb(}62)(zG!zrb-2y;sv`KL7b^q`pW01w}1RApigX literal 3114 zcmb7G&2JM&6rZ*C%Z@{!arg)!**FPcDY2nZfI}2$NtLE*qqY=iEnr!^n`DW-c4s#f zN47v!j!1PSBz&|~NP~hZuDwHI3!)OnxQNxxG9P^=CvxW(b%~G%rm5*7$u{aNAb#(LMx0_ z*m=*1mX4d3J*)H@^lh~IW1Q?&KtrZi=@>6FU^#2DS5w-&x?pz1ty+}9gE-aFL5T2P zC_4cl5I$-Z<-ib7_RPgwk$^rPN;etE!tiG(OBJE<@8q^=8s(|m_iw>GIZw`;1>bi4 zF&wimSv-CTBOD&%uifpULt}Sk*}Dc#Y_y!p(Ff9^+q9SiX)$eDtj5YHM?+ztum%Zb zBf)&^uD4llmd-L+_7%6rfVEKUl;hmva(osQ9kVpYA(Z9ZYg5SZIeJl+hY_H;(bA^S zlRsc~XUwg8WNS5I{>1G!zUXf66La2eOU`#7Enl0KUn7z8LGc?M4qw_M=gazE`Pbm4 zZ!~W^%5}hsj`;pZ+&bK=?h&_+_PFJ#C$|kinr4#Q=J?URB7r%Ri6{Gl*O#$Rjw?`>&$c!5%%Tsqv+>luj)hy0oO~(dkrt znK+?GXH?_U<$F;%J(kWGiz#i)NTm`wv@u`6-leuJ`m;ap&0pW@ zK3+KXbn3;OO80oFd%Sk6ukh{DM|H&YoT&*T#l`1co5FZS7=Jxe7AC90WPz!L&aCs# zqnn|LN@(J>S`J;QhOQL2eZ&QBOBg0fr^yf??|2kCR~r~E#;OD7UNovkPMd9mearwD4CE~#`I-8mU4yrR#~bF}EC(m5 z!HH6EqG|4~1iId_=;TOgMpS|EC6Yfp%5SfT3C)xF0l4S@IH{SPyy_XbuS6eR`Xt$F4 zU4{P_iagOPvcGw8KC98pvr(7#1Fs% z7!YZ7&cVM=C&3p{)oqY4gSrBjOO|lP7D$Gg(jd%zU@$%n#2IExp23ygMuhhOo0~)- z0tAA682LIk`Q8fOTju+!d|!$0tMP$Nez3w1mieJ7KU8XFEA(?=AGzHGTtw0Ii()b* zFDD2e5XJA8r9`7ApaYz#@uUKHA!D*LrWYUzlb0Be5JIfP!-SA6wGId-$G{>41$7edh5RFA)LI{DNY9m2FP20gjvRt1@tooPkF0|>? z0Y)S?mhOm+KP4N{O_i9kS?bn_J3FZe5_jk4?|tvyckjLLrIG>o`f~Bp`>X))TR5|& zO~K_S4!!{d5Db6?v%eI|t^`52U@0(AYUydo;0B~(Vsc@$O7Wvhg$))InU(5y{FNu4HS>dQF#;P*IM z>Qd}Sy>~cHJWPk2DYql)^*lVIm=Zam_wcmbZiEhX`wgc-`#fbLT5n2B!Tk0K(?UP8 z121aIOmPE;5T++nQKlXpJGe)3rA@5!#8abBX+oZuX6t^=Kbr6fg2`&GS`cy{onYXx zLg<|2kZaevZ{KX$-M!s*XWQQD9M}ghcG+@9?(e?-hiP~AX3Rtux@D#x4*Y=n5n;vW z$UJ`u9-%E>IUj@{M=k6fW1sT(uPLU@ID;pP>$ZcLnnR|#*-)`~iB+b}`yOeL zY{Ym$@HhYB{fN#+ghlVHk}KHAcSQvb9x{0H16=YLxH>TRd1b_meD^4El6XLgbL12A zRqPHzFQUZU_UX>x&_u}wuc#kK8#Ims!u??ma&Af7XLy}I1NldO zag)jr!Z846|J$XrY+r!-X#R}BgVFpMgU!+WNp~QqHpVwrFILvax9X`P*NhYhqiJ{5 z6bMtD-YC|-zE5RI#MC;E39}5UYa+XTXIx*M%N92@Zq{zENGafE1S;ucpr~h1Y Config: + + config = Config() + + for env_var_name, value in config_dict.items(): + + value_for_property = os.environ.get(env_var_name, None) + assert value_for_property is not None, f'Required envionrment value "{env_var_name}" could not be found.' + + if value["class"] == StringProperty: + if value["kwargs"]: + regex = value["kwargs"].get("regex") + min_len = value["kwargs"].get("min_len") + max_len = value["kwargs"].get("max_len") + else: + regex = None + min_len = None + max_len = None + + stringprop = StringProperty( + name = value["property"], + value = value_for_property, + regex = regex, + min_len = min_len, + max_len = max_len + ) + + prop_name = value["property"] + setattr(config, prop_name, stringprop) + config._properties_to_validate.append(stringprop) + elif value["class"] == IntegerProperty: + if value["kwargs"]: + min_val = value["kwargs"].get("min_val") + max_val = value["kwargs"].get("max_val") else: - raise ValueError("Incorrect value type specified for property assignment.") - - + min_val = None + max_val = None - def assert_valid_config(self, prop: BaseProperty): + intprop = IntegerProperty( + name = value["property"], + value = value_for_property, + min_val = min_val, + max_val = max_val + ) + + prop_name = value["property"] + setattr(config, prop_name, intprop) + config._properties_to_validate.append(intprop) + + else: + raise TypeError("Incorrect value type specified for property assignment.") + + return config + + + def assert_valid_config(self): """ Assert that then Config class has the properties that provided properties. """ - # For each of the properties you imbided above, run - # self.type_is_valid() - # self.secondary_validation() - prop.type_is_valid() - prop.secondary_validation() + for property in self._properties_to_validate: + property.type_is_valid() + property.secondary_validation() + + self._properties_to_validate = [] \ No newline at end of file diff --git a/dpytools/config/properties/__pycache__/__init__.cpython-311.pyc b/dpytools/config/properties/__pycache__/__init__.cpython-311.pyc index 9074554816273738b4a41b2d399c78630d8e6f57..06e33a73d446581b25fbaa09110fdd2dbfbdd87d 100644 GIT binary patch delta 20 acmX@fbdrgCIWI340}y<8vS%Z=9U}lecm?`�da3fd!)g diff --git a/dpytools/config/properties/__pycache__/test_intproperty.cpython-311-pytest-7.4.4.pyc b/dpytools/config/properties/__pycache__/test_intproperty.cpython-311-pytest-7.4.4.pyc deleted file mode 100644 index b0f6693d7ffe6b71ac14881b5de8b8585b9252a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8242 zcmeHM&u<&Y6`m!RP@k~ICLq(xD|ZQ3FdP!MbGQe21J zC1#eE#FBtp^w>jzw#cOgd~zVTJ@+qY&!j=a!uDdIC*2e{0Suq|-puZ3cS%|bkRA$X zx%~L%n>TNUv%~pjh96H)7YJOxYW&0ccb<^{U?RLyf${8TV0=VOVk!-?q43XCGhIz7 zq^WLX6p@qN$U;u4k!xxj8gS{~k&V2m0v5~+;3+c;IA!Jlr%mO3QquOZg0+(3&-}>o ztWAsFqHfEg-cB{BnSW#f)9`-Q1^9?~3THW(ikULgruw(c1C@}6@D^8(bjkgQU&s^k z0L+Insi0r@H6@Ei($CC7gL56Dpu_cZi+N19Yr5g+wrIKD3YrcC^9-kI=~c+R4Ik7p zJj>L1Ny9PqyGFw{Ikjbbb=`4wi&B@eCGOFg$LM;{Au{a#E6^y4P2INuc2!?>jHcyh zAX?kX@xRcwZ&ZTjb#RdpTHpgV#vJll0DErT)3ga({NH-C`N%x6C#0G}e<`^iC(Wagfz7apk>2I|64UFfR|d+O{H_39(_>Od_I z)p9?)pFvC#8*1)G zcD+K-V&=`lG23%? ze0#b|q7`vJ*@~ne)Ln>0JoHRFnF(HMyk7IvUossSH@&PmWlndqw!%|6?|j&Egv25h zL%y4fM~bI@tC+=YrI&(t2HxqOY8LVJ07mOWIbvbXF1}ALk!8Zvt<-jUoop!zStkm- zFsC%rVMkAYd`>fToON`!hLc^}(!ILji3t!UMaT8{ylB8Q=eaubsO@a()UcVwa7MMZ zt5yrAB{3nsh);;Of_b)6T!T1=6EL3}DgNka4xsbB?~9tMSWRq74I>0?i-*A$1ylOc zuHvU`XIJU`c=1YWXSoDZzN4dgv&0I&4h;QmPOX&K6=ZINSzrWN*Gp`PcSE69D)js` zd|_X)b~An&f+DOSTt~QpaP!3sPRG>aftRn9n6HB8wYAcWn9{Q_t->_zXGNd+`PHz; zDE_c0jzaon0Kf1Z;aV}MKU=99jYfr9En0P(ErVKqzQT-}g^WK1o|W5eyWxR;`PqgG z&dh(M!s>3jVe(Ry&4zp1XjHiF6u--x2v2Dh#mhfaskyXicol2A)i4|`E4v!S0ZLK2 z{8Lzg_+HndiPxivH=>DeiiC*!Ezv@eSYBp0o1qlrMRA(*zdE8G6(M~NS3bG|PB?3^ zG>rJDl;{(rqB+UH&P@DF1T%`Sa&5cM!SH=3p@VeN|a~GyTsu)zx=$ z|4J!#xMR;s0nofNO#1dLRWGsnp1NAT@D406C>%=Qqb( z4}j#?QREErI9bi|8FkL|6B7k4`C9ZL} z3{qU2AL=iC6_bkyml3{(a0Q`+@EXF`5xxO1M$*oYN}APdd3@_eZ$cRiGooi_kI=Ku zAb)X~zlgKox^my(dba#XTOMdDLv5w6tvuB}=<|EX@iE7N_JK%>EQ!E_!`LkF5v8Pq z3?dkr1W&;LN^+DDl};)vtCP{9%qS`1Bz&NDV4}BRz&YVB+ZlC^+NfviT+c#8JzG~$ z&q78#gqLHWXGayG*I_W6sMm>lB~^)@>}JRBX8(9h^)iB;V#D3CDDGt)E=sVQ0>aec z=*@1nn_r-w?c+*o9}i|D8`^h|t7$gVBP~s|@;DN=MsHx%6GZ9Us3--8kMu1l_BOmn zBx!bU4peFMv@YCYMI@;{L6SE68s0;Wk2wy)q{xy8JU9qXNlHVMk`6M6U}O^f1p_F_ zQAUKFR2Fg*WuuI&LXskmOoAb7VMv6SV1skQU)Ci(69!6Bol8=PC`olLNg;z`bd()P z(ot?Fl5}#w3e&;pM(IS7CLFN->2pd_-QKK^)g)v4i`JwXJjdid>%GsRNztZCQ4-Dk z--wd6-0^^=Ua{60{N%C!R`;o_`~GOOSoGJ?RMgh%kTSq1xVJo4uM7mTcH A7XSbN diff --git a/dpytools/config/properties/__pycache__/test_stringproperty.cpython-311-pytest-7.4.4.pyc b/dpytools/config/properties/__pycache__/test_stringproperty.cpython-311-pytest-7.4.4.pyc deleted file mode 100644 index 404df9793127ac31d4ddfd197e1630ecb1fc9981..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7036 zcmeGhU2ojRarchAFMV2)kvMS!!ma^d68R)6P8`5#lfX_})Kv^PHWDQO!8@)bDtF{z z$+IQ(4ls%Wc}O4HhaxY12>ReaP*CJgq|dhDA_C!u0DaQi39zd8BwJ2`KVZ z@s4w|v$Hd^!{yA*-Zvv7B?8w!_r7CZfsp@VBfK&JvU?qnuZT%ZS|2T85H_ zvY=AglUv9^Po|!46c!3V%l?@x6io$S$y5OjnK^*NCcR0@`E3+EU#9-(O^;jl(hcr3 z8TZy|flBd{2bhI>_cnm9h(`rg0F#;-GixfQ`fcvMO2{VM^6HQ_`8viK(h0c_=w{Re z3-e$}VO=k2aDBvF&(*9&&Cpz7k=6`M(k$Ec47P_`!Lsf82WJ0YlnE|Ab-dnG~QY>BOI;|#XX1K3b~#Wotu zR|S)=ihe)eux!1~Y(R`vMCQvGj?VI5c3I7_O@puLfnkrKOTnF$Ub@xU5AoSch# zv^}eG%VpfH*jDZHrqOg-o@;z=xs|I0*qYcaPX^vL;z+AcKL{HYi{GJ{Wo84BF)djRf{XT#*=*{!j2TjOW9#!qie zOm0m~b%$~%b2|jUQv~<^&>bi0#1G2!BW3!bQhBUY9)#ar5JD15sR#tIlqLWkeJOc3 zCb(9@*MWGskOqqi9Jq;26xSuvp|JdLCaEjE{5qL7UFj{{tT)md)XpX)ca(Oft=u6U zwXOb@x~ezU<6VIlS6*hJtu9ith`fuL`(VdrWJ_WM`a@jpOj3_o@=k_*gscpOc+&bi z#66XeHyrYL5w_nqJUJq=VDJc=nk94Si1tkNx2H{$^W#ar$cp`ZpnE7GvB$aZ$qe99 zl6uYIf2ixQZaO)0#2jtsEGk-g@8!^Qgd`-5hV*tmDJj|d6E(+HX(t1>3U{`nm}B_4 z536-ETCou9#%_|cWR|$f-OOtC6LObQ@(H2v!JhK?`WJ_VK@r;^0h)P}BqQgbZ-XB*r%hmQ7xk3GmWpB{+-=90*T$?RJn71`VFPGiY9|J^tN08>q z?s=rV8Fm2@biGk_FUWaz%B7BIU~u=ryBW*EwtQn$u_+ zocTrFH5M6C{9)kKt1YYULE7?jbqAPT|3%$hc3O2)jMA6tPSvREBCCwPCu{`w3&sAV z4xVioo(@m1ZrBDswv7Tmfu`V6^@mV_oY+jfaVg$-E8e&$8&dAu(n8sooptdEWB$d9 zPoRQV`XvZmtU63+{4HR@5apI3ILA}P#Nbr%Y@C$F|MH8!uRkoFd0afxC8~Oxer^0% zIQc_i_EBN>VPWoZVeUa;uB*`EZQ3P0_~gc|ZWf!*V#FPRKaEl1L(;h9mlB>_4Fsmy z(v-NOVEFZ5c)Uvv3>ZGVwId8pn-?&=bL*L47%1WTK!&)5M^`5uc!0V=42gO5oA{wV zkrJfpxbbN`&LhPJ!r$-X@bp~L0uP}SaSh6qDB+G+l}`nX(+|d>16krXg(S?B)H$1z?n7cQZx=31_k|s(y`*=V*P~u-n0p@-Dk)3hoINmLygS(^$ zcLe@4Mv3QZpoCrBS6=%Y_uID+c3|A4``ieR3lZc<>O}8&?zz|2P;P?~=>`!>0z8n*GcR z7=CA9sad51C44-PA#U^0)ky~)pl%RDVqX0weyC64Zj2kB#-(|2je+p_J`PXMB`xp} z3Y40-V0sWsO?+xSO1yUv9+a9%QE6t8yvrkgAv}iSxV!UD>GBNgf;>FJ13%90a?6AB ztBB<10~*KwKKMBtSnB<$AP&yNp9SI=NNgR&Te?B`6b`^Dcdu}z;h3#D`xXBHns_+x zehC1cJf&N>#T@V%xhFnb Date: Tue, 6 Feb 2024 11:17:25 +0000 Subject: [PATCH 4/8] Addressing feedback --- .../__pycache__/base.cpython-311.pyc | Bin 2021 -> 1919 bytes .../__pycache__/intproperty.cpython-311.pyc | Bin 2207 -> 2200 bytes .../__pycache__/string.cpython-311.pyc | Bin 2445 -> 2694 bytes dpytools/config/properties/base.py | 28 +++------- dpytools/config/properties/intproperty.py | 18 +++---- dpytools/config/properties/string.py | 20 +++---- .../test_nothing.cpython-311-pytest-7.4.4.pyc | Bin 503 -> 0 bytes tests/test_intproperty.py | 28 +++++----- tests/test_stringproperty.py | 50 +++++++++++++----- 9 files changed, 78 insertions(+), 66 deletions(-) delete mode 100644 tests/__pycache__/test_nothing.cpython-311-pytest-7.4.4.pyc diff --git a/dpytools/config/properties/__pycache__/base.cpython-311.pyc b/dpytools/config/properties/__pycache__/base.cpython-311.pyc index 1209990446e8ed1957f0d67156cf87fd7a117bbd..f3828255bd68b596ce51276a39620f86e809755d 100644 GIT binary patch delta 892 zcmZuuO=uHA7@eK{NwV1_O_PI36$SYFt~Ju`*4a%VQOH(u z5cCpOP>^2hp=XbRc+-q$aep?3>y5y?Niy?q&X_(;rhQ6|r?T z|J8ac4${Ab&B5<;JxejgKH6b{U5N5kk6E#&@yVAdoe)o$@-bF5l|HH`&DbrZ$3yL^ z;aWGTvtd!M6Uq(SShqr@v1zQet)?(B557xU@DS%EU8w27w(zVcfv}sMzFh(eigy8g zG|c4QbbrJP`{2^Vfa4{zU1ab6B7=9xJIaHQDZCIqAQNwkJB-~uio6tbvDRI@O*<`n zm3TdeG@lsuszo3v*%&uKJcsboN%t~&)b>cnX_Ka5+m1KU8~?@ps`1#fC~4WQXV_lL z@LG;t(uGjH3lq3bsY7*4=UAPg%$;3mgwzSmvYpN|IAIEDM!Odo_-HRvh!9%1fxp~2 z+^2Db&|DcGaAdq%#xxgvmd*$B(gQ66CNKb&D|jxI@{r6;aMwsf3GJ20)r0IQ#?cvh zLtZMLnUbqxIiqU27JQPg^uqXLYP^e3aV?LHf=Xak09XLv-Z?n&hLdmtfPd(|X5ddf z!(`g8_?4~7Pc7qD{pwbAD5oMU$i)aT7>P(p_wRFpL<&;W{tA4QF@(z);@Jrm1j;2L z7kpDzinBHRi7%}?W_!(ArWbKf1fwO=_ASO~f|ZixI6SFCq$hN)ENqgHn+tbQUjd)6TYPLm^wp zAxKfm9Q5W*3HmSi4|wV^EFQcF9=B8wyy$ylQzt~7VLvnPy?JlGGqXQ4U$U9Ep63u~ zpFX}0TKYleE4_d4eQuFyU9xO49XP=Zpv6p}9XM>FOWr`jJIs=8In6AHxy)W7H79m& zH^X3&w>AR4wG->>&9xvl#4~zT@6(08_&_(W+y0|q%g0E&sIHzr^}A3xL}3vbWT*Cb z4z1~9+)TWnmpVKPvp(e>4Ezirq<|`)0>+N4@wmCV9kfg1#bp5VmFn$7tIP}FTS)uNY`3SWNl%Nj5E^^5yf|;V!aSov)s)!2+xdT3@{2_Q6X9xqn@Hrq-`e(QQ~KK1gSxM%37ABo;Nw z2|0yHjS8BGDln(mU_y8n!@nV}nAd1Qte6ifqcVP2H`ZEgdo{SpFN=Z6?p&m9LdNmx Xp7b7J=o{ilBdK(^oTNt9$~*l9uUFJ~ diff --git a/dpytools/config/properties/__pycache__/intproperty.cpython-311.pyc b/dpytools/config/properties/__pycache__/intproperty.cpython-311.pyc index e7776451ab01dfb43f51b2c2a0c62bb1ff5ea5b5..7bd533ca44b55f8d3ce1d78ac68dd99a6611abd4 100644 GIT binary patch delta 474 zcmbO)I75(kIWI340}vRA97?s`$eYO|$`)Uim{Xd1i_^6tIkli9Ge7SZYy9L+rgd3a zKy?iaAGnw~lNj&v@K0cw!hMlP<_eF@1sM8qmtW!o10zr#nY=3`eL*ICg~=K#AO%D_ zQubs+SU~ckP{b9XhzoIv7kCnX0Ko@lp!Uskn1h)ZMJ9h>6=AAUnasF35t=MWOgBLh%=P;z7<% z0Q)+D5vUZ1Ccj`?pbZKL4pulR!ovzugq57UnSGfXNLGpw8#y88BUt7OnEc4hz{K4m N`GE;tagjJMhybz=nArdT delta 522 zcmbOsIA4%=IWI340}x~|Y)rM>$eYO|%vzS1Q<{2<)3qWwwV)(3KkpXHEGku0fs;B@=JVRU<67blXr!rFUW+hFj->>q=0Bg$et(& z3rJoR3cDf{b|EJI0#E!8Ao#!x(hg)4ivVqE5|Ln-!R5%oyhzcJnfV|y>*l@8mP~Te z#i_~pc`1oSmGMAlW~L;992j4aSX`W%Ql&kamrbP}$^#ivyd3Ig1_6=mKd3p}xKP4Qq&7HGO+A-ZBO$b!&Cp|~qTaTj>vK)#I!2Ua{I&;lTu{E%&d zHYof!SmC4y4=YF!R&w$h_GNA$St&+rR+YiiQ|t zh{1&MNc5ly2Z9<*1OkZ%F8CL8WCyai#EVz6i-s5vzPDxz2mSi``+l##@B8|`etp^e zyv6;_?QQ_XqTVmYZrWfiH&evbw9)fSVDxVAYeZi z;ZSuy#I=k3F!@%)AS~cJ+-gwI8kRPb&1sp*+*DG_B@J!*_I+bUGmUBEK@>Nk0Vv`d zNQ;#i(1@gDLr4?FP|>g;GGPpo6) z{Bz)^3}j_KxA3SSsYOYBeRp5dY)Qj^Q0D|ICg69q{Y`9TWOZ!AyR8<~{-WAHf90S# zNT%aXz_L%XPu$w*+71)vtb#9I^u_JQ_%}&e=&Jxm%)qkZS?patTTp^UCAiYH+P$wt zZ6%5a_->UE)Bn|9@S!G-2GBBTc;IC1@z+$9bnpR~0phCtnF3`LcpMcjouR*vz}3;) z!qFoCMyCqRCDZsMoQn8swagC6>M!{%^kuU8y|i)83=x6O-&(+ocwPYFT=l{i#LFy= F{|gt^(LMkG delta 597 zcmZn@?G@%-&dbZi00e7a?@3)Wkyny2Y@)iRUMe#agF8bCYYRgPTPo`^W(J1UKnwxP zfYfRjharkBg?(b1`Nn;B7#Ue7&tck{#SN4zP6ZMT3?I0dIpZ1c^6*b!nZniS-{ao_ zhClA|OMGBp1WF;3cZH-c$b_sgSz`&LfM`d^o+t4zm1H<&mb&Tqh895nh7_wL=-(@idI!BOImz4#~KglWsVz7ZF*d|X0 zO0a_YCs}1V*@A)I3}(<|pZuP6$>gnUPK@l6f3PXY6@fyg2;?74#v(zGw}5srC=>|; z$y?Hs1KCA5;|mgti&Imov?iysE2~3!q9CPrfJ6hsR~`l){*IEKs!sbJ`x%LsxaBW! z%THdzuB^tyDfoa#-~l&(kIe@LX3kv3r~E<_Or}_M*7wve5LqH~iC^~uzwTsx4joBm z&Kw-FWgKdP>>z275jl(xAbQqv1W8K(tzXGdBnhOz?k(Z~u|NdtWGPM$UQpO`utLen z`J4(oV5J}he!zg3#i^|U)*%nl1~=swhfQvNN@-52U6C?S0u&s@&67WI+E2FP@?Zfe F0{~Zan_U0^ diff --git a/dpytools/config/properties/base.py b/dpytools/config/properties/base.py index c058ce8..f323dad 100644 --- a/dpytools/config/properties/base.py +++ b/dpytools/config/properties/base.py @@ -4,28 +4,16 @@ @dataclass class BaseProperty(metaclass=ABCMeta): - name: str - value: Any + _name: str + _value: Any - # TODO: getter - # allow someone to get the property - def _get_name(self): - return self.name + @property + def name(self): + return self._name - def _get_value(self): - return self.value - - # TODO: setter - # categorically disallow anyone from - # changing a property after the class - # has been instantiated. - # Refuse to do it, and log an error. - - def _set_name(self, value): - self.name = value - - def _set_value(self, new_value): - self.value = new_value + @name.setter + def name(self, value): + raise ValueError(f"Trying to change name property to value {value} but you cannot change a property name after instantiation.") @abstractmethod def type_is_valid(self): diff --git a/dpytools/config/properties/intproperty.py b/dpytools/config/properties/intproperty.py index 2e0015f..f776738 100644 --- a/dpytools/config/properties/intproperty.py +++ b/dpytools/config/properties/intproperty.py @@ -13,20 +13,20 @@ def type_is_valid(self): its of the correct type """ try: - int(self.value) + int(self._value) except Exception as err: - raise Exception(f"Cannot cast {self.name} value {self.value} to integer.") from err + raise Exception(f"Cannot cast {self._name} value {self._value} to integer.") from err - def secondary_validation_passed(self): + def secondary_validation(self): """ Non type based validation you might want to run against a configuration value of this kind. """ - if not self.value: - raise ValueError(f"Integer value for {self.name} does not exist.") + if not self._value: + raise ValueError(f"Integer value for {self._name} does not exist.") - if self.min_val and self.value < self.min_val: - raise ValueError(f"Integer value for {self.name} is lower than allowed minimum.") + if self.min_val and self._value < self.min_val: + raise ValueError(f"Integer value for {self._name} is lower than allowed minimum.") - if self.max_val and self.value > self.max_val: - raise ValueError(f"Integer value for {self.name} is higher than allowed maximum.") \ No newline at end of file + if self.max_val and self._value > self.max_val: + raise ValueError(f"Integer value for {self._name} is higher than allowed maximum.") \ No newline at end of file diff --git a/dpytools/config/properties/string.py b/dpytools/config/properties/string.py index e4d72df..e56a92f 100644 --- a/dpytools/config/properties/string.py +++ b/dpytools/config/properties/string.py @@ -2,6 +2,8 @@ from dataclasses import dataclass from .base import BaseProperty +import re + @dataclass class StringProperty(BaseProperty): regex: Optional[str] @@ -14,29 +16,29 @@ def type_is_valid(self): its of the correct type """ try: - str(self.value) + str(self._value) except Exception as err: - raise Exception(f"Cannot cast {self.name} value {self.value} to string.") from err + raise Exception(f"Cannot cast {self.name} value {self._value} to string.") from err - def secondary_validation_passed(self): + def secondary_validation(self): """ Non type based validation you might want to run against a configuration value of this kind. """ - if len(self.value) == 0: + if len(self._value) == 0: raise ValueError(f"Str value for {self.name} is an empty string") if self.regex: # TODO - confirm the value matches the regex - pass + regex_search = re.search(self.regex, self._value) + if not regex_search: + raise ValueError(f"Str value for {self.name} does not match the given regex.") if self.min_len: - # TODO - confirm the string matches of exceeds the minimum length - if len(self.value) < self.min_len: + if len(self._value) < self.min_len: raise ValueError(f"Str value for {self.name} is shorter than minimum length {self.min_len}") if self.max_len: - # TODO - confirm the value matches or is less than the max length - if len(self.value) > self.max_len: + if len(self._value) > self.max_len: raise ValueError(f"Str value for {self.name} is longer than maximum length {self.max_len}") \ No newline at end of file diff --git a/tests/__pycache__/test_nothing.cpython-311-pytest-7.4.4.pyc b/tests/__pycache__/test_nothing.cpython-311-pytest-7.4.4.pyc deleted file mode 100644 index 5694b58800fc78630ab8c5f1bb1fd0e833ce7890..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 503 zcmZuty-ve05Vn*4q*cq#<_W1o8wNHILIMN}T@Xu`DoxzhYGPZq0}4|IR%RXnG4KXF zNmeGr5~*7!&Zh0uv+lbe-Q9P-_ine1Kt6xJ=quQ78*IhfIIAOY-cW)PoT3qS*310Z z!zinb>KG;73mP>Ne2;qmk8K*pn^tEqpbxrg0Kgnu=RKda3CMLOO+gIRh8RJ#5t2+J zmgb6TG8Kv(lUO`b70swCAATTJv!g)K`YwFXROyhjcp)Pxa-*XK)8Unf^Nez%!y9I9 z^GTS{uh^2;Ju#hqA|72WOc` h@|2#d0|@OQ^(jE*V~nc?!gvX*?Ryof;b0%Q;eRd>g?9h| diff --git a/tests/test_intproperty.py b/tests/test_intproperty.py index a02f32d..a393a77 100644 --- a/tests/test_intproperty.py +++ b/tests/test_intproperty.py @@ -8,14 +8,14 @@ def test_int_property(): """ test_property = IntegerProperty( - name = "Test Integer property", - value = 24, + _name = "Test Integer property", + _value = 24, min_val = 0, max_val = 101 ) test_property.type_is_valid() - test_property.secondary_validation_passed() + test_property.secondary_validation() assert test_property @@ -26,8 +26,8 @@ def test_int_property_type_invalid(): """ test_property = IntegerProperty( - name = "Test Integer Property", - value = "Not an integer", + _name = "Test Integer Property", + _value = "Not an integer", min_val = 0, max_val = 101 ) @@ -46,15 +46,15 @@ def test_int_property_empty_val(): """ test_property = IntegerProperty( - name = "Test Integer Property", - value = None, + _name = "Test Integer Property", + _value = None, min_val = 0, max_val = 101 ) with pytest.raises(ValueError) as e: - test_property.secondary_validation_passed() + test_property.secondary_validation() assert "Integer value for Test Integer property does not exist." in str(e.value) @@ -66,15 +66,15 @@ def test_int_property_min_val(): """ test_property = IntegerProperty( - name = "Test Integer Property", - value = 9, + _name = "Test Integer Property", + _value = 9, min_val = 10, max_val = 101 ) with pytest.raises(ValueError) as e: - test_property.secondary_validation_passed() + test_property.secondary_validation() assert "Integer value for Test Integer property is lower than allowed minimum." in str(e.value) @@ -87,14 +87,14 @@ def test_int_property_max_val(): """ test_property = IntegerProperty( - name = "Test Integer Property", - value = 102, + _name = "Test Integer Property", + _value = 102, min_val = 0, max_val = 101 ) with pytest.raises(ValueError) as e: - test_property.secondary_validation_passed() + test_property.secondary_validation() assert "Integer value for Test Integer property is higher than allowed maximum." in str(e.value) \ No newline at end of file diff --git a/tests/test_stringproperty.py b/tests/test_stringproperty.py index a0caec6..c1b48ef 100644 --- a/tests/test_stringproperty.py +++ b/tests/test_stringproperty.py @@ -8,14 +8,14 @@ def test_string_property(): """ test_property = StringProperty( - name = "Test String Property", - value = "Test string value", - regex = "Test regex", + _name = "Test String Property", + _value = "Test string value", + regex = "Test", min_len = 1, max_len = 40 ) - test_property.secondary_validation_passed() + test_property.secondary_validation() def test_string_property_empty_val(): @@ -25,8 +25,8 @@ def test_string_property_empty_val(): """ test_property = StringProperty( - name = "Test String Property", - value = "", + _name = "Test String Property", + _value = "", regex = "Test regex", min_len = 1, max_len = 40 @@ -34,7 +34,7 @@ def test_string_property_empty_val(): with pytest.raises(ValueError) as e: - test_property.secondary_validation_passed() + test_property.secondary_validation() assert ( f"Str value for Test String Property is an empty string") in str(e.value) @@ -47,8 +47,8 @@ def test_string_property_min_len(): """ test_property = StringProperty( - name = "Test String Property", - value = "Test string value", + _name = "Test String Property", + _value = "Test string value", regex = "Test regex", min_len = 50, max_len = 51 @@ -56,7 +56,7 @@ def test_string_property_min_len(): with pytest.raises(ValueError) as e: - test_property.secondary_validation_passed() + test_property.secondary_validation() assert "Str value for Test String Property is shorter than minimum length 50" in str(e.value) @@ -68,8 +68,8 @@ def test_string_property_max_len(): """ test_property = StringProperty( - name = "Test String Property", - value = "Test string value", + _name = "Test String Property", + _value = "Test string value", regex = "Test regex", min_len = 1, max_len = 2 @@ -77,7 +77,29 @@ def test_string_property_max_len(): with pytest.raises(ValueError) as e: - test_property.secondary_validation_passed() + test_property.secondary_validation() + + assert ( + "Str value for Test String Property is longer than maximum length 2") in str(e.value) + + +def test_string_property_regex_no_match(): + """ + Tests if a string property instance with a non-matching regex/value + raises the expected error from secondary validation. + """ + + test_property = StringProperty( + _name = "Test String Property", + _value = "Test string value", + regex = "Test regex", + min_len = 1, + max_len = 50 + ) + + with pytest.raises(ValueError) as e: + + test_property.secondary_validation() assert ( - "Str value for Test String Property is longer than maximum length 2") in str(e.value) \ No newline at end of file + "Str value for Test String Property does not match the given regex.") in str(e.value) \ No newline at end of file From affdfdd8ac3b970d4ab22cc7b83a79049d3cb51a Mon Sep 17 00:00:00 2001 From: NickPapONS Date: Wed, 7 Feb 2024 10:55:03 +0000 Subject: [PATCH 5/8] Fixing forgotten variable names --- .../config/__pycache__/config.cpython-311.pyc | Bin 3570 -> 3574 bytes dpytools/config/config.py | 8 ++++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dpytools/config/__pycache__/config.cpython-311.pyc b/dpytools/config/__pycache__/config.cpython-311.pyc index ed7fc3e5f2565273595b04d2142a9bc67965be23..26d410a4f82274a2da4dae66dd802870e360ad6d 100644 GIT binary patch delta 122 zcmew){Y{#8IWI340}z-e9!{;?$Xmw7$r_)Rn45ZwEq-zr+g`g7*$Xmw7&XSjyn|h0Nau3^G)*?Be)aC;AWJWG&g#}Vq sq;+n{=uN)Mu^NfHc@k#}6Pq4TVUf{f8J_=)=96W3B^YfdoAMq60G;m~h5!Hn diff --git a/dpytools/config/config.py b/dpytools/config/config.py index a4add5f..69c669c 100644 --- a/dpytools/config/config.py +++ b/dpytools/config/config.py @@ -33,8 +33,8 @@ def from_env(config_dict: Dict[str, Dict[str, Any]]) -> Config: max_len = None stringprop = StringProperty( - name = value["property"], - value = value_for_property, + _name = value["property"], + _value = value_for_property, regex = regex, min_len = min_len, max_len = max_len @@ -53,8 +53,8 @@ def from_env(config_dict: Dict[str, Dict[str, Any]]) -> Config: max_val = None intprop = IntegerProperty( - name = value["property"], - value = value_for_property, + _name = value["property"], + _value = value_for_property, min_val = min_val, max_val = max_val ) From 5b6105ac31f573b7ff91b06d8f4590fead65ea20 Mon Sep 17 00:00:00 2001 From: NickPapONS Date: Wed, 7 Feb 2024 11:00:50 +0000 Subject: [PATCH 6/8] Fixing unit tests again --- tests/test_config.py | 14 +++++++------- tests/test_intproperty.py | 6 +++++- tests/test_stringproperty.py | 6 ++++++ 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/tests/test_config.py b/tests/test_config.py index 6174625..2c9c5bd 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -48,19 +48,19 @@ def test_config_loader(monkeypatch): # Assertions - assert config.name1.name == "name1" - assert config.name1.value == "Some string value" + assert config.name1._name == "name1" + assert config.name1._value == "Some string value" assert config.name1.min_len == 10 assert config.name1.regex == "I match a thing" - assert config.name2.name == "name2" - assert config.name2.value == "https://test.com/some-url" + assert config.name2._name == "name2" + assert config.name2._value == "https://test.com/some-url" assert config.name2.regex == "https://.*" assert config.name2.max_len == 100 - assert config.name3.name == "name3" - assert config.name3.min_val == 5 - assert config.name3.max_val == 27 + assert config.name3._name == "name3" + assert config.name3._min_val == 5 + assert config.name3._max_val == 27 def test_config_loader_no_values_error(): diff --git a/tests/test_intproperty.py b/tests/test_intproperty.py index a393a77..64ff0be 100644 --- a/tests/test_intproperty.py +++ b/tests/test_intproperty.py @@ -16,7 +16,11 @@ def test_int_property(): test_property.type_is_valid() test_property.secondary_validation() - assert test_property + + assert test_property._name == "Test Integer property" + assert test_property._value == 24 + assert test_property.min_val == 0 + assert test_property.max_val == 101 def test_int_property_type_invalid(): diff --git a/tests/test_stringproperty.py b/tests/test_stringproperty.py index c1b48ef..61d8d50 100644 --- a/tests/test_stringproperty.py +++ b/tests/test_stringproperty.py @@ -17,6 +17,12 @@ def test_string_property(): test_property.secondary_validation() + assert test_property._name == "Test String Property" + assert test_property._value == "Test string value" + assert test_property.regex == "Test" + assert test_property.min_len == 1 + assert test_property.max_len == 40 + def test_string_property_empty_val(): """ From ff4e4c359c8da5d74ef92d2f09a0800e69949b04 Mon Sep 17 00:00:00 2001 From: NickPapONS Date: Wed, 7 Feb 2024 11:02:52 +0000 Subject: [PATCH 7/8] Forgot a test --- tests/test_config.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_config.py b/tests/test_config.py index 2c9c5bd..0b8e67d 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -59,8 +59,8 @@ def test_config_loader(monkeypatch): assert config.name2.max_len == 100 assert config.name3._name == "name3" - assert config.name3._min_val == 5 - assert config.name3._max_val == 27 + assert config.name3.min_val == 5 + assert config.name3.max_val == 27 def test_config_loader_no_values_error(): From 1b1dcecbfe44e4a6a948e6a8370818c6bdf6f625 Mon Sep 17 00:00:00 2001 From: NickPapONS Date: Thu, 8 Feb 2024 15:02:37 +0000 Subject: [PATCH 8/8] Addressing new feedback --- .../config/__pycache__/config.cpython-311.pyc | Bin 3574 -> 0 bytes dpytools/config/config.py | 3 ++- .../__pycache__/__init__.cpython-311.pyc | Bin 329 -> 0 bytes .../properties/__pycache__/base.cpython-311.pyc | Bin 1919 -> 0 bytes .../__pycache__/intproperty.cpython-311.pyc | Bin 2200 -> 0 bytes .../__pycache__/string.cpython-311.pyc | Bin 2694 -> 0 bytes dpytools/config/properties/base.py | 8 ++++++++ tests/test_config.py | 16 ++++++++-------- tests/test_intproperty.py | 4 ++-- tests/test_stringproperty.py | 4 ++-- 10 files changed, 22 insertions(+), 13 deletions(-) delete mode 100644 dpytools/config/__pycache__/config.cpython-311.pyc delete mode 100644 dpytools/config/properties/__pycache__/__init__.cpython-311.pyc delete mode 100644 dpytools/config/properties/__pycache__/base.cpython-311.pyc delete mode 100644 dpytools/config/properties/__pycache__/intproperty.cpython-311.pyc delete mode 100644 dpytools/config/properties/__pycache__/string.cpython-311.pyc diff --git a/dpytools/config/__pycache__/config.cpython-311.pyc b/dpytools/config/__pycache__/config.cpython-311.pyc deleted file mode 100644 index 26d410a4f82274a2da4dae66dd802870e360ad6d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3574 zcmbVP|8LvI6+cQO^^LY^J9V5?Rv9}%r=+ovIB|k4bCD&5)2+zXq{A?^8NrCO!$cz0 zBb7#mG#EpE@DKSx1%f$1JHQxPcY}+;KkoPa1C$}a0)YVrivG~w6gd4QzijXEELn6C zAlvEqc=ztzyZ7GRefadvz(A5fxuE^as6y*I>~ssy8r*IX8mmMnI#(nmF3)k;jua#L z2)v`kXo=7BB_S`A#JmV&ye<@DrFcFbw8dhgl*}iCcC45xNqLDQ5i(Eo_(P&6)+2;$ zz{5&@K#$xc+2jw{&2oN9vn<=yT+_Ck>)EIuy=+x|{;FAUef|T}aev^Lob(ILF@8hs zvO(P{%o}>&a*aiU_OS+Uy4185yPN`BkkKf6al2=su}Tb*=X3(zaSus8YVdko7asEK zFt))2f#wBWgi%qCfxQV|ykc7m=3)Wu=@#?~G;_O$ps`98NsXx8F^C|{kV8Cuf<3du6R`S6oNCXF9p7cA-)-EZ51+ zo9?yB?VMgdU9P%!Z0odZ+eHWZRn{m3Cg#{{x?J_+s%l!MtEx*w%>3ytLxLq88OSne z|Lo^0d@Fw33+gU9;HQ`lRfmmuegwDUW5=cMDElqgr(3stks5A=TA`@KK|v6eKLcGQ zZePU05w3GJveq|>E3*=oyGk0|t*<_TXxAh4sJnM+QS$EIz7n$5$K6u`uNs`+@cFCr zHGX;UmvGW+kuTtk|0Nn;>rY%Qsz;CXRJg(IVcmPdDW?Ab34ULK-U#Rg0eT_a ze?|0@;g#yi*P4|&Fe_#85WgfmDR*?=GSC%{VX~I`R$7M>xzRh7btx?Mk_bxwM+Bv? zg&f?JN2~4|`?l!=VF@_j9N^O6^`-O;s4P7y;`vAWbF-8Gwsu;@T(i@XX!LAf_ z1<+Z!Z72(N#nPvJp-|Ku#~1H?rqM;m7bsxx13y+WEwyM^(9j+PjrbnoRkMOGsFqeT zd=YW4Vo*G7^eB=yfv~wS!sbFF%hL%Q%^-OTi2`Kl!uwXirqn2OZFH+;LvhMR!CWxG zi3OV~-9;6!(Ok69q3LXjBG&nW=^7=+kJyeMLx-tt`O!tgrFg;pm}9_4$fa};d!kk@ z8)K<$zWtM_2N%NT-T=Ra_(mdTGI85#e4{PFmTxHC1q zJ#}tt>RfYbwly`|A-TlI+|z(IrMFf-cyi+VV^d!p{U-C*%%=2Dy?N|P>(~`f%CtvM zc%x^q&Q!b`e?S`4=IEJLz~31<)cD<_KYpFr8p?S?x%TMzlkvyzc1Ub^s+~Tz_LDDv zy`9c&rE{CHX8K|)eX;RgJ2SO*?Mr(*b7m`ZW;5H&Txw-5HRfNzZp`nb6`VAQB0#>M zIE9K&w$i8D6FF$MGbf;SQetN0DFN~fNh8^j$;4zJ)=2zYKKw*nOZ@GpO?kE@&wBD~ zTOMo4)7$d-E&2TB-KKoGC13V}x-&f1`0R1!>vy+?&w9gWdkzWU(En=rzR^ds{YEp3 z6T+KdF_33S8nMpcixyvK$}=r_#*=447B4pCxt2WV$#c+vZ9c4c%I}+F`PNw8lk+?B z*vcS9;0%405t-rPb{{}v6*85(@Mh&Ixpfl0#oX(BixJn?df8l81HQxGQNZ$32l64r zoyd}&?4IY#4x~G-;@;7a7?#3P6eWNd<&Necw|l1{bqXYVv*CW+H+8u9cu_zP2u$|| zA(Lb`c>qyDH6507`G*_>?yj!UYBvc3;LAoRUK^SQ;-G7a!mimUzzAq&qAI)eOGlZN z(=Qpjh6;WKWSMl5^-2-jlB#}M(TZ$@4uiZe zIhbS@N(SVOI?bVq86bZr!2*H5fzE&+Bsw>NEcbpLo)hLeq(?*|j&vgDg~J`vB~PQk zd-w_Cmbrv*vO``ZY(0eJ>>wJwP=N#zjHY-%=_C+egiQl{q&#vk2caUehx&Hm(yNCM*8R!OZ&pf?|n(>|l-an6DV)2`!bHKwy&DjLfiEM-l882Mh Config: config._properties_to_validate.append(intprop) else: - raise TypeError("Incorrect value type specified for property assignment.") + prop_type = value["class"] + raise TypeError(f"Unsupported property type specified via 'property' field, got {prop_type}. Should be of type StringProperty or IntegerProperty") return config diff --git a/dpytools/config/properties/__pycache__/__init__.cpython-311.pyc b/dpytools/config/properties/__pycache__/__init__.cpython-311.pyc deleted file mode 100644 index 06e33a73d446581b25fbaa09110fdd2dbfbdd87d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 329 zcmZ3^%ge<81RtL4N%aQOk3k$5V1hC}%K;hF8B!Qh7;_kM8KW2(L2RZRrd;MIW+0n6 zm_d`}B_mLgCgUx>;F6-uy!3#g{DRb?l1iWmzh_=aYIV+zDs^`X>Mv>NwL0r zW{F2>l732oZb4;9Mt+`dNq&A#F_2#gVI=40rDdk;Lru?2E!K~Z&&) diff --git a/dpytools/config/properties/__pycache__/base.cpython-311.pyc b/dpytools/config/properties/__pycache__/base.cpython-311.pyc deleted file mode 100644 index f3828255bd68b596ce51276a39620f86e809755d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1919 zcma)6&2Jk;6rb7ku0NAB)CbanwB^$J&{&+QkXk@(5@C>NpjsqWlii8E&3>4f*&k3jqdIYxVmgg9_>l%9Ixz1i4tJ|q~gfAi+eo0<3VoB3^Fp+=y+ z)BKbFXcF=l4yMgM6;65}?2>>4G$Ju|X>7O##jz2Yamg)d*^I2%cI~+Amg9ld@IH&HKq9w>Fb7O>*mT){l5z`J}I4$RdBXI|$QrPoBYGmvG|J zfVjpc;U+Hy^d4xr1(Km9J21!Of`?^Zep;DsiBVmeuLjm7Z7s0J#H|<6<&6hS@=rzD z=R$$sUczFY+uk!4W!$IJ&7nsbT|T)6uuGnkr_dJ-(nLEgDjG0+N%NBA(Y8c;=e673 zlw8Pm68bxR)=x7f*-j|iAEtg5^F+z^!%#iSw%S4eZhrvzOzx^QjUjcGzwA z3l~E!+gsrAYJZTI(AVMed;qJcLJCQQ5jk4A{=@K~vT_0=;v0yk&4ONsa|eW7qUJ&k z=yUoDu<2KG548KUnQv*!>25IK_ zEJ;!|wP$C>dMVphTsUDO6-!jekSeRds@msRgO7wrMavMF_1w}sON_&D#4>c^4S*|h zun21TF2IQVy|gkRdNB{go{U^-p24r%{gu0 zX9zcdJF3SNz+5t-G~JO-6z=eub*QA1Zfi3?6@vS)WYFi%%%Jms+W;nY=w0aqTSP zPOFhuJbj-%FRyuCoCaCML2h{7*BOhDdoVKLG0T@cPg7K%DLqeMsq@N|)S6|vEx7`w ziV}Lif^ZW-2ZN+32w6u70dJW69$+;0JE|{^)<^3v)(;y?qm9wVi;W{|VPa70#)JSI zo5WrmKPeP8v1{WmQC>4}cFn-)<(UfRn-jyb8WRG5bItKrg`zpt>Zvo(T+rU(vkeb; z@oaZm_1t7zzQ7kj$CuY F{{msF-CqCz diff --git a/dpytools/config/properties/__pycache__/intproperty.cpython-311.pyc b/dpytools/config/properties/__pycache__/intproperty.cpython-311.pyc deleted file mode 100644 index 7bd533ca44b55f8d3ce1d78ac68dd99a6611abd4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2200 zcmaJ?L2nyH6rSRmd@i91y7ly>Lj2(gOz$9Js(QSfd=Gl_Evr)LW`>sCwePU3+CGQOD13-Znz1 zR-=R~DRPZi+6J-uxVEDZvJ3xs?7(BUqmbD?tN$h`q@UtUfrjbnns0lq>3}?7nZ8+e zOevqzcvb(zl>CP9YFzk@a^eJpj{D>5pllOPW~oJHQ@0=#uAWPFa?PSspq-jc;jE=> zU_dJHeoKR}`oiJQT%Rv<(K$5iuiCEhjp=}3uAxxI*g7K(0)}$@Bd~2UK>V)NyW~!y z?SQnKXplYiCV7kako(SHaNz1%nMbcZ)C||G z@t2ut+-B0!`W5LKf z!0wZyj54rD5A@+J^@qWhp5N2+L5H3n438cW3hUkcAbUQ@fARQ(Cm+HC=nw19N-P0y zWoP!XGr_zW=;m`6M+%yQAaiisdTx|F$XreoY#6%cW0bkn$Fai_t zkfVNrpEjN_yU{>AJyd$}v)+R^@lLm|ZY)+J58~zCl{393h(F~$S*b*l7<*~#>S^y- z!f_cl>j^|lo*RR95n73b0L21;mctreomK7S6`!q|E+E@WY((8<=CWzK0BV!PFsh5# zDn@uz6}Ds*+qEVWyJohHpmrTBd4e@ZnB{TFuuAxvE&a*nn+z-+Z;9*X3 zxQk_qMhy7qLd}Vjs6T5L0#QB!hTtb7xy^48-8bk#HXn?aew+CHU3kRQ%1-ZPrvrWZ zaBz5Y3bz^b!Ihsse?0Nzy?^qTg8Ze(Xf8II3&xRJ+4;Tfe4x)KMhj;d&BsRb!8lSY zYwTr>KsT^p7NUAvpx__q7(ykbLOM(vQHL>%Fk={1&#F5dWZf{nuA2__9>Wk=B0>ii z4jV?)&!WsoSb7DQUIX?k5wD|+i4@rNBZj3XzXEo@>vuTx>Q;GkE>OpSTI$&T3H?Y- zYuFvScuv}FrHZ|^oM=Wlx%l73OXE2zL;DJteQ|om<#-b$5G}{N+N%eo{Dqu zv0$)(*pS}?g9K8#PtFIuv`;Psy|ho>2zu#|W{y&06vIE8Z#mDRmH#6COd+YkjdQ0> Hq9FeV8QUvP diff --git a/dpytools/config/properties/__pycache__/string.cpython-311.pyc b/dpytools/config/properties/__pycache__/string.cpython-311.pyc deleted file mode 100644 index 98cdffb7601895d67b58ddf9589234e7375aeca8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2694 zcma)8L2naB6rT0&I(F>fGzn?Ip&6G5$x=x!TxdfjN)bIkS}7!I-6YH6o!FaQ@0yu4 ziCw57#DPN&IiP|>kx+$Fs&L@Ip$9JQFIXcVqLm^=s(RpNL|Y+FeY0zCZ5l<4$8X=v zy!YnKoAp+ESb-J&h#)gmx=kcKqDL?t072%L|Yk&>7bffqH& zluB|=_UC0Ynu`)Kg3ci=dJ}0qMBWq;+Jb-3HsP_=9-v&0CeNU3>;<363SR8XvZLFU zY62hER7cI5Dq}B%U^V%f%E(vLE)(ihr}Lo|VA}Ru-V&4(G?a_XA|ev$P$)@cO_+ia z%tpIrBYVz@d{&cg`hEh9X;JXD$2&0NP~9rDUGZc}3S`ymDe0DC5(^l0l{0znc)P`b z;cmYA0mvN`M^4A;HMAU#Hi6p;M-WzN1|3C?)Ha0BIHJd{3l3aayJ-SgXa@n^gA3}k z2xIZS+->)oa3i8g*M;we6=4Ofir=6WAuHFu?!~P(rIMm=b%$Yl$rsDpl#)ECRLca10=48B)v{~{=T+w5S`WUeniYa;3GCRI`SF~X&PtvL zycbpcRWE*aHBbDM@FYtuk!-}17%`VTkx`rlCf*mjGwTM=#V}jxNhiUr1Z}wuE2vYZ zGgmiZ&n_VpqPUW6KZd7<^p01R`GtyRKeoVKl?JTC*HYP=MAsRQ!js$Ib)y-;-U zifTa(+o2AvSXeEnx&`H{;-F+IG|&oa*{^?{VMDjHiU0KYW!5-kwn~1kYc^q+qeMw{@CUb=EphE{`eyF`^;0X628}p*@UV$$R{~%r> z{1PIJa!~LjUbmEEDIMX&_xwZ7g{OHFn+k&SDLn=Y{Ck3}1A#Y(AZ(+w+ugTO#_jIg r=mWRA@1ppc|JxOMn~`yWpJi{lG5^wE`OBv-MHETgJoJAR-`jryWsjJ< diff --git a/dpytools/config/properties/base.py b/dpytools/config/properties/base.py index f323dad..a5cfe2b 100644 --- a/dpytools/config/properties/base.py +++ b/dpytools/config/properties/base.py @@ -15,6 +15,14 @@ def name(self): def name(self, value): raise ValueError(f"Trying to change name property to value {value} but you cannot change a property name after instantiation.") + @property + def value(self): + return self._value + + @value.setter + def value(self, value): + raise ValueError(f"Trying to change value to {value} but you cannot change a property value after instantiation.") + @abstractmethod def type_is_valid(self): """ diff --git a/tests/test_config.py b/tests/test_config.py index 0b8e67d..3f8934c 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -22,7 +22,7 @@ def test_config_loader(monkeypatch): "class": StringProperty, "property": "name1", "kwargs": { - "regex": "I match a thing", + "regex": "string value", "min_len": 10 }, }, @@ -48,17 +48,17 @@ def test_config_loader(monkeypatch): # Assertions - assert config.name1._name == "name1" - assert config.name1._value == "Some string value" + assert config.name1.name == "name1" + assert config.name1.value == "Some string value" assert config.name1.min_len == 10 - assert config.name1.regex == "I match a thing" + assert config.name1.regex == "string value" - assert config.name2._name == "name2" - assert config.name2._value == "https://test.com/some-url" + assert config.name2.name == "name2" + assert config.name2.value == "https://test.com/some-url" assert config.name2.regex == "https://.*" assert config.name2.max_len == 100 - assert config.name3._name == "name3" + assert config.name3.name == "name3" assert config.name3.min_val == 5 assert config.name3.max_val == 27 @@ -113,4 +113,4 @@ def test_config_loader_incorrect_type_error(monkeypatch): config = Config.from_env(config_dictionary) - assert "Incorrect value type specified for property assignment." in str(e.value) \ No newline at end of file + assert "Unsupported property type specified via 'property' field, got . Should be of type StringProperty or IntegerProperty" in str(e.value) \ No newline at end of file diff --git a/tests/test_intproperty.py b/tests/test_intproperty.py index 64ff0be..04efea6 100644 --- a/tests/test_intproperty.py +++ b/tests/test_intproperty.py @@ -17,8 +17,8 @@ def test_int_property(): test_property.type_is_valid() test_property.secondary_validation() - assert test_property._name == "Test Integer property" - assert test_property._value == 24 + assert test_property.name == "Test Integer property" + assert test_property.value == 24 assert test_property.min_val == 0 assert test_property.max_val == 101 diff --git a/tests/test_stringproperty.py b/tests/test_stringproperty.py index 61d8d50..a976980 100644 --- a/tests/test_stringproperty.py +++ b/tests/test_stringproperty.py @@ -17,8 +17,8 @@ def test_string_property(): test_property.secondary_validation() - assert test_property._name == "Test String Property" - assert test_property._value == "Test string value" + assert test_property.name == "Test String Property" + assert test_property.value == "Test string value" assert test_property.regex == "Test" assert test_property.min_len == 1 assert test_property.max_len == 40