ÿØÿà JFIF    ÿÛ „  ( %"1!%)+...383,7(-.+  -+++--++++---+-+-----+---------------+---+-++7-----ÿÀ  ß â" ÿÄ     ÿÄ H    !1AQaq"‘¡2B±ÁÑð#R“Ò Tbr‚²á3csƒ’ÂñDS¢³$CÿÄ   ÿÄ %  !1AQa"23‘ÿÚ   ? ôÿ ¨pŸªáÿ —åYõõ\?àÒü©ŠÄï¨pŸªáÿ —åYõõ\?àÓü©ŠÄá 0Ÿªáÿ Ÿå[úƒ ú®ði~TÁbqÐ8OÕpÿ ƒOò¤Oè`–RÂáœá™êi€ßÉ< FtŸI“öÌ8úDf´°å}“¾œ6  öFá°y¥jñÇh†ˆ¢ã/ÃÐ:ªcÈ "Y¡ðÑl>ÿ ”ÏËte:qž\oäŠe÷󲍷˜HT4&ÿ ÓÐü6ö®¿øþßèô Ÿ•7Ñi’•j|“ñì>b…þS?*Óôÿ ÓÐü*h¥£ír¶ü UãS炟[AÐaè[ûª•õ&õj?†Éö+EzP—WeÒírJFt ‘BŒ†Ï‡%#tE Øz ¥OÛ«!1›üä±Í™%ºÍãö]°î(–:@<‹ŒÊö×òÆt¦ãº+‡¦%ÌÁ²h´OƒJŒtMÜ>ÀÜÊw3Y´•牋4ǍýʏTì>œú=Íwhyë,¾Ôò×õ¿ßÊa»«þˆѪQ|%6ž™A õ%:øj<>É—ÿ Å_ˆCbõ¥š±ý¯Ýƒï…¶|RëócÍf溪“t.СøTÿ *Ä¿-{†çàczůŽ_–^XþŒ±miB[X±d 1,é”zEù»& î9gœf™9Ð'.;—™i}!ôšåîqêÛ٤ёý£½ÆA–àôe"A$˝Úsäÿ ÷Û #°xŸëí(l »ý3—¥5m! rt`†0~'j2(]S¦¦kv,ÚÇ l¦øJA£Šƒ J3E8ÙiŽ:cÉžúeZ°€¯\®kÖ(79«Ž:¯X”¾³Š&¡* ….‰Ž(ÜíŸ2¥ª‡×Hi²TF¤ò[¨íÈRëÉ䢍mgÑ.Ÿ<öäS0í„ǹÁU´f#Vß;Õ–…P@3ío<ä-±»Ž.L|kªÀê›fÂ6@»eu‚|ÓaÞÆŸ…¨ááå>åŠ?cKü6ùTÍÆ”†sĤÚ;H2RÚ†õ\Ö·Ÿn'¾ ñ#ºI¤Å´%çÁ­‚â7›‹qT3Iï¨ÖÚ5I7Ë!ÅOóŸ¶øÝñØôת¦$Tcö‘[«Ö³šÒ';Aþ ¸èíg A2Z"i¸vdÄ÷.iõ®§)¿]¤À†–‡É&ä{V¶iŽ”.Ó×Õÿ û?h¬Mt–íª[ÿ Ñÿ ÌV(í}=ibÔ¡›¥¢±b Lô¥‡piη_Z<‡z§èŒ)iÖwiÇ 2hÙ3·=’d÷8éŽ1¦¸c¤µ€7›7Ø ð\á)} ¹fËí›pAÃL%âc2 í§æQz¿;T8sæ°qø)QFMð‰XŒÂ±N¢aF¨…8¯!U  Z©RÊ ÖPVÄÀÍin™Ì-GˆªÅËŠ›•zË}º±ŽÍFò¹}Uw×#ä5B¤{î}Ð<ÙD é©¤&‡ïDbàÁôMÁ." ¤‡ú*õ'VŽ|¼´Úgllº¼klz[Æüï÷Aób‡Eÿ dÑ»Xx9ÃÜ£ÁT/`¼¸vI±Ýµ·Ë‚“G³þ*Ÿû´r|*}<¨îºœ @¦mÄ’M¹”.œ«Y–|6ÏU¤jç¥ÕÞqO ˜kDÆÁ¨5ÿ š;ÐЦ¦€GÙk \ –Þ=â¼=SͧµªS°ÚÍpÜãQűÀõ¬?ÃÁ1Ñ•õZà?hóœ€ L¦l{Y*K˜Ù›zc˜–ˆâ ø+¾ ­-Ök¥%ùEÜA'}ˆ><ÊIè“bpÍ/qÞâvoX€w,\úªò6Z[XdÒæ­@Ö—€$òJí#é>'°Ú ôª˜<)4ryÙ£|óAÅn5žêŸyÒäMÝ2{"}‰–¤l÷ûWX\l¾Á¸góÉOÔ /óñB¤f¸çñ[.P˜ZsÊË*ßT܈§QN¢’¡¨§V¼(Üù*eÕ“”5T¨‹Âê¥FŒã½Dü[8'Ò¥a…Ú¶k7a *•›¼'Ò·\8¨ª\@\õ¢¦íq+DÙrmÎ…_ªæ»ŠÓœ¡¯’Ré9MÅ×D™lælffc+ŒÑ,ý™ÿ ¯þǤ=Å’Á7µ÷ÚÛ/“Ü€ñýã¼àí¾ÕÑ+ƒ,uµMâÀÄbm:ÒÎPæ{˜Gz[ƒ¯«® KHà`ߨŠéí¯P8Aq.C‰ à€kòpj´kN¶qô€…Õ,ÜNŠª-­{Zö’æû44‰sŽè‰îVíRœÕm" 6?³D9¡ÇTíÅꋇ`4«¸ÝÁô ï’ýorqКÇZ«x4Žâéþuïf¹µö[P ,Q£éaX±`PÉÍZ ¸äYúg üAx ’6Lê‚xÝÓ*äQ  Ï’¨hÍ =²,6ï#rÃ<¯–£»ƒ‹,–ê•€ aÛsñ'%Æ"®ÛüìBᝠHÚ3ß°©$“XnœÖ’î2ËTeûìxîß ¦å¿çÉ ðK§þ{‘t‚Ϋ¬jéîZ[ ”š7L¥4VÚCE×]m¤Øy”ä4-dz£œ§¸x.*ãÊÊ b÷•h:©‡¦s`BTÁRû¾g⻩‹jø sF¢àJøFl‘È•Xᓁà~*j¯ +(ÚÕ6-£¯÷GŠØy‚<Ç’.F‹Hœw(+)ÜÜâÈzÄäT§FߘãÏ;DmVœ3Àu@mÚüXÝü•3B¨òÌÁÛ<·ÃÜ z,Ì@õÅ·d2]ü8s÷IôÞ¯^Ç9¢u„~ëAŸï4«M? K]­ÅàPl@s_ p:°¬ZR”´›JC[CS.h‹ƒïËœ«Æ]–÷ó‚wR×k7X‰k›‘´ù¦=¡«‰¨¨Â')—71ó’c‡Ðúµ `é.{§p¹ój\Ž{1h{o±Ý=áUÊïGÖŒõ–-BÄm+AZX¶¡ ïHðæ¥JmÙ;…䡟ˆ¦ ° äšiÉg«$üMk5¤L“’çÊvïâï ,=f“"íἊ5ô¬x6{ɏžID0e¸vçmi'︧ºð9$ò¹÷*£’9ÿ ²TÔ…×>JV¥}Œ}$p[bÔ®*[jzS*8 ”·T›Í–ñUîƒwo$áè=LT™ç—~ô·¤ÈÚ$榍q‰„+´kFm)ž‹©i–ËqÞŠ‰à¶ü( ‚•§ •°ò·‡#5ª•µÊ﯅¡X¨šÁ*F#TXJÊ ušJVÍ&=iÄs1‚3•'fý§5Ñ<=[íÞ­ PÚ;ѱÌ_~Ä££8rÞ ²w;’hDT°>ÈG¬8Á²ÚzŽ®ò®qZcqJêäÞ-ö[ܘbň±çb“ж31²n×iƒðÕ;1¶þÉ ªX‰,ßqÏ$>•î íZ¥Z 1{ç൵+ƒÕµ¥°T$§K]á»Ûï*·¤tMI’ÂZbŽÕiÒ˜}bÓ0£ª5›¨ [5Ž^ÝœWøÂÝh° ¢OWun£¤5 a2Z.G2³YL]jåtì”ä ÁÓ‘%"©<Ôúʰsº UZvä‡ÄiÆÒM .÷V·™ø#kèýiíÌ–ª)µT[)BˆõÑ xB¾B€ÖT¨.¥~ð@VĶr#¸ü*åZNDŽH;âi ],©£öØpù(šºãö¼T.uCê•4@ÿ GÕÛ)Cx›®0ø#:ÏðFÒbR\(€€Ä®fã4Þ‰Fä¯HXƒÅ,†öEÑÔÜ]Öv²?tLÃvBY£ú6Êu5ÅAQ³1‘’¬x–HŒÐ‡ ^ ¸KwJôÖŽ5×CÚ¨vÜ«/B0$×k°=ðbÇ(Ï)w±A†Á† 11Í=èQšµ626ŒÜ/`G«µ<}—-Ö7KEHÈÉðóȤmݱû±·ø«Snmá=“䫚mݱŸ¡¶~ó·“äUóJæúòB|E LêŽy´jDÔ$G¢þÐñ7óR8ýÒ…Ç› WVe#·Ÿ p·Fx~•ݤF÷0Èÿ K¯æS<6’¡WШ; ´ÿ ¥Êø\Òuî†åÝ–VNœkÒ7oòX¨Á­Ø÷FÎÑä±g÷ÿ M~Çî=p,X´ ÝÌÚÅ‹’ÃjÖ.ØöÏñ qïQ¤ÓZE†° =6·]܈ s¸>v•Ž^Ý\wq9r‰Î\¸¡kURÒ$­*‹Nq?Þª*!sŠÆ:TU_u±T+øX¡ ®¹¡,ÄâÃBTsÜ$Ø›4m椴zÜK]’’›Pƒ @€#â˜`é¹=I‡fiV•Ôî“nRm+µFPOhÍ0B£ €+¬5c v•:P'ÒyÎ ‰V~‚Ó†ÖuókDoh$å\*ö%Ю=£«…aȼ½÷Û.-½VŒŠ¼'lyî±1¬3ó#ÞE¿ÔS¤gV£m›=§\û"—WU¤ÚǼÿ ÂnÁGŒÃ ‚õN D³õNÚíŒÕ;HôyÄÈ©P¹Ä{:?R‘Ô¨âF÷ø£bÅó® JS|‚R÷ivýáâ€Æé¡è³´IئÑT!§˜•ت‚¬â@q€wnïCWÄ@JU€ê¯m6]Ï:£âx'+ÒðXvÓ¦Úm=–´7œ $ì“B£~p%ÕŸUþ« N@¼üï~w˜ñø5®—'Ôe»¤5ã//€ž~‰Tþ›Å7•#¤× Íö pÄ$ùeåì*«ÓŠEØWEÈsßg ¦ûvžSsLpºÊW–âµEWöˬH; ™!CYõZ ÃÄf æ#1W. \uWâ\,\Çf j’<qTbên›Î[vxx£ë 'ö¨1›˜ÀM¼Pÿ H)ƒêêŒA7s,|F“ 꺸k³9Ìö*ç®;Ö!Ö$Eiž•¹ÒÚ†ýóéÝû¾ÕS®ó$’NÝäŸz¤5r¦ãÄÃD÷Üø!°ø‡Ô&@m™Ì^Ãä­d q5Lnÿ N;.6½·N|#ä"1Nƒx“ã<3('&ñßt  ~ªu”1Tb㫨9ê–›–bìd$ߣ=#ÕãÒmU¯eí$EFù5ýYô櫨æì™Ç—±ssM]·á¿0ÕåJRÓªîiƒ+O58ÖñªŠÒx" \µâá¨i’¤i —Ö ” M+M¤ë9‚‰A¦°Qõ¾ßøK~¼Ã‘g…Ö´~÷Ï[3GUœÒ½#…kàÔ®Ò”‰³·dWV‰IP‰Ú8u¹”E ÖqLj¾êÕCBš{A^Âß;–¨`¯¬ìö ˼ ×tìø.tƐm*n¨y4o&Àx¥n¦×î‡aupáÛj8¿m›è¶ã!o½;ß0y^ý×^EÑ¿ÒjzŒ­)vÚÑnÄL …^ªô× ‡—‚3k Îý­hï]içå–îÏ*÷ñþ»Ô CÒjøjÍznˆ´ ¹#b'Fô‹ ‰v¥'’à'T´ƒHýÍ%M‰ ƒ&ÆÇŒï1 ‘ –Þ ‰i¬s žR-Ÿ kЬá¬7:þ 0ŒÅÒÕ/aÙ¬ÃÝ#Úøœ ©aiVc‰. ¹¦ãµ” ›Yg¦›ÆÎýº°f³7ƒhá·¸­}&D9¡ÂsÉÙÞèŠõØàC™¨ñbFC|´Ü(ŸƒÚÒ-%»'a Ì¿)ËÇn¿úÿ ÞŽX…4ÊÅH^ôΑí@ù¹Eh¶“L8Çjù ¼ÎåVªóR©Ï5uà V4lZß®=€xÖŸ–ÑÈ ÷”¨°¾__yM1tÉ?uÆþIkÄgæ@þ[¢†°XÃJ£j·:nkÅ¢u ‘}âGzö­/IµèЬ¼48q¦F°ŽR¼=ûì{´¯RýicS ÕÛ íNtÍÙï£,w4rêì®»~x(©Uñ§#Ñ&œÕ¤>ÎåÍÓ9’Ö{9eV­[Öjâ²ãu]˜å2›qÑšÕJç0€sÄ|Êëè0튔bÁ>“{×_F`Ø©ºê:µä,v¤ðfc1±"«ÔÍän1#=· Âøv~H½ÐßA¾¿Ü€Óš]Õ; I¾÷ç‚Qi†î¹9ywÔKG˜áñ zQY—§ÃÕZ07§X‚ Áh;ÁM)iÌCH-¯T‘ë|A0{Ò½LÚ–TâÖkÜ’dÀ“rmm»”جPF³ÖcbE§T€ÒxKºû’Ó®7±²(\4ŽÃ¸Uu@j™yĵ;³µ!Á¢b.W¤=mõ´êµK k ¸K^ÜÛ#p*Ü14qkZç5ïë †°5Ï%ÍÛ<Õ¤×Ô¥ê†C Õ´¼ú$ƒÖ“”]Ù¬qÞÚ[4©ý!ûÏ—Áb쳐XµA¬â~`›Çr¸8ìùÝ䫦<>ä÷«?xs´ÇÑ /á;¹øüÊÈÙà{"@Žïzâ¬[âß‚ U_<ÇŸ½4èN˜ú61®qŠu ¦þF£»äJ_ˆÙÎ~ ÞAã–݄ϗrŠD;xTž‘ô`É«…suãO`?³à™ô Lý#Íc5öoæØ‚y´´÷«ZR§<&JÇ+éâô´€i!Àˆ0æAoàðLèÖ-2ŸõW.’t^–(KÁmHµV@xÜÇy®Ñø­â^:Ú3w· 7½¹°ñ¸â¹®:',«Mœ—n­Á+Ãbš LÈ‘ÄnRÓÅœ%¦²‰¨ùQ:¤f‚ "PÕtô¸…cæl…&˜Ú˜Ôkv‹ž+vŠ,=¢v­6—Xy*¥t£«<™:“aîϲ=¦6rO]XI¿Œ÷¤zÚ­›¶ 6÷”w\d ü~v®ˆÌk«^m<ÿ ¢‰Õ\)ùºŽ;… lîÙÅEŠ®cѾ@vnMÏ,¼“ñ•ŽBxðÃzãÇç%3ˆ"}Ù•Åî> BÉú;Ò]V+P˜F_´ßé> Øše|ï‡ÄOmFæÇ ãqÞ$/xÐx­z`ï9"œÜij‚!7.\Td…9M‡•iŽ‹¾‘50ÞŽn¥ß4ÉôO ¹*í^QêËÜÇÌ8=ާs‰'ÂëÙ«á%Pú[O †ÅP¯Vsް.‰,kc¶ ¬A9n˜XÎ-ÞšN["¹QÕ‰ƒMýÁߺXJæÍaLj¾×Ãmã¾ãÚ uñÒþåQô¦¥ /ÄUx:‚ÍÜ’ Đ©ØÝ3V¨‰ÕnÐ6ó*óúK­«…c ¯U òhsý­jóÔj#,ímŒRµ«lbïUTŒÑ8†Ä0œÏr`ð¡¬É Ї ë"À² ™ 6¥ f¶ ¢ÚoܱԷ-<Àî)†a¶ž'Ú»¨TXqØæ¶÷YÄHy˜9ÈIW­YÀuMFë ºÏ’AqÌ4·/Ú †ô'i$øä­=Ä Ý|öK×40è|È6p‘0§)o¥ctî§H+CA-“ xØ|ÐXАç l8íºð3Ø:³¤¬KX¯UÿÙ # Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ Tests for L{twisted.python.compat}. """ from __future__ import division, absolute_import import socket, sys, traceback, io, codecs from twisted.trial import unittest from twisted.python.compat import ( reduce, execfile, _PY3, _PYPY, comparable, cmp, nativeString, networkString, unicode as unicodeCompat, lazyByteSlice, reraise, NativeStringIO, iterbytes, intToBytes, ioType, bytesEnviron, iteritems, _coercedUnicode, unichr, raw_input, _bytesRepr, _get_async_param, ) from twisted.python.filepath import FilePath from twisted.python.runtime import platform class IOTypeTests(unittest.SynchronousTestCase): """ Test cases for determining a file-like object's type. """ def test_3StringIO(self): """ An L{io.StringIO} accepts and returns text. """ self.assertEqual(ioType(io.StringIO()), unicodeCompat) def test_3BytesIO(self): """ An L{io.BytesIO} accepts and returns bytes. """ self.assertEqual(ioType(io.BytesIO()), bytes) def test_3openTextMode(self): """ A file opened via 'io.open' in text mode accepts and returns text. """ with io.open(self.mktemp(), "w") as f: self.assertEqual(ioType(f), unicodeCompat) def test_3openBinaryMode(self): """ A file opened via 'io.open' in binary mode accepts and returns bytes. """ with io.open(self.mktemp(), "wb") as f: self.assertEqual(ioType(f), bytes) def test_2openTextMode(self): """ The special built-in console file in Python 2 which has an 'encoding' attribute should qualify as a special type, since it accepts both bytes and text faithfully. """ class VerySpecificLie(file): """ In their infinite wisdom, the CPython developers saw fit not to allow us a writable 'encoding' attribute on the built-in 'file' type in Python 2, despite making it writable in C with PyFile_SetEncoding. Pretend they did not do that. """ encoding = 'utf-8' self.assertEqual(ioType(VerySpecificLie(self.mktemp(), "wb")), basestring) def test_2StringIO(self): """ Python 2's L{StringIO} and L{cStringIO} modules are both binary I/O. """ from cStringIO import StringIO as cStringIO from StringIO import StringIO self.assertEqual(ioType(StringIO()), bytes) self.assertEqual(ioType(cStringIO()), bytes) def test_2openBinaryMode(self): """ The normal 'open' builtin in Python 2 will always result in bytes I/O. """ with open(self.mktemp(), "w") as f: self.assertEqual(ioType(f), bytes) if _PY3: test_2openTextMode.skip = "The 'file' type is no longer available." test_2openBinaryMode.skip = "'io.open' is now the same as 'open'." test_2StringIO.skip = ("The 'StringIO' and 'cStringIO' modules were " "subsumed by the 'io' module.") def test_codecsOpenBytes(self): """ The L{codecs} module, oddly, returns a file-like object which returns bytes when not passed an 'encoding' argument. """ with codecs.open(self.mktemp(), 'wb') as f: self.assertEqual(ioType(f), bytes) def test_codecsOpenText(self): """ When passed an encoding, however, the L{codecs} module returns unicode. """ with codecs.open(self.mktemp(), 'wb', encoding='utf-8') as f: self.assertEqual(ioType(f), unicodeCompat) def test_defaultToText(self): """ When passed an object about which no sensible decision can be made, err on the side of unicode. """ self.assertEqual(ioType(object()), unicodeCompat) class CompatTests(unittest.SynchronousTestCase): """ Various utility functions in C{twisted.python.compat} provide same functionality as modern Python variants. """ def test_set(self): """ L{set} should behave like the expected set interface. """ a = set() a.add('b') a.add('c') a.add('a') b = list(a) b.sort() self.assertEqual(b, ['a', 'b', 'c']) a.remove('b') b = list(a) b.sort() self.assertEqual(b, ['a', 'c']) a.discard('d') b = set(['r', 's']) d = a.union(b) b = list(d) b.sort() self.assertEqual(b, ['a', 'c', 'r', 's']) def test_frozenset(self): """ L{frozenset} should behave like the expected frozenset interface. """ a = frozenset(['a', 'b']) self.assertRaises(AttributeError, getattr, a, "add") self.assertEqual(sorted(a), ['a', 'b']) b = frozenset(['r', 's']) d = a.union(b) b = list(d) b.sort() self.assertEqual(b, ['a', 'b', 'r', 's']) def test_reduce(self): """ L{reduce} should behave like the builtin reduce. """ self.assertEqual(15, reduce(lambda x, y: x + y, [1, 2, 3, 4, 5])) self.assertEqual(16, reduce(lambda x, y: x + y, [1, 2, 3, 4, 5], 1)) class IPv6Tests(unittest.SynchronousTestCase): """ C{inet_pton} and C{inet_ntop} implementations support IPv6. """ def testNToP(self): from twisted.python.compat import inet_ntop f = lambda a: inet_ntop(socket.AF_INET6, a) g = lambda a: inet_ntop(socket.AF_INET, a) self.assertEqual('::', f('\x00' * 16)) self.assertEqual('::1', f('\x00' * 15 + '\x01')) self.assertEqual( 'aef:b01:506:1001:ffff:9997:55:170', f('\x0a\xef\x0b\x01\x05\x06\x10\x01\xff\xff\x99\x97\x00\x55\x01' '\x70')) self.assertEqual('1.0.1.0', g('\x01\x00\x01\x00')) self.assertEqual('170.85.170.85', g('\xaa\x55\xaa\x55')) self.assertEqual('255.255.255.255', g('\xff\xff\xff\xff')) self.assertEqual('100::', f('\x01' + '\x00' * 15)) self.assertEqual('100::1', f('\x01' + '\x00' * 14 + '\x01')) def testPToN(self): """ L{twisted.python.compat.inet_pton} parses IPv4 and IPv6 addresses in a manner similar to that of L{socket.inet_pton}. """ from twisted.python.compat import inet_pton f = lambda a: inet_pton(socket.AF_INET6, a) g = lambda a: inet_pton(socket.AF_INET, a) self.assertEqual('\x00\x00\x00\x00', g('0.0.0.0')) self.assertEqual('\xff\x00\xff\x00', g('255.0.255.0')) self.assertEqual('\xaa\xaa\xaa\xaa', g('170.170.170.170')) self.assertEqual('\x00' * 16, f('::')) self.assertEqual('\x00' * 16, f('0::0')) self.assertEqual('\x00\x01' + '\x00' * 14, f('1::')) self.assertEqual( '\x45\xef\x76\xcb\x00\x1a\x56\xef\xaf\xeb\x0b\xac\x19\x24\xae\xae', f('45ef:76cb:1a:56ef:afeb:bac:1924:aeae')) # Scope ID doesn't affect the binary representation. self.assertEqual( '\x45\xef\x76\xcb\x00\x1a\x56\xef\xaf\xeb\x0b\xac\x19\x24\xae\xae', f('45ef:76cb:1a:56ef:afeb:bac:1924:aeae%en0')) self.assertEqual('\x00' * 14 + '\x00\x01', f('::1')) self.assertEqual('\x00' * 12 + '\x01\x02\x03\x04', f('::1.2.3.4')) self.assertEqual( '\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x01\x02\x03\xff', f('1:2:3:4:5:6:1.2.3.255')) for badaddr in ['1:2:3:4:5:6:7:8:', ':1:2:3:4:5:6:7:8', '1::2::3', '1:::3', ':::', '1:2', '::1.2', '1.2.3.4::', 'abcd:1.2.3.4:abcd:abcd:abcd:abcd:abcd', '1234:1.2.3.4:1234:1234:1234:1234:1234:1234', '1.2.3.4', '', '%eth0']: self.assertRaises(ValueError, f, badaddr) if _PY3: IPv6Tests.skip = "These tests are only relevant to old versions of Python" class ExecfileCompatTests(unittest.SynchronousTestCase): """ Tests for the Python 3-friendly L{execfile} implementation. """ def writeScript(self, content): """ Write L{content} to a new temporary file, returning the L{FilePath} for the new file. """ path = self.mktemp() with open(path, "wb") as f: f.write(content.encode("ascii")) return FilePath(path.encode("utf-8")) def test_execfileGlobals(self): """ L{execfile} executes the specified file in the given global namespace. """ script = self.writeScript(u"foo += 1\n") globalNamespace = {"foo": 1} execfile(script.path, globalNamespace) self.assertEqual(2, globalNamespace["foo"]) def test_execfileGlobalsAndLocals(self): """ L{execfile} executes the specified file in the given global and local namespaces. """ script = self.writeScript(u"foo += 1\n") globalNamespace = {"foo": 10} localNamespace = {"foo": 20} execfile(script.path, globalNamespace, localNamespace) self.assertEqual(10, globalNamespace["foo"]) self.assertEqual(21, localNamespace["foo"]) def test_execfileUniversalNewlines(self): """ L{execfile} reads in the specified file using universal newlines so that scripts written on one platform will work on another. """ for lineEnding in u"\n", u"\r", u"\r\n": script = self.writeScript(u"foo = 'okay'" + lineEnding) globalNamespace = {"foo": None} execfile(script.path, globalNamespace) self.assertEqual("okay", globalNamespace["foo"]) class PY3Tests(unittest.SynchronousTestCase): """ Identification of Python 2 vs. Python 3. """ def test_python2(self): """ On Python 2, C{_PY3} is False. """ if sys.version.startswith("2."): self.assertFalse(_PY3) def test_python3(self): """ On Python 3, C{_PY3} is True. """ if sys.version.startswith("3."): self.assertTrue(_PY3) class PYPYTest(unittest.SynchronousTestCase): """ Identification of PyPy. """ def test_PYPY(self): """ On PyPy, L{_PYPY} is True. """ if 'PyPy' in sys.version: self.assertTrue(_PYPY) else: self.assertFalse(_PYPY) @comparable class Comparable(object): """ Objects that can be compared to each other, but not others. """ def __init__(self, value): self.value = value def __cmp__(self, other): if not isinstance(other, Comparable): return NotImplemented return cmp(self.value, other.value) class ComparableTests(unittest.SynchronousTestCase): """ L{comparable} decorated classes emulate Python 2's C{__cmp__} semantics. """ def test_equality(self): """ Instances of a class that is decorated by C{comparable} support equality comparisons. """ # Make explicitly sure we're using ==: self.assertTrue(Comparable(1) == Comparable(1)) self.assertFalse(Comparable(2) == Comparable(1)) def test_nonEquality(self): """ Instances of a class that is decorated by C{comparable} support inequality comparisons. """ # Make explicitly sure we're using !=: self.assertFalse(Comparable(1) != Comparable(1)) self.assertTrue(Comparable(2) != Comparable(1)) def test_greaterThan(self): """ Instances of a class that is decorated by C{comparable} support greater-than comparisons. """ self.assertTrue(Comparable(2) > Comparable(1)) self.assertFalse(Comparable(0) > Comparable(3)) def test_greaterThanOrEqual(self): """ Instances of a class that is decorated by C{comparable} support greater-than-or-equal comparisons. """ self.assertTrue(Comparable(1) >= Comparable(1)) self.assertTrue(Comparable(2) >= Comparable(1)) self.assertFalse(Comparable(0) >= Comparable(3)) def test_lessThan(self): """ Instances of a class that is decorated by C{comparable} support less-than comparisons. """ self.assertTrue(Comparable(0) < Comparable(3)) self.assertFalse(Comparable(2) < Comparable(0)) def test_lessThanOrEqual(self): """ Instances of a class that is decorated by C{comparable} support less-than-or-equal comparisons. """ self.assertTrue(Comparable(3) <= Comparable(3)) self.assertTrue(Comparable(0) <= Comparable(3)) self.assertFalse(Comparable(2) <= Comparable(0)) class Python3ComparableTests(unittest.SynchronousTestCase): """ Python 3-specific functionality of C{comparable}. """ def test_notImplementedEquals(self): """ Instances of a class that is decorated by C{comparable} support returning C{NotImplemented} from C{__eq__} if it is returned by the underlying C{__cmp__} call. """ self.assertEqual(Comparable(1).__eq__(object()), NotImplemented) def test_notImplementedNotEquals(self): """ Instances of a class that is decorated by C{comparable} support returning C{NotImplemented} from C{__ne__} if it is returned by the underlying C{__cmp__} call. """ self.assertEqual(Comparable(1).__ne__(object()), NotImplemented) def test_notImplementedGreaterThan(self): """ Instances of a class that is decorated by C{comparable} support returning C{NotImplemented} from C{__gt__} if it is returned by the underlying C{__cmp__} call. """ self.assertEqual(Comparable(1).__gt__(object()), NotImplemented) def test_notImplementedLessThan(self): """ Instances of a class that is decorated by C{comparable} support returning C{NotImplemented} from C{__lt__} if it is returned by the underlying C{__cmp__} call. """ self.assertEqual(Comparable(1).__lt__(object()), NotImplemented) def test_notImplementedGreaterThanEquals(self): """ Instances of a class that is decorated by C{comparable} support returning C{NotImplemented} from C{__ge__} if it is returned by the underlying C{__cmp__} call. """ self.assertEqual(Comparable(1).__ge__(object()), NotImplemented) def test_notImplementedLessThanEquals(self): """ Instances of a class that is decorated by C{comparable} support returning C{NotImplemented} from C{__le__} if it is returned by the underlying C{__cmp__} call. """ self.assertEqual(Comparable(1).__le__(object()), NotImplemented) if not _PY3: # On Python 2, we just use __cmp__ directly, so checking detailed # comparison methods doesn't makes sense. Python3ComparableTests.skip = "Python 3 only." class CmpTests(unittest.SynchronousTestCase): """ L{cmp} should behave like the built-in Python 2 C{cmp}. """ def test_equals(self): """ L{cmp} returns 0 for equal objects. """ self.assertEqual(cmp(u"a", u"a"), 0) self.assertEqual(cmp(1, 1), 0) self.assertEqual(cmp([1], [1]), 0) def test_greaterThan(self): """ L{cmp} returns 1 if its first argument is bigger than its second. """ self.assertEqual(cmp(4, 0), 1) self.assertEqual(cmp(b"z", b"a"), 1) def test_lessThan(self): """ L{cmp} returns -1 if its first argument is smaller than its second. """ self.assertEqual(cmp(0.1, 2.3), -1) self.assertEqual(cmp(b"a", b"d"), -1) class StringTests(unittest.SynchronousTestCase): """ Compatibility functions and types for strings. """ def assertNativeString(self, original, expected): """ Raise an exception indicating a failed test if the output of C{nativeString(original)} is unequal to the expected string, or is not a native string. """ self.assertEqual(nativeString(original), expected) self.assertIsInstance(nativeString(original), str) def test_nonASCIIBytesToString(self): """ C{nativeString} raises a C{UnicodeError} if input bytes are not ASCII decodable. """ self.assertRaises(UnicodeError, nativeString, b"\xFF") def test_nonASCIIUnicodeToString(self): """ C{nativeString} raises a C{UnicodeError} if input Unicode is not ASCII encodable. """ self.assertRaises(UnicodeError, nativeString, u"\u1234") def test_bytesToString(self): """ C{nativeString} converts bytes to the native string format, assuming an ASCII encoding if applicable. """ self.assertNativeString(b"hello", "hello") def test_unicodeToString(self): """ C{nativeString} converts unicode to the native string format, assuming an ASCII encoding if applicable. """ self.assertNativeString(u"Good day", "Good day") def test_stringToString(self): """ C{nativeString} leaves native strings as native strings. """ self.assertNativeString("Hello!", "Hello!") def test_unexpectedType(self): """ C{nativeString} raises a C{TypeError} if given an object that is not a string of some sort. """ self.assertRaises(TypeError, nativeString, 1) def test_unicode(self): """ C{compat.unicode} is C{str} on Python 3, C{unicode} on Python 2. """ if _PY3: expected = str else: expected = unicode self.assertIs(unicodeCompat, expected) def test_nativeStringIO(self): """ L{NativeStringIO} is a file-like object that stores native strings in memory. """ f = NativeStringIO() f.write("hello") f.write(" there") self.assertEqual(f.getvalue(), "hello there") class NetworkStringTests(unittest.SynchronousTestCase): """ Tests for L{networkString}. """ def test_bytes(self): """ L{networkString} returns a C{bytes} object passed to it unmodified. """ self.assertEqual(b"foo", networkString(b"foo")) def test_bytesOutOfRange(self): """ L{networkString} raises C{UnicodeError} if passed a C{bytes} instance containing bytes not used by ASCII. """ self.assertRaises( UnicodeError, networkString, u"\N{SNOWMAN}".encode('utf-8')) if _PY3: test_bytes.skip = test_bytesOutOfRange.skip = ( "Bytes behavior of networkString only provided on Python 2.") def test_unicode(self): """ L{networkString} returns a C{unicode} object passed to it encoded into a C{bytes} instance. """ self.assertEqual(b"foo", networkString(u"foo")) def test_unicodeOutOfRange(self): """ L{networkString} raises L{UnicodeError} if passed a C{unicode} instance containing characters not encodable in ASCII. """ self.assertRaises( UnicodeError, networkString, u"\N{SNOWMAN}") if not _PY3: test_unicode.skip = test_unicodeOutOfRange.skip = ( "Unicode behavior of networkString only provided on Python 3.") def test_nonString(self): """ L{networkString} raises L{TypeError} if passed a non-string object or the wrong type of string object. """ self.assertRaises(TypeError, networkString, object()) if _PY3: self.assertRaises(TypeError, networkString, b"bytes") else: self.assertRaises(TypeError, networkString, u"text") class ReraiseTests(unittest.SynchronousTestCase): """ L{reraise} re-raises exceptions on both Python 2 and Python 3. """ def test_reraiseWithNone(self): """ Calling L{reraise} with an exception instance and a traceback of L{None} re-raises it with a new traceback. """ try: 1/0 except: typ, value, tb = sys.exc_info() try: reraise(value, None) except: typ2, value2, tb2 = sys.exc_info() self.assertEqual(typ2, ZeroDivisionError) self.assertIs(value, value2) self.assertNotEqual(traceback.format_tb(tb)[-1], traceback.format_tb(tb2)[-1]) else: self.fail("The exception was not raised.") def test_reraiseWithTraceback(self): """ Calling L{reraise} with an exception instance and a traceback re-raises the exception with the given traceback. """ try: 1/0 except: typ, value, tb = sys.exc_info() try: reraise(value, tb) except: typ2, value2, tb2 = sys.exc_info() self.assertEqual(typ2, ZeroDivisionError) self.assertIs(value, value2) self.assertEqual(traceback.format_tb(tb)[-1], traceback.format_tb(tb2)[-1]) else: self.fail("The exception was not raised.") class Python3BytesTests(unittest.SynchronousTestCase): """ Tests for L{iterbytes}, L{intToBytes}, L{lazyByteSlice}. """ def test_iteration(self): """ When L{iterbytes} is called with a bytestring, the returned object can be iterated over, resulting in the individual bytes of the bytestring. """ input = b"abcd" result = list(iterbytes(input)) self.assertEqual(result, [b'a', b'b', b'c', b'd']) def test_intToBytes(self): """ When L{intToBytes} is called with an integer, the result is an ASCII-encoded string representation of the number. """ self.assertEqual(intToBytes(213), b"213") def test_lazyByteSliceNoOffset(self): """ L{lazyByteSlice} called with some bytes returns a semantically equal version of these bytes. """ data = b'123XYZ' self.assertEqual(bytes(lazyByteSlice(data)), data) def test_lazyByteSliceOffset(self): """ L{lazyByteSlice} called with some bytes and an offset returns a semantically equal version of these bytes starting at the given offset. """ data = b'123XYZ' self.assertEqual(bytes(lazyByteSlice(data, 2)), data[2:]) def test_lazyByteSliceOffsetAndLength(self): """ L{lazyByteSlice} called with some bytes, an offset and a length returns a semantically equal version of these bytes starting at the given offset, up to the given length. """ data = b'123XYZ' self.assertEqual(bytes(lazyByteSlice(data, 2, 3)), data[2:5]) class BytesEnvironTests(unittest.TestCase): """ Tests for L{BytesEnviron}. """ def test_alwaysBytes(self): """ The output of L{BytesEnviron} should always be a L{dict} with L{bytes} values and L{bytes} keys. """ result = bytesEnviron() types = set() for key, val in iteritems(result): types.add(type(key)) types.add(type(val)) self.assertEqual(list(types), [bytes]) if platform.isWindows(): test_alwaysBytes.skip = "Environment vars are always str on Windows." class OrderedDictTests(unittest.TestCase): """ Tests for L{twisted.python.compat.OrderedDict}. """ def test_deprecated(self): """ L{twisted.python.compat.OrderedDict} is deprecated. """ from twisted.python.compat import OrderedDict OrderedDict # Shh pyflakes currentWarnings = self.flushWarnings(offendingFunctions=[ self.test_deprecated]) self.assertEqual( currentWarnings[0]['message'], "twisted.python.compat.OrderedDict was deprecated in Twisted " "15.5.0: Use collections.OrderedDict instead.") self.assertEqual(currentWarnings[0]['category'], DeprecationWarning) self.assertEqual(len(currentWarnings), 1) class CoercedUnicodeTests(unittest.TestCase): """ Tests for L{twisted.python.compat._coercedUnicode}. """ def test_unicodeASCII(self): """ Unicode strings with ASCII code points are unchanged. """ result = _coercedUnicode(u'text') self.assertEqual(result, u'text') self.assertIsInstance(result, unicodeCompat) def test_unicodeNonASCII(self): """ Unicode strings with non-ASCII code points are unchanged. """ result = _coercedUnicode(u'\N{SNOWMAN}') self.assertEqual(result, u'\N{SNOWMAN}') self.assertIsInstance(result, unicodeCompat) def test_nativeASCII(self): """ Native strings with ASCII code points are unchanged. On Python 2, this verifies that ASCII-only byte strings are accepted, whereas for Python 3 it is identical to L{test_unicodeASCII}. """ result = _coercedUnicode('text') self.assertEqual(result, u'text') self.assertIsInstance(result, unicodeCompat) def test_bytesPy3(self): """ Byte strings are not accceptable in Python 3. """ exc = self.assertRaises(TypeError, _coercedUnicode, b'bytes') self.assertEqual(str(exc), "Expected str not b'bytes' (bytes)") if not _PY3: test_bytesPy3.skip = ( "Bytes behavior of _coercedUnicode only provided on Python 2.") def test_bytesNonASCII(self): """ Byte strings with non-ASCII code points raise an exception. """ self.assertRaises(UnicodeError, _coercedUnicode, b'\xe2\x98\x83') if _PY3: test_bytesNonASCII.skip = ( "Bytes behavior of _coercedUnicode only provided on Python 2.") class UnichrTests(unittest.TestCase): """ Tests for L{unichr}. """ def test_unichr(self): """ unichar exists and returns a unicode string with the given code point. """ self.assertEqual(unichr(0x2603), u"\N{SNOWMAN}") class RawInputTests(unittest.TestCase): """ Tests for L{raw_input} """ def test_raw_input(self): """ L{twisted.python.compat.raw_input} """ class FakeStdin: def readline(self): return "User input\n" class FakeStdout: data = "" def write(self, data): self.data += data self.patch(sys, "stdin", FakeStdin()) stdout = FakeStdout() self.patch(sys, "stdout", stdout) self.assertEqual(raw_input("Prompt"), "User input") self.assertEqual(stdout.data, "Prompt") class FutureBytesReprTests(unittest.TestCase): """ Tests for L{twisted.python.compat._bytesRepr}. """ def test_bytesReprNotBytes(self): """ L{twisted.python.compat._bytesRepr} raises a L{TypeError} when called any object that is not an instance of L{bytes}. """ exc = self.assertRaises(TypeError, _bytesRepr, ["not bytes"]) self.assertEquals(str(exc), "Expected bytes not ['not bytes']") def test_bytesReprPrefix(self): """ L{twisted.python.compat._bytesRepr} always prepends ``b`` to the returned repr on both Python 2 and 3. """ self.assertEqual(_bytesRepr(b'\x00'), "b'\\x00'") class GetAsyncParamTests(unittest.SynchronousTestCase): """ Tests for L{twisted.python.compat._get_async_param} """ def test_get_async_param(self): """ L{twisted.python.compat._get_async_param} uses isAsync by default, or deprecated async keyword argument if isAsync is None. """ self.assertEqual(_get_async_param(isAsync=False), False) self.assertEqual(_get_async_param(isAsync=True), True) self.assertEqual( _get_async_param(isAsync=None, **{'async': False}), False) self.assertEqual( _get_async_param(isAsync=None, **{'async': True}), True) self.assertRaises(TypeError, _get_async_param, False, {'async': False}) def test_get_async_param_deprecation(self): """ L{twisted.python.compat._get_async_param} raises a deprecation warning if async keyword argument is passed. """ self.assertEqual( _get_async_param(isAsync=None, **{'async': False}), False) currentWarnings = self.flushWarnings( offendingFunctions=[self.test_get_async_param_deprecation]) self.assertEqual( currentWarnings[0]['message'], "'async' keyword argument is deprecated, please use isAsync")