test_dataclasses.py 134 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292
  1. # Deliberately use "from dataclasses import *". Every name in __all__
  2. # is tested, so they all must be present. This is a way to catch
  3. # missing ones.
  4. from dataclasses import *
  5. import abc
  6. import pickle
  7. import inspect
  8. import builtins
  9. import types
  10. import weakref
  11. import unittest
  12. from unittest.mock import Mock
  13. from typing import ClassVar, Any, List, Union, Tuple, Dict, Generic, TypeVar, Optional, Protocol
  14. from typing import get_type_hints
  15. from collections import deque, OrderedDict, namedtuple
  16. from functools import total_ordering
  17. import typing # Needed for the string "typing.ClassVar[int]" to work as an annotation.
  18. import dataclasses # Needed for the string "dataclasses.InitVar[int]" to work as an annotation.
  19. # Just any custom exception we can catch.
  20. class CustomError(Exception): pass
  21. class TestCase(unittest.TestCase):
  22. def test_no_fields(self):
  23. @dataclass
  24. class C:
  25. pass
  26. o = C()
  27. self.assertEqual(len(fields(C)), 0)
  28. def test_no_fields_but_member_variable(self):
  29. @dataclass
  30. class C:
  31. i = 0
  32. o = C()
  33. self.assertEqual(len(fields(C)), 0)
  34. def test_one_field_no_default(self):
  35. @dataclass
  36. class C:
  37. x: int
  38. o = C(42)
  39. self.assertEqual(o.x, 42)
  40. def test_field_default_default_factory_error(self):
  41. msg = "cannot specify both default and default_factory"
  42. with self.assertRaisesRegex(ValueError, msg):
  43. @dataclass
  44. class C:
  45. x: int = field(default=1, default_factory=int)
  46. def test_field_repr(self):
  47. int_field = field(default=1, init=True, repr=False)
  48. int_field.name = "id"
  49. repr_output = repr(int_field)
  50. expected_output = "Field(name='id',type=None," \
  51. f"default=1,default_factory={MISSING!r}," \
  52. "init=True,repr=False,hash=None," \
  53. "compare=True,metadata=mappingproxy({})," \
  54. f"kw_only={MISSING!r}," \
  55. "_field_type=None)"
  56. self.assertEqual(repr_output, expected_output)
  57. def test_field_recursive_repr(self):
  58. rec_field = field()
  59. rec_field.type = rec_field
  60. rec_field.name = "id"
  61. repr_output = repr(rec_field)
  62. self.assertIn(",type=...,", repr_output)
  63. def test_recursive_annotation(self):
  64. class C:
  65. pass
  66. @dataclass
  67. class D:
  68. C: C = field()
  69. self.assertIn(",type=...,", repr(D.__dataclass_fields__["C"]))
  70. def test_named_init_params(self):
  71. @dataclass
  72. class C:
  73. x: int
  74. o = C(x=32)
  75. self.assertEqual(o.x, 32)
  76. def test_two_fields_one_default(self):
  77. @dataclass
  78. class C:
  79. x: int
  80. y: int = 0
  81. o = C(3)
  82. self.assertEqual((o.x, o.y), (3, 0))
  83. # Non-defaults following defaults.
  84. with self.assertRaisesRegex(TypeError,
  85. "non-default argument 'y' follows "
  86. "default argument"):
  87. @dataclass
  88. class C:
  89. x: int = 0
  90. y: int
  91. # A derived class adds a non-default field after a default one.
  92. with self.assertRaisesRegex(TypeError,
  93. "non-default argument 'y' follows "
  94. "default argument"):
  95. @dataclass
  96. class B:
  97. x: int = 0
  98. @dataclass
  99. class C(B):
  100. y: int
  101. # Override a base class field and add a default to
  102. # a field which didn't use to have a default.
  103. with self.assertRaisesRegex(TypeError,
  104. "non-default argument 'y' follows "
  105. "default argument"):
  106. @dataclass
  107. class B:
  108. x: int
  109. y: int
  110. @dataclass
  111. class C(B):
  112. x: int = 0
  113. def test_overwrite_hash(self):
  114. # Test that declaring this class isn't an error. It should
  115. # use the user-provided __hash__.
  116. @dataclass(frozen=True)
  117. class C:
  118. x: int
  119. def __hash__(self):
  120. return 301
  121. self.assertEqual(hash(C(100)), 301)
  122. # Test that declaring this class isn't an error. It should
  123. # use the generated __hash__.
  124. @dataclass(frozen=True)
  125. class C:
  126. x: int
  127. def __eq__(self, other):
  128. return False
  129. self.assertEqual(hash(C(100)), hash((100,)))
  130. # But this one should generate an exception, because with
  131. # unsafe_hash=True, it's an error to have a __hash__ defined.
  132. with self.assertRaisesRegex(TypeError,
  133. 'Cannot overwrite attribute __hash__'):
  134. @dataclass(unsafe_hash=True)
  135. class C:
  136. def __hash__(self):
  137. pass
  138. # Creating this class should not generate an exception,
  139. # because even though __hash__ exists before @dataclass is
  140. # called, (due to __eq__ being defined), since it's None
  141. # that's okay.
  142. @dataclass(unsafe_hash=True)
  143. class C:
  144. x: int
  145. def __eq__(self):
  146. pass
  147. # The generated hash function works as we'd expect.
  148. self.assertEqual(hash(C(10)), hash((10,)))
  149. # Creating this class should generate an exception, because
  150. # __hash__ exists and is not None, which it would be if it
  151. # had been auto-generated due to __eq__ being defined.
  152. with self.assertRaisesRegex(TypeError,
  153. 'Cannot overwrite attribute __hash__'):
  154. @dataclass(unsafe_hash=True)
  155. class C:
  156. x: int
  157. def __eq__(self):
  158. pass
  159. def __hash__(self):
  160. pass
  161. def test_overwrite_fields_in_derived_class(self):
  162. # Note that x from C1 replaces x in Base, but the order remains
  163. # the same as defined in Base.
  164. @dataclass
  165. class Base:
  166. x: Any = 15.0
  167. y: int = 0
  168. @dataclass
  169. class C1(Base):
  170. z: int = 10
  171. x: int = 15
  172. o = Base()
  173. self.assertEqual(repr(o), 'TestCase.test_overwrite_fields_in_derived_class.<locals>.Base(x=15.0, y=0)')
  174. o = C1()
  175. self.assertEqual(repr(o), 'TestCase.test_overwrite_fields_in_derived_class.<locals>.C1(x=15, y=0, z=10)')
  176. o = C1(x=5)
  177. self.assertEqual(repr(o), 'TestCase.test_overwrite_fields_in_derived_class.<locals>.C1(x=5, y=0, z=10)')
  178. def test_field_named_self(self):
  179. @dataclass
  180. class C:
  181. self: str
  182. c=C('foo')
  183. self.assertEqual(c.self, 'foo')
  184. # Make sure the first parameter is not named 'self'.
  185. sig = inspect.signature(C.__init__)
  186. first = next(iter(sig.parameters))
  187. self.assertNotEqual('self', first)
  188. # But we do use 'self' if no field named self.
  189. @dataclass
  190. class C:
  191. selfx: str
  192. # Make sure the first parameter is named 'self'.
  193. sig = inspect.signature(C.__init__)
  194. first = next(iter(sig.parameters))
  195. self.assertEqual('self', first)
  196. def test_field_named_object(self):
  197. @dataclass
  198. class C:
  199. object: str
  200. c = C('foo')
  201. self.assertEqual(c.object, 'foo')
  202. def test_field_named_object_frozen(self):
  203. @dataclass(frozen=True)
  204. class C:
  205. object: str
  206. c = C('foo')
  207. self.assertEqual(c.object, 'foo')
  208. def test_field_named_BUILTINS_frozen(self):
  209. # gh-96151
  210. @dataclass(frozen=True)
  211. class C:
  212. BUILTINS: int
  213. c = C(5)
  214. self.assertEqual(c.BUILTINS, 5)
  215. def test_field_named_like_builtin(self):
  216. # Attribute names can shadow built-in names
  217. # since code generation is used.
  218. # Ensure that this is not happening.
  219. exclusions = {'None', 'True', 'False'}
  220. builtins_names = sorted(
  221. b for b in builtins.__dict__.keys()
  222. if not b.startswith('__') and b not in exclusions
  223. )
  224. attributes = [(name, str) for name in builtins_names]
  225. C = make_dataclass('C', attributes)
  226. c = C(*[name for name in builtins_names])
  227. for name in builtins_names:
  228. self.assertEqual(getattr(c, name), name)
  229. def test_field_named_like_builtin_frozen(self):
  230. # Attribute names can shadow built-in names
  231. # since code generation is used.
  232. # Ensure that this is not happening
  233. # for frozen data classes.
  234. exclusions = {'None', 'True', 'False'}
  235. builtins_names = sorted(
  236. b for b in builtins.__dict__.keys()
  237. if not b.startswith('__') and b not in exclusions
  238. )
  239. attributes = [(name, str) for name in builtins_names]
  240. C = make_dataclass('C', attributes, frozen=True)
  241. c = C(*[name for name in builtins_names])
  242. for name in builtins_names:
  243. self.assertEqual(getattr(c, name), name)
  244. def test_0_field_compare(self):
  245. # Ensure that order=False is the default.
  246. @dataclass
  247. class C0:
  248. pass
  249. @dataclass(order=False)
  250. class C1:
  251. pass
  252. for cls in [C0, C1]:
  253. with self.subTest(cls=cls):
  254. self.assertEqual(cls(), cls())
  255. for idx, fn in enumerate([lambda a, b: a < b,
  256. lambda a, b: a <= b,
  257. lambda a, b: a > b,
  258. lambda a, b: a >= b]):
  259. with self.subTest(idx=idx):
  260. with self.assertRaisesRegex(TypeError,
  261. f"not supported between instances of '{cls.__name__}' and '{cls.__name__}'"):
  262. fn(cls(), cls())
  263. @dataclass(order=True)
  264. class C:
  265. pass
  266. self.assertLessEqual(C(), C())
  267. self.assertGreaterEqual(C(), C())
  268. def test_1_field_compare(self):
  269. # Ensure that order=False is the default.
  270. @dataclass
  271. class C0:
  272. x: int
  273. @dataclass(order=False)
  274. class C1:
  275. x: int
  276. for cls in [C0, C1]:
  277. with self.subTest(cls=cls):
  278. self.assertEqual(cls(1), cls(1))
  279. self.assertNotEqual(cls(0), cls(1))
  280. for idx, fn in enumerate([lambda a, b: a < b,
  281. lambda a, b: a <= b,
  282. lambda a, b: a > b,
  283. lambda a, b: a >= b]):
  284. with self.subTest(idx=idx):
  285. with self.assertRaisesRegex(TypeError,
  286. f"not supported between instances of '{cls.__name__}' and '{cls.__name__}'"):
  287. fn(cls(0), cls(0))
  288. @dataclass(order=True)
  289. class C:
  290. x: int
  291. self.assertLess(C(0), C(1))
  292. self.assertLessEqual(C(0), C(1))
  293. self.assertLessEqual(C(1), C(1))
  294. self.assertGreater(C(1), C(0))
  295. self.assertGreaterEqual(C(1), C(0))
  296. self.assertGreaterEqual(C(1), C(1))
  297. def test_simple_compare(self):
  298. # Ensure that order=False is the default.
  299. @dataclass
  300. class C0:
  301. x: int
  302. y: int
  303. @dataclass(order=False)
  304. class C1:
  305. x: int
  306. y: int
  307. for cls in [C0, C1]:
  308. with self.subTest(cls=cls):
  309. self.assertEqual(cls(0, 0), cls(0, 0))
  310. self.assertEqual(cls(1, 2), cls(1, 2))
  311. self.assertNotEqual(cls(1, 0), cls(0, 0))
  312. self.assertNotEqual(cls(1, 0), cls(1, 1))
  313. for idx, fn in enumerate([lambda a, b: a < b,
  314. lambda a, b: a <= b,
  315. lambda a, b: a > b,
  316. lambda a, b: a >= b]):
  317. with self.subTest(idx=idx):
  318. with self.assertRaisesRegex(TypeError,
  319. f"not supported between instances of '{cls.__name__}' and '{cls.__name__}'"):
  320. fn(cls(0, 0), cls(0, 0))
  321. @dataclass(order=True)
  322. class C:
  323. x: int
  324. y: int
  325. for idx, fn in enumerate([lambda a, b: a == b,
  326. lambda a, b: a <= b,
  327. lambda a, b: a >= b]):
  328. with self.subTest(idx=idx):
  329. self.assertTrue(fn(C(0, 0), C(0, 0)))
  330. for idx, fn in enumerate([lambda a, b: a < b,
  331. lambda a, b: a <= b,
  332. lambda a, b: a != b]):
  333. with self.subTest(idx=idx):
  334. self.assertTrue(fn(C(0, 0), C(0, 1)))
  335. self.assertTrue(fn(C(0, 1), C(1, 0)))
  336. self.assertTrue(fn(C(1, 0), C(1, 1)))
  337. for idx, fn in enumerate([lambda a, b: a > b,
  338. lambda a, b: a >= b,
  339. lambda a, b: a != b]):
  340. with self.subTest(idx=idx):
  341. self.assertTrue(fn(C(0, 1), C(0, 0)))
  342. self.assertTrue(fn(C(1, 0), C(0, 1)))
  343. self.assertTrue(fn(C(1, 1), C(1, 0)))
  344. def test_compare_subclasses(self):
  345. # Comparisons fail for subclasses, even if no fields
  346. # are added.
  347. @dataclass
  348. class B:
  349. i: int
  350. @dataclass
  351. class C(B):
  352. pass
  353. for idx, (fn, expected) in enumerate([(lambda a, b: a == b, False),
  354. (lambda a, b: a != b, True)]):
  355. with self.subTest(idx=idx):
  356. self.assertEqual(fn(B(0), C(0)), expected)
  357. for idx, fn in enumerate([lambda a, b: a < b,
  358. lambda a, b: a <= b,
  359. lambda a, b: a > b,
  360. lambda a, b: a >= b]):
  361. with self.subTest(idx=idx):
  362. with self.assertRaisesRegex(TypeError,
  363. "not supported between instances of 'B' and 'C'"):
  364. fn(B(0), C(0))
  365. def test_eq_order(self):
  366. # Test combining eq and order.
  367. for (eq, order, result ) in [
  368. (False, False, 'neither'),
  369. (False, True, 'exception'),
  370. (True, False, 'eq_only'),
  371. (True, True, 'both'),
  372. ]:
  373. with self.subTest(eq=eq, order=order):
  374. if result == 'exception':
  375. with self.assertRaisesRegex(ValueError, 'eq must be true if order is true'):
  376. @dataclass(eq=eq, order=order)
  377. class C:
  378. pass
  379. else:
  380. @dataclass(eq=eq, order=order)
  381. class C:
  382. pass
  383. if result == 'neither':
  384. self.assertNotIn('__eq__', C.__dict__)
  385. self.assertNotIn('__lt__', C.__dict__)
  386. self.assertNotIn('__le__', C.__dict__)
  387. self.assertNotIn('__gt__', C.__dict__)
  388. self.assertNotIn('__ge__', C.__dict__)
  389. elif result == 'both':
  390. self.assertIn('__eq__', C.__dict__)
  391. self.assertIn('__lt__', C.__dict__)
  392. self.assertIn('__le__', C.__dict__)
  393. self.assertIn('__gt__', C.__dict__)
  394. self.assertIn('__ge__', C.__dict__)
  395. elif result == 'eq_only':
  396. self.assertIn('__eq__', C.__dict__)
  397. self.assertNotIn('__lt__', C.__dict__)
  398. self.assertNotIn('__le__', C.__dict__)
  399. self.assertNotIn('__gt__', C.__dict__)
  400. self.assertNotIn('__ge__', C.__dict__)
  401. else:
  402. assert False, f'unknown result {result!r}'
  403. def test_field_no_default(self):
  404. @dataclass
  405. class C:
  406. x: int = field()
  407. self.assertEqual(C(5).x, 5)
  408. with self.assertRaisesRegex(TypeError,
  409. r"__init__\(\) missing 1 required "
  410. "positional argument: 'x'"):
  411. C()
  412. def test_field_default(self):
  413. default = object()
  414. @dataclass
  415. class C:
  416. x: object = field(default=default)
  417. self.assertIs(C.x, default)
  418. c = C(10)
  419. self.assertEqual(c.x, 10)
  420. # If we delete the instance attribute, we should then see the
  421. # class attribute.
  422. del c.x
  423. self.assertIs(c.x, default)
  424. self.assertIs(C().x, default)
  425. def test_not_in_repr(self):
  426. @dataclass
  427. class C:
  428. x: int = field(repr=False)
  429. with self.assertRaises(TypeError):
  430. C()
  431. c = C(10)
  432. self.assertEqual(repr(c), 'TestCase.test_not_in_repr.<locals>.C()')
  433. @dataclass
  434. class C:
  435. x: int = field(repr=False)
  436. y: int
  437. c = C(10, 20)
  438. self.assertEqual(repr(c), 'TestCase.test_not_in_repr.<locals>.C(y=20)')
  439. def test_not_in_compare(self):
  440. @dataclass
  441. class C:
  442. x: int = 0
  443. y: int = field(compare=False, default=4)
  444. self.assertEqual(C(), C(0, 20))
  445. self.assertEqual(C(1, 10), C(1, 20))
  446. self.assertNotEqual(C(3), C(4, 10))
  447. self.assertNotEqual(C(3, 10), C(4, 10))
  448. def test_no_unhashable_default(self):
  449. # See bpo-44674.
  450. class Unhashable:
  451. __hash__ = None
  452. unhashable_re = 'mutable default .* for field a is not allowed'
  453. with self.assertRaisesRegex(ValueError, unhashable_re):
  454. @dataclass
  455. class A:
  456. a: dict = {}
  457. with self.assertRaisesRegex(ValueError, unhashable_re):
  458. @dataclass
  459. class A:
  460. a: Any = Unhashable()
  461. # Make sure that the machinery looking for hashability is using the
  462. # class's __hash__, not the instance's __hash__.
  463. with self.assertRaisesRegex(ValueError, unhashable_re):
  464. unhashable = Unhashable()
  465. # This shouldn't make the variable hashable.
  466. unhashable.__hash__ = lambda: 0
  467. @dataclass
  468. class A:
  469. a: Any = unhashable
  470. def test_hash_field_rules(self):
  471. # Test all 6 cases of:
  472. # hash=True/False/None
  473. # compare=True/False
  474. for (hash_, compare, result ) in [
  475. (True, False, 'field' ),
  476. (True, True, 'field' ),
  477. (False, False, 'absent'),
  478. (False, True, 'absent'),
  479. (None, False, 'absent'),
  480. (None, True, 'field' ),
  481. ]:
  482. with self.subTest(hash=hash_, compare=compare):
  483. @dataclass(unsafe_hash=True)
  484. class C:
  485. x: int = field(compare=compare, hash=hash_, default=5)
  486. if result == 'field':
  487. # __hash__ contains the field.
  488. self.assertEqual(hash(C(5)), hash((5,)))
  489. elif result == 'absent':
  490. # The field is not present in the hash.
  491. self.assertEqual(hash(C(5)), hash(()))
  492. else:
  493. assert False, f'unknown result {result!r}'
  494. def test_init_false_no_default(self):
  495. # If init=False and no default value, then the field won't be
  496. # present in the instance.
  497. @dataclass
  498. class C:
  499. x: int = field(init=False)
  500. self.assertNotIn('x', C().__dict__)
  501. @dataclass
  502. class C:
  503. x: int
  504. y: int = 0
  505. z: int = field(init=False)
  506. t: int = 10
  507. self.assertNotIn('z', C(0).__dict__)
  508. self.assertEqual(vars(C(5)), {'t': 10, 'x': 5, 'y': 0})
  509. def test_class_marker(self):
  510. @dataclass
  511. class C:
  512. x: int
  513. y: str = field(init=False, default=None)
  514. z: str = field(repr=False)
  515. the_fields = fields(C)
  516. # the_fields is a tuple of 3 items, each value
  517. # is in __annotations__.
  518. self.assertIsInstance(the_fields, tuple)
  519. for f in the_fields:
  520. self.assertIs(type(f), Field)
  521. self.assertIn(f.name, C.__annotations__)
  522. self.assertEqual(len(the_fields), 3)
  523. self.assertEqual(the_fields[0].name, 'x')
  524. self.assertEqual(the_fields[0].type, int)
  525. self.assertFalse(hasattr(C, 'x'))
  526. self.assertTrue (the_fields[0].init)
  527. self.assertTrue (the_fields[0].repr)
  528. self.assertEqual(the_fields[1].name, 'y')
  529. self.assertEqual(the_fields[1].type, str)
  530. self.assertIsNone(getattr(C, 'y'))
  531. self.assertFalse(the_fields[1].init)
  532. self.assertTrue (the_fields[1].repr)
  533. self.assertEqual(the_fields[2].name, 'z')
  534. self.assertEqual(the_fields[2].type, str)
  535. self.assertFalse(hasattr(C, 'z'))
  536. self.assertTrue (the_fields[2].init)
  537. self.assertFalse(the_fields[2].repr)
  538. def test_field_order(self):
  539. @dataclass
  540. class B:
  541. a: str = 'B:a'
  542. b: str = 'B:b'
  543. c: str = 'B:c'
  544. @dataclass
  545. class C(B):
  546. b: str = 'C:b'
  547. self.assertEqual([(f.name, f.default) for f in fields(C)],
  548. [('a', 'B:a'),
  549. ('b', 'C:b'),
  550. ('c', 'B:c')])
  551. @dataclass
  552. class D(B):
  553. c: str = 'D:c'
  554. self.assertEqual([(f.name, f.default) for f in fields(D)],
  555. [('a', 'B:a'),
  556. ('b', 'B:b'),
  557. ('c', 'D:c')])
  558. @dataclass
  559. class E(D):
  560. a: str = 'E:a'
  561. d: str = 'E:d'
  562. self.assertEqual([(f.name, f.default) for f in fields(E)],
  563. [('a', 'E:a'),
  564. ('b', 'B:b'),
  565. ('c', 'D:c'),
  566. ('d', 'E:d')])
  567. def test_class_attrs(self):
  568. # We only have a class attribute if a default value is
  569. # specified, either directly or via a field with a default.
  570. default = object()
  571. @dataclass
  572. class C:
  573. x: int
  574. y: int = field(repr=False)
  575. z: object = default
  576. t: int = field(default=100)
  577. self.assertFalse(hasattr(C, 'x'))
  578. self.assertFalse(hasattr(C, 'y'))
  579. self.assertIs (C.z, default)
  580. self.assertEqual(C.t, 100)
  581. def test_disallowed_mutable_defaults(self):
  582. # For the known types, don't allow mutable default values.
  583. for typ, empty, non_empty in [(list, [], [1]),
  584. (dict, {}, {0:1}),
  585. (set, set(), set([1])),
  586. ]:
  587. with self.subTest(typ=typ):
  588. # Can't use a zero-length value.
  589. with self.assertRaisesRegex(ValueError,
  590. f'mutable default {typ} for field '
  591. 'x is not allowed'):
  592. @dataclass
  593. class Point:
  594. x: typ = empty
  595. # Nor a non-zero-length value
  596. with self.assertRaisesRegex(ValueError,
  597. f'mutable default {typ} for field '
  598. 'y is not allowed'):
  599. @dataclass
  600. class Point:
  601. y: typ = non_empty
  602. # Check subtypes also fail.
  603. class Subclass(typ): pass
  604. with self.assertRaisesRegex(ValueError,
  605. f"mutable default .*Subclass'>"
  606. ' for field z is not allowed'
  607. ):
  608. @dataclass
  609. class Point:
  610. z: typ = Subclass()
  611. # Because this is a ClassVar, it can be mutable.
  612. @dataclass
  613. class C:
  614. z: ClassVar[typ] = typ()
  615. # Because this is a ClassVar, it can be mutable.
  616. @dataclass
  617. class C:
  618. x: ClassVar[typ] = Subclass()
  619. def test_deliberately_mutable_defaults(self):
  620. # If a mutable default isn't in the known list of
  621. # (list, dict, set), then it's okay.
  622. class Mutable:
  623. def __init__(self):
  624. self.l = []
  625. @dataclass
  626. class C:
  627. x: Mutable
  628. # These 2 instances will share this value of x.
  629. lst = Mutable()
  630. o1 = C(lst)
  631. o2 = C(lst)
  632. self.assertEqual(o1, o2)
  633. o1.x.l.extend([1, 2])
  634. self.assertEqual(o1, o2)
  635. self.assertEqual(o1.x.l, [1, 2])
  636. self.assertIs(o1.x, o2.x)
  637. def test_no_options(self):
  638. # Call with dataclass().
  639. @dataclass()
  640. class C:
  641. x: int
  642. self.assertEqual(C(42).x, 42)
  643. def test_not_tuple(self):
  644. # Make sure we can't be compared to a tuple.
  645. @dataclass
  646. class Point:
  647. x: int
  648. y: int
  649. self.assertNotEqual(Point(1, 2), (1, 2))
  650. # And that we can't compare to another unrelated dataclass.
  651. @dataclass
  652. class C:
  653. x: int
  654. y: int
  655. self.assertNotEqual(Point(1, 3), C(1, 3))
  656. def test_not_other_dataclass(self):
  657. # Test that some of the problems with namedtuple don't happen
  658. # here.
  659. @dataclass
  660. class Point3D:
  661. x: int
  662. y: int
  663. z: int
  664. @dataclass
  665. class Date:
  666. year: int
  667. month: int
  668. day: int
  669. self.assertNotEqual(Point3D(2017, 6, 3), Date(2017, 6, 3))
  670. self.assertNotEqual(Point3D(1, 2, 3), (1, 2, 3))
  671. # Make sure we can't unpack.
  672. with self.assertRaisesRegex(TypeError, 'unpack'):
  673. x, y, z = Point3D(4, 5, 6)
  674. # Make sure another class with the same field names isn't
  675. # equal.
  676. @dataclass
  677. class Point3Dv1:
  678. x: int = 0
  679. y: int = 0
  680. z: int = 0
  681. self.assertNotEqual(Point3D(0, 0, 0), Point3Dv1())
  682. def test_function_annotations(self):
  683. # Some dummy class and instance to use as a default.
  684. class F:
  685. pass
  686. f = F()
  687. def validate_class(cls):
  688. # First, check __annotations__, even though they're not
  689. # function annotations.
  690. self.assertEqual(cls.__annotations__['i'], int)
  691. self.assertEqual(cls.__annotations__['j'], str)
  692. self.assertEqual(cls.__annotations__['k'], F)
  693. self.assertEqual(cls.__annotations__['l'], float)
  694. self.assertEqual(cls.__annotations__['z'], complex)
  695. # Verify __init__.
  696. signature = inspect.signature(cls.__init__)
  697. # Check the return type, should be None.
  698. self.assertIs(signature.return_annotation, None)
  699. # Check each parameter.
  700. params = iter(signature.parameters.values())
  701. param = next(params)
  702. # This is testing an internal name, and probably shouldn't be tested.
  703. self.assertEqual(param.name, 'self')
  704. param = next(params)
  705. self.assertEqual(param.name, 'i')
  706. self.assertIs (param.annotation, int)
  707. self.assertEqual(param.default, inspect.Parameter.empty)
  708. self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_OR_KEYWORD)
  709. param = next(params)
  710. self.assertEqual(param.name, 'j')
  711. self.assertIs (param.annotation, str)
  712. self.assertEqual(param.default, inspect.Parameter.empty)
  713. self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_OR_KEYWORD)
  714. param = next(params)
  715. self.assertEqual(param.name, 'k')
  716. self.assertIs (param.annotation, F)
  717. # Don't test for the default, since it's set to MISSING.
  718. self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_OR_KEYWORD)
  719. param = next(params)
  720. self.assertEqual(param.name, 'l')
  721. self.assertIs (param.annotation, float)
  722. # Don't test for the default, since it's set to MISSING.
  723. self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_OR_KEYWORD)
  724. self.assertRaises(StopIteration, next, params)
  725. @dataclass
  726. class C:
  727. i: int
  728. j: str
  729. k: F = f
  730. l: float=field(default=None)
  731. z: complex=field(default=3+4j, init=False)
  732. validate_class(C)
  733. # Now repeat with __hash__.
  734. @dataclass(frozen=True, unsafe_hash=True)
  735. class C:
  736. i: int
  737. j: str
  738. k: F = f
  739. l: float=field(default=None)
  740. z: complex=field(default=3+4j, init=False)
  741. validate_class(C)
  742. def test_missing_default(self):
  743. # Test that MISSING works the same as a default not being
  744. # specified.
  745. @dataclass
  746. class C:
  747. x: int=field(default=MISSING)
  748. with self.assertRaisesRegex(TypeError,
  749. r'__init__\(\) missing 1 required '
  750. 'positional argument'):
  751. C()
  752. self.assertNotIn('x', C.__dict__)
  753. @dataclass
  754. class D:
  755. x: int
  756. with self.assertRaisesRegex(TypeError,
  757. r'__init__\(\) missing 1 required '
  758. 'positional argument'):
  759. D()
  760. self.assertNotIn('x', D.__dict__)
  761. def test_missing_default_factory(self):
  762. # Test that MISSING works the same as a default factory not
  763. # being specified (which is really the same as a default not
  764. # being specified, too).
  765. @dataclass
  766. class C:
  767. x: int=field(default_factory=MISSING)
  768. with self.assertRaisesRegex(TypeError,
  769. r'__init__\(\) missing 1 required '
  770. 'positional argument'):
  771. C()
  772. self.assertNotIn('x', C.__dict__)
  773. @dataclass
  774. class D:
  775. x: int=field(default=MISSING, default_factory=MISSING)
  776. with self.assertRaisesRegex(TypeError,
  777. r'__init__\(\) missing 1 required '
  778. 'positional argument'):
  779. D()
  780. self.assertNotIn('x', D.__dict__)
  781. def test_missing_repr(self):
  782. self.assertIn('MISSING_TYPE object', repr(MISSING))
  783. def test_dont_include_other_annotations(self):
  784. @dataclass
  785. class C:
  786. i: int
  787. def foo(self) -> int:
  788. return 4
  789. @property
  790. def bar(self) -> int:
  791. return 5
  792. self.assertEqual(list(C.__annotations__), ['i'])
  793. self.assertEqual(C(10).foo(), 4)
  794. self.assertEqual(C(10).bar, 5)
  795. self.assertEqual(C(10).i, 10)
  796. def test_post_init(self):
  797. # Just make sure it gets called
  798. @dataclass
  799. class C:
  800. def __post_init__(self):
  801. raise CustomError()
  802. with self.assertRaises(CustomError):
  803. C()
  804. @dataclass
  805. class C:
  806. i: int = 10
  807. def __post_init__(self):
  808. if self.i == 10:
  809. raise CustomError()
  810. with self.assertRaises(CustomError):
  811. C()
  812. # post-init gets called, but doesn't raise. This is just
  813. # checking that self is used correctly.
  814. C(5)
  815. # If there's not an __init__, then post-init won't get called.
  816. @dataclass(init=False)
  817. class C:
  818. def __post_init__(self):
  819. raise CustomError()
  820. # Creating the class won't raise
  821. C()
  822. @dataclass
  823. class C:
  824. x: int = 0
  825. def __post_init__(self):
  826. self.x *= 2
  827. self.assertEqual(C().x, 0)
  828. self.assertEqual(C(2).x, 4)
  829. # Make sure that if we're frozen, post-init can't set
  830. # attributes.
  831. @dataclass(frozen=True)
  832. class C:
  833. x: int = 0
  834. def __post_init__(self):
  835. self.x *= 2
  836. with self.assertRaises(FrozenInstanceError):
  837. C()
  838. def test_post_init_super(self):
  839. # Make sure super() post-init isn't called by default.
  840. class B:
  841. def __post_init__(self):
  842. raise CustomError()
  843. @dataclass
  844. class C(B):
  845. def __post_init__(self):
  846. self.x = 5
  847. self.assertEqual(C().x, 5)
  848. # Now call super(), and it will raise.
  849. @dataclass
  850. class C(B):
  851. def __post_init__(self):
  852. super().__post_init__()
  853. with self.assertRaises(CustomError):
  854. C()
  855. # Make sure post-init is called, even if not defined in our
  856. # class.
  857. @dataclass
  858. class C(B):
  859. pass
  860. with self.assertRaises(CustomError):
  861. C()
  862. def test_post_init_staticmethod(self):
  863. flag = False
  864. @dataclass
  865. class C:
  866. x: int
  867. y: int
  868. @staticmethod
  869. def __post_init__():
  870. nonlocal flag
  871. flag = True
  872. self.assertFalse(flag)
  873. c = C(3, 4)
  874. self.assertEqual((c.x, c.y), (3, 4))
  875. self.assertTrue(flag)
  876. def test_post_init_classmethod(self):
  877. @dataclass
  878. class C:
  879. flag = False
  880. x: int
  881. y: int
  882. @classmethod
  883. def __post_init__(cls):
  884. cls.flag = True
  885. self.assertFalse(C.flag)
  886. c = C(3, 4)
  887. self.assertEqual((c.x, c.y), (3, 4))
  888. self.assertTrue(C.flag)
  889. def test_post_init_not_auto_added(self):
  890. # See bpo-46757, which had proposed always adding __post_init__. As
  891. # Raymond Hettinger pointed out, that would be a breaking change. So,
  892. # add a test to make sure that the current behavior doesn't change.
  893. @dataclass
  894. class A0:
  895. pass
  896. @dataclass
  897. class B0:
  898. b_called: bool = False
  899. def __post_init__(self):
  900. self.b_called = True
  901. @dataclass
  902. class C0(A0, B0):
  903. c_called: bool = False
  904. def __post_init__(self):
  905. super().__post_init__()
  906. self.c_called = True
  907. # Since A0 has no __post_init__, and one wasn't automatically added
  908. # (because that's the rule: it's never added by @dataclass, it's only
  909. # the class author that can add it), then B0.__post_init__ is called.
  910. # Verify that.
  911. c = C0()
  912. self.assertTrue(c.b_called)
  913. self.assertTrue(c.c_called)
  914. ######################################
  915. # Now, the same thing, except A1 defines __post_init__.
  916. @dataclass
  917. class A1:
  918. def __post_init__(self):
  919. pass
  920. @dataclass
  921. class B1:
  922. b_called: bool = False
  923. def __post_init__(self):
  924. self.b_called = True
  925. @dataclass
  926. class C1(A1, B1):
  927. c_called: bool = False
  928. def __post_init__(self):
  929. super().__post_init__()
  930. self.c_called = True
  931. # This time, B1.__post_init__ isn't being called. This mimics what
  932. # would happen if A1.__post_init__ had been automatically added,
  933. # instead of manually added as we see here. This test isn't really
  934. # needed, but I'm including it just to demonstrate the changed
  935. # behavior when A1 does define __post_init__.
  936. c = C1()
  937. self.assertFalse(c.b_called)
  938. self.assertTrue(c.c_called)
  939. def test_class_var(self):
  940. # Make sure ClassVars are ignored in __init__, __repr__, etc.
  941. @dataclass
  942. class C:
  943. x: int
  944. y: int = 10
  945. z: ClassVar[int] = 1000
  946. w: ClassVar[int] = 2000
  947. t: ClassVar[int] = 3000
  948. s: ClassVar = 4000
  949. c = C(5)
  950. self.assertEqual(repr(c), 'TestCase.test_class_var.<locals>.C(x=5, y=10)')
  951. self.assertEqual(len(fields(C)), 2) # We have 2 fields.
  952. self.assertEqual(len(C.__annotations__), 6) # And 4 ClassVars.
  953. self.assertEqual(c.z, 1000)
  954. self.assertEqual(c.w, 2000)
  955. self.assertEqual(c.t, 3000)
  956. self.assertEqual(c.s, 4000)
  957. C.z += 1
  958. self.assertEqual(c.z, 1001)
  959. c = C(20)
  960. self.assertEqual((c.x, c.y), (20, 10))
  961. self.assertEqual(c.z, 1001)
  962. self.assertEqual(c.w, 2000)
  963. self.assertEqual(c.t, 3000)
  964. self.assertEqual(c.s, 4000)
  965. def test_class_var_no_default(self):
  966. # If a ClassVar has no default value, it should not be set on the class.
  967. @dataclass
  968. class C:
  969. x: ClassVar[int]
  970. self.assertNotIn('x', C.__dict__)
  971. def test_class_var_default_factory(self):
  972. # It makes no sense for a ClassVar to have a default factory. When
  973. # would it be called? Call it yourself, since it's class-wide.
  974. with self.assertRaisesRegex(TypeError,
  975. 'cannot have a default factory'):
  976. @dataclass
  977. class C:
  978. x: ClassVar[int] = field(default_factory=int)
  979. self.assertNotIn('x', C.__dict__)
  980. def test_class_var_with_default(self):
  981. # If a ClassVar has a default value, it should be set on the class.
  982. @dataclass
  983. class C:
  984. x: ClassVar[int] = 10
  985. self.assertEqual(C.x, 10)
  986. @dataclass
  987. class C:
  988. x: ClassVar[int] = field(default=10)
  989. self.assertEqual(C.x, 10)
  990. def test_class_var_frozen(self):
  991. # Make sure ClassVars work even if we're frozen.
  992. @dataclass(frozen=True)
  993. class C:
  994. x: int
  995. y: int = 10
  996. z: ClassVar[int] = 1000
  997. w: ClassVar[int] = 2000
  998. t: ClassVar[int] = 3000
  999. c = C(5)
  1000. self.assertEqual(repr(C(5)), 'TestCase.test_class_var_frozen.<locals>.C(x=5, y=10)')
  1001. self.assertEqual(len(fields(C)), 2) # We have 2 fields
  1002. self.assertEqual(len(C.__annotations__), 5) # And 3 ClassVars
  1003. self.assertEqual(c.z, 1000)
  1004. self.assertEqual(c.w, 2000)
  1005. self.assertEqual(c.t, 3000)
  1006. # We can still modify the ClassVar, it's only instances that are
  1007. # frozen.
  1008. C.z += 1
  1009. self.assertEqual(c.z, 1001)
  1010. c = C(20)
  1011. self.assertEqual((c.x, c.y), (20, 10))
  1012. self.assertEqual(c.z, 1001)
  1013. self.assertEqual(c.w, 2000)
  1014. self.assertEqual(c.t, 3000)
  1015. def test_init_var_no_default(self):
  1016. # If an InitVar has no default value, it should not be set on the class.
  1017. @dataclass
  1018. class C:
  1019. x: InitVar[int]
  1020. self.assertNotIn('x', C.__dict__)
  1021. def test_init_var_default_factory(self):
  1022. # It makes no sense for an InitVar to have a default factory. When
  1023. # would it be called? Call it yourself, since it's class-wide.
  1024. with self.assertRaisesRegex(TypeError,
  1025. 'cannot have a default factory'):
  1026. @dataclass
  1027. class C:
  1028. x: InitVar[int] = field(default_factory=int)
  1029. self.assertNotIn('x', C.__dict__)
  1030. def test_init_var_with_default(self):
  1031. # If an InitVar has a default value, it should be set on the class.
  1032. @dataclass
  1033. class C:
  1034. x: InitVar[int] = 10
  1035. self.assertEqual(C.x, 10)
  1036. @dataclass
  1037. class C:
  1038. x: InitVar[int] = field(default=10)
  1039. self.assertEqual(C.x, 10)
  1040. def test_init_var(self):
  1041. @dataclass
  1042. class C:
  1043. x: int = None
  1044. init_param: InitVar[int] = None
  1045. def __post_init__(self, init_param):
  1046. if self.x is None:
  1047. self.x = init_param*2
  1048. c = C(init_param=10)
  1049. self.assertEqual(c.x, 20)
  1050. def test_init_var_preserve_type(self):
  1051. self.assertEqual(InitVar[int].type, int)
  1052. # Make sure the repr is correct.
  1053. self.assertEqual(repr(InitVar[int]), 'dataclasses.InitVar[int]')
  1054. self.assertEqual(repr(InitVar[List[int]]),
  1055. 'dataclasses.InitVar[typing.List[int]]')
  1056. self.assertEqual(repr(InitVar[list[int]]),
  1057. 'dataclasses.InitVar[list[int]]')
  1058. self.assertEqual(repr(InitVar[int|str]),
  1059. 'dataclasses.InitVar[int | str]')
  1060. def test_init_var_inheritance(self):
  1061. # Note that this deliberately tests that a dataclass need not
  1062. # have a __post_init__ function if it has an InitVar field.
  1063. # It could just be used in a derived class, as shown here.
  1064. @dataclass
  1065. class Base:
  1066. x: int
  1067. init_base: InitVar[int]
  1068. # We can instantiate by passing the InitVar, even though
  1069. # it's not used.
  1070. b = Base(0, 10)
  1071. self.assertEqual(vars(b), {'x': 0})
  1072. @dataclass
  1073. class C(Base):
  1074. y: int
  1075. init_derived: InitVar[int]
  1076. def __post_init__(self, init_base, init_derived):
  1077. self.x = self.x + init_base
  1078. self.y = self.y + init_derived
  1079. c = C(10, 11, 50, 51)
  1080. self.assertEqual(vars(c), {'x': 21, 'y': 101})
  1081. def test_default_factory(self):
  1082. # Test a factory that returns a new list.
  1083. @dataclass
  1084. class C:
  1085. x: int
  1086. y: list = field(default_factory=list)
  1087. c0 = C(3)
  1088. c1 = C(3)
  1089. self.assertEqual(c0.x, 3)
  1090. self.assertEqual(c0.y, [])
  1091. self.assertEqual(c0, c1)
  1092. self.assertIsNot(c0.y, c1.y)
  1093. self.assertEqual(astuple(C(5, [1])), (5, [1]))
  1094. # Test a factory that returns a shared list.
  1095. l = []
  1096. @dataclass
  1097. class C:
  1098. x: int
  1099. y: list = field(default_factory=lambda: l)
  1100. c0 = C(3)
  1101. c1 = C(3)
  1102. self.assertEqual(c0.x, 3)
  1103. self.assertEqual(c0.y, [])
  1104. self.assertEqual(c0, c1)
  1105. self.assertIs(c0.y, c1.y)
  1106. self.assertEqual(astuple(C(5, [1])), (5, [1]))
  1107. # Test various other field flags.
  1108. # repr
  1109. @dataclass
  1110. class C:
  1111. x: list = field(default_factory=list, repr=False)
  1112. self.assertEqual(repr(C()), 'TestCase.test_default_factory.<locals>.C()')
  1113. self.assertEqual(C().x, [])
  1114. # hash
  1115. @dataclass(unsafe_hash=True)
  1116. class C:
  1117. x: list = field(default_factory=list, hash=False)
  1118. self.assertEqual(astuple(C()), ([],))
  1119. self.assertEqual(hash(C()), hash(()))
  1120. # init (see also test_default_factory_with_no_init)
  1121. @dataclass
  1122. class C:
  1123. x: list = field(default_factory=list, init=False)
  1124. self.assertEqual(astuple(C()), ([],))
  1125. # compare
  1126. @dataclass
  1127. class C:
  1128. x: list = field(default_factory=list, compare=False)
  1129. self.assertEqual(C(), C([1]))
  1130. def test_default_factory_with_no_init(self):
  1131. # We need a factory with a side effect.
  1132. factory = Mock()
  1133. @dataclass
  1134. class C:
  1135. x: list = field(default_factory=factory, init=False)
  1136. # Make sure the default factory is called for each new instance.
  1137. C().x
  1138. self.assertEqual(factory.call_count, 1)
  1139. C().x
  1140. self.assertEqual(factory.call_count, 2)
  1141. def test_default_factory_not_called_if_value_given(self):
  1142. # We need a factory that we can test if it's been called.
  1143. factory = Mock()
  1144. @dataclass
  1145. class C:
  1146. x: int = field(default_factory=factory)
  1147. # Make sure that if a field has a default factory function,
  1148. # it's not called if a value is specified.
  1149. C().x
  1150. self.assertEqual(factory.call_count, 1)
  1151. self.assertEqual(C(10).x, 10)
  1152. self.assertEqual(factory.call_count, 1)
  1153. C().x
  1154. self.assertEqual(factory.call_count, 2)
  1155. def test_default_factory_derived(self):
  1156. # See bpo-32896.
  1157. @dataclass
  1158. class Foo:
  1159. x: dict = field(default_factory=dict)
  1160. @dataclass
  1161. class Bar(Foo):
  1162. y: int = 1
  1163. self.assertEqual(Foo().x, {})
  1164. self.assertEqual(Bar().x, {})
  1165. self.assertEqual(Bar().y, 1)
  1166. @dataclass
  1167. class Baz(Foo):
  1168. pass
  1169. self.assertEqual(Baz().x, {})
  1170. def test_intermediate_non_dataclass(self):
  1171. # Test that an intermediate class that defines
  1172. # annotations does not define fields.
  1173. @dataclass
  1174. class A:
  1175. x: int
  1176. class B(A):
  1177. y: int
  1178. @dataclass
  1179. class C(B):
  1180. z: int
  1181. c = C(1, 3)
  1182. self.assertEqual((c.x, c.z), (1, 3))
  1183. # .y was not initialized.
  1184. with self.assertRaisesRegex(AttributeError,
  1185. 'object has no attribute'):
  1186. c.y
  1187. # And if we again derive a non-dataclass, no fields are added.
  1188. class D(C):
  1189. t: int
  1190. d = D(4, 5)
  1191. self.assertEqual((d.x, d.z), (4, 5))
  1192. def test_classvar_default_factory(self):
  1193. # It's an error for a ClassVar to have a factory function.
  1194. with self.assertRaisesRegex(TypeError,
  1195. 'cannot have a default factory'):
  1196. @dataclass
  1197. class C:
  1198. x: ClassVar[int] = field(default_factory=int)
  1199. def test_is_dataclass(self):
  1200. class NotDataClass:
  1201. pass
  1202. self.assertFalse(is_dataclass(0))
  1203. self.assertFalse(is_dataclass(int))
  1204. self.assertFalse(is_dataclass(NotDataClass))
  1205. self.assertFalse(is_dataclass(NotDataClass()))
  1206. @dataclass
  1207. class C:
  1208. x: int
  1209. @dataclass
  1210. class D:
  1211. d: C
  1212. e: int
  1213. c = C(10)
  1214. d = D(c, 4)
  1215. self.assertTrue(is_dataclass(C))
  1216. self.assertTrue(is_dataclass(c))
  1217. self.assertFalse(is_dataclass(c.x))
  1218. self.assertTrue(is_dataclass(d.d))
  1219. self.assertFalse(is_dataclass(d.e))
  1220. def test_is_dataclass_when_getattr_always_returns(self):
  1221. # See bpo-37868.
  1222. class A:
  1223. def __getattr__(self, key):
  1224. return 0
  1225. self.assertFalse(is_dataclass(A))
  1226. a = A()
  1227. # Also test for an instance attribute.
  1228. class B:
  1229. pass
  1230. b = B()
  1231. b.__dataclass_fields__ = []
  1232. for obj in a, b:
  1233. with self.subTest(obj=obj):
  1234. self.assertFalse(is_dataclass(obj))
  1235. # Indirect tests for _is_dataclass_instance().
  1236. with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'):
  1237. asdict(obj)
  1238. with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'):
  1239. astuple(obj)
  1240. with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'):
  1241. replace(obj, x=0)
  1242. def test_is_dataclass_genericalias(self):
  1243. @dataclass
  1244. class A(types.GenericAlias):
  1245. origin: type
  1246. args: type
  1247. self.assertTrue(is_dataclass(A))
  1248. a = A(list, int)
  1249. self.assertTrue(is_dataclass(type(a)))
  1250. self.assertTrue(is_dataclass(a))
  1251. def test_helper_fields_with_class_instance(self):
  1252. # Check that we can call fields() on either a class or instance,
  1253. # and get back the same thing.
  1254. @dataclass
  1255. class C:
  1256. x: int
  1257. y: float
  1258. self.assertEqual(fields(C), fields(C(0, 0.0)))
  1259. def test_helper_fields_exception(self):
  1260. # Check that TypeError is raised if not passed a dataclass or
  1261. # instance.
  1262. with self.assertRaisesRegex(TypeError, 'dataclass type or instance'):
  1263. fields(0)
  1264. class C: pass
  1265. with self.assertRaisesRegex(TypeError, 'dataclass type or instance'):
  1266. fields(C)
  1267. with self.assertRaisesRegex(TypeError, 'dataclass type or instance'):
  1268. fields(C())
  1269. def test_helper_asdict(self):
  1270. # Basic tests for asdict(), it should return a new dictionary.
  1271. @dataclass
  1272. class C:
  1273. x: int
  1274. y: int
  1275. c = C(1, 2)
  1276. self.assertEqual(asdict(c), {'x': 1, 'y': 2})
  1277. self.assertEqual(asdict(c), asdict(c))
  1278. self.assertIsNot(asdict(c), asdict(c))
  1279. c.x = 42
  1280. self.assertEqual(asdict(c), {'x': 42, 'y': 2})
  1281. self.assertIs(type(asdict(c)), dict)
  1282. def test_helper_asdict_raises_on_classes(self):
  1283. # asdict() should raise on a class object.
  1284. @dataclass
  1285. class C:
  1286. x: int
  1287. y: int
  1288. with self.assertRaisesRegex(TypeError, 'dataclass instance'):
  1289. asdict(C)
  1290. with self.assertRaisesRegex(TypeError, 'dataclass instance'):
  1291. asdict(int)
  1292. def test_helper_asdict_copy_values(self):
  1293. @dataclass
  1294. class C:
  1295. x: int
  1296. y: List[int] = field(default_factory=list)
  1297. initial = []
  1298. c = C(1, initial)
  1299. d = asdict(c)
  1300. self.assertEqual(d['y'], initial)
  1301. self.assertIsNot(d['y'], initial)
  1302. c = C(1)
  1303. d = asdict(c)
  1304. d['y'].append(1)
  1305. self.assertEqual(c.y, [])
  1306. def test_helper_asdict_nested(self):
  1307. @dataclass
  1308. class UserId:
  1309. token: int
  1310. group: int
  1311. @dataclass
  1312. class User:
  1313. name: str
  1314. id: UserId
  1315. u = User('Joe', UserId(123, 1))
  1316. d = asdict(u)
  1317. self.assertEqual(d, {'name': 'Joe', 'id': {'token': 123, 'group': 1}})
  1318. self.assertIsNot(asdict(u), asdict(u))
  1319. u.id.group = 2
  1320. self.assertEqual(asdict(u), {'name': 'Joe',
  1321. 'id': {'token': 123, 'group': 2}})
  1322. def test_helper_asdict_builtin_containers(self):
  1323. @dataclass
  1324. class User:
  1325. name: str
  1326. id: int
  1327. @dataclass
  1328. class GroupList:
  1329. id: int
  1330. users: List[User]
  1331. @dataclass
  1332. class GroupTuple:
  1333. id: int
  1334. users: Tuple[User, ...]
  1335. @dataclass
  1336. class GroupDict:
  1337. id: int
  1338. users: Dict[str, User]
  1339. a = User('Alice', 1)
  1340. b = User('Bob', 2)
  1341. gl = GroupList(0, [a, b])
  1342. gt = GroupTuple(0, (a, b))
  1343. gd = GroupDict(0, {'first': a, 'second': b})
  1344. self.assertEqual(asdict(gl), {'id': 0, 'users': [{'name': 'Alice', 'id': 1},
  1345. {'name': 'Bob', 'id': 2}]})
  1346. self.assertEqual(asdict(gt), {'id': 0, 'users': ({'name': 'Alice', 'id': 1},
  1347. {'name': 'Bob', 'id': 2})})
  1348. self.assertEqual(asdict(gd), {'id': 0, 'users': {'first': {'name': 'Alice', 'id': 1},
  1349. 'second': {'name': 'Bob', 'id': 2}}})
  1350. def test_helper_asdict_builtin_object_containers(self):
  1351. @dataclass
  1352. class Child:
  1353. d: object
  1354. @dataclass
  1355. class Parent:
  1356. child: Child
  1357. self.assertEqual(asdict(Parent(Child([1]))), {'child': {'d': [1]}})
  1358. self.assertEqual(asdict(Parent(Child({1: 2}))), {'child': {'d': {1: 2}}})
  1359. def test_helper_asdict_factory(self):
  1360. @dataclass
  1361. class C:
  1362. x: int
  1363. y: int
  1364. c = C(1, 2)
  1365. d = asdict(c, dict_factory=OrderedDict)
  1366. self.assertEqual(d, OrderedDict([('x', 1), ('y', 2)]))
  1367. self.assertIsNot(d, asdict(c, dict_factory=OrderedDict))
  1368. c.x = 42
  1369. d = asdict(c, dict_factory=OrderedDict)
  1370. self.assertEqual(d, OrderedDict([('x', 42), ('y', 2)]))
  1371. self.assertIs(type(d), OrderedDict)
  1372. def test_helper_asdict_namedtuple(self):
  1373. T = namedtuple('T', 'a b c')
  1374. @dataclass
  1375. class C:
  1376. x: str
  1377. y: T
  1378. c = C('outer', T(1, C('inner', T(11, 12, 13)), 2))
  1379. d = asdict(c)
  1380. self.assertEqual(d, {'x': 'outer',
  1381. 'y': T(1,
  1382. {'x': 'inner',
  1383. 'y': T(11, 12, 13)},
  1384. 2),
  1385. }
  1386. )
  1387. # Now with a dict_factory. OrderedDict is convenient, but
  1388. # since it compares to dicts, we also need to have separate
  1389. # assertIs tests.
  1390. d = asdict(c, dict_factory=OrderedDict)
  1391. self.assertEqual(d, {'x': 'outer',
  1392. 'y': T(1,
  1393. {'x': 'inner',
  1394. 'y': T(11, 12, 13)},
  1395. 2),
  1396. }
  1397. )
  1398. # Make sure that the returned dicts are actually OrderedDicts.
  1399. self.assertIs(type(d), OrderedDict)
  1400. self.assertIs(type(d['y'][1]), OrderedDict)
  1401. def test_helper_asdict_namedtuple_key(self):
  1402. # Ensure that a field that contains a dict which has a
  1403. # namedtuple as a key works with asdict().
  1404. @dataclass
  1405. class C:
  1406. f: dict
  1407. T = namedtuple('T', 'a')
  1408. c = C({T('an a'): 0})
  1409. self.assertEqual(asdict(c), {'f': {T(a='an a'): 0}})
  1410. def test_helper_asdict_namedtuple_derived(self):
  1411. class T(namedtuple('Tbase', 'a')):
  1412. def my_a(self):
  1413. return self.a
  1414. @dataclass
  1415. class C:
  1416. f: T
  1417. t = T(6)
  1418. c = C(t)
  1419. d = asdict(c)
  1420. self.assertEqual(d, {'f': T(a=6)})
  1421. # Make sure that t has been copied, not used directly.
  1422. self.assertIsNot(d['f'], t)
  1423. self.assertEqual(d['f'].my_a(), 6)
  1424. def test_helper_astuple(self):
  1425. # Basic tests for astuple(), it should return a new tuple.
  1426. @dataclass
  1427. class C:
  1428. x: int
  1429. y: int = 0
  1430. c = C(1)
  1431. self.assertEqual(astuple(c), (1, 0))
  1432. self.assertEqual(astuple(c), astuple(c))
  1433. self.assertIsNot(astuple(c), astuple(c))
  1434. c.y = 42
  1435. self.assertEqual(astuple(c), (1, 42))
  1436. self.assertIs(type(astuple(c)), tuple)
  1437. def test_helper_astuple_raises_on_classes(self):
  1438. # astuple() should raise on a class object.
  1439. @dataclass
  1440. class C:
  1441. x: int
  1442. y: int
  1443. with self.assertRaisesRegex(TypeError, 'dataclass instance'):
  1444. astuple(C)
  1445. with self.assertRaisesRegex(TypeError, 'dataclass instance'):
  1446. astuple(int)
  1447. def test_helper_astuple_copy_values(self):
  1448. @dataclass
  1449. class C:
  1450. x: int
  1451. y: List[int] = field(default_factory=list)
  1452. initial = []
  1453. c = C(1, initial)
  1454. t = astuple(c)
  1455. self.assertEqual(t[1], initial)
  1456. self.assertIsNot(t[1], initial)
  1457. c = C(1)
  1458. t = astuple(c)
  1459. t[1].append(1)
  1460. self.assertEqual(c.y, [])
  1461. def test_helper_astuple_nested(self):
  1462. @dataclass
  1463. class UserId:
  1464. token: int
  1465. group: int
  1466. @dataclass
  1467. class User:
  1468. name: str
  1469. id: UserId
  1470. u = User('Joe', UserId(123, 1))
  1471. t = astuple(u)
  1472. self.assertEqual(t, ('Joe', (123, 1)))
  1473. self.assertIsNot(astuple(u), astuple(u))
  1474. u.id.group = 2
  1475. self.assertEqual(astuple(u), ('Joe', (123, 2)))
  1476. def test_helper_astuple_builtin_containers(self):
  1477. @dataclass
  1478. class User:
  1479. name: str
  1480. id: int
  1481. @dataclass
  1482. class GroupList:
  1483. id: int
  1484. users: List[User]
  1485. @dataclass
  1486. class GroupTuple:
  1487. id: int
  1488. users: Tuple[User, ...]
  1489. @dataclass
  1490. class GroupDict:
  1491. id: int
  1492. users: Dict[str, User]
  1493. a = User('Alice', 1)
  1494. b = User('Bob', 2)
  1495. gl = GroupList(0, [a, b])
  1496. gt = GroupTuple(0, (a, b))
  1497. gd = GroupDict(0, {'first': a, 'second': b})
  1498. self.assertEqual(astuple(gl), (0, [('Alice', 1), ('Bob', 2)]))
  1499. self.assertEqual(astuple(gt), (0, (('Alice', 1), ('Bob', 2))))
  1500. self.assertEqual(astuple(gd), (0, {'first': ('Alice', 1), 'second': ('Bob', 2)}))
  1501. def test_helper_astuple_builtin_object_containers(self):
  1502. @dataclass
  1503. class Child:
  1504. d: object
  1505. @dataclass
  1506. class Parent:
  1507. child: Child
  1508. self.assertEqual(astuple(Parent(Child([1]))), (([1],),))
  1509. self.assertEqual(astuple(Parent(Child({1: 2}))), (({1: 2},),))
  1510. def test_helper_astuple_factory(self):
  1511. @dataclass
  1512. class C:
  1513. x: int
  1514. y: int
  1515. NT = namedtuple('NT', 'x y')
  1516. def nt(lst):
  1517. return NT(*lst)
  1518. c = C(1, 2)
  1519. t = astuple(c, tuple_factory=nt)
  1520. self.assertEqual(t, NT(1, 2))
  1521. self.assertIsNot(t, astuple(c, tuple_factory=nt))
  1522. c.x = 42
  1523. t = astuple(c, tuple_factory=nt)
  1524. self.assertEqual(t, NT(42, 2))
  1525. self.assertIs(type(t), NT)
  1526. def test_helper_astuple_namedtuple(self):
  1527. T = namedtuple('T', 'a b c')
  1528. @dataclass
  1529. class C:
  1530. x: str
  1531. y: T
  1532. c = C('outer', T(1, C('inner', T(11, 12, 13)), 2))
  1533. t = astuple(c)
  1534. self.assertEqual(t, ('outer', T(1, ('inner', (11, 12, 13)), 2)))
  1535. # Now, using a tuple_factory. list is convenient here.
  1536. t = astuple(c, tuple_factory=list)
  1537. self.assertEqual(t, ['outer', T(1, ['inner', T(11, 12, 13)], 2)])
  1538. def test_dynamic_class_creation(self):
  1539. cls_dict = {'__annotations__': {'x': int, 'y': int},
  1540. }
  1541. # Create the class.
  1542. cls = type('C', (), cls_dict)
  1543. # Make it a dataclass.
  1544. cls1 = dataclass(cls)
  1545. self.assertEqual(cls1, cls)
  1546. self.assertEqual(asdict(cls(1, 2)), {'x': 1, 'y': 2})
  1547. def test_dynamic_class_creation_using_field(self):
  1548. cls_dict = {'__annotations__': {'x': int, 'y': int},
  1549. 'y': field(default=5),
  1550. }
  1551. # Create the class.
  1552. cls = type('C', (), cls_dict)
  1553. # Make it a dataclass.
  1554. cls1 = dataclass(cls)
  1555. self.assertEqual(cls1, cls)
  1556. self.assertEqual(asdict(cls1(1)), {'x': 1, 'y': 5})
  1557. def test_init_in_order(self):
  1558. @dataclass
  1559. class C:
  1560. a: int
  1561. b: int = field()
  1562. c: list = field(default_factory=list, init=False)
  1563. d: list = field(default_factory=list)
  1564. e: int = field(default=4, init=False)
  1565. f: int = 4
  1566. calls = []
  1567. def setattr(self, name, value):
  1568. calls.append((name, value))
  1569. C.__setattr__ = setattr
  1570. c = C(0, 1)
  1571. self.assertEqual(('a', 0), calls[0])
  1572. self.assertEqual(('b', 1), calls[1])
  1573. self.assertEqual(('c', []), calls[2])
  1574. self.assertEqual(('d', []), calls[3])
  1575. self.assertNotIn(('e', 4), calls)
  1576. self.assertEqual(('f', 4), calls[4])
  1577. def test_items_in_dicts(self):
  1578. @dataclass
  1579. class C:
  1580. a: int
  1581. b: list = field(default_factory=list, init=False)
  1582. c: list = field(default_factory=list)
  1583. d: int = field(default=4, init=False)
  1584. e: int = 0
  1585. c = C(0)
  1586. # Class dict
  1587. self.assertNotIn('a', C.__dict__)
  1588. self.assertNotIn('b', C.__dict__)
  1589. self.assertNotIn('c', C.__dict__)
  1590. self.assertIn('d', C.__dict__)
  1591. self.assertEqual(C.d, 4)
  1592. self.assertIn('e', C.__dict__)
  1593. self.assertEqual(C.e, 0)
  1594. # Instance dict
  1595. self.assertIn('a', c.__dict__)
  1596. self.assertEqual(c.a, 0)
  1597. self.assertIn('b', c.__dict__)
  1598. self.assertEqual(c.b, [])
  1599. self.assertIn('c', c.__dict__)
  1600. self.assertEqual(c.c, [])
  1601. self.assertNotIn('d', c.__dict__)
  1602. self.assertIn('e', c.__dict__)
  1603. self.assertEqual(c.e, 0)
  1604. def test_alternate_classmethod_constructor(self):
  1605. # Since __post_init__ can't take params, use a classmethod
  1606. # alternate constructor. This is mostly an example to show
  1607. # how to use this technique.
  1608. @dataclass
  1609. class C:
  1610. x: int
  1611. @classmethod
  1612. def from_file(cls, filename):
  1613. # In a real example, create a new instance
  1614. # and populate 'x' from contents of a file.
  1615. value_in_file = 20
  1616. return cls(value_in_file)
  1617. self.assertEqual(C.from_file('filename').x, 20)
  1618. def test_field_metadata_default(self):
  1619. # Make sure the default metadata is read-only and of
  1620. # zero length.
  1621. @dataclass
  1622. class C:
  1623. i: int
  1624. self.assertFalse(fields(C)[0].metadata)
  1625. self.assertEqual(len(fields(C)[0].metadata), 0)
  1626. with self.assertRaisesRegex(TypeError,
  1627. 'does not support item assignment'):
  1628. fields(C)[0].metadata['test'] = 3
  1629. def test_field_metadata_mapping(self):
  1630. # Make sure only a mapping can be passed as metadata
  1631. # zero length.
  1632. with self.assertRaises(TypeError):
  1633. @dataclass
  1634. class C:
  1635. i: int = field(metadata=0)
  1636. # Make sure an empty dict works.
  1637. d = {}
  1638. @dataclass
  1639. class C:
  1640. i: int = field(metadata=d)
  1641. self.assertFalse(fields(C)[0].metadata)
  1642. self.assertEqual(len(fields(C)[0].metadata), 0)
  1643. # Update should work (see bpo-35960).
  1644. d['foo'] = 1
  1645. self.assertEqual(len(fields(C)[0].metadata), 1)
  1646. self.assertEqual(fields(C)[0].metadata['foo'], 1)
  1647. with self.assertRaisesRegex(TypeError,
  1648. 'does not support item assignment'):
  1649. fields(C)[0].metadata['test'] = 3
  1650. # Make sure a non-empty dict works.
  1651. d = {'test': 10, 'bar': '42', 3: 'three'}
  1652. @dataclass
  1653. class C:
  1654. i: int = field(metadata=d)
  1655. self.assertEqual(len(fields(C)[0].metadata), 3)
  1656. self.assertEqual(fields(C)[0].metadata['test'], 10)
  1657. self.assertEqual(fields(C)[0].metadata['bar'], '42')
  1658. self.assertEqual(fields(C)[0].metadata[3], 'three')
  1659. # Update should work.
  1660. d['foo'] = 1
  1661. self.assertEqual(len(fields(C)[0].metadata), 4)
  1662. self.assertEqual(fields(C)[0].metadata['foo'], 1)
  1663. with self.assertRaises(KeyError):
  1664. # Non-existent key.
  1665. fields(C)[0].metadata['baz']
  1666. with self.assertRaisesRegex(TypeError,
  1667. 'does not support item assignment'):
  1668. fields(C)[0].metadata['test'] = 3
  1669. def test_field_metadata_custom_mapping(self):
  1670. # Try a custom mapping.
  1671. class SimpleNameSpace:
  1672. def __init__(self, **kw):
  1673. self.__dict__.update(kw)
  1674. def __getitem__(self, item):
  1675. if item == 'xyzzy':
  1676. return 'plugh'
  1677. return getattr(self, item)
  1678. def __len__(self):
  1679. return self.__dict__.__len__()
  1680. @dataclass
  1681. class C:
  1682. i: int = field(metadata=SimpleNameSpace(a=10))
  1683. self.assertEqual(len(fields(C)[0].metadata), 1)
  1684. self.assertEqual(fields(C)[0].metadata['a'], 10)
  1685. with self.assertRaises(AttributeError):
  1686. fields(C)[0].metadata['b']
  1687. # Make sure we're still talking to our custom mapping.
  1688. self.assertEqual(fields(C)[0].metadata['xyzzy'], 'plugh')
  1689. def test_generic_dataclasses(self):
  1690. T = TypeVar('T')
  1691. @dataclass
  1692. class LabeledBox(Generic[T]):
  1693. content: T
  1694. label: str = '<unknown>'
  1695. box = LabeledBox(42)
  1696. self.assertEqual(box.content, 42)
  1697. self.assertEqual(box.label, '<unknown>')
  1698. # Subscripting the resulting class should work, etc.
  1699. Alias = List[LabeledBox[int]]
  1700. def test_generic_extending(self):
  1701. S = TypeVar('S')
  1702. T = TypeVar('T')
  1703. @dataclass
  1704. class Base(Generic[T, S]):
  1705. x: T
  1706. y: S
  1707. @dataclass
  1708. class DataDerived(Base[int, T]):
  1709. new_field: str
  1710. Alias = DataDerived[str]
  1711. c = Alias(0, 'test1', 'test2')
  1712. self.assertEqual(astuple(c), (0, 'test1', 'test2'))
  1713. class NonDataDerived(Base[int, T]):
  1714. def new_method(self):
  1715. return self.y
  1716. Alias = NonDataDerived[float]
  1717. c = Alias(10, 1.0)
  1718. self.assertEqual(c.new_method(), 1.0)
  1719. def test_generic_dynamic(self):
  1720. T = TypeVar('T')
  1721. @dataclass
  1722. class Parent(Generic[T]):
  1723. x: T
  1724. Child = make_dataclass('Child', [('y', T), ('z', Optional[T], None)],
  1725. bases=(Parent[int], Generic[T]), namespace={'other': 42})
  1726. self.assertIs(Child[int](1, 2).z, None)
  1727. self.assertEqual(Child[int](1, 2, 3).z, 3)
  1728. self.assertEqual(Child[int](1, 2, 3).other, 42)
  1729. # Check that type aliases work correctly.
  1730. Alias = Child[T]
  1731. self.assertEqual(Alias[int](1, 2).x, 1)
  1732. # Check MRO resolution.
  1733. self.assertEqual(Child.__mro__, (Child, Parent, Generic, object))
  1734. def test_dataclasses_pickleable(self):
  1735. global P, Q, R
  1736. @dataclass
  1737. class P:
  1738. x: int
  1739. y: int = 0
  1740. @dataclass
  1741. class Q:
  1742. x: int
  1743. y: int = field(default=0, init=False)
  1744. @dataclass
  1745. class R:
  1746. x: int
  1747. y: List[int] = field(default_factory=list)
  1748. q = Q(1)
  1749. q.y = 2
  1750. samples = [P(1), P(1, 2), Q(1), q, R(1), R(1, [2, 3, 4])]
  1751. for sample in samples:
  1752. for proto in range(pickle.HIGHEST_PROTOCOL + 1):
  1753. with self.subTest(sample=sample, proto=proto):
  1754. new_sample = pickle.loads(pickle.dumps(sample, proto))
  1755. self.assertEqual(sample.x, new_sample.x)
  1756. self.assertEqual(sample.y, new_sample.y)
  1757. self.assertIsNot(sample, new_sample)
  1758. new_sample.x = 42
  1759. another_new_sample = pickle.loads(pickle.dumps(new_sample, proto))
  1760. self.assertEqual(new_sample.x, another_new_sample.x)
  1761. self.assertEqual(sample.y, another_new_sample.y)
  1762. def test_dataclasses_qualnames(self):
  1763. @dataclass(order=True, unsafe_hash=True, frozen=True)
  1764. class A:
  1765. x: int
  1766. y: int
  1767. self.assertEqual(A.__init__.__name__, "__init__")
  1768. for function in (
  1769. '__eq__',
  1770. '__lt__',
  1771. '__le__',
  1772. '__gt__',
  1773. '__ge__',
  1774. '__hash__',
  1775. '__init__',
  1776. '__repr__',
  1777. '__setattr__',
  1778. '__delattr__',
  1779. ):
  1780. self.assertEqual(getattr(A, function).__qualname__, f"TestCase.test_dataclasses_qualnames.<locals>.A.{function}")
  1781. with self.assertRaisesRegex(TypeError, r"A\.__init__\(\) missing"):
  1782. A()
  1783. class TestFieldNoAnnotation(unittest.TestCase):
  1784. def test_field_without_annotation(self):
  1785. with self.assertRaisesRegex(TypeError,
  1786. "'f' is a field but has no type annotation"):
  1787. @dataclass
  1788. class C:
  1789. f = field()
  1790. def test_field_without_annotation_but_annotation_in_base(self):
  1791. @dataclass
  1792. class B:
  1793. f: int
  1794. with self.assertRaisesRegex(TypeError,
  1795. "'f' is a field but has no type annotation"):
  1796. # This is still an error: make sure we don't pick up the
  1797. # type annotation in the base class.
  1798. @dataclass
  1799. class C(B):
  1800. f = field()
  1801. def test_field_without_annotation_but_annotation_in_base_not_dataclass(self):
  1802. # Same test, but with the base class not a dataclass.
  1803. class B:
  1804. f: int
  1805. with self.assertRaisesRegex(TypeError,
  1806. "'f' is a field but has no type annotation"):
  1807. # This is still an error: make sure we don't pick up the
  1808. # type annotation in the base class.
  1809. @dataclass
  1810. class C(B):
  1811. f = field()
  1812. class TestDocString(unittest.TestCase):
  1813. def assertDocStrEqual(self, a, b):
  1814. # Because 3.6 and 3.7 differ in how inspect.signature work
  1815. # (see bpo #32108), for the time being just compare them with
  1816. # whitespace stripped.
  1817. self.assertEqual(a.replace(' ', ''), b.replace(' ', ''))
  1818. def test_existing_docstring_not_overridden(self):
  1819. @dataclass
  1820. class C:
  1821. """Lorem ipsum"""
  1822. x: int
  1823. self.assertEqual(C.__doc__, "Lorem ipsum")
  1824. def test_docstring_no_fields(self):
  1825. @dataclass
  1826. class C:
  1827. pass
  1828. self.assertDocStrEqual(C.__doc__, "C()")
  1829. def test_docstring_one_field(self):
  1830. @dataclass
  1831. class C:
  1832. x: int
  1833. self.assertDocStrEqual(C.__doc__, "C(x:int)")
  1834. def test_docstring_two_fields(self):
  1835. @dataclass
  1836. class C:
  1837. x: int
  1838. y: int
  1839. self.assertDocStrEqual(C.__doc__, "C(x:int, y:int)")
  1840. def test_docstring_three_fields(self):
  1841. @dataclass
  1842. class C:
  1843. x: int
  1844. y: int
  1845. z: str
  1846. self.assertDocStrEqual(C.__doc__, "C(x:int, y:int, z:str)")
  1847. def test_docstring_one_field_with_default(self):
  1848. @dataclass
  1849. class C:
  1850. x: int = 3
  1851. self.assertDocStrEqual(C.__doc__, "C(x:int=3)")
  1852. def test_docstring_one_field_with_default_none(self):
  1853. @dataclass
  1854. class C:
  1855. x: Union[int, type(None)] = None
  1856. self.assertDocStrEqual(C.__doc__, "C(x:Optional[int]=None)")
  1857. def test_docstring_list_field(self):
  1858. @dataclass
  1859. class C:
  1860. x: List[int]
  1861. self.assertDocStrEqual(C.__doc__, "C(x:List[int])")
  1862. def test_docstring_list_field_with_default_factory(self):
  1863. @dataclass
  1864. class C:
  1865. x: List[int] = field(default_factory=list)
  1866. self.assertDocStrEqual(C.__doc__, "C(x:List[int]=<factory>)")
  1867. def test_docstring_deque_field(self):
  1868. @dataclass
  1869. class C:
  1870. x: deque
  1871. self.assertDocStrEqual(C.__doc__, "C(x:collections.deque)")
  1872. def test_docstring_deque_field_with_default_factory(self):
  1873. @dataclass
  1874. class C:
  1875. x: deque = field(default_factory=deque)
  1876. self.assertDocStrEqual(C.__doc__, "C(x:collections.deque=<factory>)")
  1877. class TestInit(unittest.TestCase):
  1878. def test_base_has_init(self):
  1879. class B:
  1880. def __init__(self):
  1881. self.z = 100
  1882. pass
  1883. # Make sure that declaring this class doesn't raise an error.
  1884. # The issue is that we can't override __init__ in our class,
  1885. # but it should be okay to add __init__ to us if our base has
  1886. # an __init__.
  1887. @dataclass
  1888. class C(B):
  1889. x: int = 0
  1890. c = C(10)
  1891. self.assertEqual(c.x, 10)
  1892. self.assertNotIn('z', vars(c))
  1893. # Make sure that if we don't add an init, the base __init__
  1894. # gets called.
  1895. @dataclass(init=False)
  1896. class C(B):
  1897. x: int = 10
  1898. c = C()
  1899. self.assertEqual(c.x, 10)
  1900. self.assertEqual(c.z, 100)
  1901. def test_no_init(self):
  1902. @dataclass(init=False)
  1903. class C:
  1904. i: int = 0
  1905. self.assertEqual(C().i, 0)
  1906. @dataclass(init=False)
  1907. class C:
  1908. i: int = 2
  1909. def __init__(self):
  1910. self.i = 3
  1911. self.assertEqual(C().i, 3)
  1912. def test_overwriting_init(self):
  1913. # If the class has __init__, use it no matter the value of
  1914. # init=.
  1915. @dataclass
  1916. class C:
  1917. x: int
  1918. def __init__(self, x):
  1919. self.x = 2 * x
  1920. self.assertEqual(C(3).x, 6)
  1921. @dataclass(init=True)
  1922. class C:
  1923. x: int
  1924. def __init__(self, x):
  1925. self.x = 2 * x
  1926. self.assertEqual(C(4).x, 8)
  1927. @dataclass(init=False)
  1928. class C:
  1929. x: int
  1930. def __init__(self, x):
  1931. self.x = 2 * x
  1932. self.assertEqual(C(5).x, 10)
  1933. def test_inherit_from_protocol(self):
  1934. # Dataclasses inheriting from protocol should preserve their own `__init__`.
  1935. # See bpo-45081.
  1936. class P(Protocol):
  1937. a: int
  1938. @dataclass
  1939. class C(P):
  1940. a: int
  1941. self.assertEqual(C(5).a, 5)
  1942. @dataclass
  1943. class D(P):
  1944. def __init__(self, a):
  1945. self.a = a * 2
  1946. self.assertEqual(D(5).a, 10)
  1947. class TestRepr(unittest.TestCase):
  1948. def test_repr(self):
  1949. @dataclass
  1950. class B:
  1951. x: int
  1952. @dataclass
  1953. class C(B):
  1954. y: int = 10
  1955. o = C(4)
  1956. self.assertEqual(repr(o), 'TestRepr.test_repr.<locals>.C(x=4, y=10)')
  1957. @dataclass
  1958. class D(C):
  1959. x: int = 20
  1960. self.assertEqual(repr(D()), 'TestRepr.test_repr.<locals>.D(x=20, y=10)')
  1961. @dataclass
  1962. class C:
  1963. @dataclass
  1964. class D:
  1965. i: int
  1966. @dataclass
  1967. class E:
  1968. pass
  1969. self.assertEqual(repr(C.D(0)), 'TestRepr.test_repr.<locals>.C.D(i=0)')
  1970. self.assertEqual(repr(C.E()), 'TestRepr.test_repr.<locals>.C.E()')
  1971. def test_no_repr(self):
  1972. # Test a class with no __repr__ and repr=False.
  1973. @dataclass(repr=False)
  1974. class C:
  1975. x: int
  1976. self.assertIn(f'{__name__}.TestRepr.test_no_repr.<locals>.C object at',
  1977. repr(C(3)))
  1978. # Test a class with a __repr__ and repr=False.
  1979. @dataclass(repr=False)
  1980. class C:
  1981. x: int
  1982. def __repr__(self):
  1983. return 'C-class'
  1984. self.assertEqual(repr(C(3)), 'C-class')
  1985. def test_overwriting_repr(self):
  1986. # If the class has __repr__, use it no matter the value of
  1987. # repr=.
  1988. @dataclass
  1989. class C:
  1990. x: int
  1991. def __repr__(self):
  1992. return 'x'
  1993. self.assertEqual(repr(C(0)), 'x')
  1994. @dataclass(repr=True)
  1995. class C:
  1996. x: int
  1997. def __repr__(self):
  1998. return 'x'
  1999. self.assertEqual(repr(C(0)), 'x')
  2000. @dataclass(repr=False)
  2001. class C:
  2002. x: int
  2003. def __repr__(self):
  2004. return 'x'
  2005. self.assertEqual(repr(C(0)), 'x')
  2006. class TestEq(unittest.TestCase):
  2007. def test_no_eq(self):
  2008. # Test a class with no __eq__ and eq=False.
  2009. @dataclass(eq=False)
  2010. class C:
  2011. x: int
  2012. self.assertNotEqual(C(0), C(0))
  2013. c = C(3)
  2014. self.assertEqual(c, c)
  2015. # Test a class with an __eq__ and eq=False.
  2016. @dataclass(eq=False)
  2017. class C:
  2018. x: int
  2019. def __eq__(self, other):
  2020. return other == 10
  2021. self.assertEqual(C(3), 10)
  2022. def test_overwriting_eq(self):
  2023. # If the class has __eq__, use it no matter the value of
  2024. # eq=.
  2025. @dataclass
  2026. class C:
  2027. x: int
  2028. def __eq__(self, other):
  2029. return other == 3
  2030. self.assertEqual(C(1), 3)
  2031. self.assertNotEqual(C(1), 1)
  2032. @dataclass(eq=True)
  2033. class C:
  2034. x: int
  2035. def __eq__(self, other):
  2036. return other == 4
  2037. self.assertEqual(C(1), 4)
  2038. self.assertNotEqual(C(1), 1)
  2039. @dataclass(eq=False)
  2040. class C:
  2041. x: int
  2042. def __eq__(self, other):
  2043. return other == 5
  2044. self.assertEqual(C(1), 5)
  2045. self.assertNotEqual(C(1), 1)
  2046. class TestOrdering(unittest.TestCase):
  2047. def test_functools_total_ordering(self):
  2048. # Test that functools.total_ordering works with this class.
  2049. @total_ordering
  2050. @dataclass
  2051. class C:
  2052. x: int
  2053. def __lt__(self, other):
  2054. # Perform the test "backward", just to make
  2055. # sure this is being called.
  2056. return self.x >= other
  2057. self.assertLess(C(0), -1)
  2058. self.assertLessEqual(C(0), -1)
  2059. self.assertGreater(C(0), 1)
  2060. self.assertGreaterEqual(C(0), 1)
  2061. def test_no_order(self):
  2062. # Test that no ordering functions are added by default.
  2063. @dataclass(order=False)
  2064. class C:
  2065. x: int
  2066. # Make sure no order methods are added.
  2067. self.assertNotIn('__le__', C.__dict__)
  2068. self.assertNotIn('__lt__', C.__dict__)
  2069. self.assertNotIn('__ge__', C.__dict__)
  2070. self.assertNotIn('__gt__', C.__dict__)
  2071. # Test that __lt__ is still called
  2072. @dataclass(order=False)
  2073. class C:
  2074. x: int
  2075. def __lt__(self, other):
  2076. return False
  2077. # Make sure other methods aren't added.
  2078. self.assertNotIn('__le__', C.__dict__)
  2079. self.assertNotIn('__ge__', C.__dict__)
  2080. self.assertNotIn('__gt__', C.__dict__)
  2081. def test_overwriting_order(self):
  2082. with self.assertRaisesRegex(TypeError,
  2083. 'Cannot overwrite attribute __lt__'
  2084. '.*using functools.total_ordering'):
  2085. @dataclass(order=True)
  2086. class C:
  2087. x: int
  2088. def __lt__(self):
  2089. pass
  2090. with self.assertRaisesRegex(TypeError,
  2091. 'Cannot overwrite attribute __le__'
  2092. '.*using functools.total_ordering'):
  2093. @dataclass(order=True)
  2094. class C:
  2095. x: int
  2096. def __le__(self):
  2097. pass
  2098. with self.assertRaisesRegex(TypeError,
  2099. 'Cannot overwrite attribute __gt__'
  2100. '.*using functools.total_ordering'):
  2101. @dataclass(order=True)
  2102. class C:
  2103. x: int
  2104. def __gt__(self):
  2105. pass
  2106. with self.assertRaisesRegex(TypeError,
  2107. 'Cannot overwrite attribute __ge__'
  2108. '.*using functools.total_ordering'):
  2109. @dataclass(order=True)
  2110. class C:
  2111. x: int
  2112. def __ge__(self):
  2113. pass
  2114. class TestHash(unittest.TestCase):
  2115. def test_unsafe_hash(self):
  2116. @dataclass(unsafe_hash=True)
  2117. class C:
  2118. x: int
  2119. y: str
  2120. self.assertEqual(hash(C(1, 'foo')), hash((1, 'foo')))
  2121. def test_hash_rules(self):
  2122. def non_bool(value):
  2123. # Map to something else that's True, but not a bool.
  2124. if value is None:
  2125. return None
  2126. if value:
  2127. return (3,)
  2128. return 0
  2129. def test(case, unsafe_hash, eq, frozen, with_hash, result):
  2130. with self.subTest(case=case, unsafe_hash=unsafe_hash, eq=eq,
  2131. frozen=frozen):
  2132. if result != 'exception':
  2133. if with_hash:
  2134. @dataclass(unsafe_hash=unsafe_hash, eq=eq, frozen=frozen)
  2135. class C:
  2136. def __hash__(self):
  2137. return 0
  2138. else:
  2139. @dataclass(unsafe_hash=unsafe_hash, eq=eq, frozen=frozen)
  2140. class C:
  2141. pass
  2142. # See if the result matches what's expected.
  2143. if result == 'fn':
  2144. # __hash__ contains the function we generated.
  2145. self.assertIn('__hash__', C.__dict__)
  2146. self.assertIsNotNone(C.__dict__['__hash__'])
  2147. elif result == '':
  2148. # __hash__ is not present in our class.
  2149. if not with_hash:
  2150. self.assertNotIn('__hash__', C.__dict__)
  2151. elif result == 'none':
  2152. # __hash__ is set to None.
  2153. self.assertIn('__hash__', C.__dict__)
  2154. self.assertIsNone(C.__dict__['__hash__'])
  2155. elif result == 'exception':
  2156. # Creating the class should cause an exception.
  2157. # This only happens with with_hash==True.
  2158. assert(with_hash)
  2159. with self.assertRaisesRegex(TypeError, 'Cannot overwrite attribute __hash__'):
  2160. @dataclass(unsafe_hash=unsafe_hash, eq=eq, frozen=frozen)
  2161. class C:
  2162. def __hash__(self):
  2163. return 0
  2164. else:
  2165. assert False, f'unknown result {result!r}'
  2166. # There are 8 cases of:
  2167. # unsafe_hash=True/False
  2168. # eq=True/False
  2169. # frozen=True/False
  2170. # And for each of these, a different result if
  2171. # __hash__ is defined or not.
  2172. for case, (unsafe_hash, eq, frozen, res_no_defined_hash, res_defined_hash) in enumerate([
  2173. (False, False, False, '', ''),
  2174. (False, False, True, '', ''),
  2175. (False, True, False, 'none', ''),
  2176. (False, True, True, 'fn', ''),
  2177. (True, False, False, 'fn', 'exception'),
  2178. (True, False, True, 'fn', 'exception'),
  2179. (True, True, False, 'fn', 'exception'),
  2180. (True, True, True, 'fn', 'exception'),
  2181. ], 1):
  2182. test(case, unsafe_hash, eq, frozen, False, res_no_defined_hash)
  2183. test(case, unsafe_hash, eq, frozen, True, res_defined_hash)
  2184. # Test non-bool truth values, too. This is just to
  2185. # make sure the data-driven table in the decorator
  2186. # handles non-bool values.
  2187. test(case, non_bool(unsafe_hash), non_bool(eq), non_bool(frozen), False, res_no_defined_hash)
  2188. test(case, non_bool(unsafe_hash), non_bool(eq), non_bool(frozen), True, res_defined_hash)
  2189. def test_eq_only(self):
  2190. # If a class defines __eq__, __hash__ is automatically added
  2191. # and set to None. This is normal Python behavior, not
  2192. # related to dataclasses. Make sure we don't interfere with
  2193. # that (see bpo=32546).
  2194. @dataclass
  2195. class C:
  2196. i: int
  2197. def __eq__(self, other):
  2198. return self.i == other.i
  2199. self.assertEqual(C(1), C(1))
  2200. self.assertNotEqual(C(1), C(4))
  2201. # And make sure things work in this case if we specify
  2202. # unsafe_hash=True.
  2203. @dataclass(unsafe_hash=True)
  2204. class C:
  2205. i: int
  2206. def __eq__(self, other):
  2207. return self.i == other.i
  2208. self.assertEqual(C(1), C(1.0))
  2209. self.assertEqual(hash(C(1)), hash(C(1.0)))
  2210. # And check that the classes __eq__ is being used, despite
  2211. # specifying eq=True.
  2212. @dataclass(unsafe_hash=True, eq=True)
  2213. class C:
  2214. i: int
  2215. def __eq__(self, other):
  2216. return self.i == 3 and self.i == other.i
  2217. self.assertEqual(C(3), C(3))
  2218. self.assertNotEqual(C(1), C(1))
  2219. self.assertEqual(hash(C(1)), hash(C(1.0)))
  2220. def test_0_field_hash(self):
  2221. @dataclass(frozen=True)
  2222. class C:
  2223. pass
  2224. self.assertEqual(hash(C()), hash(()))
  2225. @dataclass(unsafe_hash=True)
  2226. class C:
  2227. pass
  2228. self.assertEqual(hash(C()), hash(()))
  2229. def test_1_field_hash(self):
  2230. @dataclass(frozen=True)
  2231. class C:
  2232. x: int
  2233. self.assertEqual(hash(C(4)), hash((4,)))
  2234. self.assertEqual(hash(C(42)), hash((42,)))
  2235. @dataclass(unsafe_hash=True)
  2236. class C:
  2237. x: int
  2238. self.assertEqual(hash(C(4)), hash((4,)))
  2239. self.assertEqual(hash(C(42)), hash((42,)))
  2240. def test_hash_no_args(self):
  2241. # Test dataclasses with no hash= argument. This exists to
  2242. # make sure that if the @dataclass parameter name is changed
  2243. # or the non-default hashing behavior changes, the default
  2244. # hashability keeps working the same way.
  2245. class Base:
  2246. def __hash__(self):
  2247. return 301
  2248. # If frozen or eq is None, then use the default value (do not
  2249. # specify any value in the decorator).
  2250. for frozen, eq, base, expected in [
  2251. (None, None, object, 'unhashable'),
  2252. (None, None, Base, 'unhashable'),
  2253. (None, False, object, 'object'),
  2254. (None, False, Base, 'base'),
  2255. (None, True, object, 'unhashable'),
  2256. (None, True, Base, 'unhashable'),
  2257. (False, None, object, 'unhashable'),
  2258. (False, None, Base, 'unhashable'),
  2259. (False, False, object, 'object'),
  2260. (False, False, Base, 'base'),
  2261. (False, True, object, 'unhashable'),
  2262. (False, True, Base, 'unhashable'),
  2263. (True, None, object, 'tuple'),
  2264. (True, None, Base, 'tuple'),
  2265. (True, False, object, 'object'),
  2266. (True, False, Base, 'base'),
  2267. (True, True, object, 'tuple'),
  2268. (True, True, Base, 'tuple'),
  2269. ]:
  2270. with self.subTest(frozen=frozen, eq=eq, base=base, expected=expected):
  2271. # First, create the class.
  2272. if frozen is None and eq is None:
  2273. @dataclass
  2274. class C(base):
  2275. i: int
  2276. elif frozen is None:
  2277. @dataclass(eq=eq)
  2278. class C(base):
  2279. i: int
  2280. elif eq is None:
  2281. @dataclass(frozen=frozen)
  2282. class C(base):
  2283. i: int
  2284. else:
  2285. @dataclass(frozen=frozen, eq=eq)
  2286. class C(base):
  2287. i: int
  2288. # Now, make sure it hashes as expected.
  2289. if expected == 'unhashable':
  2290. c = C(10)
  2291. with self.assertRaisesRegex(TypeError, 'unhashable type'):
  2292. hash(c)
  2293. elif expected == 'base':
  2294. self.assertEqual(hash(C(10)), 301)
  2295. elif expected == 'object':
  2296. # I'm not sure what test to use here. object's
  2297. # hash isn't based on id(), so calling hash()
  2298. # won't tell us much. So, just check the
  2299. # function used is object's.
  2300. self.assertIs(C.__hash__, object.__hash__)
  2301. elif expected == 'tuple':
  2302. self.assertEqual(hash(C(42)), hash((42,)))
  2303. else:
  2304. assert False, f'unknown value for expected={expected!r}'
  2305. class TestFrozen(unittest.TestCase):
  2306. def test_frozen(self):
  2307. @dataclass(frozen=True)
  2308. class C:
  2309. i: int
  2310. c = C(10)
  2311. self.assertEqual(c.i, 10)
  2312. with self.assertRaises(FrozenInstanceError):
  2313. c.i = 5
  2314. self.assertEqual(c.i, 10)
  2315. def test_inherit(self):
  2316. @dataclass(frozen=True)
  2317. class C:
  2318. i: int
  2319. @dataclass(frozen=True)
  2320. class D(C):
  2321. j: int
  2322. d = D(0, 10)
  2323. with self.assertRaises(FrozenInstanceError):
  2324. d.i = 5
  2325. with self.assertRaises(FrozenInstanceError):
  2326. d.j = 6
  2327. self.assertEqual(d.i, 0)
  2328. self.assertEqual(d.j, 10)
  2329. def test_inherit_nonfrozen_from_empty_frozen(self):
  2330. @dataclass(frozen=True)
  2331. class C:
  2332. pass
  2333. with self.assertRaisesRegex(TypeError,
  2334. 'cannot inherit non-frozen dataclass from a frozen one'):
  2335. @dataclass
  2336. class D(C):
  2337. j: int
  2338. def test_inherit_nonfrozen_from_empty(self):
  2339. @dataclass
  2340. class C:
  2341. pass
  2342. @dataclass
  2343. class D(C):
  2344. j: int
  2345. d = D(3)
  2346. self.assertEqual(d.j, 3)
  2347. self.assertIsInstance(d, C)
  2348. # Test both ways: with an intermediate normal (non-dataclass)
  2349. # class and without an intermediate class.
  2350. def test_inherit_nonfrozen_from_frozen(self):
  2351. for intermediate_class in [True, False]:
  2352. with self.subTest(intermediate_class=intermediate_class):
  2353. @dataclass(frozen=True)
  2354. class C:
  2355. i: int
  2356. if intermediate_class:
  2357. class I(C): pass
  2358. else:
  2359. I = C
  2360. with self.assertRaisesRegex(TypeError,
  2361. 'cannot inherit non-frozen dataclass from a frozen one'):
  2362. @dataclass
  2363. class D(I):
  2364. pass
  2365. def test_inherit_frozen_from_nonfrozen(self):
  2366. for intermediate_class in [True, False]:
  2367. with self.subTest(intermediate_class=intermediate_class):
  2368. @dataclass
  2369. class C:
  2370. i: int
  2371. if intermediate_class:
  2372. class I(C): pass
  2373. else:
  2374. I = C
  2375. with self.assertRaisesRegex(TypeError,
  2376. 'cannot inherit frozen dataclass from a non-frozen one'):
  2377. @dataclass(frozen=True)
  2378. class D(I):
  2379. pass
  2380. def test_inherit_from_normal_class(self):
  2381. for intermediate_class in [True, False]:
  2382. with self.subTest(intermediate_class=intermediate_class):
  2383. class C:
  2384. pass
  2385. if intermediate_class:
  2386. class I(C): pass
  2387. else:
  2388. I = C
  2389. @dataclass(frozen=True)
  2390. class D(I):
  2391. i: int
  2392. d = D(10)
  2393. with self.assertRaises(FrozenInstanceError):
  2394. d.i = 5
  2395. def test_non_frozen_normal_derived(self):
  2396. # See bpo-32953.
  2397. @dataclass(frozen=True)
  2398. class D:
  2399. x: int
  2400. y: int = 10
  2401. class S(D):
  2402. pass
  2403. s = S(3)
  2404. self.assertEqual(s.x, 3)
  2405. self.assertEqual(s.y, 10)
  2406. s.cached = True
  2407. # But can't change the frozen attributes.
  2408. with self.assertRaises(FrozenInstanceError):
  2409. s.x = 5
  2410. with self.assertRaises(FrozenInstanceError):
  2411. s.y = 5
  2412. self.assertEqual(s.x, 3)
  2413. self.assertEqual(s.y, 10)
  2414. self.assertEqual(s.cached, True)
  2415. def test_overwriting_frozen(self):
  2416. # frozen uses __setattr__ and __delattr__.
  2417. with self.assertRaisesRegex(TypeError,
  2418. 'Cannot overwrite attribute __setattr__'):
  2419. @dataclass(frozen=True)
  2420. class C:
  2421. x: int
  2422. def __setattr__(self):
  2423. pass
  2424. with self.assertRaisesRegex(TypeError,
  2425. 'Cannot overwrite attribute __delattr__'):
  2426. @dataclass(frozen=True)
  2427. class C:
  2428. x: int
  2429. def __delattr__(self):
  2430. pass
  2431. @dataclass(frozen=False)
  2432. class C:
  2433. x: int
  2434. def __setattr__(self, name, value):
  2435. self.__dict__['x'] = value * 2
  2436. self.assertEqual(C(10).x, 20)
  2437. def test_frozen_hash(self):
  2438. @dataclass(frozen=True)
  2439. class C:
  2440. x: Any
  2441. # If x is immutable, we can compute the hash. No exception is
  2442. # raised.
  2443. hash(C(3))
  2444. # If x is mutable, computing the hash is an error.
  2445. with self.assertRaisesRegex(TypeError, 'unhashable type'):
  2446. hash(C({}))
  2447. class TestSlots(unittest.TestCase):
  2448. def test_simple(self):
  2449. @dataclass
  2450. class C:
  2451. __slots__ = ('x',)
  2452. x: Any
  2453. # There was a bug where a variable in a slot was assumed to
  2454. # also have a default value (of type
  2455. # types.MemberDescriptorType).
  2456. with self.assertRaisesRegex(TypeError,
  2457. r"__init__\(\) missing 1 required positional argument: 'x'"):
  2458. C()
  2459. # We can create an instance, and assign to x.
  2460. c = C(10)
  2461. self.assertEqual(c.x, 10)
  2462. c.x = 5
  2463. self.assertEqual(c.x, 5)
  2464. # We can't assign to anything else.
  2465. with self.assertRaisesRegex(AttributeError, "'C' object has no attribute 'y'"):
  2466. c.y = 5
  2467. def test_derived_added_field(self):
  2468. # See bpo-33100.
  2469. @dataclass
  2470. class Base:
  2471. __slots__ = ('x',)
  2472. x: Any
  2473. @dataclass
  2474. class Derived(Base):
  2475. x: int
  2476. y: int
  2477. d = Derived(1, 2)
  2478. self.assertEqual((d.x, d.y), (1, 2))
  2479. # We can add a new field to the derived instance.
  2480. d.z = 10
  2481. def test_generated_slots(self):
  2482. @dataclass(slots=True)
  2483. class C:
  2484. x: int
  2485. y: int
  2486. c = C(1, 2)
  2487. self.assertEqual((c.x, c.y), (1, 2))
  2488. c.x = 3
  2489. c.y = 4
  2490. self.assertEqual((c.x, c.y), (3, 4))
  2491. with self.assertRaisesRegex(AttributeError, "'C' object has no attribute 'z'"):
  2492. c.z = 5
  2493. def test_add_slots_when_slots_exists(self):
  2494. with self.assertRaisesRegex(TypeError, '^C already specifies __slots__$'):
  2495. @dataclass(slots=True)
  2496. class C:
  2497. __slots__ = ('x',)
  2498. x: int
  2499. def test_generated_slots_value(self):
  2500. class Root:
  2501. __slots__ = {'x'}
  2502. class Root2(Root):
  2503. __slots__ = {'k': '...', 'j': ''}
  2504. class Root3(Root2):
  2505. __slots__ = ['h']
  2506. class Root4(Root3):
  2507. __slots__ = 'aa'
  2508. @dataclass(slots=True)
  2509. class Base(Root4):
  2510. y: int
  2511. j: str
  2512. h: str
  2513. self.assertEqual(Base.__slots__, ('y', ))
  2514. @dataclass(slots=True)
  2515. class Derived(Base):
  2516. aa: float
  2517. x: str
  2518. z: int
  2519. k: str
  2520. h: str
  2521. self.assertEqual(Derived.__slots__, ('z', ))
  2522. @dataclass
  2523. class AnotherDerived(Base):
  2524. z: int
  2525. self.assertNotIn('__slots__', AnotherDerived.__dict__)
  2526. def test_cant_inherit_from_iterator_slots(self):
  2527. class Root:
  2528. __slots__ = iter(['a'])
  2529. class Root2(Root):
  2530. __slots__ = ('b', )
  2531. with self.assertRaisesRegex(
  2532. TypeError,
  2533. "^Slots of 'Root' cannot be determined"
  2534. ):
  2535. @dataclass(slots=True)
  2536. class C(Root2):
  2537. x: int
  2538. def test_returns_new_class(self):
  2539. class A:
  2540. x: int
  2541. B = dataclass(A, slots=True)
  2542. self.assertIsNot(A, B)
  2543. self.assertFalse(hasattr(A, "__slots__"))
  2544. self.assertTrue(hasattr(B, "__slots__"))
  2545. # Can't be local to test_frozen_pickle.
  2546. @dataclass(frozen=True, slots=True)
  2547. class FrozenSlotsClass:
  2548. foo: str
  2549. bar: int
  2550. @dataclass(frozen=True)
  2551. class FrozenWithoutSlotsClass:
  2552. foo: str
  2553. bar: int
  2554. def test_frozen_pickle(self):
  2555. # bpo-43999
  2556. self.assertEqual(self.FrozenSlotsClass.__slots__, ("foo", "bar"))
  2557. for proto in range(pickle.HIGHEST_PROTOCOL + 1):
  2558. with self.subTest(proto=proto):
  2559. obj = self.FrozenSlotsClass("a", 1)
  2560. p = pickle.loads(pickle.dumps(obj, protocol=proto))
  2561. self.assertIsNot(obj, p)
  2562. self.assertEqual(obj, p)
  2563. obj = self.FrozenWithoutSlotsClass("a", 1)
  2564. p = pickle.loads(pickle.dumps(obj, protocol=proto))
  2565. self.assertIsNot(obj, p)
  2566. self.assertEqual(obj, p)
  2567. def test_slots_with_default_no_init(self):
  2568. # Originally reported in bpo-44649.
  2569. @dataclass(slots=True)
  2570. class A:
  2571. a: str
  2572. b: str = field(default='b', init=False)
  2573. obj = A("a")
  2574. self.assertEqual(obj.a, 'a')
  2575. self.assertEqual(obj.b, 'b')
  2576. def test_slots_with_default_factory_no_init(self):
  2577. # Originally reported in bpo-44649.
  2578. @dataclass(slots=True)
  2579. class A:
  2580. a: str
  2581. b: str = field(default_factory=lambda:'b', init=False)
  2582. obj = A("a")
  2583. self.assertEqual(obj.a, 'a')
  2584. self.assertEqual(obj.b, 'b')
  2585. def test_slots_no_weakref(self):
  2586. @dataclass(slots=True)
  2587. class A:
  2588. # No weakref.
  2589. pass
  2590. self.assertNotIn("__weakref__", A.__slots__)
  2591. a = A()
  2592. with self.assertRaisesRegex(TypeError,
  2593. "cannot create weak reference"):
  2594. weakref.ref(a)
  2595. def test_slots_weakref(self):
  2596. @dataclass(slots=True, weakref_slot=True)
  2597. class A:
  2598. a: int
  2599. self.assertIn("__weakref__", A.__slots__)
  2600. a = A(1)
  2601. weakref.ref(a)
  2602. def test_slots_weakref_base_str(self):
  2603. class Base:
  2604. __slots__ = '__weakref__'
  2605. @dataclass(slots=True)
  2606. class A(Base):
  2607. a: int
  2608. # __weakref__ is in the base class, not A. But an A is still weakref-able.
  2609. self.assertIn("__weakref__", Base.__slots__)
  2610. self.assertNotIn("__weakref__", A.__slots__)
  2611. a = A(1)
  2612. weakref.ref(a)
  2613. def test_slots_weakref_base_tuple(self):
  2614. # Same as test_slots_weakref_base, but use a tuple instead of a string
  2615. # in the base class.
  2616. class Base:
  2617. __slots__ = ('__weakref__',)
  2618. @dataclass(slots=True)
  2619. class A(Base):
  2620. a: int
  2621. # __weakref__ is in the base class, not A. But an A is still
  2622. # weakref-able.
  2623. self.assertIn("__weakref__", Base.__slots__)
  2624. self.assertNotIn("__weakref__", A.__slots__)
  2625. a = A(1)
  2626. weakref.ref(a)
  2627. def test_weakref_slot_without_slot(self):
  2628. with self.assertRaisesRegex(TypeError,
  2629. "weakref_slot is True but slots is False"):
  2630. @dataclass(weakref_slot=True)
  2631. class A:
  2632. a: int
  2633. def test_weakref_slot_make_dataclass(self):
  2634. A = make_dataclass('A', [('a', int),], slots=True, weakref_slot=True)
  2635. self.assertIn("__weakref__", A.__slots__)
  2636. a = A(1)
  2637. weakref.ref(a)
  2638. # And make sure if raises if slots=True is not given.
  2639. with self.assertRaisesRegex(TypeError,
  2640. "weakref_slot is True but slots is False"):
  2641. B = make_dataclass('B', [('a', int),], weakref_slot=True)
  2642. def test_weakref_slot_subclass_weakref_slot(self):
  2643. @dataclass(slots=True, weakref_slot=True)
  2644. class Base:
  2645. field: int
  2646. # A *can* also specify weakref_slot=True if it wants to (gh-93521)
  2647. @dataclass(slots=True, weakref_slot=True)
  2648. class A(Base):
  2649. ...
  2650. # __weakref__ is in the base class, not A. But an instance of A
  2651. # is still weakref-able.
  2652. self.assertIn("__weakref__", Base.__slots__)
  2653. self.assertNotIn("__weakref__", A.__slots__)
  2654. a = A(1)
  2655. weakref.ref(a)
  2656. def test_weakref_slot_subclass_no_weakref_slot(self):
  2657. @dataclass(slots=True, weakref_slot=True)
  2658. class Base:
  2659. field: int
  2660. @dataclass(slots=True)
  2661. class A(Base):
  2662. ...
  2663. # __weakref__ is in the base class, not A. Even though A doesn't
  2664. # specify weakref_slot, it should still be weakref-able.
  2665. self.assertIn("__weakref__", Base.__slots__)
  2666. self.assertNotIn("__weakref__", A.__slots__)
  2667. a = A(1)
  2668. weakref.ref(a)
  2669. def test_weakref_slot_normal_base_weakref_slot(self):
  2670. class Base:
  2671. __slots__ = ('__weakref__',)
  2672. @dataclass(slots=True, weakref_slot=True)
  2673. class A(Base):
  2674. field: int
  2675. # __weakref__ is in the base class, not A. But an instance of
  2676. # A is still weakref-able.
  2677. self.assertIn("__weakref__", Base.__slots__)
  2678. self.assertNotIn("__weakref__", A.__slots__)
  2679. a = A(1)
  2680. weakref.ref(a)
  2681. class TestDescriptors(unittest.TestCase):
  2682. def test_set_name(self):
  2683. # See bpo-33141.
  2684. # Create a descriptor.
  2685. class D:
  2686. def __set_name__(self, owner, name):
  2687. self.name = name + 'x'
  2688. def __get__(self, instance, owner):
  2689. if instance is not None:
  2690. return 1
  2691. return self
  2692. # This is the case of just normal descriptor behavior, no
  2693. # dataclass code is involved in initializing the descriptor.
  2694. @dataclass
  2695. class C:
  2696. c: int=D()
  2697. self.assertEqual(C.c.name, 'cx')
  2698. # Now test with a default value and init=False, which is the
  2699. # only time this is really meaningful. If not using
  2700. # init=False, then the descriptor will be overwritten, anyway.
  2701. @dataclass
  2702. class C:
  2703. c: int=field(default=D(), init=False)
  2704. self.assertEqual(C.c.name, 'cx')
  2705. self.assertEqual(C().c, 1)
  2706. def test_non_descriptor(self):
  2707. # PEP 487 says __set_name__ should work on non-descriptors.
  2708. # Create a descriptor.
  2709. class D:
  2710. def __set_name__(self, owner, name):
  2711. self.name = name + 'x'
  2712. @dataclass
  2713. class C:
  2714. c: int=field(default=D(), init=False)
  2715. self.assertEqual(C.c.name, 'cx')
  2716. def test_lookup_on_instance(self):
  2717. # See bpo-33175.
  2718. class D:
  2719. pass
  2720. d = D()
  2721. # Create an attribute on the instance, not type.
  2722. d.__set_name__ = Mock()
  2723. # Make sure d.__set_name__ is not called.
  2724. @dataclass
  2725. class C:
  2726. i: int=field(default=d, init=False)
  2727. self.assertEqual(d.__set_name__.call_count, 0)
  2728. def test_lookup_on_class(self):
  2729. # See bpo-33175.
  2730. class D:
  2731. pass
  2732. D.__set_name__ = Mock()
  2733. # Make sure D.__set_name__ is called.
  2734. @dataclass
  2735. class C:
  2736. i: int=field(default=D(), init=False)
  2737. self.assertEqual(D.__set_name__.call_count, 1)
  2738. def test_init_calls_set(self):
  2739. class D:
  2740. pass
  2741. D.__set__ = Mock()
  2742. @dataclass
  2743. class C:
  2744. i: D = D()
  2745. # Make sure D.__set__ is called.
  2746. D.__set__.reset_mock()
  2747. c = C(5)
  2748. self.assertEqual(D.__set__.call_count, 1)
  2749. def test_getting_field_calls_get(self):
  2750. class D:
  2751. pass
  2752. D.__set__ = Mock()
  2753. D.__get__ = Mock()
  2754. @dataclass
  2755. class C:
  2756. i: D = D()
  2757. c = C(5)
  2758. # Make sure D.__get__ is called.
  2759. D.__get__.reset_mock()
  2760. value = c.i
  2761. self.assertEqual(D.__get__.call_count, 1)
  2762. def test_setting_field_calls_set(self):
  2763. class D:
  2764. pass
  2765. D.__set__ = Mock()
  2766. @dataclass
  2767. class C:
  2768. i: D = D()
  2769. c = C(5)
  2770. # Make sure D.__set__ is called.
  2771. D.__set__.reset_mock()
  2772. c.i = 10
  2773. self.assertEqual(D.__set__.call_count, 1)
  2774. def test_setting_uninitialized_descriptor_field(self):
  2775. class D:
  2776. pass
  2777. D.__set__ = Mock()
  2778. @dataclass
  2779. class C:
  2780. i: D
  2781. # D.__set__ is not called because there's no D instance to call it on
  2782. D.__set__.reset_mock()
  2783. c = C(5)
  2784. self.assertEqual(D.__set__.call_count, 0)
  2785. # D.__set__ still isn't called after setting i to an instance of D
  2786. # because descriptors don't behave like that when stored as instance vars
  2787. c.i = D()
  2788. c.i = 5
  2789. self.assertEqual(D.__set__.call_count, 0)
  2790. def test_default_value(self):
  2791. class D:
  2792. def __get__(self, instance: Any, owner: object) -> int:
  2793. if instance is None:
  2794. return 100
  2795. return instance._x
  2796. def __set__(self, instance: Any, value: int) -> None:
  2797. instance._x = value
  2798. @dataclass
  2799. class C:
  2800. i: D = D()
  2801. c = C()
  2802. self.assertEqual(c.i, 100)
  2803. c = C(5)
  2804. self.assertEqual(c.i, 5)
  2805. def test_no_default_value(self):
  2806. class D:
  2807. def __get__(self, instance: Any, owner: object) -> int:
  2808. if instance is None:
  2809. raise AttributeError()
  2810. return instance._x
  2811. def __set__(self, instance: Any, value: int) -> None:
  2812. instance._x = value
  2813. @dataclass
  2814. class C:
  2815. i: D = D()
  2816. with self.assertRaisesRegex(TypeError, 'missing 1 required positional argument'):
  2817. c = C()
  2818. class TestStringAnnotations(unittest.TestCase):
  2819. def test_classvar(self):
  2820. # Some expressions recognized as ClassVar really aren't. But
  2821. # if you're using string annotations, it's not an exact
  2822. # science.
  2823. # These tests assume that both "import typing" and "from
  2824. # typing import *" have been run in this file.
  2825. for typestr in ('ClassVar[int]',
  2826. 'ClassVar [int]',
  2827. ' ClassVar [int]',
  2828. 'ClassVar',
  2829. ' ClassVar ',
  2830. 'typing.ClassVar[int]',
  2831. 'typing.ClassVar[str]',
  2832. ' typing.ClassVar[str]',
  2833. 'typing .ClassVar[str]',
  2834. 'typing. ClassVar[str]',
  2835. 'typing.ClassVar [str]',
  2836. 'typing.ClassVar [ str]',
  2837. # Not syntactically valid, but these will
  2838. # be treated as ClassVars.
  2839. 'typing.ClassVar.[int]',
  2840. 'typing.ClassVar+',
  2841. ):
  2842. with self.subTest(typestr=typestr):
  2843. @dataclass
  2844. class C:
  2845. x: typestr
  2846. # x is a ClassVar, so C() takes no args.
  2847. C()
  2848. # And it won't appear in the class's dict because it doesn't
  2849. # have a default.
  2850. self.assertNotIn('x', C.__dict__)
  2851. def test_isnt_classvar(self):
  2852. for typestr in ('CV',
  2853. 't.ClassVar',
  2854. 't.ClassVar[int]',
  2855. 'typing..ClassVar[int]',
  2856. 'Classvar',
  2857. 'Classvar[int]',
  2858. 'typing.ClassVarx[int]',
  2859. 'typong.ClassVar[int]',
  2860. 'dataclasses.ClassVar[int]',
  2861. 'typingxClassVar[str]',
  2862. ):
  2863. with self.subTest(typestr=typestr):
  2864. @dataclass
  2865. class C:
  2866. x: typestr
  2867. # x is not a ClassVar, so C() takes one arg.
  2868. self.assertEqual(C(10).x, 10)
  2869. def test_initvar(self):
  2870. # These tests assume that both "import dataclasses" and "from
  2871. # dataclasses import *" have been run in this file.
  2872. for typestr in ('InitVar[int]',
  2873. 'InitVar [int]'
  2874. ' InitVar [int]',
  2875. 'InitVar',
  2876. ' InitVar ',
  2877. 'dataclasses.InitVar[int]',
  2878. 'dataclasses.InitVar[str]',
  2879. ' dataclasses.InitVar[str]',
  2880. 'dataclasses .InitVar[str]',
  2881. 'dataclasses. InitVar[str]',
  2882. 'dataclasses.InitVar [str]',
  2883. 'dataclasses.InitVar [ str]',
  2884. # Not syntactically valid, but these will
  2885. # be treated as InitVars.
  2886. 'dataclasses.InitVar.[int]',
  2887. 'dataclasses.InitVar+',
  2888. ):
  2889. with self.subTest(typestr=typestr):
  2890. @dataclass
  2891. class C:
  2892. x: typestr
  2893. # x is an InitVar, so doesn't create a member.
  2894. with self.assertRaisesRegex(AttributeError,
  2895. "object has no attribute 'x'"):
  2896. C(1).x
  2897. def test_isnt_initvar(self):
  2898. for typestr in ('IV',
  2899. 'dc.InitVar',
  2900. 'xdataclasses.xInitVar',
  2901. 'typing.xInitVar[int]',
  2902. ):
  2903. with self.subTest(typestr=typestr):
  2904. @dataclass
  2905. class C:
  2906. x: typestr
  2907. # x is not an InitVar, so there will be a member x.
  2908. self.assertEqual(C(10).x, 10)
  2909. def test_classvar_module_level_import(self):
  2910. from test import dataclass_module_1
  2911. from test import dataclass_module_1_str
  2912. from test import dataclass_module_2
  2913. from test import dataclass_module_2_str
  2914. for m in (dataclass_module_1, dataclass_module_1_str,
  2915. dataclass_module_2, dataclass_module_2_str,
  2916. ):
  2917. with self.subTest(m=m):
  2918. # There's a difference in how the ClassVars are
  2919. # interpreted when using string annotations or
  2920. # not. See the imported modules for details.
  2921. if m.USING_STRINGS:
  2922. c = m.CV(10)
  2923. else:
  2924. c = m.CV()
  2925. self.assertEqual(c.cv0, 20)
  2926. # There's a difference in how the InitVars are
  2927. # interpreted when using string annotations or
  2928. # not. See the imported modules for details.
  2929. c = m.IV(0, 1, 2, 3, 4)
  2930. for field_name in ('iv0', 'iv1', 'iv2', 'iv3'):
  2931. with self.subTest(field_name=field_name):
  2932. with self.assertRaisesRegex(AttributeError, f"object has no attribute '{field_name}'"):
  2933. # Since field_name is an InitVar, it's
  2934. # not an instance field.
  2935. getattr(c, field_name)
  2936. if m.USING_STRINGS:
  2937. # iv4 is interpreted as a normal field.
  2938. self.assertIn('not_iv4', c.__dict__)
  2939. self.assertEqual(c.not_iv4, 4)
  2940. else:
  2941. # iv4 is interpreted as an InitVar, so it
  2942. # won't exist on the instance.
  2943. self.assertNotIn('not_iv4', c.__dict__)
  2944. def test_text_annotations(self):
  2945. from test import dataclass_textanno
  2946. self.assertEqual(
  2947. get_type_hints(dataclass_textanno.Bar),
  2948. {'foo': dataclass_textanno.Foo})
  2949. self.assertEqual(
  2950. get_type_hints(dataclass_textanno.Bar.__init__),
  2951. {'foo': dataclass_textanno.Foo,
  2952. 'return': type(None)})
  2953. class TestMakeDataclass(unittest.TestCase):
  2954. def test_simple(self):
  2955. C = make_dataclass('C',
  2956. [('x', int),
  2957. ('y', int, field(default=5))],
  2958. namespace={'add_one': lambda self: self.x + 1})
  2959. c = C(10)
  2960. self.assertEqual((c.x, c.y), (10, 5))
  2961. self.assertEqual(c.add_one(), 11)
  2962. def test_no_mutate_namespace(self):
  2963. # Make sure a provided namespace isn't mutated.
  2964. ns = {}
  2965. C = make_dataclass('C',
  2966. [('x', int),
  2967. ('y', int, field(default=5))],
  2968. namespace=ns)
  2969. self.assertEqual(ns, {})
  2970. def test_base(self):
  2971. class Base1:
  2972. pass
  2973. class Base2:
  2974. pass
  2975. C = make_dataclass('C',
  2976. [('x', int)],
  2977. bases=(Base1, Base2))
  2978. c = C(2)
  2979. self.assertIsInstance(c, C)
  2980. self.assertIsInstance(c, Base1)
  2981. self.assertIsInstance(c, Base2)
  2982. def test_base_dataclass(self):
  2983. @dataclass
  2984. class Base1:
  2985. x: int
  2986. class Base2:
  2987. pass
  2988. C = make_dataclass('C',
  2989. [('y', int)],
  2990. bases=(Base1, Base2))
  2991. with self.assertRaisesRegex(TypeError, 'required positional'):
  2992. c = C(2)
  2993. c = C(1, 2)
  2994. self.assertIsInstance(c, C)
  2995. self.assertIsInstance(c, Base1)
  2996. self.assertIsInstance(c, Base2)
  2997. self.assertEqual((c.x, c.y), (1, 2))
  2998. def test_init_var(self):
  2999. def post_init(self, y):
  3000. self.x *= y
  3001. C = make_dataclass('C',
  3002. [('x', int),
  3003. ('y', InitVar[int]),
  3004. ],
  3005. namespace={'__post_init__': post_init},
  3006. )
  3007. c = C(2, 3)
  3008. self.assertEqual(vars(c), {'x': 6})
  3009. self.assertEqual(len(fields(c)), 1)
  3010. def test_class_var(self):
  3011. C = make_dataclass('C',
  3012. [('x', int),
  3013. ('y', ClassVar[int], 10),
  3014. ('z', ClassVar[int], field(default=20)),
  3015. ])
  3016. c = C(1)
  3017. self.assertEqual(vars(c), {'x': 1})
  3018. self.assertEqual(len(fields(c)), 1)
  3019. self.assertEqual(C.y, 10)
  3020. self.assertEqual(C.z, 20)
  3021. def test_other_params(self):
  3022. C = make_dataclass('C',
  3023. [('x', int),
  3024. ('y', ClassVar[int], 10),
  3025. ('z', ClassVar[int], field(default=20)),
  3026. ],
  3027. init=False)
  3028. # Make sure we have a repr, but no init.
  3029. self.assertNotIn('__init__', vars(C))
  3030. self.assertIn('__repr__', vars(C))
  3031. # Make sure random other params don't work.
  3032. with self.assertRaisesRegex(TypeError, 'unexpected keyword argument'):
  3033. C = make_dataclass('C',
  3034. [],
  3035. xxinit=False)
  3036. def test_no_types(self):
  3037. C = make_dataclass('Point', ['x', 'y', 'z'])
  3038. c = C(1, 2, 3)
  3039. self.assertEqual(vars(c), {'x': 1, 'y': 2, 'z': 3})
  3040. self.assertEqual(C.__annotations__, {'x': 'typing.Any',
  3041. 'y': 'typing.Any',
  3042. 'z': 'typing.Any'})
  3043. C = make_dataclass('Point', ['x', ('y', int), 'z'])
  3044. c = C(1, 2, 3)
  3045. self.assertEqual(vars(c), {'x': 1, 'y': 2, 'z': 3})
  3046. self.assertEqual(C.__annotations__, {'x': 'typing.Any',
  3047. 'y': int,
  3048. 'z': 'typing.Any'})
  3049. def test_invalid_type_specification(self):
  3050. for bad_field in [(),
  3051. (1, 2, 3, 4),
  3052. ]:
  3053. with self.subTest(bad_field=bad_field):
  3054. with self.assertRaisesRegex(TypeError, r'Invalid field: '):
  3055. make_dataclass('C', ['a', bad_field])
  3056. # And test for things with no len().
  3057. for bad_field in [float,
  3058. lambda x:x,
  3059. ]:
  3060. with self.subTest(bad_field=bad_field):
  3061. with self.assertRaisesRegex(TypeError, r'has no len\(\)'):
  3062. make_dataclass('C', ['a', bad_field])
  3063. def test_duplicate_field_names(self):
  3064. for field in ['a', 'ab']:
  3065. with self.subTest(field=field):
  3066. with self.assertRaisesRegex(TypeError, 'Field name duplicated'):
  3067. make_dataclass('C', [field, 'a', field])
  3068. def test_keyword_field_names(self):
  3069. for field in ['for', 'async', 'await', 'as']:
  3070. with self.subTest(field=field):
  3071. with self.assertRaisesRegex(TypeError, 'must not be keywords'):
  3072. make_dataclass('C', ['a', field])
  3073. with self.assertRaisesRegex(TypeError, 'must not be keywords'):
  3074. make_dataclass('C', [field])
  3075. with self.assertRaisesRegex(TypeError, 'must not be keywords'):
  3076. make_dataclass('C', [field, 'a'])
  3077. def test_non_identifier_field_names(self):
  3078. for field in ['()', 'x,y', '*', '2@3', '', 'little johnny tables']:
  3079. with self.subTest(field=field):
  3080. with self.assertRaisesRegex(TypeError, 'must be valid identifiers'):
  3081. make_dataclass('C', ['a', field])
  3082. with self.assertRaisesRegex(TypeError, 'must be valid identifiers'):
  3083. make_dataclass('C', [field])
  3084. with self.assertRaisesRegex(TypeError, 'must be valid identifiers'):
  3085. make_dataclass('C', [field, 'a'])
  3086. def test_underscore_field_names(self):
  3087. # Unlike namedtuple, it's okay if dataclass field names have
  3088. # an underscore.
  3089. make_dataclass('C', ['_', '_a', 'a_a', 'a_'])
  3090. def test_funny_class_names_names(self):
  3091. # No reason to prevent weird class names, since
  3092. # types.new_class allows them.
  3093. for classname in ['()', 'x,y', '*', '2@3', '']:
  3094. with self.subTest(classname=classname):
  3095. C = make_dataclass(classname, ['a', 'b'])
  3096. self.assertEqual(C.__name__, classname)
  3097. class TestReplace(unittest.TestCase):
  3098. def test(self):
  3099. @dataclass(frozen=True)
  3100. class C:
  3101. x: int
  3102. y: int
  3103. c = C(1, 2)
  3104. c1 = replace(c, x=3)
  3105. self.assertEqual(c1.x, 3)
  3106. self.assertEqual(c1.y, 2)
  3107. def test_frozen(self):
  3108. @dataclass(frozen=True)
  3109. class C:
  3110. x: int
  3111. y: int
  3112. z: int = field(init=False, default=10)
  3113. t: int = field(init=False, default=100)
  3114. c = C(1, 2)
  3115. c1 = replace(c, x=3)
  3116. self.assertEqual((c.x, c.y, c.z, c.t), (1, 2, 10, 100))
  3117. self.assertEqual((c1.x, c1.y, c1.z, c1.t), (3, 2, 10, 100))
  3118. with self.assertRaisesRegex(ValueError, 'init=False'):
  3119. replace(c, x=3, z=20, t=50)
  3120. with self.assertRaisesRegex(ValueError, 'init=False'):
  3121. replace(c, z=20)
  3122. replace(c, x=3, z=20, t=50)
  3123. # Make sure the result is still frozen.
  3124. with self.assertRaisesRegex(FrozenInstanceError, "cannot assign to field 'x'"):
  3125. c1.x = 3
  3126. # Make sure we can't replace an attribute that doesn't exist,
  3127. # if we're also replacing one that does exist. Test this
  3128. # here, because setting attributes on frozen instances is
  3129. # handled slightly differently from non-frozen ones.
  3130. with self.assertRaisesRegex(TypeError, r"__init__\(\) got an unexpected "
  3131. "keyword argument 'a'"):
  3132. c1 = replace(c, x=20, a=5)
  3133. def test_invalid_field_name(self):
  3134. @dataclass(frozen=True)
  3135. class C:
  3136. x: int
  3137. y: int
  3138. c = C(1, 2)
  3139. with self.assertRaisesRegex(TypeError, r"__init__\(\) got an unexpected "
  3140. "keyword argument 'z'"):
  3141. c1 = replace(c, z=3)
  3142. def test_invalid_object(self):
  3143. @dataclass(frozen=True)
  3144. class C:
  3145. x: int
  3146. y: int
  3147. with self.assertRaisesRegex(TypeError, 'dataclass instance'):
  3148. replace(C, x=3)
  3149. with self.assertRaisesRegex(TypeError, 'dataclass instance'):
  3150. replace(0, x=3)
  3151. def test_no_init(self):
  3152. @dataclass
  3153. class C:
  3154. x: int
  3155. y: int = field(init=False, default=10)
  3156. c = C(1)
  3157. c.y = 20
  3158. # Make sure y gets the default value.
  3159. c1 = replace(c, x=5)
  3160. self.assertEqual((c1.x, c1.y), (5, 10))
  3161. # Trying to replace y is an error.
  3162. with self.assertRaisesRegex(ValueError, 'init=False'):
  3163. replace(c, x=2, y=30)
  3164. with self.assertRaisesRegex(ValueError, 'init=False'):
  3165. replace(c, y=30)
  3166. def test_classvar(self):
  3167. @dataclass
  3168. class C:
  3169. x: int
  3170. y: ClassVar[int] = 1000
  3171. c = C(1)
  3172. d = C(2)
  3173. self.assertIs(c.y, d.y)
  3174. self.assertEqual(c.y, 1000)
  3175. # Trying to replace y is an error: can't replace ClassVars.
  3176. with self.assertRaisesRegex(TypeError, r"__init__\(\) got an "
  3177. "unexpected keyword argument 'y'"):
  3178. replace(c, y=30)
  3179. replace(c, x=5)
  3180. def test_initvar_is_specified(self):
  3181. @dataclass
  3182. class C:
  3183. x: int
  3184. y: InitVar[int]
  3185. def __post_init__(self, y):
  3186. self.x *= y
  3187. c = C(1, 10)
  3188. self.assertEqual(c.x, 10)
  3189. with self.assertRaisesRegex(ValueError, r"InitVar 'y' must be "
  3190. "specified with replace()"):
  3191. replace(c, x=3)
  3192. c = replace(c, x=3, y=5)
  3193. self.assertEqual(c.x, 15)
  3194. def test_initvar_with_default_value(self):
  3195. @dataclass
  3196. class C:
  3197. x: int
  3198. y: InitVar[int] = None
  3199. z: InitVar[int] = 42
  3200. def __post_init__(self, y, z):
  3201. if y is not None:
  3202. self.x += y
  3203. if z is not None:
  3204. self.x += z
  3205. c = C(x=1, y=10, z=1)
  3206. self.assertEqual(replace(c), C(x=12))
  3207. self.assertEqual(replace(c, y=4), C(x=12, y=4, z=42))
  3208. self.assertEqual(replace(c, y=4, z=1), C(x=12, y=4, z=1))
  3209. def test_recursive_repr(self):
  3210. @dataclass
  3211. class C:
  3212. f: "C"
  3213. c = C(None)
  3214. c.f = c
  3215. self.assertEqual(repr(c), "TestReplace.test_recursive_repr.<locals>.C(f=...)")
  3216. def test_recursive_repr_two_attrs(self):
  3217. @dataclass
  3218. class C:
  3219. f: "C"
  3220. g: "C"
  3221. c = C(None, None)
  3222. c.f = c
  3223. c.g = c
  3224. self.assertEqual(repr(c), "TestReplace.test_recursive_repr_two_attrs"
  3225. ".<locals>.C(f=..., g=...)")
  3226. def test_recursive_repr_indirection(self):
  3227. @dataclass
  3228. class C:
  3229. f: "D"
  3230. @dataclass
  3231. class D:
  3232. f: "C"
  3233. c = C(None)
  3234. d = D(None)
  3235. c.f = d
  3236. d.f = c
  3237. self.assertEqual(repr(c), "TestReplace.test_recursive_repr_indirection"
  3238. ".<locals>.C(f=TestReplace.test_recursive_repr_indirection"
  3239. ".<locals>.D(f=...))")
  3240. def test_recursive_repr_indirection_two(self):
  3241. @dataclass
  3242. class C:
  3243. f: "D"
  3244. @dataclass
  3245. class D:
  3246. f: "E"
  3247. @dataclass
  3248. class E:
  3249. f: "C"
  3250. c = C(None)
  3251. d = D(None)
  3252. e = E(None)
  3253. c.f = d
  3254. d.f = e
  3255. e.f = c
  3256. self.assertEqual(repr(c), "TestReplace.test_recursive_repr_indirection_two"
  3257. ".<locals>.C(f=TestReplace.test_recursive_repr_indirection_two"
  3258. ".<locals>.D(f=TestReplace.test_recursive_repr_indirection_two"
  3259. ".<locals>.E(f=...)))")
  3260. def test_recursive_repr_misc_attrs(self):
  3261. @dataclass
  3262. class C:
  3263. f: "C"
  3264. g: int
  3265. c = C(None, 1)
  3266. c.f = c
  3267. self.assertEqual(repr(c), "TestReplace.test_recursive_repr_misc_attrs"
  3268. ".<locals>.C(f=..., g=1)")
  3269. ## def test_initvar(self):
  3270. ## @dataclass
  3271. ## class C:
  3272. ## x: int
  3273. ## y: InitVar[int]
  3274. ## c = C(1, 10)
  3275. ## d = C(2, 20)
  3276. ## # In our case, replacing an InitVar is a no-op
  3277. ## self.assertEqual(c, replace(c, y=5))
  3278. ## replace(c, x=5)
  3279. class TestAbstract(unittest.TestCase):
  3280. def test_abc_implementation(self):
  3281. class Ordered(abc.ABC):
  3282. @abc.abstractmethod
  3283. def __lt__(self, other):
  3284. pass
  3285. @abc.abstractmethod
  3286. def __le__(self, other):
  3287. pass
  3288. @dataclass(order=True)
  3289. class Date(Ordered):
  3290. year: int
  3291. month: 'Month'
  3292. day: 'int'
  3293. self.assertFalse(inspect.isabstract(Date))
  3294. self.assertGreater(Date(2020,12,25), Date(2020,8,31))
  3295. def test_maintain_abc(self):
  3296. class A(abc.ABC):
  3297. @abc.abstractmethod
  3298. def foo(self):
  3299. pass
  3300. @dataclass
  3301. class Date(A):
  3302. year: int
  3303. month: 'Month'
  3304. day: 'int'
  3305. self.assertTrue(inspect.isabstract(Date))
  3306. msg = 'class Date with abstract method foo'
  3307. self.assertRaisesRegex(TypeError, msg, Date)
  3308. class TestMatchArgs(unittest.TestCase):
  3309. def test_match_args(self):
  3310. @dataclass
  3311. class C:
  3312. a: int
  3313. self.assertEqual(C(42).__match_args__, ('a',))
  3314. def test_explicit_match_args(self):
  3315. ma = ()
  3316. @dataclass
  3317. class C:
  3318. a: int
  3319. __match_args__ = ma
  3320. self.assertIs(C(42).__match_args__, ma)
  3321. def test_bpo_43764(self):
  3322. @dataclass(repr=False, eq=False, init=False)
  3323. class X:
  3324. a: int
  3325. b: int
  3326. c: int
  3327. self.assertEqual(X.__match_args__, ("a", "b", "c"))
  3328. def test_match_args_argument(self):
  3329. @dataclass(match_args=False)
  3330. class X:
  3331. a: int
  3332. self.assertNotIn('__match_args__', X.__dict__)
  3333. @dataclass(match_args=False)
  3334. class Y:
  3335. a: int
  3336. __match_args__ = ('b',)
  3337. self.assertEqual(Y.__match_args__, ('b',))
  3338. @dataclass(match_args=False)
  3339. class Z(Y):
  3340. z: int
  3341. self.assertEqual(Z.__match_args__, ('b',))
  3342. # Ensure parent dataclass __match_args__ is seen, if child class
  3343. # specifies match_args=False.
  3344. @dataclass
  3345. class A:
  3346. a: int
  3347. z: int
  3348. @dataclass(match_args=False)
  3349. class B(A):
  3350. b: int
  3351. self.assertEqual(B.__match_args__, ('a', 'z'))
  3352. def test_make_dataclasses(self):
  3353. C = make_dataclass('C', [('x', int), ('y', int)])
  3354. self.assertEqual(C.__match_args__, ('x', 'y'))
  3355. C = make_dataclass('C', [('x', int), ('y', int)], match_args=True)
  3356. self.assertEqual(C.__match_args__, ('x', 'y'))
  3357. C = make_dataclass('C', [('x', int), ('y', int)], match_args=False)
  3358. self.assertNotIn('__match__args__', C.__dict__)
  3359. C = make_dataclass('C', [('x', int), ('y', int)], namespace={'__match_args__': ('z',)})
  3360. self.assertEqual(C.__match_args__, ('z',))
  3361. class TestKeywordArgs(unittest.TestCase):
  3362. def test_no_classvar_kwarg(self):
  3363. msg = 'field a is a ClassVar but specifies kw_only'
  3364. with self.assertRaisesRegex(TypeError, msg):
  3365. @dataclass
  3366. class A:
  3367. a: ClassVar[int] = field(kw_only=True)
  3368. with self.assertRaisesRegex(TypeError, msg):
  3369. @dataclass
  3370. class A:
  3371. a: ClassVar[int] = field(kw_only=False)
  3372. with self.assertRaisesRegex(TypeError, msg):
  3373. @dataclass(kw_only=True)
  3374. class A:
  3375. a: ClassVar[int] = field(kw_only=False)
  3376. def test_field_marked_as_kwonly(self):
  3377. #######################
  3378. # Using dataclass(kw_only=True)
  3379. @dataclass(kw_only=True)
  3380. class A:
  3381. a: int
  3382. self.assertTrue(fields(A)[0].kw_only)
  3383. @dataclass(kw_only=True)
  3384. class A:
  3385. a: int = field(kw_only=True)
  3386. self.assertTrue(fields(A)[0].kw_only)
  3387. @dataclass(kw_only=True)
  3388. class A:
  3389. a: int = field(kw_only=False)
  3390. self.assertFalse(fields(A)[0].kw_only)
  3391. #######################
  3392. # Using dataclass(kw_only=False)
  3393. @dataclass(kw_only=False)
  3394. class A:
  3395. a: int
  3396. self.assertFalse(fields(A)[0].kw_only)
  3397. @dataclass(kw_only=False)
  3398. class A:
  3399. a: int = field(kw_only=True)
  3400. self.assertTrue(fields(A)[0].kw_only)
  3401. @dataclass(kw_only=False)
  3402. class A:
  3403. a: int = field(kw_only=False)
  3404. self.assertFalse(fields(A)[0].kw_only)
  3405. #######################
  3406. # Not specifying dataclass(kw_only)
  3407. @dataclass
  3408. class A:
  3409. a: int
  3410. self.assertFalse(fields(A)[0].kw_only)
  3411. @dataclass
  3412. class A:
  3413. a: int = field(kw_only=True)
  3414. self.assertTrue(fields(A)[0].kw_only)
  3415. @dataclass
  3416. class A:
  3417. a: int = field(kw_only=False)
  3418. self.assertFalse(fields(A)[0].kw_only)
  3419. def test_match_args(self):
  3420. # kw fields don't show up in __match_args__.
  3421. @dataclass(kw_only=True)
  3422. class C:
  3423. a: int
  3424. self.assertEqual(C(a=42).__match_args__, ())
  3425. @dataclass
  3426. class C:
  3427. a: int
  3428. b: int = field(kw_only=True)
  3429. self.assertEqual(C(42, b=10).__match_args__, ('a',))
  3430. def test_KW_ONLY(self):
  3431. @dataclass
  3432. class A:
  3433. a: int
  3434. _: KW_ONLY
  3435. b: int
  3436. c: int
  3437. A(3, c=5, b=4)
  3438. msg = "takes 2 positional arguments but 4 were given"
  3439. with self.assertRaisesRegex(TypeError, msg):
  3440. A(3, 4, 5)
  3441. @dataclass(kw_only=True)
  3442. class B:
  3443. a: int
  3444. _: KW_ONLY
  3445. b: int
  3446. c: int
  3447. B(a=3, b=4, c=5)
  3448. msg = "takes 1 positional argument but 4 were given"
  3449. with self.assertRaisesRegex(TypeError, msg):
  3450. B(3, 4, 5)
  3451. # Explicitly make a field that follows KW_ONLY be non-keyword-only.
  3452. @dataclass
  3453. class C:
  3454. a: int
  3455. _: KW_ONLY
  3456. b: int
  3457. c: int = field(kw_only=False)
  3458. c = C(1, 2, b=3)
  3459. self.assertEqual(c.a, 1)
  3460. self.assertEqual(c.b, 3)
  3461. self.assertEqual(c.c, 2)
  3462. c = C(1, b=3, c=2)
  3463. self.assertEqual(c.a, 1)
  3464. self.assertEqual(c.b, 3)
  3465. self.assertEqual(c.c, 2)
  3466. c = C(1, b=3, c=2)
  3467. self.assertEqual(c.a, 1)
  3468. self.assertEqual(c.b, 3)
  3469. self.assertEqual(c.c, 2)
  3470. c = C(c=2, b=3, a=1)
  3471. self.assertEqual(c.a, 1)
  3472. self.assertEqual(c.b, 3)
  3473. self.assertEqual(c.c, 2)
  3474. def test_KW_ONLY_as_string(self):
  3475. @dataclass
  3476. class A:
  3477. a: int
  3478. _: 'dataclasses.KW_ONLY'
  3479. b: int
  3480. c: int
  3481. A(3, c=5, b=4)
  3482. msg = "takes 2 positional arguments but 4 were given"
  3483. with self.assertRaisesRegex(TypeError, msg):
  3484. A(3, 4, 5)
  3485. def test_KW_ONLY_twice(self):
  3486. msg = "'Y' is KW_ONLY, but KW_ONLY has already been specified"
  3487. with self.assertRaisesRegex(TypeError, msg):
  3488. @dataclass
  3489. class A:
  3490. a: int
  3491. X: KW_ONLY
  3492. Y: KW_ONLY
  3493. b: int
  3494. c: int
  3495. with self.assertRaisesRegex(TypeError, msg):
  3496. @dataclass
  3497. class A:
  3498. a: int
  3499. X: KW_ONLY
  3500. b: int
  3501. Y: KW_ONLY
  3502. c: int
  3503. with self.assertRaisesRegex(TypeError, msg):
  3504. @dataclass
  3505. class A:
  3506. a: int
  3507. X: KW_ONLY
  3508. b: int
  3509. c: int
  3510. Y: KW_ONLY
  3511. # But this usage is okay, since it's not using KW_ONLY.
  3512. @dataclass
  3513. class A:
  3514. a: int
  3515. _: KW_ONLY
  3516. b: int
  3517. c: int = field(kw_only=True)
  3518. # And if inheriting, it's okay.
  3519. @dataclass
  3520. class A:
  3521. a: int
  3522. _: KW_ONLY
  3523. b: int
  3524. c: int
  3525. @dataclass
  3526. class B(A):
  3527. _: KW_ONLY
  3528. d: int
  3529. # Make sure the error is raised in a derived class.
  3530. with self.assertRaisesRegex(TypeError, msg):
  3531. @dataclass
  3532. class A:
  3533. a: int
  3534. _: KW_ONLY
  3535. b: int
  3536. c: int
  3537. @dataclass
  3538. class B(A):
  3539. X: KW_ONLY
  3540. d: int
  3541. Y: KW_ONLY
  3542. def test_post_init(self):
  3543. @dataclass
  3544. class A:
  3545. a: int
  3546. _: KW_ONLY
  3547. b: InitVar[int]
  3548. c: int
  3549. d: InitVar[int]
  3550. def __post_init__(self, b, d):
  3551. raise CustomError(f'{b=} {d=}')
  3552. with self.assertRaisesRegex(CustomError, 'b=3 d=4'):
  3553. A(1, c=2, b=3, d=4)
  3554. @dataclass
  3555. class B:
  3556. a: int
  3557. _: KW_ONLY
  3558. b: InitVar[int]
  3559. c: int
  3560. d: InitVar[int]
  3561. def __post_init__(self, b, d):
  3562. self.a = b
  3563. self.c = d
  3564. b = B(1, c=2, b=3, d=4)
  3565. self.assertEqual(asdict(b), {'a': 3, 'c': 4})
  3566. def test_defaults(self):
  3567. # For kwargs, make sure we can have defaults after non-defaults.
  3568. @dataclass
  3569. class A:
  3570. a: int = 0
  3571. _: KW_ONLY
  3572. b: int
  3573. c: int = 1
  3574. d: int
  3575. a = A(d=4, b=3)
  3576. self.assertEqual(a.a, 0)
  3577. self.assertEqual(a.b, 3)
  3578. self.assertEqual(a.c, 1)
  3579. self.assertEqual(a.d, 4)
  3580. # Make sure we still check for non-kwarg non-defaults not following
  3581. # defaults.
  3582. err_regex = "non-default argument 'z' follows default argument"
  3583. with self.assertRaisesRegex(TypeError, err_regex):
  3584. @dataclass
  3585. class A:
  3586. a: int = 0
  3587. z: int
  3588. _: KW_ONLY
  3589. b: int
  3590. c: int = 1
  3591. d: int
  3592. def test_make_dataclass(self):
  3593. A = make_dataclass("A", ['a'], kw_only=True)
  3594. self.assertTrue(fields(A)[0].kw_only)
  3595. B = make_dataclass("B",
  3596. ['a', ('b', int, field(kw_only=False))],
  3597. kw_only=True)
  3598. self.assertTrue(fields(B)[0].kw_only)
  3599. self.assertFalse(fields(B)[1].kw_only)
  3600. if __name__ == '__main__':
  3601. unittest.main()